#define MSP_GAME_OWNED_H_
#include <stdexcept>
+#include "accessguard.h"
+#include "events.h"
#include "handle.h"
+#include "stage.h"
namespace Msp::Game {
class Component;
class Entity;
-class Root;
-class Stage;
template<typename T>
class Owned: public Handle<T>
public:
Owned() = default;
- template<typename... Args>
- Owned(Handle<Entity>, Args &&...);
+ template<typename P, typename... Args>
+ Owned(Handle<P>, Args &&...);
- template<typename... Args>
- Owned(Entity &parent, Args &&... args): Owned(Handle<Entity>::from_object(&parent), std::forward<Args>(args)...) { }
+ template<typename P, typename... Args>
+ Owned(P *parent, Args &&... args): Owned(Handle<P>::from_object(parent), std::forward<Args>(args)...) { }
Owned(Owned &&other): Handle<T>(other) { other.ptr = nullptr; }
- Owned &operator=(Owned &&other);
+
+ template<typename U>
+ requires std::is_base_of_v<T, U>
+ Owned(Owned<U> &&other): Handle<T>(other) { other.ptr = nullptr; }
+
+ Owned &operator=(Owned &&other) { assign(std::move(other)); return *this; }
+
+ template<typename U>
+ requires std::is_base_of_v<T, U>
+ Owned &operator=(Owned<U> &&other) { assign(std::move(other)); return *this; }
+
~Owned() { destroy(); }
private:
+ template<typename U>
+ void assign(Owned<U> &&);
+
template<typename O>
static Stage &get_stage(O &);
template<typename T>
-template<typename... Args>
-Owned<T>::Owned(Handle<Entity> parent, Args &&... args)
+template<typename P, typename... Args>
+Owned<T>::Owned(Handle<P> parent, Args &&... args)
{
+#ifdef DEBUG
+ AccessGuard::get_instance().check<AccessGuard::Create>();
+#endif
+
if(!parent)
throw std::invalid_argument("Owned::Owned");
- using DependentEntity = std::conditional_t<sizeof(T), Entity, Entity>;
- Handle<DependentEntity> dparent = parent;
-
- Pool<T> &pool = get_stage(*dparent).get_pools().template get_pool<T>();
+ Stage &stage = get_stage(*parent);
+ Pool<T> &pool = stage.get_pools().get_pool<T>();
+ bool first_created = !pool.get_capacity();
this->ptr = pool.create(parent, std::forward<Args>(args)...);
if constexpr(std::is_base_of_v<Component, T>)
- dparent->add_component(*this);
+ {
+ if(first_created)
+ stage.get_reflector().get_or_create_class<T>().template set_polymorphic_base<Component>(**this);
+ parent->add_component(*this);
+ stage.get_event_source().emit<Events::ComponentCreated>(*this);
+ }
else
- dparent->add_child(*this);
+ {
+ if(first_created)
+ stage.get_reflector().get_or_create_class<T>().template set_polymorphic_base<Entity>(**this);
+ parent->add_child(*this);
+ stage.get_event_source().emit<Events::EntityCreated>(*this);
+ }
}
template<typename T>
-Owned<T> &Owned<T>::operator=(Owned &&other)
+template<typename U>
+void Owned<T>::assign(Owned<U> &&other)
{
destroy();
this->ptr = other.ptr;
other.ptr = nullptr;
-
- return *this;
}
template<typename T>
template<typename O>
Stage &Owned<T>::get_stage(O &obj)
{
- using DependentRoot = std::conditional_t<sizeof(T), Root, Root>;
if constexpr(std::is_base_of_v<Component, O>)
return get_stage(*obj.get_entity());
- else if constexpr(std::is_base_of_v<Entity, O>)
- return dynamic_cast<DependentRoot &>(*obj.get_root()).get_stage();
else
- return obj;
+ return obj.get_stage();
}
template<typename T>
if(!obj)
return;
- Pool<T> &pool = get_stage(*obj).get_pools().template get_pool<T>();
+#ifdef DEBUG
+ AccessGuard::get_instance().check<AccessGuard::Destroy>();
+#endif
+
+ Stage &stage = get_stage(*obj);
if constexpr(std::is_base_of_v<Component, T>)
+ {
+ stage.get_event_source().emit<Events::ComponentDestroyed>(*this);
obj->get_entity()->remove_component(*this);
+ }
else if(auto parent = obj->get_parent().get())
+ {
+ stage.get_event_source().emit<Events::EntityDestroyed>(*this);
parent->remove_child(*this);
+ }
+ Pool<T> &pool = stage.get_pools().get_pool<T>();
pool.destroy(this->ptr);
}