]> git.tdb.fi Git - libs/game.git/blob - source/game/owned.h
Emit events on entity and component creation and destruction
[libs/game.git] / source / game / owned.h
1 #ifndef MSP_GAME_OWNED_H_
2 #define MSP_GAME_OWNED_H_
3
4 #include <stdexcept>
5 #include "events.h"
6 #include "handle.h"
7 #include "stage.h"
8
9 namespace Msp::Game {
10
11 class Component;
12 class Entity;
13
14 template<typename T>
15 class Owned: public Handle<T>
16 {
17 public:
18         Owned() = default;
19
20         template<typename P, typename... Args>
21         Owned(Handle<P>, Args &&...);
22
23         template<typename P, typename... Args>
24         Owned(P &parent, Args &&... args): Owned(Handle<P>::from_object(&parent), std::forward<Args>(args)...) { }
25
26         Owned(Owned &&other): Handle<T>(other) { other.ptr = nullptr; }
27         Owned &operator=(Owned &&other);
28         ~Owned() { destroy(); }
29
30 private:
31         template<typename O>
32         static Stage &get_stage(O &);
33
34         void destroy();
35 };
36
37
38 template<typename T>
39 template<typename P, typename... Args>
40 Owned<T>::Owned(Handle<P> parent, Args &&... args)
41 {
42         if(!parent)
43                 throw std::invalid_argument("Owned::Owned");
44
45         Stage &stage = get_stage(*parent);
46         Pool<T> &pool = stage.get_pools().template get_pool<T>();
47         this->ptr = pool.create(parent, std::forward<Args>(args)...);
48         if constexpr(std::is_base_of_v<Component, T>)
49         {
50                 parent->add_component(*this);
51                 stage.get_event_source().emit<Events::ComponentCreated>(*this);
52         }
53         else
54         {
55                 parent->add_child(*this);
56                 stage.get_event_source().emit<Events::EntityCreated>(*this);
57         }
58 }
59
60 template<typename T>
61 Owned<T> &Owned<T>::operator=(Owned &&other)
62 {
63         destroy();
64
65         this->ptr = other.ptr;
66         other.ptr = nullptr;
67
68         return *this;
69 }
70
71 template<typename T>
72 template<typename O>
73 Stage &Owned<T>::get_stage(O &obj)
74 {
75         if constexpr(std::is_base_of_v<Component, O>)
76                 return get_stage(*obj.get_entity());
77         else
78                 return obj.get_stage();
79 }
80
81 template<typename T>
82 void Owned<T>::destroy()
83 {
84         T *obj = this->get();
85         if(!obj)
86                 return;
87
88         Stage &stage = get_stage(*obj);
89
90         if constexpr(std::is_base_of_v<Component, T>)
91         {
92                 stage.get_event_source().emit<Events::ComponentDestroyed>(*this);
93                 obj->get_entity()->remove_component(*this);
94         }
95         else if(auto parent = obj->get_parent().get())
96         {
97                 stage.get_event_source().emit<Events::EntityDestroyed>(*this);
98                 parent->remove_child(*this);
99         }
100
101         Pool<T> &pool = stage.get_pools().template get_pool<T>();
102         pool.destroy(this->ptr);
103 }
104
105 } // namespace Msp::Game
106
107 #endif