1 #ifndef MSP_GAME_SYSTEM_H_
2 #define MSP_GAME_SYSTEM_H_
5 #include <msp/time/timedelta.h>
7 #include "reflection.h"
21 UPDATE = READ_OLD | WRITE,
22 CHAINED_UPDATE = READ_FRESH | WRITE
27 DependencyFlags flags = NO_DEPENDENCY;
28 const Reflection::ClassBase &type;
29 void (*prepare)(Stage &) = nullptr;
30 void (*commit)(Stage &) = nullptr;
32 Dependency(const Reflection::ClassBase &t): type(t) { }
35 class Activator: public NonCopyable
41 Activator(System &s): system(s) { system.begin_tick(); }
42 ~Activator() { system.end_tick(); }
47 std::vector<std::function<void()>> deferred_queue;
48 std::vector<Dependency> dependencies;
50 static thread_local System *active;
52 System(Stage &s): stage(s) { }
54 virtual ~System() = default;
56 Stage &get_stage() const { return stage; }
60 void declare_dependency(DependencyFlags);
64 virtual void tick(Time::TimeDelta) = 0;
66 virtual void deferred_tick();
70 void defer(F &&f) { deferred_queue.emplace_back(std::forward<F>(f)); }
75 inline void System::declare_dependency(DependencyFlags flags)
77 if(!std::is_base_of_v<Component, T>)
78 throw std::invalid_argument("System::declare_dependency");
80 const Reflection::ClassBase &type = stage.get_reflector().get_or_create_class<T>();
81 auto i = find_if(dependencies, [&type](const Dependency &d){ return &d.type==&type; });
83 if(i!=dependencies.end())
84 flags = static_cast<DependencyFlags>(flags|i->flags);
86 Dependency &dep = (i!=dependencies.end() ? *i : dependencies.emplace_back(type));
88 if constexpr(requires(T &c) { typename T::Data; c.prepare_tick(); c.commit_tick(); })
91 dep.prepare = +[](Stage &s){ s.iterate_objects<T>([](T &c){ c.prepare_tick(); }); };
92 dep.commit = +[](Stage &s){ s.iterate_objects<T>([](T &c){ c.commit_tick(); }); };
96 } // namespace Msp::Game