]> git.tdb.fi Git - libs/game.git/blob - source/game/owned.h
7159c7d9622a06fd83301b7565dc1d55c0beedcc
[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(Owned<P> &p, Args &&... a): Owned(static_cast<Handle<P> &>(p), std::forward<Args>(a)...) { }
25
26         template<typename P, typename... Args>
27                 requires(!std::is_const_v<P>)
28         Owned(P &parent, Args &&... args): Owned(Handle<P>::from_object(&parent), std::forward<Args>(args)...) { }
29
30         Owned(Owned &&other): Handle<T>(other) { other.ptr = nullptr; }
31         Owned &operator=(Owned &&other);
32         ~Owned() { destroy(); }
33
34 private:
35         template<typename O>
36         static Stage &get_stage(O &);
37
38         void destroy();
39 };
40
41
42 template<typename T>
43 template<typename P, typename... Args>
44 Owned<T>::Owned(Handle<P> parent, Args &&... args)
45 {
46         if(!parent)
47                 throw std::invalid_argument("Owned::Owned");
48
49         Stage &stage = get_stage(*parent);
50         Pool<T> &pool = stage.get_pools().get_pool<T>();
51         this->ptr = pool.create(parent, std::forward<Args>(args)...);
52         if constexpr(std::is_base_of_v<Component, T>)
53         {
54                 parent->add_component(*this);
55                 stage.get_event_source().emit<Events::ComponentCreated>(*this);
56         }
57         else
58         {
59                 parent->add_child(*this);
60                 stage.get_event_source().emit<Events::EntityCreated>(*this);
61         }
62 }
63
64 template<typename T>
65 Owned<T> &Owned<T>::operator=(Owned &&other)
66 {
67         destroy();
68
69         this->ptr = other.ptr;
70         other.ptr = nullptr;
71
72         return *this;
73 }
74
75 template<typename T>
76 template<typename O>
77 Stage &Owned<T>::get_stage(O &obj)
78 {
79         if constexpr(std::is_base_of_v<Component, O>)
80                 return get_stage(*obj.get_entity());
81         else
82                 return obj.get_stage();
83 }
84
85 template<typename T>
86 void Owned<T>::destroy()
87 {
88         T *obj = this->get();
89         if(!obj)
90                 return;
91
92         Stage &stage = get_stage(*obj);
93
94         if constexpr(std::is_base_of_v<Component, T>)
95         {
96                 stage.get_event_source().emit<Events::ComponentDestroyed>(*this);
97                 obj->get_entity()->remove_component(*this);
98         }
99         else if(auto parent = obj->get_parent().get())
100         {
101                 stage.get_event_source().emit<Events::EntityDestroyed>(*this);
102                 parent->remove_child(*this);
103         }
104
105         Pool<T> &pool = stage.get_pools().get_pool<T>();
106         pool.destroy(this->ptr);
107 }
108
109 } // namespace Msp::Game
110
111 #endif