]> git.tdb.fi Git - libs/game.git/blobdiff - source/game/stage.cpp
Schedule systems based on their declared dependencies
[libs/game.git] / source / game / stage.cpp
index bdd0ed676d27200fe87c9ee89e4231874b643f69..3888410a43c8bc976034b753693b56ab35f16d72 100644 (file)
@@ -1,4 +1,6 @@
 #include "stage.h"
+#include <msp/debug/demangle.h>
+#include <msp/strings/format.h>
 #include "accessguard.h"
 #include "camera.h"
 #include "root.h"
@@ -8,11 +10,13 @@ using namespace std;
 
 namespace Msp::Game {
 
-Stage::Stage(DataFile::Collection &r):
+Stage::Stage(Reflection::Reflector &f, DataFile::Collection &r):
+       reflector(f),
        resources(r),
        event_source(event_bus),
        event_observer(event_bus),
-       root(std::make_unique<Root>(*this))
+       root(std::make_unique<Root>(*this)),
+       scheduler(reflector)
 {
        event_observer.observe<Events::ComponentCreated>([this](auto &e){
                if(!active_camera)
@@ -27,7 +31,9 @@ Stage::~Stage()
 
 void Stage::remove_system(System &s)
 {
+       scheduler.remove_system(s);
        erase_if(systems, [&s](auto &p){ return p.get()==&s; });
+       pending_reschedule = true;
 }
 
 void Stage::set_active_camera(Handle<Camera> c)
@@ -54,12 +60,29 @@ void Stage::synthesize_initial_events(Handle<Entity> entity, EventObserver &targ
 
 void Stage::tick(Time::TimeDelta dt)
 {
+       if(pending_reschedule)
+       {
+               scheduler.schedule();
+               pending_reschedule = false;
+       }
+
        {
 #ifdef DEBUG
-               AccessGuard::BlockForScope _block;;
+               AccessGuard::BlockForScope _block;
 #endif
-               for(const auto &s: systems)
-                       s->tick(dt);
+               for(const SystemScheduler::Group &g: scheduler.get_groups())
+                       for(System *s: g.systems)
+                       {
+                               System::Activator act(*s);
+                               try
+                               {
+                                       s->tick(dt);
+                               }
+                               catch(const invalid_access &exc)
+                               {
+                                       throw invalid_access(format("%s by %s", exc.what(), Debug::demangle(typeid(*s).name())));
+                               }
+                       }
        }
 
        for(const auto &s: systems)