diff --git a/SDK/include/NDK/BaseComponent.hpp b/SDK/include/NDK/BaseComponent.hpp index 5ec1d53b6..f045ae2a6 100644 --- a/SDK/include/NDK/BaseComponent.hpp +++ b/SDK/include/NDK/BaseComponent.hpp @@ -7,7 +7,7 @@ #ifndef NDK_BASECOMPONENT_HPP #define NDK_BASECOMPONENT_HPP -#include +#include #include #include #include diff --git a/SDK/include/NDK/BaseSystem.hpp b/SDK/include/NDK/BaseSystem.hpp index 9a81c83e0..8e828149d 100644 --- a/SDK/include/NDK/BaseSystem.hpp +++ b/SDK/include/NDK/BaseSystem.hpp @@ -8,7 +8,7 @@ #define NDK_BASESYSTEM_HPP #include -#include +#include #include namespace Ndk diff --git a/SDK/include/NDK/Entity.hpp b/SDK/include/NDK/Entity.hpp index 71f5a4fc7..6069a13c0 100644 --- a/SDK/include/NDK/Entity.hpp +++ b/SDK/include/NDK/Entity.hpp @@ -8,6 +8,7 @@ #define NDK_ENTITY_HPP #include +#include #include #include #include @@ -15,13 +16,14 @@ namespace Ndk { class BaseComponent; - class EntityHandle; + class Entity; class World; - class NDK_API Entity + using EntityHandle = Nz::ObjectHandle; + + class NDK_API Entity : public Nz::HandledObject { friend class BaseSystem; - friend EntityHandle; friend World; public: @@ -32,8 +34,6 @@ namespace Ndk BaseComponent& AddComponent(std::unique_ptr&& component); template ComponentType& AddComponent(Args&&... args); - EntityHandle CreateHandle(); - inline void Enable(bool enable); inline BaseComponent& GetComponent(ComponentIndex index); @@ -56,6 +56,8 @@ namespace Ndk void RemoveComponent(ComponentIndex index); template void RemoveComponent(); + inline Nz::String ToString() const; + Entity& operator=(const Entity&) = delete; Entity& operator=(Entity&&) = delete; @@ -65,16 +67,13 @@ namespace Ndk void Create(); void Destroy(); - inline void RegisterHandle(EntityHandle* handle); inline void RegisterSystem(SystemIndex index); inline void SetWorld(World* world) noexcept; - inline void UnregisterHandle(EntityHandle* handle); inline void UnregisterSystem(SystemIndex index); std::vector> m_components; - std::vector m_handles; Nz::Bitset<> m_componentBits; Nz::Bitset<> m_systemBits; EntityId m_id; diff --git a/SDK/include/NDK/Entity.inl b/SDK/include/NDK/Entity.inl index caca8b766..799ffd97e 100644 --- a/SDK/include/NDK/Entity.inl +++ b/SDK/include/NDK/Entity.inl @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Prerequesites.hpp #include +#include #include #include #include @@ -102,10 +103,10 @@ namespace Ndk RemoveComponent(index); } - inline void Entity::RegisterHandle(EntityHandle* handle) + inline Nz::String Entity::ToString() const { - ///DOC: Un handle ne doit être enregistré qu'une fois, des erreurs se produisent s'il l'est plus d'une fois - m_handles.push_back(handle); + Nz::StringStream ss; + return ss << "Entity(" << GetId() << ')'; } inline void Entity::RegisterSystem(SystemIndex index) @@ -120,18 +121,24 @@ namespace Ndk m_world = world; } - inline void Entity::UnregisterHandle(EntityHandle* handle) - { - ///DOC: Un handle ne doit être libéré qu'une fois, et doit faire partie de la liste, sous peine de crash - auto it = std::find(m_handles.begin(), m_handles.end(), handle); - - // On échange cet élément avec le dernier, et on diminue la taille du vector de 1 - std::swap(*it, m_handles.back()); - m_handles.pop_back(); - } - inline void Entity::UnregisterSystem(SystemIndex index) { m_systemBits.UnboundedReset(index); } } + +namespace std +{ + template<> + struct hash + { + size_t operator()(const Ndk::EntityHandle& handle) const + { + // Hasher le pointeur fonctionnerait jusqu'à ce que l'entité soit mise à jour et déplacée + // pour cette raison, nous devons hasher l'ID de l'entité (qui reste constante) + Ndk::EntityId id = (handle.IsValid()) ? handle->GetId() : std::numeric_limits::max(); + + return hash()(id); + } + }; +} \ No newline at end of file diff --git a/SDK/include/NDK/EntityHandle.hpp b/SDK/include/NDK/EntityHandle.hpp deleted file mode 100644 index 8a5594dbe..000000000 --- a/SDK/include/NDK/EntityHandle.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Development Kit" -// For conditions of distribution and use, see copyright notice in Prerequesites.hpp - -#pragma once - -#ifndef NDK_ENTITYHANDLE_HPP -#define NDK_ENTITYHANDLE_HPP - -#include -#include - -namespace Ndk -{ - class EntityHandle - { - friend Entity; - - public: - EntityHandle(); - explicit EntityHandle(Entity* entity); - EntityHandle(const EntityHandle& handle); - EntityHandle(EntityHandle&& handle); - ~EntityHandle(); - - Entity* GetEntity() const; - - bool IsValid() const; - - void Reset(Entity* entity = nullptr); - void Reset(const EntityHandle& handle); - void Reset(EntityHandle&& handle); - - EntityHandle& Swap(EntityHandle& handle); - - Nz::String ToString() const; - - operator bool() const; - operator Entity*() const; - Entity* operator->() const; - - EntityHandle& operator=(Entity* entity); - EntityHandle& operator=(const EntityHandle& handle); - EntityHandle& operator=(EntityHandle&& handle); - - friend std::ostream& operator<<(std::ostream& out, const EntityHandle& handle); - - friend bool operator==(const EntityHandle& lhs, const EntityHandle& rhs); - friend bool operator==(const Entity& lhs, const EntityHandle& rhs); - friend bool operator==(const EntityHandle& lhs, const Entity& rhs); - - friend bool operator!=(const EntityHandle& lhs, const EntityHandle& rhs); - friend bool operator!=(const Entity& lhs, const EntityHandle& rhs); - friend bool operator!=(const EntityHandle& lhs, const Entity& rhs); - - friend bool operator<(const EntityHandle& lhs, const EntityHandle& rhs); - friend bool operator<(const Entity& lhs, const EntityHandle& rhs); - friend bool operator<(const EntityHandle& lhs, const Entity& rhs); - - friend bool operator<=(const EntityHandle& lhs, const EntityHandle& rhs); - friend bool operator<=(const Entity& lhs, const EntityHandle& rhs); - friend bool operator<=(const EntityHandle& lhs, const Entity& rhs); - - friend bool operator>(const EntityHandle& lhs, const EntityHandle& rhs); - friend bool operator>(const Entity& lhs, const EntityHandle& rhs); - friend bool operator>(const EntityHandle& lhs, const Entity& rhs); - - friend bool operator>=(const EntityHandle& lhs, const EntityHandle& rhs); - friend bool operator>=(const Entity& lhs, const EntityHandle& rhs); - friend bool operator>=(const EntityHandle& lhs, const Entity& rhs); - - static const EntityHandle InvalidHandle; - - protected: - void OnEntityDestroyed(); - void OnEntityMoved(Entity* newEntity); - - Entity* m_entity; - }; -} - -namespace std -{ - void swap(Ndk::EntityHandle& lhs, Ndk::EntityHandle& rhs); -} - -#include - -#endif // NDK_ENTITYHANDLE_HPP diff --git a/SDK/include/NDK/EntityHandle.inl b/SDK/include/NDK/EntityHandle.inl deleted file mode 100644 index 03e7ad829..000000000 --- a/SDK/include/NDK/EntityHandle.inl +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Development Kit" -// For conditions of distribution and use, see copyright notice in Prerequesites.hpp - -#include -#include -#include - -namespace Ndk -{ - inline EntityHandle::EntityHandle() : - m_entity(nullptr) - { - } - - inline EntityHandle::EntityHandle(Entity* entity) : - EntityHandle() - { - Reset(entity); - } - - inline EntityHandle::EntityHandle(const EntityHandle& handle) : - EntityHandle() - { - Reset(handle); - } - - inline EntityHandle::EntityHandle(EntityHandle&& handle) : - EntityHandle() - { - Reset(handle); - } - - inline EntityHandle::~EntityHandle() - { - Reset(nullptr); - } - - inline Entity* EntityHandle::GetEntity() const - { - return m_entity; - } - - inline bool EntityHandle::IsValid() const - { - return m_entity != nullptr; - } - - inline void EntityHandle::Reset(Entity* entity) - { - // Si nous avions déjà une entité, nous devons l'informer que nous ne pointons plus sur elle - if (m_entity) - m_entity->UnregisterHandle(this); - - m_entity = entity; - if (m_entity) - // On informe la nouvelle entité que nous pointons sur elle - m_entity->RegisterHandle(this); - } - - inline void EntityHandle::Reset(const EntityHandle& handle) - { - Reset(handle.GetEntity()); - } - - inline void EntityHandle::Reset(EntityHandle&& handle) - { - Reset(handle.GetEntity()); - } - - inline EntityHandle& EntityHandle::Swap(EntityHandle& handle) - { - // Comme nous inversons les handles, nous devons prévenir les entités - // La version par défaut de swap (à base de move) aurait fonctionné, - // mais en enregistrant les handles une fois de plus que nécessaire (à cause de la copie temporaire). - if (m_entity) - { - m_entity->UnregisterHandle(this); - m_entity->RegisterHandle(&handle); - } - - if (handle.m_entity) - { - handle.m_entity->UnregisterHandle(&handle); - handle.m_entity->RegisterHandle(this); - } - - // On effectue l'échange - std::swap(m_entity, handle.m_entity); - return *this; - } - - inline Nz::String EntityHandle::ToString() const - { - Nz::StringStream ss; - ss << "EntityHandle("; - if (IsValid()) - ss << "Entity(" << m_entity->GetId() << ')'; - else - ss << "Null entity"; - - ss << ')'; - - return ss; - } - - inline EntityHandle::operator bool() const - { - return IsValid(); - } - - inline EntityHandle::operator Entity*() const - { - return m_entity; - } - - inline Entity* EntityHandle::operator->() const - { - return m_entity; - } - - inline EntityHandle& EntityHandle::operator=(Entity* entity) - { - Reset(entity); - - return *this; - } - - inline EntityHandle& EntityHandle::operator=(const EntityHandle& handle) - { - Reset(handle); - - return *this; - } - - inline EntityHandle& EntityHandle::operator=(EntityHandle&& handle) - { - Reset(std::move(handle)); - - return *this; - } - - inline void EntityHandle::OnEntityDestroyed() - { - // Un raccourci, un appel à Reset nous enlèverait de la liste des handles que nous ne pouvons pas modifier - // maintenant car elle est actuellement parcourue - m_entity = nullptr; - } - - inline void EntityHandle::OnEntityMoved(Entity* newEntity) - { - // L'entité a été déplacée (peut arriver lors d'un changement de taille du conteneur du monde) - // nous mettons à jour notre pointeur - m_entity = newEntity; - } - - inline std::ostream& operator<<(std::ostream& out, const EntityHandle& handle) - { - out << "EntityHandle("; - if (handle.IsValid()) - out << "Entity(" << handle->GetId() << ')'; - else - out << "Null entity"; - - out << ')'; - - return out; - } - - inline bool operator==(const EntityHandle& lhs, const EntityHandle& rhs) - { - return lhs.m_entity == rhs.m_entity; - } - - inline bool operator==(const Entity& lhs, const EntityHandle& rhs) - { - return &lhs == rhs.m_entity; - } - - inline bool operator==(const EntityHandle& lhs, const Entity& rhs) - { - return lhs.m_entity == &rhs; - } - - inline bool operator!=(const EntityHandle& lhs, const EntityHandle& rhs) - { - return !(lhs == rhs); - } - - inline bool operator!=(const Entity& lhs, const EntityHandle& rhs) - { - return !(lhs == rhs); - } - - inline bool operator!=(const EntityHandle& lhs, const Entity& rhs) - { - return !(lhs == rhs); - } - - inline bool operator<(const EntityHandle& lhs, const EntityHandle& rhs) - { - return lhs.m_entity < rhs.m_entity; - } - - inline bool operator<(const Entity& lhs, const EntityHandle& rhs) - { - return &lhs < rhs.m_entity; - } - - inline bool operator<(const EntityHandle& lhs, const Entity& rhs) - { - return lhs.m_entity < &rhs; - } - - inline bool operator<=(const EntityHandle& lhs, const EntityHandle& rhs) - { - return !(lhs > rhs); - } - - inline bool operator<=(const Entity& lhs, const EntityHandle& rhs) - { - return !(lhs > rhs); - } - - inline bool operator<=(const EntityHandle& lhs, const Entity& rhs) - { - return !(lhs > rhs); - } - - inline bool operator>(const EntityHandle& lhs, const EntityHandle& rhs) - { - return rhs < lhs; - } - - inline bool operator>(const Entity& lhs, const EntityHandle& rhs) - { - return rhs < lhs; - } - - inline bool operator>(const EntityHandle& lhs, const Entity& rhs) - { - return rhs < lhs; - } - - inline bool operator>=(const EntityHandle& lhs, const EntityHandle& rhs) - { - return !(lhs < rhs); - } - - inline bool operator>=(const Entity& lhs, const EntityHandle& rhs) - { - return !(lhs < rhs); - } - - inline bool operator>=(const EntityHandle& lhs, const Entity& rhs) - { - return !(lhs < rhs); - } -} - -namespace std -{ - template<> - struct hash - { - size_t operator()(const Ndk::EntityHandle& handle) const - { - // Hasher le pointeur fonctionnerait jusqu'à ce que l'entité soit mise à jour et déplacée - // pour cette raison, nous devons hasher l'ID de l'entité (qui reste constante) - Ndk::EntityId id = (handle.IsValid()) ? handle->GetId() : std::numeric_limits::max(); - - return hash()(id); - } - }; - - inline void swap(Ndk::EntityHandle& lhs, Ndk::EntityHandle& rhs) - { - lhs.Swap(rhs); - } -} diff --git a/SDK/include/NDK/EntityList.hpp b/SDK/include/NDK/EntityList.hpp index 0edefde11..006967413 100644 --- a/SDK/include/NDK/EntityList.hpp +++ b/SDK/include/NDK/EntityList.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace Ndk { diff --git a/SDK/include/NDK/EntityOwner.hpp b/SDK/include/NDK/EntityOwner.hpp index 94dcf0566..c7cab901f 100644 --- a/SDK/include/NDK/EntityOwner.hpp +++ b/SDK/include/NDK/EntityOwner.hpp @@ -7,7 +7,7 @@ #ifndef NDK_ENTITYOWNER_HPP #define NDK_ENTITYOWNER_HPP -#include +#include namespace Ndk { diff --git a/SDK/include/NDK/EntityOwner.inl b/SDK/include/NDK/EntityOwner.inl index e32094eaa..607f3229d 100644 --- a/SDK/include/NDK/EntityOwner.inl +++ b/SDK/include/NDK/EntityOwner.inl @@ -26,16 +26,16 @@ namespace Ndk inline void EntityOwner::Reset(Entity* entity) { - if (m_entity) - m_entity->Kill(); + if (m_object) + m_object->Kill(); EntityHandle::Reset(entity); } inline void EntityOwner::Reset(EntityOwner&& handle) { - Reset(handle.GetEntity()); - handle.m_entity = nullptr; + Reset(handle.GetObject()); + handle.m_object = nullptr; } inline EntityOwner& EntityOwner::operator=(Entity* entity) diff --git a/SDK/src/NDK/Entity.cpp b/SDK/src/NDK/Entity.cpp index afd3aa1b6..17730a234 100644 --- a/SDK/src/NDK/Entity.cpp +++ b/SDK/src/NDK/Entity.cpp @@ -4,14 +4,13 @@ #include #include -#include #include namespace Ndk { Entity::Entity(Entity&& entity) : + HandledObject(std::move(entity)), m_components(std::move(entity.m_components)), - m_handles(std::move(entity.m_handles)), m_componentBits(std::move(entity.m_componentBits)), m_systemBits(std::move(entity.m_systemBits)), m_id(entity.m_id), @@ -19,8 +18,6 @@ namespace Ndk m_enabled(entity.m_enabled), m_valid(entity.m_valid) { - for (EntityHandle* handle : m_handles) - handle->OnEntityMoved(this); } Entity::Entity(World* world, EntityId id) : @@ -63,11 +60,6 @@ namespace Ndk return component; } - EntityHandle Entity::CreateHandle() - { - return EntityHandle(this); - } - void Entity::Kill() { m_world->KillEntity(this); @@ -132,11 +124,7 @@ namespace Ndk } m_systemBits.Clear(); - // On informe chaque handle de notre destruction pour éviter qu'il ne continue de pointer sur nous - for (EntityHandle* handle : m_handles) - handle->OnEntityDestroyed(); - - m_handles.clear(); + UnregisterAllHandles(); m_valid = false; } diff --git a/SDK/src/NDK/EntityHandle.cpp b/SDK/src/NDK/EntityHandle.cpp deleted file mode 100644 index 7b9d035e3..000000000 --- a/SDK/src/NDK/EntityHandle.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Development Kit" -// For conditions of distribution and use, see copyright notice in Prerequesites.hpp - -#include - -namespace Ndk -{ - const EntityHandle EntityHandle::InvalidHandle; -} diff --git a/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index 483af6d27..1762f1d12 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -61,7 +61,7 @@ namespace Ndk void World::Clear() noexcept { - ///DOC: Tous les handles sont correctement invalidés + ///DOC: Tous les handles sont correctement invalidés, les entités sont immédiatement invalidées // Destruction des entités d'abord, et des handles ensuite // ceci pour éviter que les handles n'informent les entités inutilement lors de leur destruction diff --git a/include/Nazara/Core/HandledObject.hpp b/include/Nazara/Core/HandledObject.hpp new file mode 100644 index 000000000..f1e096748 --- /dev/null +++ b/include/Nazara/Core/HandledObject.hpp @@ -0,0 +1,47 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NAZARA_OBJECTHANDLER_HPP +#define NAZARA_OBJECTHANDLER_HPP + +#include +#include +#include + +namespace Nz +{ + template class ObjectHandle; + + template + class HandledObject + { + friend ObjectHandle; + + public: + HandledObject() = default; + HandledObject(const HandledObject& object); + HandledObject(HandledObject&& object); + ~HandledObject(); + + ObjectHandle CreateHandle(); + + HandledObject& operator=(const HandledObject& object); + HandledObject& operator=(HandledObject&& object); + + protected: + void UnregisterAllHandles(); + + private: + void RegisterHandle(ObjectHandle* handle); + void UnregisterHandle(ObjectHandle* handle); + + std::vector*> m_handles; + }; +} + +#include + +#endif // NAZARA_OBJECTHANDLER_HPP diff --git a/include/Nazara/Core/HandledObject.inl b/include/Nazara/Core/HandledObject.inl new file mode 100644 index 000000000..53a5065f4 --- /dev/null +++ b/include/Nazara/Core/HandledObject.inl @@ -0,0 +1,84 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include + +namespace Nz +{ + template + HandledObject::HandledObject(const HandledObject& object) + { + // Don't copy anything, we're a copy of the object, we have no handle right now + } + + template + HandledObject::HandledObject(HandledObject&& object) : + m_handles(std::move(object.m_handles)) + { + for (ObjectHandle* handle : m_handles) + handle->OnObjectMoved(static_cast(this)); + } + + template + HandledObject::~HandledObject() + { + UnregisterAllHandles(); + } + + template + ObjectHandle HandledObject::CreateHandle() + { + return ObjectHandle(static_cast(this)); + } + + template + HandledObject& HandledObject::operator=(const HandledObject& object) + { + // Nothing to do + return *this; + } + + template + HandledObject& HandledObject::operator=(HandledObject&& object) + { + m_handles = std::move(object.m_handles); + for (ObjectHandle* handle : m_handles) + handle->OnObjectMoved(static_cast(this)); + + return *this; + } + + template + void HandledObject::RegisterHandle(ObjectHandle* handle) + { + ///DOC: Un handle ne doit être enregistré qu'une fois, des erreurs se produisent s'il l'est plus d'une fois + m_handles.push_back(handle); + } + + template + void HandledObject::UnregisterAllHandles() + { + // Tell every handle we got destroyed, to null them + for (ObjectHandle* handle : m_handles) + handle->OnObjectDestroyed(); + + m_handles.clear(); + } + + template + void HandledObject::UnregisterHandle(ObjectHandle* handle) + { + ///DOC: Un handle ne doit être libéré qu'une fois, et doit faire partie de la liste, sous peine de crash + auto it = std::find(m_handles.begin(), m_handles.end(), handle); + NazaraAssert(it != m_handles.end(), "Handle not registred"); + + // On échange cet élément avec le dernier, et on diminue la taille du vector de 1 + std::swap(*it, m_handles.back()); + m_handles.pop_back(); + } +} diff --git a/include/Nazara/Core/ObjectHandle.hpp b/include/Nazara/Core/ObjectHandle.hpp new file mode 100644 index 000000000..d7a53e281 --- /dev/null +++ b/include/Nazara/Core/ObjectHandle.hpp @@ -0,0 +1,93 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_OBJECTHANDLE_HPP +#define NAZARA_OBJECTHANDLE_HPP + +#include +#include + +namespace Nz +{ + template class HandledObject; + + template + class ObjectHandle + { + friend HandledObject; + + public: + ObjectHandle(); + explicit ObjectHandle(T* object); + ObjectHandle(const ObjectHandle& handle); + ~ObjectHandle(); + + T* GetObject() const; + + bool IsValid() const; + + void Reset(T* object = nullptr); + void Reset(const ObjectHandle& handle); + + ObjectHandle& Swap(ObjectHandle& handle); + + Nz::String ToString() const; + + operator bool() const; + operator T*() const; + T* operator->() const; + + ObjectHandle& operator=(T* object); + ObjectHandle& operator=(const ObjectHandle& handle); + + static const ObjectHandle InvalidHandle; + + protected: + void OnObjectDestroyed(); + void OnObjectMoved(T* newObject); + + T* m_object; + }; + + template std::ostream& operator<<(std::ostream& out, const ObjectHandle& handle); + + template bool operator==(const ObjectHandle& lhs, const ObjectHandle& rhs); + template bool operator==(const T& lhs, const ObjectHandle& rhs); + template bool operator==(const ObjectHandle& lhs, const T& rhs); + + template bool operator!=(const ObjectHandle& lhs, const ObjectHandle& rhs); + template bool operator!=(const T& lhs, const ObjectHandle& rhs); + template bool operator!=(const ObjectHandle& lhs, const T& rhs); + + template bool operator<(const ObjectHandle& lhs, const ObjectHandle& rhs); + template bool operator<(const T& lhs, const ObjectHandle& rhs); + template bool operator<(const ObjectHandle& lhs, const T& rhs); + + template bool operator<=(const ObjectHandle, const ObjectHandle& rhs); + template bool operator<=(const T& lhs, const ObjectHandle& rhs); + template bool operator<=(const ObjectHandle& lhs, const T& rhs); + + template bool operator>(const ObjectHandle& lhs, const ObjectHandle& rhs); + template bool operator>(const T& lhs, const ObjectHandle& rhs); + template bool operator>(const ObjectHandle& lhs, const T& rhs); + + template bool operator>=(const ObjectHandle& lhs, const ObjectHandle& rhs); + template bool operator>=(const T& lhs, const ObjectHandle& rhs); + template bool operator>=(const ObjectHandle& lhs, const T& rhs); + + template struct PointedType> { typedef T type; }; + template struct PointedType> { typedef T type; }; +} + +namespace std +{ + template + void swap(Nz::ObjectHandle& lhs, Nz::ObjectHandle& rhs); +} + +#include + +#endif // NAZARA_OBJECTHANDLE_HPP diff --git a/include/Nazara/Core/ObjectHandle.inl b/include/Nazara/Core/ObjectHandle.inl new file mode 100644 index 000000000..752cb96c0 --- /dev/null +++ b/include/Nazara/Core/ObjectHandle.inl @@ -0,0 +1,280 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + template + ObjectHandle::ObjectHandle() : + m_object(nullptr) + { + } + + template + ObjectHandle::ObjectHandle(T* object) : + ObjectHandle() + { + Reset(object); + } + + template + ObjectHandle::ObjectHandle(const ObjectHandle& handle) : + ObjectHandle() + { + Reset(handle); + } + + template + ObjectHandle::~ObjectHandle() + { + Reset(nullptr); + } + + template + T* ObjectHandle::GetObject() const + { + return m_object; + } + + template + bool ObjectHandle::IsValid() const + { + return m_object != nullptr; + } + + template + void ObjectHandle::Reset(T* object) + { + // Si nous avions déjà une entité, nous devons l'informer que nous ne pointons plus sur elle + if (m_object) + m_object->UnregisterHandle(this); + + m_object = object; + if (m_object) + // On informe la nouvelle entité que nous pointons sur elle + m_object->RegisterHandle(this); + } + + template + void ObjectHandle::Reset(const ObjectHandle& handle) + { + Reset(handle.GetObject()); + } + + template + ObjectHandle& ObjectHandle::Swap(ObjectHandle& handle) + { + // Comme nous inversons les handles, nous devons prévenir les entités + // La version par défaut de swap (à base de move) aurait fonctionné, + // mais en enregistrant les handles une fois de plus que nécessaire (à cause de la copie temporaire). + if (m_object) + { + m_object->UnregisterHandle(this); + m_object->RegisterHandle(&handle); + } + + if (handle.m_object) + { + handle.m_object->UnregisterHandle(&handle); + handle.m_object->RegisterHandle(this); + } + + // On effectue l'échange + std::swap(m_object, handle.m_object); + return *this; + } + + template + Nz::String ObjectHandle::ToString() const + { + Nz::StringStream ss; + ss << "ObjectHandle("; + if (IsValid()) + ss << m_object->ToString(); + else + ss << "Null"; + + ss << ')'; + + return ss; + } + + template + ObjectHandle::operator bool() const + { + return IsValid(); + } + + template + ObjectHandle::operator T*() const + { + return m_object; + } + + template + T* ObjectHandle::operator->() const + { + return m_object; + } + + template + ObjectHandle& ObjectHandle::operator=(T* entity) + { + Reset(entity); + + return *this; + } + + template + ObjectHandle& ObjectHandle::operator=(const ObjectHandle& handle) + { + Reset(handle); + + return *this; + } + + template + void ObjectHandle::OnObjectDestroyed() + { + // Shortcut + m_object = nullptr; + } + + template + void ObjectHandle::OnObjectMoved(T* newObject) + { + // The object has been moved, update our pointer + m_object = newObject; + } + + template + std::ostream& operator<<(std::ostream& out, const ObjectHandle& handle) + { + return handle.ToString(); + } + + template + bool operator==(const ObjectHandle& lhs, const ObjectHandle& rhs) + { + return lhs.GetObject() == rhs.GetObject(); + } + + template + bool operator==(const T& lhs, const ObjectHandle& rhs) + { + return &lhs == rhs.GetObject(); + } + + template + bool operator==(const ObjectHandle& lhs, const T& rhs) + { + return lhs.GetObject() == &rhs; + } + + template + bool operator!=(const ObjectHandle& lhs, const ObjectHandle& rhs) + { + return !(lhs == rhs); + } + + template + bool operator!=(const T& lhs, const ObjectHandle& rhs) + { + return !(lhs == rhs); + } + + template + bool operator!=(const ObjectHandle& lhs, const T& rhs) + { + return !(lhs == rhs); + } + + template + bool operator<(const ObjectHandle& lhs, const ObjectHandle& rhs) + { + return lhs.m_object < rhs.m_object; + } + + template + bool operator<(const T& lhs, const ObjectHandle& rhs) + { + return &lhs < rhs.m_object; + } + + template + bool operator<(const ObjectHandle& lhs, const T& rhs) + { + return lhs.m_object < &rhs; + } + + template + bool operator<=(const ObjectHandle& lhs, const ObjectHandle& rhs) + { + return !(lhs > rhs); + } + + template + bool operator<=(const T& lhs, const ObjectHandle& rhs) + { + return !(lhs > rhs); + } + + template + bool operator<=(const ObjectHandle& lhs, const T& rhs) + { + return !(lhs > rhs); + } + + template + bool operator>(const ObjectHandle& lhs, const ObjectHandle& rhs) + { + return rhs < lhs; + } + + template + bool operator>(const T& lhs, const ObjectHandle& rhs) + { + return rhs < lhs; + } + + template + bool operator>(const ObjectHandle& lhs, const T& rhs) + { + return rhs < lhs; + } + + template + bool operator>=(const ObjectHandle& lhs, const ObjectHandle& rhs) + { + return !(lhs < rhs); + } + + template + bool operator>=(const T& lhs, const ObjectHandle& rhs) + { + return !(lhs < rhs); + } + + template + bool operator>=(const ObjectHandle& lhs, const T& rhs) + { + return !(lhs < rhs); + } + + template + const ObjectHandle ObjectHandle::InvalidHandle; +} + +namespace std +{ + template + void swap(Nz::ObjectHandle& lhs, Nz::ObjectHandle& rhs) + { + lhs.Swap(rhs); + } +}