Merge branch 'master' into graphics-next

This commit is contained in:
Jérôme Leclercq
2021-05-17 18:58:04 +02:00
15 changed files with 348 additions and 188 deletions

View File

@@ -37,7 +37,10 @@ namespace Nz
HandledObject(HandledObject&& object) noexcept;
~HandledObject();
ObjectHandle<T> CreateHandle();
template<typename U = T>
ObjectHandle<U> CreateHandle();
std::shared_ptr<const Detail::HandleData> GetHandleData();
HandledObject& operator=(const HandledObject& object);
HandledObject& operator=(HandledObject&& object) noexcept;
@@ -48,7 +51,6 @@ namespace Nz
void UnregisterAllHandles() noexcept;
private:
std::shared_ptr<const Detail::HandleData> GetHandleData();
void InitHandleData();
std::shared_ptr<Detail::HandleData> m_handleData;

View File

@@ -58,9 +58,20 @@ namespace Nz
* \return ObjectHandle to this
*/
template<typename T>
ObjectHandle<T> HandledObject<T>::CreateHandle()
template<typename U>
ObjectHandle<U> HandledObject<T>::CreateHandle()
{
return ObjectHandle<T>(static_cast<T*>(this));
static_assert(std::is_base_of<T, U>::value, "Cannot retrieve a handle for a non-related class");
return ObjectHandle<U>(static_cast<U*>(this));
}
template<typename T>
std::shared_ptr<const Detail::HandleData> HandledObject<T>::GetHandleData()
{
if (!m_handleData)
InitHandleData();
return std::shared_ptr<const Detail::HandleData>(m_handleData);
}
/*!
@@ -112,15 +123,6 @@ namespace Nz
}
}
template<typename T>
std::shared_ptr<const Detail::HandleData> HandledObject<T>::GetHandleData()
{
if (!m_handleData)
InitHandleData();
return std::shared_ptr<const Detail::HandleData>(m_handleData);
}
template<typename T>
void HandledObject<T>::InitHandleData()
{

View File

@@ -23,6 +23,8 @@ namespace Nz
public:
ObjectHandle();
explicit ObjectHandle(T* object);
template<typename U> ObjectHandle(const ObjectHandle<U>& ref);
template<typename U> ObjectHandle(ObjectHandle<U>&& ref);
ObjectHandle(const ObjectHandle& handle) = default;
ObjectHandle(ObjectHandle&& handle) noexcept;
~ObjectHandle();
@@ -79,6 +81,11 @@ namespace Nz
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, typename U> ObjectHandle<T> ConstRefCast(const ObjectHandle<U>& ref);
template<typename T, typename U> ObjectHandle<T> DynamicRefCast(const ObjectHandle<U>& ref);
template<typename T, typename U> ObjectHandle<T> ReinterpretRefCast(const ObjectHandle<U>& ref);
template<typename T, typename U> ObjectHandle<T> StaticRefCast(const ObjectHandle<U>& ref);
template<typename T> struct PointedType<ObjectHandle<T>> { using type = T; };
template<typename T> struct PointedType<const ObjectHandle<T>> { using type = T; };
}

View File

@@ -26,15 +26,34 @@ namespace Nz
{
}
template<typename T>
template<typename U>
ObjectHandle<T>::ObjectHandle(const ObjectHandle<U>& ref) :
m_handleData(ref.m_handleData)
{
static_assert(std::is_base_of<T, U>::value, "Can only implicitly convert from a derived to a base");
}
template<typename T>
template<typename U>
ObjectHandle<T>::ObjectHandle(ObjectHandle<U>&& ref) :
m_handleData(std::move(ref.m_handleData))
{
ref.m_handleData = Detail::HandleData::GetEmptyObject();
static_assert(std::is_base_of<T, U>::value, "Can only implicitly convert from a derived to a base");
}
/*!
* \brief Constructs a ObjectHandle object by move semantic
*
* \param handle ObjectHandle to move into this
*/
template<typename T>
ObjectHandle<T>::ObjectHandle(ObjectHandle&& handle) noexcept
ObjectHandle<T>::ObjectHandle(ObjectHandle&& handle) noexcept :
m_handleData(std::move(handle.m_handleData))
{
Reset(std::move(handle));
handle.m_handleData = Detail::HandleData::GetEmptyObject();
}
/*!
@@ -458,6 +477,60 @@ namespace Nz
return !(lhs < rhs);
}
/*!
* \brief Casts an ObjectHandle from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*
* \remark It is an undefined behavior to cast between incompatible types
*/
template<typename T, typename U>
ObjectHandle<T> ConstRefCast(const ObjectHandle<U>& ref)
{
return ObjectHandle<T>(const_cast<T*>(ref.GetObject()));
}
/*!
* \brief Casts an ObjectHandle from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*/
template<typename T, typename U>
ObjectHandle<T> DynamicRefCast(const ObjectHandle<U>& ref)
{
return ObjectHandle<T>(dynamic_cast<T*>(ref.GetObject()));
}
/*!
* \brief Casts an ObjectHandle from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*
* \remark It is an undefined behavior to cast between incompatible types
*/
template<typename T, typename U>
ObjectHandle<T> ReinterpretRefCast(const ObjectHandle<U>& ref)
{
return ObjectHandle<T>(static_cast<T*>(ref.GetObject()));
}
/*!
* \brief Casts an ObjectHandle from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*
* \remark It is an undefined behavior to cast between incompatible types
*/
template<typename T, typename U>
ObjectHandle<T> StaticRefCast(const ObjectHandle<U>& ref)
{
return ObjectHandle<T>(static_cast<T*>(ref.GetObject()));
}
template<typename T>
const ObjectHandle<T> ObjectHandle<T>::InvalidHandle;
}

