]> git.tdb.fi Git - libs/game.git/blob - source/game/stage.cpp
Report which system caused invalid access
[libs/game.git] / source / game / stage.cpp
1 #include "stage.h"
2 #include <msp/debug/demangle.h>
3 #include <msp/strings/format.h>
4 #include "accessguard.h"
5 #include "camera.h"
6 #include "root.h"
7 #include "system.h"
8
9 using namespace std;
10
11 namespace Msp::Game {
12
13 Stage::Stage(Reflection::Reflector &f, DataFile::Collection &r):
14         reflector(f),
15         resources(r),
16         event_source(event_bus),
17         event_observer(event_bus),
18         root(std::make_unique<Root>(*this))
19 {
20         event_observer.observe<Events::ComponentCreated>([this](auto &e){
21                 if(!active_camera)
22                         if(Handle<Camera> camera = dynamic_handle_cast<Camera>(e.component))
23                                 set_active_camera(camera);
24         });
25 }
26
27 // Hide unique_ptr destructors from the header
28 Stage::~Stage()
29 { }
30
31 void Stage::remove_system(System &s)
32 {
33         erase_if(systems, [&s](auto &p){ return p.get()==&s; });
34 }
35
36 void Stage::set_active_camera(Handle<Camera> c)
37 {
38         active_camera = c;
39         event_source.emit<Events::CameraChanged>(active_camera);
40 }
41
42 void Stage::synthesize_initial_events(EventObserver &target_observer)
43 {
44         synthesize_initial_events(Handle<Entity>::from_object(root.get()), target_observer);
45         if(active_camera)
46                 event_source.emit_to<Events::CameraChanged>(target_observer, active_camera);
47 }
48
49 void Stage::synthesize_initial_events(Handle<Entity> entity, EventObserver &target_observer)
50 {
51         for(Handle<Component> c: entity->get_components())
52                 event_source.emit_to<Events::ComponentCreated>(target_observer, c);
53         for(Handle<Entity> e: entity->get_children())
54                 synthesize_initial_events(e, target_observer);
55         event_source.emit_to<Events::EntityCreated>(target_observer, entity);
56 }
57
58 void Stage::tick(Time::TimeDelta dt)
59 {
60         {
61 #ifdef DEBUG
62                 AccessGuard::BlockForScope _block;;
63 #endif
64                 for(const auto &s: systems)
65                 {
66                         System::Activator act(*s);
67                         try
68                         {
69                                 s->tick(dt);
70                         }
71                         catch(const invalid_access &exc)
72                         {
73                                 throw invalid_access(format("%s by %s", exc.what(), Debug::demangle(typeid(*s).name())));
74                         }
75                 }
76         }
77
78         for(const auto &s: systems)
79                 s->deferred_tick();
80 }
81
82 } // namespace Msp::Game