From f52c43df49a469e9a206c6b55e6cc1e343c9a021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sat, 31 Oct 2020 17:33:56 +0100 Subject: [PATCH 01/13] Network: Fix TcpClient::PollConnection on Linux --- src/Nazara/Network/Posix/SocketImpl.cpp | 52 +++++++++++------------- src/Nazara/Network/Win32/SocketImpl.cpp | 54 ++++++++++++------------- 2 files changed, 49 insertions(+), 57 deletions(-) diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index af0b5557f..d0386a891 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -411,32 +411,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) @@ -447,18 +455,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 f9e4b42f5..157f14811 100644 --- a/src/Nazara/Network/Win32/SocketImpl.cpp +++ b/src/Nazara/Network/Win32/SocketImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018 Jérôme Leclercq +// Copyright (C) 2020 Jérôme Leclercq // This file is part of the "Nazara Engine - Network module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -452,32 +452,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) @@ -488,18 +496,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) From 8e6b4cc673b05801059fc3f0d9c33336cfa7cf8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Sun, 1 Nov 2020 17:40:12 +0100 Subject: [PATCH 02/13] Graphics/Model: Fix copy constructor --- include/Nazara/Graphics/Model.inl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Graphics/Model.inl b/include/Nazara/Graphics/Model.inl index 9c1809368..482470caa 100644 --- a/include/Nazara/Graphics/Model.inl +++ b/include/Nazara/Graphics/Model.inl @@ -22,7 +22,8 @@ namespace Nz * \param model Model to copy */ inline Model::Model(const Model& model) : - InstancedRenderable(model) + InstancedRenderable(model), + Resource(model) { SetMesh(model.m_mesh); From af55ecc2a5bf97b2b876754135ff0189fe1b5a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 12 Nov 2020 16:28:33 +0100 Subject: [PATCH 03/13] Fix SDL2 crash when creating cursor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enfoiré de REMqb --- src/Nazara/Platform/SDL2/CursorImpl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nazara/Platform/SDL2/CursorImpl.cpp b/src/Nazara/Platform/SDL2/CursorImpl.cpp index c9497a2e8..bd4f9ea21 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(), + 4 * m_iconImage.GetWidth(), SDL_PIXELFORMAT_BGRA8888 - ); + ); if (!m_icon) { From 7526923a8d6bb5fab586e0c9a22fdd7f4087724a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 17 Nov 2020 17:43:42 +0100 Subject: [PATCH 04/13] Platform: Fix space not generating a text event --- src/Nazara/Platform/SDL2/WindowImpl.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Nazara/Platform/SDL2/WindowImpl.cpp b/src/Nazara/Platform/SDL2/WindowImpl.cpp index e2a71f27b..f17ce3c3c 100644 --- a/src/Nazara/Platform/SDL2/WindowImpl.cpp +++ b/src/Nazara/Platform/SDL2/WindowImpl.cpp @@ -2,8 +2,6 @@ // This file is part of the "Nazara Engine - Platform module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include -#include #include #include #include @@ -19,6 +17,9 @@ #include #include #include +#include +#include +#include namespace Nz { @@ -488,23 +489,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 : String::Unicode(event->text.text).Simplify().GetUtf32String()) + 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) From bd9d30407cfd151db2407d91f1735ffa9adf88f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 17 Nov 2020 17:44:31 +0100 Subject: [PATCH 05/13] Fix SDL2 cursor --- src/Nazara/Platform/SDL2/CursorImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Platform/SDL2/CursorImpl.cpp b/src/Nazara/Platform/SDL2/CursorImpl.cpp index bd4f9ea21..37638c412 100644 --- a/src/Nazara/Platform/SDL2/CursorImpl.cpp +++ b/src/Nazara/Platform/SDL2/CursorImpl.cpp @@ -25,7 +25,7 @@ namespace Nz m_iconImage.GetHeight(), 32, 4 * m_iconImage.GetWidth(), - SDL_PIXELFORMAT_BGRA8888 + SDL_PIXELFORMAT_BGRA32 ); if (!m_icon) From fd0060a7e1a7eb23361c069e826f00f664e76773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 19 Nov 2020 14:54:13 +0100 Subject: [PATCH 06/13] Sdk/BoxLayout: Fix widgets not taking up free space --- SDK/src/NDK/Widgets/BoxLayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/src/NDK/Widgets/BoxLayout.cpp b/SDK/src/NDK/Widgets/BoxLayout.cpp index caf4720a1..bcef8a3c3 100644 --- a/SDK/src/NDK/Widgets/BoxLayout.cpp +++ b/SDK/src/NDK/Widgets/BoxLayout.cpp @@ -81,7 +81,7 @@ namespace Ndk if (maximumSize < std::numeric_limits::infinity()) m_state->solver.addConstraint({ sizeVar <= maximumSize | kiwi::strength::required }); - m_state->solver.addConstraint({ sizeVar == perfectSpacePerWidget | kiwi::strength::medium }); + m_state->solver.addConstraint({ sizeVar >= perfectSpacePerWidget | kiwi::strength::medium }); sizeSum = sizeSum + sizeVar; }); From 420e87eb1acec619aec3f3289bd326100bfe5965 Mon Sep 17 00:00:00 2001 From: Antoine James Tournepiche Date: Sat, 12 Dec 2020 22:06:32 +0100 Subject: [PATCH 07/13] Fix typo in project readme Developer was spelled with 2 p instead of one --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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, ... From 8ec11d61937cae2e0af6245a71b791447c5481f1 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Tue, 16 Feb 2021 17:06:38 +0100 Subject: [PATCH 08/13] Fix Linux compilation --- thirdparty/src/chipmunk/cpHastySpace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/thirdparty/src/chipmunk/cpHastySpace.c b/thirdparty/src/chipmunk/cpHastySpace.c index 7093bfc48..49de81cb7 100644 --- a/thirdparty/src/chipmunk/cpHastySpace.c +++ b/thirdparty/src/chipmunk/cpHastySpace.c @@ -8,7 +8,9 @@ //#include #ifndef _WIN32 +#ifdef __MACOSX__ #include +#endif #include #else #ifndef WIN32_LEAN_AND_MEAN From 48ab2a4b04d1a46841e4c268974ba6357727ba3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 19 Mar 2021 09:55:36 +0100 Subject: [PATCH 09/13] ObjectHandle: Fix handling of --- include/Nazara/Core/HandledObject.hpp | 6 ++- include/Nazara/Core/HandledObject.inl | 24 +++++---- include/Nazara/Core/ObjectHandle.hpp | 7 +++ include/Nazara/Core/ObjectHandle.inl | 77 ++++++++++++++++++++++++++- 4 files changed, 99 insertions(+), 15 deletions(-) diff --git a/include/Nazara/Core/HandledObject.hpp b/include/Nazara/Core/HandledObject.hpp index 390a4e612..c2bd59d0c 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 ed0115f5b..8f1e497a0 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_v, "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 e2e72f185..6d62dc582 100644 --- a/include/Nazara/Core/ObjectHandle.hpp +++ b/include/Nazara/Core/ObjectHandle.hpp @@ -22,6 +22,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(); @@ -78,6 +80,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 fc43fdffe..1a3d09b9b 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_v, "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_v, "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(); } /*! @@ -457,6 +476,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; } From 02805aade3e03b1e7216423a993811a3288ee192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 30 Mar 2021 10:12:55 +0200 Subject: [PATCH 10/13] Update BaseWidget.cpp --- SDK/src/NDK/BaseWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/src/NDK/BaseWidget.cpp b/SDK/src/NDK/BaseWidget.cpp index ecfddf33c..6cee67002 100644 --- a/SDK/src/NDK/BaseWidget.cpp +++ b/SDK/src/NDK/BaseWidget.cpp @@ -183,7 +183,7 @@ namespace Ndk { if (entity.isEnabled) { - entity.handle->Enable(show); //< This will override isEnabled + entity.handle->Enable(show); //< This will override isEnabled, so reset it next line entity.isEnabled = true; } } From 560061b4a506e4f8c98f6a1de230caad049a5df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 30 Mar 2021 10:24:36 +0200 Subject: [PATCH 11/13] Sdk/EntityList: Fix crash when world was moved --- SDK/include/NDK/EntityList.hpp | 12 +-- SDK/include/NDK/EntityList.inl | 109 ++----------------------- SDK/include/NDK/World.hpp | 4 + SDK/include/NDK/World.inl | 25 +++++- SDK/src/NDK/EntityList.cpp | 143 +++++++++++++++++++++++++++++++++ SDK/src/NDK/World.cpp | 5 ++ 6 files changed, 188 insertions(+), 110 deletions(-) diff --git a/SDK/include/NDK/EntityList.hpp b/SDK/include/NDK/EntityList.hpp index 3b4f1580a..7602b6b21 100644 --- a/SDK/include/NDK/EntityList.hpp +++ b/SDK/include/NDK/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/SDK/include/NDK/EntityList.inl b/SDK/include/NDK/EntityList.inl index a34165a68..27dfbb48d 100644 --- a/SDK/include/NDK/EntityList.inl +++ b/SDK/include/NDK/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/SDK/include/NDK/World.hpp b/SDK/include/NDK/World.hpp index ca6e917b7..072ce0637 100644 --- a/SDK/include/NDK/World.hpp +++ b/SDK/include/NDK/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/SDK/include/NDK/World.inl b/SDK/include/NDK/World.inl index 1c3e446e1..85a34c9cc 100644 --- a/SDK/include/NDK/World.inl +++ b/SDK/include/NDK/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/SDK/src/NDK/EntityList.cpp b/SDK/src/NDK/EntityList.cpp index 49841843d..fdae20097 100644 --- a/SDK/src/NDK/EntityList.cpp +++ b/SDK/src/NDK/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/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index ef59463bc..9b255c71e 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -131,6 +131,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(); From 6d6391ca46eae4412d911cc9589cfa2eaeb86502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 30 Mar 2021 17:48:32 +0200 Subject: [PATCH 12/13] Fix compilation I forgot master was still in C++14 --- include/Nazara/Core/HandledObject.inl | 2 +- include/Nazara/Core/ObjectHandle.inl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/Nazara/Core/HandledObject.inl b/include/Nazara/Core/HandledObject.inl index 8f1e497a0..6addf9c77 100644 --- a/include/Nazara/Core/HandledObject.inl +++ b/include/Nazara/Core/HandledObject.inl @@ -61,7 +61,7 @@ namespace Nz template ObjectHandle HandledObject::CreateHandle() { - static_assert(std::is_base_of_v, "Cannot retrieve a handle for a non-related class"); + static_assert(std::is_base_of::value, "Cannot retrieve a handle for a non-related class"); return ObjectHandle(static_cast(this)); } diff --git a/include/Nazara/Core/ObjectHandle.inl b/include/Nazara/Core/ObjectHandle.inl index 1a3d09b9b..be3ec5c0c 100644 --- a/include/Nazara/Core/ObjectHandle.inl +++ b/include/Nazara/Core/ObjectHandle.inl @@ -31,7 +31,7 @@ namespace Nz ObjectHandle::ObjectHandle(const ObjectHandle& ref) : m_handleData(ref.m_handleData) { - static_assert(std::is_base_of_v, "Can only implicitly convert from a derived to a base"); + static_assert(std::is_base_of::value, "Can only implicitly convert from a derived to a base"); } template @@ -41,7 +41,7 @@ namespace Nz { ref.m_handleData = Detail::HandleData::GetEmptyObject(); - static_assert(std::is_base_of_v, "Can only implicitly convert from a derived to a base"); + static_assert(std::is_base_of::value, "Can only implicitly convert from a derived to a base"); } /*! From 3d8a3998174d7b6bf728ce0be49d62544bf0c8d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 14 May 2021 16:22:02 +0200 Subject: [PATCH 13/13] Enable AppVeyor only on master branch --- appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 735cd9e84..197fbd440 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,10 @@ version: '{branch}-rev{build}' shallow_clone: true +branches: + only: + - master + skip_commits: files: - .travis.yml