Add generic handlers
Former-commit-id: 8fc343d3a056de8031cf453748b8801d50d3710e
This commit is contained in:
47
include/Nazara/Core/HandledObject.hpp
Normal file
47
include/Nazara/Core/HandledObject.hpp
Normal file
@@ -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 <Nazara/Core/Bitset.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T> class ObjectHandle;
|
||||
|
||||
template<typename T>
|
||||
class HandledObject
|
||||
{
|
||||
friend ObjectHandle<T>;
|
||||
|
||||
public:
|
||||
HandledObject() = default;
|
||||
HandledObject(const HandledObject& object);
|
||||
HandledObject(HandledObject&& object);
|
||||
~HandledObject();
|
||||
|
||||
ObjectHandle<T> CreateHandle();
|
||||
|
||||
HandledObject& operator=(const HandledObject& object);
|
||||
HandledObject& operator=(HandledObject&& object);
|
||||
|
||||
protected:
|
||||
void UnregisterAllHandles();
|
||||
|
||||
private:
|
||||
void RegisterHandle(ObjectHandle<T>* handle);
|
||||
void UnregisterHandle(ObjectHandle<T>* handle);
|
||||
|
||||
std::vector<ObjectHandle<T>*> m_handles;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Core/HandledObject.inl>
|
||||
|
||||
#endif // NAZARA_OBJECTHANDLER_HPP
|
||||
84
include/Nazara/Core/HandledObject.inl
Normal file
84
include/Nazara/Core/HandledObject.inl
Normal file
@@ -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 <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/ObjectHandle.hpp>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T>
|
||||
HandledObject<T>::HandledObject(const HandledObject& object)
|
||||
{
|
||||
// Don't copy anything, we're a copy of the object, we have no handle right now
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
HandledObject<T>::HandledObject(HandledObject&& object) :
|
||||
m_handles(std::move(object.m_handles))
|
||||
{
|
||||
for (ObjectHandle<T>* handle : m_handles)
|
||||
handle->OnObjectMoved(static_cast<T*>(this));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
HandledObject<T>::~HandledObject()
|
||||
{
|
||||
UnregisterAllHandles();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectHandle<T> HandledObject<T>::CreateHandle()
|
||||
{
|
||||
return ObjectHandle<T>(static_cast<T*>(this));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
HandledObject<T>& HandledObject<T>::operator=(const HandledObject& object)
|
||||
{
|
||||
// Nothing to do
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
HandledObject<T>& HandledObject<T>::operator=(HandledObject&& object)
|
||||
{
|
||||
m_handles = std::move(object.m_handles);
|
||||
for (ObjectHandle<T>* handle : m_handles)
|
||||
handle->OnObjectMoved(static_cast<T*>(this));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void HandledObject<T>::RegisterHandle(ObjectHandle<T>* 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<typename T>
|
||||
void HandledObject<T>::UnregisterAllHandles()
|
||||
{
|
||||
// Tell every handle we got destroyed, to null them
|
||||
for (ObjectHandle<T>* handle : m_handles)
|
||||
handle->OnObjectDestroyed();
|
||||
|
||||
m_handles.clear();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void HandledObject<T>::UnregisterHandle(ObjectHandle<T>* 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();
|
||||
}
|
||||
}
|
||||
93
include/Nazara/Core/ObjectHandle.hpp
Normal file
93
include/Nazara/Core/ObjectHandle.hpp
Normal file
@@ -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 <Nazara/Core/Algorithm.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T> class HandledObject;
|
||||
|
||||
template<typename T>
|
||||
class ObjectHandle
|
||||
{
|
||||
friend HandledObject<T>;
|
||||
|
||||
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<typename T> std::ostream& operator<<(std::ostream& out, const ObjectHandle<T>& handle);
|
||||
|
||||
template<typename T> bool operator==(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator==(const T& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator==(const ObjectHandle<T>& lhs, const T& rhs);
|
||||
|
||||
template<typename T> bool operator!=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator!=(const T& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator!=(const ObjectHandle<T>& lhs, const T& rhs);
|
||||
|
||||
template<typename T> bool operator<(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator<(const T& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator<(const ObjectHandle<T>& lhs, const T& rhs);
|
||||
|
||||
template<typename T> bool operator<=(const ObjectHandle<T>, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator<=(const T& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator<=(const ObjectHandle<T>& lhs, const T& rhs);
|
||||
|
||||
template<typename T> bool operator>(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator>(const T& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator>(const ObjectHandle<T>& lhs, const T& rhs);
|
||||
|
||||
template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator>=(const T& lhs, const ObjectHandle<T>& rhs);
|
||||
template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const T& rhs);
|
||||
|
||||
template<typename T> struct PointedType<ObjectHandle<T>> { typedef T type; };
|
||||
template<typename T> struct PointedType<const ObjectHandle<T>> { typedef T type; };
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<typename T>
|
||||
void swap(Nz::ObjectHandle<T>& lhs, Nz::ObjectHandle<T>& rhs);
|
||||
}
|
||||
|
||||
#include <Nazara/Core/ObjectHandle.inl>
|
||||
|
||||
#endif // NAZARA_OBJECTHANDLE_HPP
|
||||
280
include/Nazara/Core/ObjectHandle.inl
Normal file
280
include/Nazara/Core/ObjectHandle.inl
Normal file
@@ -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 <Nazara/Core/ObjectHandle.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T>
|
||||
ObjectHandle<T>::ObjectHandle() :
|
||||
m_object(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectHandle<T>::ObjectHandle(T* object) :
|
||||
ObjectHandle()
|
||||
{
|
||||
Reset(object);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectHandle<T>::ObjectHandle(const ObjectHandle<T>& handle) :
|
||||
ObjectHandle()
|
||||
{
|
||||
Reset(handle);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectHandle<T>::~ObjectHandle()
|
||||
{
|
||||
Reset(nullptr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* ObjectHandle<T>::GetObject() const
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ObjectHandle<T>::IsValid() const
|
||||
{
|
||||
return m_object != nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ObjectHandle<T>::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<typename T>
|
||||
void ObjectHandle<T>::Reset(const ObjectHandle<T>& handle)
|
||||
{
|
||||
Reset(handle.GetObject());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectHandle<T>& ObjectHandle<T>::Swap(ObjectHandle<T>& 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<typename T>
|
||||
Nz::String ObjectHandle<T>::ToString() const
|
||||
{
|
||||
Nz::StringStream ss;
|
||||
ss << "ObjectHandle(";
|
||||
if (IsValid())
|
||||
ss << m_object->ToString();
|
||||
else
|
||||
ss << "Null";
|
||||
|
||||
ss << ')';
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectHandle<T>::operator bool() const
|
||||
{
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectHandle<T>::operator T*() const
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* ObjectHandle<T>::operator->() const
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectHandle<T>& ObjectHandle<T>::operator=(T* entity)
|
||||
{
|
||||
Reset(entity);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ObjectHandle<T>& ObjectHandle<T>::operator=(const ObjectHandle<T>& handle)
|
||||
{
|
||||
Reset(handle);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ObjectHandle<T>::OnObjectDestroyed()
|
||||
{
|
||||
// Shortcut
|
||||
m_object = nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ObjectHandle<T>::OnObjectMoved(T* newObject)
|
||||
{
|
||||
// The object has been moved, update our pointer
|
||||
m_object = newObject;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const ObjectHandle<T>& handle)
|
||||
{
|
||||
return handle.ToString();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator==(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return lhs.GetObject() == rhs.GetObject();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator==(const T& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return &lhs == rhs.GetObject();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator==(const ObjectHandle<T>& lhs, const T& rhs)
|
||||
{
|
||||
return lhs.GetObject() == &rhs;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator!=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator!=(const T& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator!=(const ObjectHandle<T>& lhs, const T& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator<(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return lhs.m_object < rhs.m_object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator<(const T& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return &lhs < rhs.m_object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator<(const ObjectHandle<T>& lhs, const T& rhs)
|
||||
{
|
||||
return lhs.m_object < &rhs;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator<=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return !(lhs > rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator<=(const T& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return !(lhs > rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator<=(const ObjectHandle<T>& lhs, const T& rhs)
|
||||
{
|
||||
return !(lhs > rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator>(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator>(const T& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator>(const ObjectHandle<T>& lhs, const T& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator>=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator>=(const T& lhs, const ObjectHandle<T>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator>=(const ObjectHandle<T>& lhs, const T& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const ObjectHandle<T> ObjectHandle<T>::InvalidHandle;
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<typename T>
|
||||
void swap(Nz::ObjectHandle<T>& lhs, Nz::ObjectHandle<T>& rhs)
|
||||
{
|
||||
lhs.Swap(rhs);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user