View File

@@ -16,6 +16,7 @@ namespace Ndk
class NDK_API EntityList
{
friend Entity;
friend World;
public:
class iterator;
@@ -23,16 +24,16 @@ namespace Ndk
using size_type = std::size_t;
inline EntityList();
inline EntityList(const EntityList& entityList);
inline EntityList(EntityList&& entityList) noexcept;
inline ~EntityList();
EntityList(const EntityList& entityList);
EntityList(EntityList&& entityList) noexcept;
~EntityList();
inline void Clear();
void Clear();
inline bool Has(const Entity* entity) const;
inline bool Has(EntityId entity) const;
inline void Insert(Entity* entity);
void Insert(Entity* entity);
inline void Remove(Entity* entity);
inline void Reserve(std::size_t entityCount);
@@ -50,6 +51,7 @@ namespace Ndk
inline std::size_t FindNext(std::size_t currentId) const;
inline World* GetWorld() const;
inline void NotifyEntityDestruction(const Entity* entity);
inline void SetWorld(World* world);
Nz::Bitset<Nz::UInt64> m_entityBits;
World* m_world;

View File

@@ -2,6 +2,7 @@
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/EntityList.hpp>
#include <Nazara/Core/Error.hpp>
#include <algorithm>
@@ -21,52 +22,6 @@ namespace Ndk
{
}
/*!
* \brief Construct a new entity list by copying another one
*/
inline EntityList::EntityList(const EntityList& entityList) :
m_entityBits(entityList.m_entityBits),
m_world(entityList.m_world)
{
for (const Ndk::EntityHandle& entity : *this)
entity->RegisterEntityList(this);
}
/*!
* \brief Construct a new entity list by moving a list into this one
*/
inline EntityList::EntityList(EntityList&& entityList) noexcept :
m_entityBits(std::move(entityList.m_entityBits)),
m_world(entityList.m_world)
{
for (const Ndk::EntityHandle& entity : *this)
{
entity->UnregisterEntityList(&entityList);
entity->RegisterEntityList(this);
}
}
inline EntityList::~EntityList()
{
for (const Ndk::EntityHandle& entity : *this)
entity->UnregisterEntityList(this);
}
/*!
* \brief Clears the set from every entities
*
* \remark This resets the implicit world member, allowing you to insert entities from a different world than previously
*/
inline void EntityList::Clear()
{
for (const Ndk::EntityHandle& entity : *this)
entity->UnregisterEntityList(this);
m_entityBits.Clear();
m_world = nullptr;
}
/*!
* \brief Checks whether or not the EntityList contains the entity
* \return true If it is the case
@@ -93,29 +48,6 @@ namespace Ndk
return m_entityBits.UnboundedTest(entity);
}
/*!
* \brief Inserts the entity into the set
*
* Marks an entity as present in this entity list, it must belongs to the same world as others entities contained in this list.
*
* \param entity Valid pointer to an entity
*
* \remark If entity is already contained, no action is performed
* \remark If any entity has been inserted since construction (or last Clear call), the entity must belong to the same world as the previously inserted entities
*/
inline void EntityList::Insert(Entity* entity)
{
NazaraAssert(entity, "Invalid entity");
if (!Has(entity))
{
entity->RegisterEntityList(this);
m_entityBits.UnboundedSet(entity->GetId(), true);
m_world = entity->GetWorld();
}
}
/*!
* \brief Removes the entity from the set
*
@@ -167,40 +99,6 @@ namespace Ndk
return m_entityBits.Count();
}
inline EntityList& EntityList::operator=(const EntityList& entityList)
{
for (const Ndk::EntityHandle& entity : *this)
entity->UnregisterEntityList(this);
m_entityBits = entityList.m_entityBits;
m_world = entityList.m_world;
for (const Ndk::EntityHandle& entity : *this)
entity->RegisterEntityList(this);
return *this;
}
inline EntityList& EntityList::operator=(EntityList&& entityList) noexcept
{
if (this == &entityList)
return *this;
for (const Ndk::EntityHandle& entity : *this)
entity->UnregisterEntityList(this);
m_entityBits = std::move(entityList.m_entityBits);
m_world = entityList.m_world;
for (const Ndk::EntityHandle& entity : *this)
{
entity->UnregisterEntityList(&entityList);
entity->RegisterEntityList(this);
}
return *this;
}
inline std::size_t EntityList::FindNext(std::size_t currentId) const
{
return m_entityBits.FindNext(currentId);
@@ -218,6 +116,11 @@ namespace Ndk
m_entityBits.Reset(entity->GetId());
}
inline void EntityList::SetWorld(World* world)
{
m_world = world;
}
inline EntityList::iterator::iterator(const EntityList* list, std::size_t nextId) :
m_nextEntityId(nextId),

View File

@@ -26,6 +26,7 @@ namespace Ndk
{
friend BaseSystem;
friend Entity;
friend EntityList;
public:
using EntityVector = std::vector<EntityHandle>;
@@ -97,7 +98,9 @@ namespace Ndk
inline void Invalidate();
inline void Invalidate(EntityId id);
inline void InvalidateSystemOrder();
inline void RegisterEntityList(EntityList* list);
void ReorderSystems();
inline void UnregisterEntityList(EntityList* list);
struct DoubleBitset
{
@@ -123,6 +126,7 @@ namespace Ndk
std::vector<BaseSystem*> m_orderedSystems;
std::vector<EntityBlock> m_entities;
std::vector<EntityBlock*> m_entityBlocks;
std::vector<EntityList*> m_referencedByLists;
std::vector<std::unique_ptr<EntityBlock>> m_waitingEntities;
EntityList m_aliveEntities;
ProfilerData m_profilerData;

View File

@@ -443,25 +443,31 @@ namespace Ndk
m_dirtyEntities = std::move(world.m_dirtyEntities);
m_entityBlocks = std::move(world.m_entityBlocks);
m_freeEntityIds = std::move(world.m_freeEntityIds);
m_isProfilerEnabled = world.m_isProfilerEnabled;
m_killedEntities = std::move(world.m_killedEntities);
m_orderedSystems = std::move(world.m_orderedSystems);
m_orderedSystemsUpdated = world.m_orderedSystemsUpdated;
m_profilerData = std::move(world.m_profilerData);
m_isProfilerEnabled = world.m_isProfilerEnabled;
m_referencedByLists = std::move(world.m_referencedByLists);
m_entities = std::move(world.m_entities);
for (EntityBlock& block : m_entities)
block.entity.SetWorld(this);
for (EntityList* list : m_referencedByLists)
list->SetWorld(this);
m_waitingEntities = std::move(world.m_waitingEntities);
for (auto& blockPtr : m_waitingEntities)
blockPtr->entity.SetWorld(this);
m_systems = std::move(world.m_systems);
for (const auto& systemPtr : m_systems)
{
if (systemPtr)
systemPtr->SetWorld(this);
}
return *this;
}
@@ -480,4 +486,19 @@ namespace Ndk
{
m_orderedSystemsUpdated = false;
}
inline void World::RegisterEntityList(EntityList* list)
{
m_referencedByLists.push_back(list);
}
inline void World::UnregisterEntityList(EntityList* list)
{
auto it = std::find(m_referencedByLists.begin(), m_referencedByLists.end(), list);
assert(it != m_referencedByLists.end());
// Swap and pop idiom
*it = m_referencedByLists.back();
m_referencedByLists.pop_back();
}
}