diff --git a/include/Nazara/Core/HandledObject.hpp b/include/Nazara/Core/HandledObject.hpp index 50a283059..d5293dc84 100644 --- a/include/Nazara/Core/HandledObject.hpp +++ b/include/Nazara/Core/HandledObject.hpp @@ -37,7 +37,10 @@ namespace Nz HandledObject(HandledObject&& object) noexcept; ~HandledObject(); - ObjectHandle CreateHandle(); + template + ObjectHandle CreateHandle(); + + std::shared_ptr GetHandleData(); HandledObject& operator=(const HandledObject& object); HandledObject& operator=(HandledObject&& object) noexcept; @@ -48,7 +51,6 @@ namespace Nz void UnregisterAllHandles() noexcept; private: - std::shared_ptr GetHandleData(); void InitHandleData(); std::shared_ptr m_handleData; diff --git a/include/Nazara/Core/HandledObject.inl b/include/Nazara/Core/HandledObject.inl index 909828277..fd731b536 100644 --- a/include/Nazara/Core/HandledObject.inl +++ b/include/Nazara/Core/HandledObject.inl @@ -58,9 +58,20 @@ namespace Nz * \return ObjectHandle to this */ template - ObjectHandle HandledObject::CreateHandle() + template + ObjectHandle HandledObject::CreateHandle() { - return ObjectHandle(static_cast(this)); + static_assert(std::is_base_of::value, "Cannot retrieve a handle for a non-related class"); + return ObjectHandle(static_cast(this)); + } + + template + std::shared_ptr HandledObject::GetHandleData() + { + if (!m_handleData) + InitHandleData(); + + return std::shared_ptr(m_handleData); } /*! @@ -112,15 +123,6 @@ namespace Nz } } - template - std::shared_ptr HandledObject::GetHandleData() - { - if (!m_handleData) - InitHandleData(); - - return std::shared_ptr(m_handleData); - } - template void HandledObject::InitHandleData() { diff --git a/include/Nazara/Core/ObjectHandle.hpp b/include/Nazara/Core/ObjectHandle.hpp index 5173838ad..08795b8f0 100644 --- a/include/Nazara/Core/ObjectHandle.hpp +++ b/include/Nazara/Core/ObjectHandle.hpp @@ -23,6 +23,8 @@ namespace Nz public: ObjectHandle(); explicit ObjectHandle(T* object); + template ObjectHandle(const ObjectHandle& ref); + template ObjectHandle(ObjectHandle&& ref); ObjectHandle(const ObjectHandle& handle) = default; ObjectHandle(ObjectHandle&& handle) noexcept; ~ObjectHandle(); @@ -79,6 +81,11 @@ namespace Nz template bool operator>=(const T& lhs, const ObjectHandle& rhs); template bool operator>=(const ObjectHandle& lhs, const T& rhs); + template ObjectHandle ConstRefCast(const ObjectHandle& ref); + template ObjectHandle DynamicRefCast(const ObjectHandle& ref); + template ObjectHandle ReinterpretRefCast(const ObjectHandle& ref); + template ObjectHandle StaticRefCast(const ObjectHandle& ref); + template struct PointedType> { using type = T; }; template struct PointedType> { using type = T; }; } diff --git a/include/Nazara/Core/ObjectHandle.inl b/include/Nazara/Core/ObjectHandle.inl index e94624780..d6e10d3e6 100644 --- a/include/Nazara/Core/ObjectHandle.inl +++ b/include/Nazara/Core/ObjectHandle.inl @@ -26,15 +26,34 @@ namespace Nz { } + template + template + ObjectHandle::ObjectHandle(const ObjectHandle& ref) : + m_handleData(ref.m_handleData) + { + static_assert(std::is_base_of::value, "Can only implicitly convert from a derived to a base"); + } + + template + template + ObjectHandle::ObjectHandle(ObjectHandle&& ref) : + m_handleData(std::move(ref.m_handleData)) + { + ref.m_handleData = Detail::HandleData::GetEmptyObject(); + + static_assert(std::is_base_of::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 - ObjectHandle::ObjectHandle(ObjectHandle&& handle) noexcept + ObjectHandle::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 + ObjectHandle ConstRefCast(const ObjectHandle& ref) + { + return ObjectHandle(const_cast(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 + ObjectHandle DynamicRefCast(const ObjectHandle& ref) + { + return ObjectHandle(dynamic_cast(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 + ObjectHandle ReinterpretRefCast(const ObjectHandle& ref) + { + return ObjectHandle(static_cast(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 + ObjectHandle StaticRefCast(const ObjectHandle& ref) + { + return ObjectHandle(static_cast(ref.GetObject())); + } + template const ObjectHandle ObjectHandle::InvalidHandle; } diff --git a/include/NazaraSDK/EntityList.hpp b/include/NazaraSDK/EntityList.hpp index ae9a5e63d..ce613fcf4 100644 --- a/include/NazaraSDK/EntityList.hpp +++ b/include/NazaraSDK/EntityList.hpp @@ -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 m_entityBits; World* m_world; diff --git a/include/NazaraSDK/EntityList.inl b/include/NazaraSDK/EntityList.inl index 48876faf8..4fa991f30 100644 --- a/include/NazaraSDK/EntityList.inl +++ b/include/NazaraSDK/EntityList.inl @@ -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 #include #include @@ -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), diff --git a/include/NazaraSDK/World.hpp b/include/NazaraSDK/World.hpp index b8765d379..bffc12004 100644 --- a/include/NazaraSDK/World.hpp +++ b/include/NazaraSDK/World.hpp @@ -26,6 +26,7 @@ namespace Ndk { friend BaseSystem; friend Entity; + friend EntityList; public: using EntityVector = std::vector; @@ -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 m_orderedSystems; std::vector m_entities; std::vector m_entityBlocks; + std::vector m_referencedByLists; std::vector> m_waitingEntities; EntityList m_aliveEntities; ProfilerData m_profilerData; diff --git a/include/NazaraSDK/World.inl b/include/NazaraSDK/World.inl index e0c60d4c4..41f10c3c3 100644 --- a/include/NazaraSDK/World.inl +++ b/include/NazaraSDK/World.inl @@ -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(); + } } diff --git a/readme.md b/readme.md index 2eaabc09e..320c7fe7c 100644 --- a/readme.md +++ b/readme.md @@ -5,7 +5,7 @@ Linux | [![Travis CI Build Status](https://travis-ci.org/DigitalPulseSoftware/Na # Nazara Engine -Nazara Engine is a fast, complete, cross-platform, object-oriented API which can help you in your daily developper life. +Nazara Engine is a fast, complete, cross-platform, object-oriented API which can help you in your daily developer life. Its goal is to provide a set of useful classes : Its core provides unicode strings, filesystem access, hashs, threads, ... It also provide a set of libraries, such as audio, network, physics, renderer, 2D and 3D graphics engines, ... diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index fbe762ff1..ae57046be 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -420,32 +420,40 @@ namespace Nz SocketState SocketImpl::PollConnection(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error) { - // http://developerweb.net/viewtopic.php?id=3196 - fd_set localSet; - FD_ZERO(&localSet); - FD_SET(handle, &localSet); + // Wait until socket is available for writing or an error occurs (ie when connection succeeds or fails) + pollfd descriptor; + descriptor.events = POLLOUT; + descriptor.fd = handle; + descriptor.revents = 0; - timeval tv; - tv.tv_sec = static_cast(msTimeout / 1000ULL); - tv.tv_usec = static_cast((msTimeout % 1000ULL) * 1000ULL); - - int ret = ::select(0, nullptr, &localSet, &localSet, (msTimeout != std::numeric_limits::max()) ? &tv : nullptr); - if (ret > 0) + int ret = ::poll(&descriptor, 1, (msTimeout != std::numeric_limits::max()) ? int(msTimeout) : -1); + if (ret == SOCKET_ERROR) { - int code = GetLastErrorCode(handle, error); - if (code < 0) //< GetLastErrorCode() failed - return SocketState_NotConnected; + if (error) + *error = TranslateErrnoToSocketError(GetLastErrorCode()); - if (code) + return SocketState_NotConnected; + } + else if (ret > 0) + { + if (descriptor.revents & (POLLERR | POLLHUP)) { if (error) - *error = TranslateErrnoToSocketError(code); + *error = GetLastError(handle); return SocketState_NotConnected; } + else if (descriptor.revents & POLLOUT) + return SocketState_Connected; + else + { + NazaraWarning("Socket " + String::Number(handle) + " was returned by poll without POLLOUT nor error events (events: 0x" + String::Number(descriptor.revents, 16) + ')'); + return SocketState_NotConnected; + } } - else if (ret == 0) + else { + // Still connecting if (error) { if (msTimeout > 0) @@ -456,18 +464,6 @@ namespace Nz return SocketState_Connecting; } - else - { - if (error) - *error = TranslateErrnoToSocketError(GetLastErrorCode()); - - return SocketState_NotConnected; - } - - if (error) - *error = SocketError_NoError; - - return SocketState_Connected; } bool SocketImpl::Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error) diff --git a/src/Nazara/Network/Win32/SocketImpl.cpp b/src/Nazara/Network/Win32/SocketImpl.cpp index 349dfea0a..00ea94eb7 100644 --- a/src/Nazara/Network/Win32/SocketImpl.cpp +++ b/src/Nazara/Network/Win32/SocketImpl.cpp @@ -453,32 +453,40 @@ namespace Nz SocketState SocketImpl::PollConnection(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error) { - // http://developerweb.net/viewtopic.php?id=3196 - fd_set localSet; - FD_ZERO(&localSet); - FD_SET(handle, &localSet); + // Wait until socket is available for writing or an error occurs (ie when connection succeeds or fails) + WSAPOLLFD descriptor; + descriptor.events = POLLWRNORM; + descriptor.fd = handle; + descriptor.revents = 0; - timeval tv; - tv.tv_sec = static_cast(msTimeout / 1000ULL); - tv.tv_usec = static_cast((msTimeout % 1000ULL) * 1000ULL); - - int ret = ::select(0, nullptr, &localSet, &localSet, (msTimeout != std::numeric_limits::max()) ? &tv : nullptr); - if (ret > 0) + int ret = WSAPoll(&descriptor, 1, (msTimeout != std::numeric_limits::max()) ? INT(msTimeout) : INT(-1)); + if (ret == SOCKET_ERROR) { - int code = GetLastErrorCode(handle, error); - if (code < 0) //< GetLastErrorCode() failed - return SocketState_NotConnected; + if (error) + *error = TranslateWSAErrorToSocketError(WSAGetLastError()); - if (code) + return SocketState_NotConnected; + } + else if (ret > 0) + { + if (descriptor.revents & (POLLERR | POLLHUP)) { if (error) - *error = TranslateWSAErrorToSocketError(code); + *error = GetLastError(handle); return SocketState_NotConnected; } + else if (descriptor.revents & POLLWRNORM) + return SocketState_Connected; + else + { + NazaraWarning("Socket " + String::Number(handle) + " was returned by poll without POLLOUT nor error events (events: 0x" + String::Number(descriptor.revents, 16) + ')'); + return SocketState_NotConnected; + } } - else if (ret == 0) + else { + // Still connecting if (error) { if (msTimeout > 0) @@ -489,18 +497,6 @@ namespace Nz return SocketState_Connecting; } - else - { - if (error) - *error = TranslateWSAErrorToSocketError(WSAGetLastError()); - - return SocketState_NotConnected; - } - - if (error) - *error = SocketError_NoError; - - return SocketState_Connected; } bool SocketImpl::Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error) diff --git a/src/Nazara/Platform/SDL2/CursorImpl.cpp b/src/Nazara/Platform/SDL2/CursorImpl.cpp index 5c963ab99..306f8a23d 100644 --- a/src/Nazara/Platform/SDL2/CursorImpl.cpp +++ b/src/Nazara/Platform/SDL2/CursorImpl.cpp @@ -24,9 +24,9 @@ namespace Nz m_iconImage.GetWidth(), m_iconImage.GetHeight(), 32, - 32 * m_iconImage.GetWidth(), - SDL_PIXELFORMAT_BGRA8888 - ); + 4 * m_iconImage.GetWidth(), + SDL_PIXELFORMAT_BGRA32 + ); if (!m_icon) { diff --git a/src/Nazara/Platform/SDL2/WindowImpl.cpp b/src/Nazara/Platform/SDL2/WindowImpl.cpp index c50b976c7..74cb9b162 100644 --- a/src/Nazara/Platform/SDL2/WindowImpl.cpp +++ b/src/Nazara/Platform/SDL2/WindowImpl.cpp @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include namespace Nz { @@ -485,23 +488,26 @@ namespace Nz break; case SDL_TEXTINPUT: + { if (SDL_GetWindowID(window->m_handle) != event->text.windowID) return 0; evt.type = WindowEventType_TextEntered; evt.text.repeated = false; - for (decltype(evt.text.character) codepoint : ToUtf32String(event->text.text)) + utf8::unchecked::iterator it(event->text.text); + do { - evt.text.character = codepoint; + evt.text.character = *it; window->m_parent->PushEvent(evt); - } + } while (*it++); // prevent post switch event evt.type = WindowEventType::WindowEventType_Max; break; + } case SDL_TEXTEDITING: if (SDL_GetWindowID(window->m_handle) != event->edit.windowID) diff --git a/src/NazaraSDK/EntityList.cpp b/src/NazaraSDK/EntityList.cpp index a6a9d1140..9f15ad0a7 100644 --- a/src/NazaraSDK/EntityList.cpp +++ b/src/NazaraSDK/EntityList.cpp @@ -7,6 +7,149 @@ namespace Ndk { + /*! + * \brief Construct a new entity list by copying another one + */ + EntityList::EntityList(const EntityList& entityList) : + m_entityBits(entityList.m_entityBits), + m_world(entityList.m_world) + { + for (const Ndk::EntityHandle& entity : *this) + entity->RegisterEntityList(this); + + if (m_world) + m_world->RegisterEntityList(this); + } + + /*! + * \brief Construct a new entity list by moving a list into this one + */ + 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); + } + + if (m_world) + { + m_world->UnregisterEntityList(&entityList); + m_world->RegisterEntityList(this); + + entityList.m_world = nullptr; + } + } + + EntityList::~EntityList() + { + for (const Ndk::EntityHandle& entity : *this) + entity->UnregisterEntityList(this); + + if (m_world) + m_world->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 + */ + void EntityList::Clear() + { + for (const Ndk::EntityHandle& entity : *this) + entity->UnregisterEntityList(this); + + m_entityBits.Clear(); + + if (m_world) + { + m_world->UnregisterEntityList(this); + m_world = nullptr; + } + } + + /*! + * \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 + */ + void EntityList::Insert(Entity* entity) + { + NazaraAssert(entity, "Invalid entity"); + + if (!Has(entity)) + { + entity->RegisterEntityList(this); + + m_entityBits.UnboundedSet(entity->GetId(), true); + if (!m_world) + { + m_world = entity->GetWorld(); + m_world->RegisterEntityList(this); + } + } + } + + EntityList& EntityList::operator=(const EntityList& entityList) + { + if (m_world) + m_world->UnregisterEntityList(this); + + 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); + + if (m_world) + m_world->RegisterEntityList(this); + + return *this; + } + + EntityList& EntityList::operator=(EntityList&& entityList) noexcept + { + if (this == &entityList) + return *this; + + if (m_world) + m_world->UnregisterEntityList(this); + + for (const Ndk::EntityHandle& entity : *this) + entity->UnregisterEntityList(this); + + m_entityBits = std::move(entityList.m_entityBits); + m_world = entityList.m_world; + + if (m_world) + { + m_world->UnregisterEntityList(&entityList); + m_world->RegisterEntityList(this); + + entityList.m_world = nullptr; + } + + for (const Ndk::EntityHandle& entity : *this) + { + entity->UnregisterEntityList(&entityList); + entity->RegisterEntityList(this); + } + + return *this; + } + const EntityHandle& EntityList::iterator::operator*() const { return m_list->GetWorld()->GetEntity(static_cast(m_nextEntityId)); diff --git a/src/NazaraSDK/World.cpp b/src/NazaraSDK/World.cpp index 42650b169..89b84b4bf 100644 --- a/src/NazaraSDK/World.cpp +++ b/src/NazaraSDK/World.cpp @@ -125,6 +125,11 @@ namespace Ndk } m_entityBlocks.clear(); + // Reset world for entity lists + for (EntityList* list : m_referencedByLists) + list->SetWorld(nullptr); + m_referencedByLists.clear(); + m_entities.clear(); m_waitingEntities.clear();