]> git.tdb.fi Git - libs/game.git/blob - source/game/owned.h
19daa7efe12afbbffeb3676d635088daca4889ff
[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 "handle.h"
6 #include "stage.h"
7
8 namespace Msp::Game {
9
10 class Component;
11 class Entity;
12
13 template<typename T>
14 class Owned: public Handle<T>
15 {
16 public:
17         Owned() = default;
18
19         template<typename... Args>
20         Owned(Handle<Entity>, Args &&...);
21
22         template<typename... Args>
23         Owned(Entity &parent, Args &&... args): Owned(Handle<Entity>::from_object(&parent), std::forward<Args>(args)...) { }
24
25         Owned(Owned &&other): Handle<T>(other) { other.ptr = nullptr; }
26         Owned &operator=(Owned &&other);
27         ~Owned() { destroy(); }
28
29 private:
30         template<typename O>
31         static Stage &get_stage(O &);
32
33         void destroy();
34 };
35
36
37 template<typename T>
38 template<typename... Args>
39 Owned<T>::Owned(Handle<Entity> parent, Args &&... args)
40 {
41         if(!parent)
42                 throw std::invalid_argument("Owned::Owned");
43
44         using DependentEntity = std::conditional_t<sizeof(T), Entity, Entity>;
45         Handle<DependentEntity> dparent = parent;
46
47         Pool<T> &pool = get_stage(*dparent).get_pools().template get_pool<T>();
48         this->ptr = pool.create(parent, std::forward<Args>(args)...);
49         if constexpr(std::is_base_of_v<Component, T>)
50                 dparent->add_component(*this);
51         else
52                 dparent->add_child(*this);
53 }
54
55 template<typename T>
56 Owned<T> &Owned<T>::operator=(Owned &&other)
57 {
58         destroy();
59
60         this->ptr = other.ptr;
61         other.ptr = nullptr;
62
63         return *this;
64 }
65
66 template<typename T>
67 template<typename O>
68 Stage &Owned<T>::get_stage(O &obj)
69 {
70         if constexpr(std::is_base_of_v<Component, O>)
71                 return get_stage(*obj.get_entity());
72         else
73                 return obj.get_stage();
74 }
75
76 template<typename T>
77 void Owned<T>::destroy()
78 {
79         T *obj = this->get();
80         if(!obj)
81                 return;
82
83         Pool<T> &pool = get_stage(*obj).get_pools().template get_pool<T>();
84
85         if constexpr(std::is_base_of_v<Component, T>)
86                 obj->get_entity()->remove_component(*this);
87         else if(auto parent = obj->get_parent().get())
88                 parent->remove_child(*this);
89
90         pool.destroy(this->ptr);
91 }
92
93 } // namespace Msp::Game
94
95 #endif