#include <msp/time/timedelta.h>
#include "accessguard.h"
#include "component.h"
+#include "mspgame_api.h"
#include "reflection.h"
#include "stage.h"
namespace Msp::Game {
-class System
+class MSPGAME_API System
{
public:
enum DependencyFlags
READ_FRESH = 3,
WRITE = 4,
UPDATE = READ_OLD | WRITE,
- CHAINED_UPDATE = READ_FRESH | WRITE
+ CHAINED_UPDATE = READ_FRESH | WRITE,
+ DATA_MASK = 7,
+ RUN_BEFORE = 8,
+ RUN_AFTER = 16,
+ ORDER_MASK = 24
};
- struct Dependency
+ class Dependency
{
+ friend class System;
+
+ private:
DependencyFlags flags = NO_DEPENDENCY;
const Reflection::ClassBase &type;
void (*prepare)(Stage &) = nullptr;
void (*unblock)(DependencyFlags) = nullptr;
void (*block)(DependencyFlags) = nullptr;
+ public:
Dependency(const Reflection::ClassBase &t): type(t) { }
+
+ DependencyFlags get_flags() const { return flags; }
+ const Reflection::ClassBase &get_type() const { return type; }
};
class Activator: public NonCopyable
void declare_dependency(DependencyFlags);
public:
+ const std::vector<Dependency> &get_dependencies() const { return dependencies; }
+
void begin_tick();
virtual void tick(Time::TimeDelta) = 0;
void end_tick();
template<typename T>
inline void System::declare_dependency(DependencyFlags flags)
{
- if(!std::is_base_of_v<Component, T>)
+ if((flags&DATA_MASK) && !std::is_base_of_v<Component, T>)
+ throw std::invalid_argument("System::declare_dependency");
+ if((flags&ORDER_MASK) && !std::is_base_of_v<System, T>)
throw std::invalid_argument("System::declare_dependency");
const Reflection::ClassBase &type = stage.get_reflector().get_or_create_class<T>();
if(i!=dependencies.end())
flags = static_cast<DependencyFlags>(flags|i->flags);
+ if((flags&RUN_BEFORE) && (flags&RUN_AFTER))
+ throw std::logic_error("conflicting order flags");
Dependency &dep = (i!=dependencies.end() ? *i : dependencies.emplace_back(type));
dep.flags = flags;