]> git.tdb.fi Git - libs/game.git/blob - source/game/owned.h
Change Owned's constructor to take a pointer to the parent
[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 "accessguard.h"
6 #include "events.h"
7 #include "handle.h"
8 #include "stage.h"
9
10 namespace Msp::Game {
11
12 class Component;
13 class Entity;
14
15 template<typename T>
16 class Owned: public Handle<T>
17 {
18 public:
19         Owned() = default;
20
21         template<typename P, typename... Args>
22         Owned(Handle<P>, Args &&...);
23
24         template<typename P, typename... Args>
25         Owned(P *parent, Args &&... args): Owned(Handle<P>::from_object(parent), std::forward<Args>(args)...) { }
26
27         Owned(Owned &&other): Handle<T>(other) { other.ptr = nullptr; }
28         Owned &operator=(Owned &&other);
29         ~Owned() { destroy(); }
30
31 private:
32         template<typename O>
33         static Stage &get_stage(O &);
34
35         void destroy();
36 };
37
38
39 template<typename T>
40 template<typename P, typename... Args>
41 Owned<T>::Owned(Handle<P> parent, Args &&... args)
42 {
43 #ifdef DEBUG
44         AccessGuard::get_instance().check<AccessGuard::Create>();
45 #endif
46
47         if(!parent)
48                 throw std::invalid_argument("Owned::Owned");
49
50         Stage &stage = get_stage(*parent);
51         Pool<T> &pool = stage.get_pools().get_pool<T>();
52         bool first_created = !pool.get_capacity();
53         this->ptr = pool.create(parent, std::forward<Args>(args)...);
54         if constexpr(std::is_base_of_v<Component, T>)
55         {
56                 if(first_created)
57                         stage.get_reflector().get_or_create_class<T>().template set_polymorphic_base<Component>(**this);
58                 parent->add_component(*this);
59                 stage.get_event_source().emit<Events::ComponentCreated>(*this);
60         }
61         else
62         {
63                 if(first_created)
64                         stage.get_reflector().get_or_create_class<T>().template set_polymorphic_base<Entity>(**this);
65                 parent->add_child(*this);
66                 stage.get_event_source().emit<Events::EntityCreated>(*this);
67         }
68 }
69
70 template<typename T>
71 Owned<T> &Owned<T>::operator=(Owned &&other)
72 {
73         destroy();
74
75         this->ptr = other.ptr;
76         other.ptr = nullptr;
77
78         return *this;
79 }
80
81 template<typename T>
82 template<typename O>
83 Stage &Owned<T>::get_stage(O &obj)
84 {
85         if constexpr(std::is_base_of_v<Component, O>)
86                 return get_stage(*obj.get_entity());
87         else
88                 return obj.get_stage();
89 }
90
91 template<typename T>
92 void Owned<T>::destroy()
93 {
94         T *obj = this->get();
95         if(!obj)
96                 return;
97
98 #ifdef DEBUG
99         AccessGuard::get_instance().check<AccessGuard::Destroy>();
100 #endif
101
102         Stage &stage = get_stage(*obj);
103
104         if constexpr(std::is_base_of_v<Component, T>)
105         {
106                 stage.get_event_source().emit<Events::ComponentDestroyed>(*this);
107                 obj->get_entity()->remove_component(*this);
108         }
109         else if(auto parent = obj->get_parent().get())
110         {
111                 stage.get_event_source().emit<Events::EntityDestroyed>(*this);
112                 parent->remove_child(*this);
113         }
114
115         Pool<T> &pool = stage.get_pools().get_pool<T>();
116         pool.destroy(this->ptr);
117 }
118
119 } // namespace Msp::Game
120
121 #endif