From 55d9a226656736f55887519f0ea473952a3fd76b Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 23 Feb 2017 00:09:39 +0100 Subject: [PATCH 01/25] NDK/BaseWidget: Children widgets are now automatically parented to their parent --- SDK/include/NDK/BaseWidget.inl | 1 + 1 file changed, 1 insertion(+) diff --git a/SDK/include/NDK/BaseWidget.inl b/SDK/include/NDK/BaseWidget.inl index 17592241f..e84a67a49 100644 --- a/SDK/include/NDK/BaseWidget.inl +++ b/SDK/include/NDK/BaseWidget.inl @@ -33,6 +33,7 @@ namespace Ndk inline void BaseWidget::AddChild(std::unique_ptr&& widget) { widget->Show(m_visible); + widget->SetParent(this); m_children.emplace_back(std::move(widget)); } From b4ecf563c1fa444c7b903c2479a1ac9526284bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 27 Feb 2017 16:29:24 +0100 Subject: [PATCH 02/25] Add pdb to package --- build/scripts/actions/package.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/scripts/actions/package.lua b/build/scripts/actions/package.lua index 62d4792b3..cbdae329c 100644 --- a/build/scripts/actions/package.lua +++ b/build/scripts/actions/package.lua @@ -86,7 +86,7 @@ ACTION.Function = function () local exeFilterFunc if (os.is("windows")) then binFileMasks = {"**.dll"} - libFileMasks = {"**.lib", "**.a"} + libFileMasks = {"**.lib", "**.a", "**.pdb"} exeFileExt = ".exe" exeFilterFunc = function (filePath) return true end else From f22dd81d35e455672784123036984f1097367f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 27 Feb 2017 16:30:18 +0100 Subject: [PATCH 03/25] Physics2D/RigidBody2D: Add AddImpulse method --- include/Nazara/Physics2D/RigidBody2D.hpp | 2 ++ src/Nazara/Physics2D/RigidBody2D.cpp | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/Nazara/Physics2D/RigidBody2D.hpp b/include/Nazara/Physics2D/RigidBody2D.hpp index f57ce6a48..9763aba47 100644 --- a/include/Nazara/Physics2D/RigidBody2D.hpp +++ b/include/Nazara/Physics2D/RigidBody2D.hpp @@ -34,6 +34,8 @@ namespace Nz void AddForce(const Vector2f& force, CoordSys coordSys = CoordSys_Global); void AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys = CoordSys_Global); + void AddImpulse(const Vector2f& impulse, CoordSys coordSys = CoordSys_Global); + void AddImpulse(const Vector2f& impulse, const Vector2f& point, CoordSys coordSys = CoordSys_Global); void AddTorque(float torque); Rectf GetAABB() const; diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index 8993fe398..d01a426a2 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -93,6 +93,25 @@ namespace Nz } } + void RigidBody2D::AddImpulse(const Vector2f& impulse, CoordSys coordSys) + { + return AddImpulse(impulse, GetCenterOfGravity(coordSys), coordSys); + } + + void RigidBody2D::AddImpulse(const Vector2f& impulse, const Vector2f& point, CoordSys coordSys) + { + switch (coordSys) + { + case CoordSys_Global: + cpBodyApplyImpulseAtWorldPoint(m_handle, cpv(impulse.x, impulse.y), cpv(point.x, point.y)); + break; + + case CoordSys_Local: + cpBodyApplyImpulseAtLocalPoint(m_handle, cpv(impulse.x, impulse.y), cpv(point.x, point.y)); + break; + } + } + void RigidBody2D::AddTorque(float torque) { cpBodySetTorque(m_handle, cpBodyGetTorque(m_handle) + torque); From 5ebf1254740e793668efb81a9a4f5b7c1c3fca51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 1 Mar 2017 17:40:12 +0100 Subject: [PATCH 04/25] Physics2D: Add NearestBodyQuery --- include/Nazara/Physics2D/Collider2D.hpp | 11 ++++++- include/Nazara/Physics2D/Collider2D.inl | 39 ++++++++++++++++++++++-- include/Nazara/Physics2D/PhysWorld2D.hpp | 15 +++++++++ src/Nazara/Physics2D/Collider2D.cpp | 3 ++ src/Nazara/Physics2D/PhysWorld2D.cpp | 34 +++++++++++++++++++++ src/Nazara/Physics2D/RigidBody2D.cpp | 3 ++ 6 files changed, 101 insertions(+), 4 deletions(-) diff --git a/include/Nazara/Physics2D/Collider2D.hpp b/include/Nazara/Physics2D/Collider2D.hpp index e5b988756..b09e8781f 100644 --- a/include/Nazara/Physics2D/Collider2D.hpp +++ b/include/Nazara/Physics2D/Collider2D.hpp @@ -42,13 +42,19 @@ namespace Nz virtual float ComputeInertialMatrix(float mass) const = 0; + inline Nz::UInt32 GetCategoryMask() const; + inline Nz::UInt32 GetCollisionGroup() const; inline unsigned int GetCollisionId() const; + inline Nz::UInt32 GetCollisionMask() const; virtual ColliderType2D GetType() const = 0; inline bool IsTrigger() const; - inline void SetCollisionId(unsigned long typeId); + inline void SetCategoryMask(Nz::UInt32 categoryMask); + inline void SetCollisionGroup(Nz::UInt32 groupId); + inline void SetCollisionId(unsigned int typeId); + inline void SetCollisionMask(Nz::UInt32 mask); inline void SetTrigger(bool trigger); Collider2D& operator=(const Collider2D&) = delete; @@ -61,7 +67,10 @@ namespace Nz virtual std::vector CreateShapes(RigidBody2D* body) const = 0; bool m_trigger; + Nz::UInt32 m_categoryMask; + Nz::UInt32 m_collisionGroup; unsigned int m_collisionId; + Nz::UInt32 m_collisionMask; private: virtual std::vector GenerateShapes(RigidBody2D* body) const; diff --git a/include/Nazara/Physics2D/Collider2D.inl b/include/Nazara/Physics2D/Collider2D.inl index 71b909a2c..60cf8559f 100644 --- a/include/Nazara/Physics2D/Collider2D.inl +++ b/include/Nazara/Physics2D/Collider2D.inl @@ -2,32 +2,66 @@ // This file is part of the "Nazara Engine - Physics 2D module" // For conditions of distribution and use, see copyright notice in Config.hpp +#include #include #include namespace Nz { inline Collider2D::Collider2D() : + m_trigger(false), + m_categoryMask(0xFFFFFFFF), + m_collisionGroup(0), m_collisionId(0), - m_trigger(false) + m_collisionMask(0xFFFFFFFF) { } + inline Nz::UInt32 Collider2D::GetCategoryMask() const + { + return m_categoryMask; + } + + inline Nz::UInt32 Collider2D::GetCollisionGroup() const + { + return m_collisionGroup; + } + inline unsigned int Collider2D::GetCollisionId() const { return m_collisionId; } + inline Nz::UInt32 Collider2D::GetCollisionMask() const + { + return m_collisionMask; + } + inline bool Collider2D::IsTrigger() const { return m_trigger; } - inline void Collider2D::SetCollisionId(unsigned long typeId) + inline void Collider2D::SetCategoryMask(Nz::UInt32 categoryMask) + { + m_categoryMask = categoryMask; + } + + inline void Collider2D::SetCollisionGroup(Nz::UInt32 groupId) + { + m_collisionGroup = groupId; + } + + inline void Collider2D::SetCollisionId(unsigned int typeId) { m_collisionId = typeId; } + inline void Collider2D::SetCollisionMask(Nz::UInt32 mask) + { + m_collisionMask = mask; + } + inline void Collider2D::SetTrigger(bool trigger) { m_trigger = trigger; @@ -108,4 +142,3 @@ namespace Nz } #include -#include "Collider2D.hpp" diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index 760773c7d..09e39959b 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -8,6 +8,7 @@ #define NAZARA_PHYSWORLD2D_HPP #include +#include #include #include #include @@ -29,6 +30,7 @@ namespace Nz public: struct Callback; + struct NearestQueryResult; PhysWorld2D(); PhysWorld2D(const PhysWorld2D&) = delete; @@ -39,6 +41,8 @@ namespace Nz cpSpace* GetHandle() const; float GetStepSize() const; + bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result); + void RegisterCallbacks(unsigned int collisionId, const Callback& callbacks); void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, const Callback& callbacks); @@ -59,6 +63,17 @@ namespace Nz void* userdata; }; + struct NearestQueryResult + { + Nz::RigidBody2D* nearestBody; + Nz::Vector2f closestPoint; + Nz::Vector2f fraction; + float distance; + }; + + NazaraSignal(OnPhysWorld2DPreStep, const PhysWorld2D* /*physWorld*/); + NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/); + private: void InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks); diff --git a/src/Nazara/Physics2D/Collider2D.cpp b/src/Nazara/Physics2D/Collider2D.cpp index cce3301aa..3a679fad9 100644 --- a/src/Nazara/Physics2D/Collider2D.cpp +++ b/src/Nazara/Physics2D/Collider2D.cpp @@ -13,9 +13,12 @@ namespace Nz std::vector Collider2D::GenerateShapes(RigidBody2D* body) const { + cpShapeFilter filter = cpShapeFilterNew(m_collisionGroup, m_categoryMask, m_collisionMask); + std::vector shapes = CreateShapes(body); for (cpShape* shape : shapes) { + cpShapeSetFilter(shape, filter); cpShapeSetCollisionType(shape, m_collisionId); cpShapeSetSensor(shape, (m_trigger) ? cpTrue : cpFalse); } diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index 7c15beee3..52881b827 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -37,6 +37,35 @@ namespace Nz return m_stepSize; } + bool PhysWorld2D::NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result) + { + cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask); + + if (result) + { + cpPointQueryInfo queryInfo; + + if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, &queryInfo)) + { + result->closestPoint.Set(queryInfo.point.x, queryInfo.point.y); + result->distance = queryInfo.distance; + result->fraction.Set(queryInfo.gradient.x, queryInfo.gradient.y); + result->nearestBody = static_cast(cpShapeGetUserData(shape)); + + return true; + } + else + return false; + } + else + { + if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, nullptr)) + return true; + else + return false; + } + } + void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, const Callback& callbacks) { InitCallbacks(cpSpaceAddWildcardHandler(m_handle, collisionId), callbacks); @@ -63,7 +92,12 @@ namespace Nz while (m_timestepAccumulator >= m_stepSize) { + OnPhysWorld2DPreStep(this); + cpSpaceStep(m_handle, m_stepSize); + + OnPhysWorld2DPostStep(this); + m_timestepAccumulator -= m_stepSize; } } diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index d01a426a2..d4d5aafd0 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -229,7 +229,10 @@ namespace Nz cpSpace* space = m_world->GetHandle(); for (cpShape* shape : m_shapes) + { + cpShapeSetUserData(shape, this); cpSpaceAddShape(space, shape); + } cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); } From 834f65c0ae2b75e674fa61202dd7ca71fd46035f Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 2 Mar 2017 10:34:02 +0100 Subject: [PATCH 05/25] Physics2D/PhysWorld2D: Add optimized NearestBodyQuery --- include/Nazara/Physics2D/PhysWorld2D.hpp | 1 + src/Nazara/Physics2D/PhysWorld2D.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index 09e39959b..3360b6584 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -41,6 +41,7 @@ namespace Nz cpSpace* GetHandle() const; float GetStepSize() const; + bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D* nearestBody); bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result); void RegisterCallbacks(unsigned int collisionId, const Callback& callbacks); diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index 52881b827..81d1824f1 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -37,6 +37,21 @@ namespace Nz return m_stepSize; } + bool PhysWorld2D::NearestBodyQuery(const Vector2f & from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D* nearestBody) + { + cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask); + + if (cpShape* shape = cpSpacePointQueryNearest(m_handle, {from.x, from.y}, maxDistance, filter, nullptr)) + { + if (nearestBody) + nearestBody = static_cast(cpShapeGetUserData(shape)); + + return true; + } + else + return false; + } + bool PhysWorld2D::NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result) { cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask); From a50a822fade1482af1af45ed3e8354f328e07b72 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 2 Mar 2017 11:22:59 +0100 Subject: [PATCH 06/25] Physics2D/PhysWorld2D: Fix NearestBodyQuery --- include/Nazara/Physics2D/PhysWorld2D.hpp | 2 +- src/Nazara/Physics2D/PhysWorld2D.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index 3360b6584..efd49c008 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -41,7 +41,7 @@ namespace Nz cpSpace* GetHandle() const; float GetStepSize() const; - bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D* nearestBody); + bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody); bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result); void RegisterCallbacks(unsigned int collisionId, const Callback& callbacks); diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index 81d1824f1..1383f931b 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -37,14 +37,14 @@ namespace Nz return m_stepSize; } - bool PhysWorld2D::NearestBodyQuery(const Vector2f & from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D* nearestBody) + bool PhysWorld2D::NearestBodyQuery(const Vector2f & from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody) { cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask); if (cpShape* shape = cpSpacePointQueryNearest(m_handle, {from.x, from.y}, maxDistance, filter, nullptr)) { if (nearestBody) - nearestBody = static_cast(cpShapeGetUserData(shape)); + *nearestBody = static_cast(cpShapeGetUserData(shape)); return true; } From 04f7b401500def9530bb76a8f467ecea55466e3b Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 2 Mar 2017 13:07:02 +0100 Subject: [PATCH 07/25] Physics2D/RigidBody2D: Fix querying --- include/Nazara/Physics2D/PhysWorld2D.hpp | 2 +- src/Nazara/Physics2D/RigidBody2D.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index efd49c008..f116b7729 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -41,7 +41,7 @@ namespace Nz cpSpace* GetHandle() const; float GetStepSize() const; - bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody); + bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody = nullptr); bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result); void RegisterCallbacks(unsigned int collisionId, const Callback& callbacks); diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index d4d5aafd0..d96ba3eb1 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -61,6 +61,8 @@ namespace Nz m_mass(object.m_mass) { cpBodySetUserData(m_handle, this); + for (cpShape* shape : m_shapes) + cpShapeSetUserData(shape, this); object.m_handle = nullptr; @@ -312,6 +314,8 @@ namespace Nz m_world = object.m_world; cpBodySetUserData(m_handle, this); + for (cpShape* shape : m_shapes) + cpShapeSetUserData(shape, this); object.m_handle = nullptr; @@ -324,6 +328,7 @@ namespace Nz { m_handle = cpBodyNew(mass, moment); cpBodySetUserData(m_handle, this); + cpSpaceAddBody(m_world->GetHandle(), m_handle); } From 605e5c2fd0ee3563517e7aee6f5933d1ffb4e306 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 3 Mar 2017 17:52:07 +0100 Subject: [PATCH 08/25] Sdk/BaseComponent: Add OnEntityDestruction callback Also fixes physics component callbacks (OnContactEnd by example) being fired while entity is destroyed --- SDK/include/NDK/BaseComponent.hpp | 1 + SDK/include/NDK/Components/PhysicsComponent2D.hpp | 1 + SDK/include/NDK/Components/PhysicsComponent3D.hpp | 1 + SDK/src/NDK/BaseComponent.cpp | 9 +++++++++ SDK/src/NDK/Components/PhysicsComponent2D.cpp | 6 ++++++ SDK/src/NDK/Components/PhysicsComponent3D.cpp | 7 +++++++ SDK/src/NDK/Entity.cpp | 4 ++++ 7 files changed, 29 insertions(+) diff --git a/SDK/include/NDK/BaseComponent.hpp b/SDK/include/NDK/BaseComponent.hpp index 8a4d51bfe..e21a1e38f 100644 --- a/SDK/include/NDK/BaseComponent.hpp +++ b/SDK/include/NDK/BaseComponent.hpp @@ -47,6 +47,7 @@ namespace Ndk virtual void OnComponentAttached(BaseComponent& component); virtual void OnComponentDetached(BaseComponent& component); virtual void OnDetached(); + virtual void OnEntityDestruction(); void SetEntity(Entity* entity); diff --git a/SDK/include/NDK/Components/PhysicsComponent2D.hpp b/SDK/include/NDK/Components/PhysicsComponent2D.hpp index 1f4cc63c9..2bbe693a1 100644 --- a/SDK/include/NDK/Components/PhysicsComponent2D.hpp +++ b/SDK/include/NDK/Components/PhysicsComponent2D.hpp @@ -55,6 +55,7 @@ namespace Ndk void OnComponentAttached(BaseComponent& component) override; void OnComponentDetached(BaseComponent& component) override; void OnDetached() override; + void OnEntityDestruction() override; std::unique_ptr m_object; }; diff --git a/SDK/include/NDK/Components/PhysicsComponent3D.hpp b/SDK/include/NDK/Components/PhysicsComponent3D.hpp index f6f13ec09..8be86537e 100644 --- a/SDK/include/NDK/Components/PhysicsComponent3D.hpp +++ b/SDK/include/NDK/Components/PhysicsComponent3D.hpp @@ -62,6 +62,7 @@ namespace Ndk void OnComponentAttached(BaseComponent& component) override; void OnComponentDetached(BaseComponent& component) override; void OnDetached() override; + void OnEntityDestruction() override; std::unique_ptr m_object; }; diff --git a/SDK/src/NDK/BaseComponent.cpp b/SDK/src/NDK/BaseComponent.cpp index 4af8caed2..204076e54 100644 --- a/SDK/src/NDK/BaseComponent.cpp +++ b/SDK/src/NDK/BaseComponent.cpp @@ -54,6 +54,15 @@ namespace Ndk { } + /*! + * \brief Operation to perform when the entity is destroyed and we're still attached to it + * + * \remark This is always called before the entity proper destruction, and thus its components. + */ + void BaseComponent::OnEntityDestruction() + { + } + std::vector BaseComponent::s_entries; std::unordered_map BaseComponent::s_idToIndex; } diff --git a/SDK/src/NDK/Components/PhysicsComponent2D.cpp b/SDK/src/NDK/Components/PhysicsComponent2D.cpp index b64ee37b5..58cab2982 100644 --- a/SDK/src/NDK/Components/PhysicsComponent2D.cpp +++ b/SDK/src/NDK/Components/PhysicsComponent2D.cpp @@ -88,5 +88,11 @@ namespace Ndk m_object.reset(); } + void PhysicsComponent2D::OnEntityDestruction() + { + // Kill rigidbody before entity destruction to force contact callbacks to be called while the entity is still valid + m_object.reset(); + } + ComponentIndex PhysicsComponent2D::componentIndex; } diff --git a/SDK/src/NDK/Components/PhysicsComponent3D.cpp b/SDK/src/NDK/Components/PhysicsComponent3D.cpp index 2581723a7..e0a22d08f 100644 --- a/SDK/src/NDK/Components/PhysicsComponent3D.cpp +++ b/SDK/src/NDK/Components/PhysicsComponent3D.cpp @@ -88,5 +88,12 @@ namespace Ndk m_object.reset(); } + void PhysicsComponent3D::OnEntityDestruction() + { + // Kill rigid body before entity destruction to force contact callbacks to be called while the entity is still valid + m_object.reset(); + + } + ComponentIndex PhysicsComponent3D::componentIndex; } diff --git a/SDK/src/NDK/Entity.cpp b/SDK/src/NDK/Entity.cpp index d88556a31..b8c37c761 100644 --- a/SDK/src/NDK/Entity.cpp +++ b/SDK/src/NDK/Entity.cpp @@ -145,6 +145,10 @@ namespace Ndk void Entity::Destroy() { + // We prepare components for entity destruction (some components needs this to handle some final callbacks while the entity is still valid) + for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i)) + m_components[i]->OnEntityDestruction(); + // We alert each system for (std::size_t index = m_systemBits.FindFirst(); index != m_systemBits.npos; index = m_systemBits.FindNext(index)) { From 3fe54ff777531f1a69a958fc39cd2fc58f2f56fd Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 3 Mar 2017 17:52:19 +0100 Subject: [PATCH 09/25] Sdk/Entity: Add OnEntityDestruction callback --- SDK/include/NDK/Entity.hpp | 3 +++ SDK/src/NDK/Entity.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/SDK/include/NDK/Entity.hpp b/SDK/include/NDK/Entity.hpp index ecf9fcc62..e386100f8 100644 --- a/SDK/include/NDK/Entity.hpp +++ b/SDK/include/NDK/Entity.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -65,6 +66,8 @@ namespace Ndk Entity& operator=(const Entity&) = delete; Entity& operator=(Entity&&) = delete; + NazaraSignal(OnEntityDestruction, Entity* /*entity*/); + private: Entity(World* world, EntityId id); diff --git a/SDK/src/NDK/Entity.cpp b/SDK/src/NDK/Entity.cpp index b8c37c761..ae5743163 100644 --- a/SDK/src/NDK/Entity.cpp +++ b/SDK/src/NDK/Entity.cpp @@ -145,6 +145,9 @@ namespace Ndk void Entity::Destroy() { + OnEntityDestruction(this); + OnEntityDestruction.Clear(); + // We prepare components for entity destruction (some components needs this to handle some final callbacks while the entity is still valid) for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i)) m_components[i]->OnEntityDestruction(); From d14574151a8fe6b838e8ce390be481ba18a90384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 6 Mar 2017 13:11:17 +0100 Subject: [PATCH 10/25] Build: Add AdditionalCompilationFlags build option --- build/config.lua | 3 +++ build/scripts/common.lua | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/build/config.lua b/build/config.lua index 8ecc7c24e..7c3e5a910 100644 --- a/build/config.lua +++ b/build/config.lua @@ -1,6 +1,9 @@ -- This file contains special configurations values, such as directories to extern libraries (Qt) -- Editing this file is not required to use/compile the engine, as default values should be enough +-- Additionnal compilation flags +--AdditionalCompilationFlags = -fsanitize=address -- Enable ASan + -- Builds Nazara extern libraries (such as lua/STB) BuildDependencies = true diff --git a/build/scripts/common.lua b/build/scripts/common.lua index e3ea13d62..55654c641 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -505,10 +505,24 @@ function NazaraBuild:LoadConfig() end end + local AddStringOption = function (option, name, description) + newoption({ + trigger = name, + description = description + }) + + local str = _OPTIONS[name] + if (str) then + configTable[option] = str + end + end + + AddBoolOption("BuildDependencies", "with-extlibs", "Builds the extern libraries") AddBoolOption("BuildExamples", "with-examples", "Builds the examples") AddBoolOption("ServerMode", "server", "Excludes client-only modules/tools/examples") AddBoolOption("UniteModules", "united", "Builds all the modules as one united library") + AddStringOption("AdditionalCompilationFlags", "compile-flags", "Specify additionnal compilation flags to be added to every generated project") -- Configurations do From 8147b0807e1e27d5d0d02cc516600349c7808bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 6 Mar 2017 13:16:55 +0100 Subject: [PATCH 11/25] Woops --- build/config.lua | 4 ++-- build/scripts/common.lua | 26 +++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/build/config.lua b/build/config.lua index 7c3e5a910..12a9f8e77 100644 --- a/build/config.lua +++ b/build/config.lua @@ -1,8 +1,8 @@ -- This file contains special configurations values, such as directories to extern libraries (Qt) -- Editing this file is not required to use/compile the engine, as default values should be enough --- Additionnal compilation flags ---AdditionalCompilationFlags = -fsanitize=address -- Enable ASan +-- Additionnal compilation options +--AdditionalCompilationOptions = "-fsanitize=address" -- Enable ASan -- Builds Nazara extern libraries (such as lua/STB) BuildDependencies = true diff --git a/build/scripts/common.lua b/build/scripts/common.lua index 55654c641..790ef2469 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -522,7 +522,29 @@ function NazaraBuild:LoadConfig() AddBoolOption("BuildExamples", "with-examples", "Builds the examples") AddBoolOption("ServerMode", "server", "Excludes client-only modules/tools/examples") AddBoolOption("UniteModules", "united", "Builds all the modules as one united library") - AddStringOption("AdditionalCompilationFlags", "compile-flags", "Specify additionnal compilation flags to be added to every generated project") + + -- AdditionalCompilationOptions + do + newoption({ + trigger = "compile-options", + description = "Specify additionnal compilation options to be added to every generated project." + }) + + configTable["AdditionalCompilationOptions"] = configTable["AdditionalCompilationOptions"] or "" + if (_OPTIONS["compile-options"] ~= nil) then + configTable["AdditionalCompilationOptions"] = configTable["AdditionalCompilationOptions"] .. ";" .. _OPTIONS["compile-options"] + end + + local configs = {} + local paths = string.explode(configTable["AdditionalCompilationOptions"], ";") + for k,v in pairs(paths) do + if (#v > 0) then + table.insert(configs, v) + end + end + + configTable["Configurations"] = configs + end -- Configurations do @@ -806,6 +828,8 @@ function NazaraBuild:PrepareGeneric() buildoptions("-ftree-vectorize") filter({}) + + buildoptions(self.Config["AdditionalCompilationOptions"]) end function NazaraBuild:PrepareMainWorkspace() From f88174c8cafcbebf245ae3f7f1fbe39f7e61e4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 6 Mar 2017 13:20:02 +0100 Subject: [PATCH 12/25] Woops again (works this time) --- build/scripts/common.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/scripts/common.lua b/build/scripts/common.lua index 790ef2469..ea7097e97 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -543,7 +543,7 @@ function NazaraBuild:LoadConfig() end end - configTable["Configurations"] = configs + configTable["AdditionalCompilationOptions"] = configs end -- Configurations From ede6dd90b80c0618d2db17cd62a0a9b3034c3240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Mon, 6 Mar 2017 14:02:35 +0100 Subject: [PATCH 13/25] Physics2D/PhysWorld: Add Raycast queries --- include/Nazara/Physics2D/PhysWorld2D.hpp | 12 ++++++ src/Nazara/Physics2D/PhysWorld2D.cpp | 52 ++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index f116b7729..3f4c3e696 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -31,6 +31,7 @@ namespace Nz public: struct Callback; struct NearestQueryResult; + struct RaycastHit; PhysWorld2D(); PhysWorld2D(const PhysWorld2D&) = delete; @@ -44,6 +45,9 @@ namespace Nz bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody = nullptr); bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result); + bool RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector* hitInfos); + bool RaycastQueryFirst(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RaycastHit* hitInfo = nullptr); + void RegisterCallbacks(unsigned int collisionId, const Callback& callbacks); void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, const Callback& callbacks); @@ -72,6 +76,14 @@ namespace Nz float distance; }; + struct RaycastHit + { + Nz::RigidBody2D* nearestBody; + Nz::Vector2f hitPos; + Nz::Vector2f hitNormal; + float fraction; + }; + NazaraSignal(OnPhysWorld2DPreStep, const PhysWorld2D* /*physWorld*/); NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/); diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index 1383f931b..6b18dbdd8 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -81,6 +81,58 @@ namespace Nz } } + bool PhysWorld2D::RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector* hitInfos) + { + auto callback = [](cpShape* shape, cpVect point, cpVect normal, cpFloat alpha, void* data) + { + std::vector* results = reinterpret_cast*>(data); + + RaycastHit hitInfo; + hitInfo.fraction = alpha; + hitInfo.hitNormal.Set(normal.x, normal.y); + hitInfo.hitPos.Set(point.x, point.y); + hitInfo.nearestBody = static_cast(cpShapeGetUserData(shape)); + + results->emplace_back(std::move(hitInfo)); + }; + + cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask); + + std::size_t previousSize = hitInfos->size(); + cpSpaceSegmentQuery(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, callback, hitInfos); + + return hitInfos->size() != previousSize; + } + + bool PhysWorld2D::RaycastQueryFirst(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RaycastHit* hitInfo) + { + cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask); + + if (hitInfo) + { + cpSegmentQueryInfo queryInfo; + + if (cpShape* shape = cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, &queryInfo)) + { + hitInfo->fraction = queryInfo.alpha; + hitInfo->hitNormal.Set(queryInfo.normal.x, queryInfo.normal.y); + hitInfo->hitPos.Set(queryInfo.point.x, queryInfo.point.y); + hitInfo->nearestBody = static_cast(cpShapeGetUserData(queryInfo.shape)); + + return true; + } + else + return false; + } + else + { + if (cpShape* shape = cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, nullptr)) + return true; + else + return false; + } + } + void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, const Callback& callbacks) { InitCallbacks(cpSpaceAddWildcardHandler(m_handle, collisionId), callbacks); From 78d6a69bcbbc84f36e091edbda641f6c9248c1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 7 Mar 2017 09:36:29 +0100 Subject: [PATCH 14/25] Physics2D/PhysWorld2D: Fix SetMass calls during callbacks --- include/Nazara/Physics2D/PhysWorld2D.hpp | 21 ++++++++++- src/Nazara/Physics2D/PhysWorld2D.cpp | 47 ++++++++++++++++++++++++ src/Nazara/Physics2D/RigidBody2D.cpp | 11 ++++-- 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index 3f4c3e696..c3858dc1a 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -19,10 +20,10 @@ struct cpSpace; namespace Nz { - class RigidBody2D; - class NAZARA_PHYSICS2D_API PhysWorld2D { + friend RigidBody2D; + using ContactEndCallback = void(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata); using ContactPreSolveCallback = bool(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata); using ContactPostSolveCallback = void(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata); @@ -90,7 +91,23 @@ namespace Nz private: void InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks); + using PostStep = std::function; + + void OnRigidBodyMoved(RigidBody2D* oldPointer, RigidBody2D* newPointer); + void OnRigidBodyRelease(RigidBody2D* rigidBody); + + void RegisterPostStep(RigidBody2D* rigidBody, PostStep&& func); + + struct PostStepContainer + { + NazaraSlot(RigidBody2D, OnRigidBody2DMove, onMovedSlot); + NazaraSlot(RigidBody2D, OnRigidBody2DRelease, onReleaseSlot); + + std::vector funcs; + }; + std::unordered_map> m_callbacks; + std::unordered_map m_rigidPostSteps; cpSpace* m_handle; float m_stepSize; float m_timestepAccumulator; diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index 6b18dbdd8..f3dcba77d 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -164,6 +164,16 @@ namespace Nz cpSpaceStep(m_handle, m_stepSize); OnPhysWorld2DPostStep(this); + if (!m_rigidPostSteps.empty()) + { + for (const auto& pair : m_rigidPostSteps) + { + for (const auto& step : pair.second.funcs) + step(); + } + + m_rigidPostSteps.clear(); + } m_timestepAccumulator -= m_stepSize; } @@ -263,4 +273,41 @@ namespace Nz }; } } + + void PhysWorld2D::OnRigidBodyMoved(RigidBody2D* oldPointer, RigidBody2D* newPointer) + { + auto it = m_rigidPostSteps.find(oldPointer); + if (it == m_rigidPostSteps.end()) + return; //< Shouldn't happen + + m_rigidPostSteps.emplace(std::make_pair(newPointer, std::move(it->second))); + m_rigidPostSteps.erase(oldPointer); + } + + void PhysWorld2D::OnRigidBodyRelease(RigidBody2D* rigidBody) + { + m_rigidPostSteps.erase(rigidBody); + } + + void PhysWorld2D::RegisterPostStep(RigidBody2D* rigidBody, PostStep&& func) + { + // If space isn't locked, no need to wait + if (!cpSpaceIsLocked(m_handle)) + { + func(); + return; + } + + auto it = m_rigidPostSteps.find(rigidBody); + if (it == m_rigidPostSteps.end()) + { + PostStepContainer postStep; + postStep.onMovedSlot.Connect(rigidBody->OnRigidBody2DMove, this, &PhysWorld2D::OnRigidBodyMoved); + postStep.onReleaseSlot.Connect(rigidBody->OnRigidBody2DRelease, this, &PhysWorld2D::OnRigidBodyRelease); + + it = m_rigidPostSteps.insert(std::make_pair(rigidBody, std::move(postStep))).first; + } + + it->second.funcs.emplace_back(std::move(func)); + } } diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index d96ba3eb1..aef36d0ad 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -249,15 +249,18 @@ namespace Nz cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); } else - cpBodySetType(m_handle, CP_BODY_TYPE_STATIC); + m_world->RegisterPostStep(this, [this]() { cpBodySetType(m_handle, CP_BODY_TYPE_STATIC); } ); } else if (mass > 0.f) { if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC) { - cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC); - cpBodySetMass(m_handle, mass); - cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + m_world->RegisterPostStep(this, [this, mass]() + { + cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC); + cpBodySetMass(m_handle, mass); + cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + }); } } From 43f8f21df6a9d3cfb37ff214193d31a03d98a362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 8 Mar 2017 13:16:53 +0100 Subject: [PATCH 15/25] Physics2D/RigidBody2D: Fix SetMass occasionnal crash --- src/Nazara/Physics2D/RigidBody2D.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index aef36d0ad..8bf713402 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -245,23 +245,26 @@ namespace Nz { if (mass > 0.f) { - cpBodySetMass(m_handle, mass); - cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + m_world->RegisterPostStep(this, [this, mass]() + { + cpBodySetMass(m_handle, mass); + cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + }); } else m_world->RegisterPostStep(this, [this]() { cpBodySetType(m_handle, CP_BODY_TYPE_STATIC); } ); } else if (mass > 0.f) { - if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC) + m_world->RegisterPostStep(this, [this, mass]() { - m_world->RegisterPostStep(this, [this, mass]() + if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC) { cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC); cpBodySetMass(m_handle, mass); cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); - }); - } + } + }); } m_mass = mass; From b0d61802b626858e530db0097ea57b1fd85942a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 8 Mar 2017 13:17:04 +0100 Subject: [PATCH 16/25] Network/SocketPoller: Fix documentation --- src/Nazara/Network/SocketPoller.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Nazara/Network/SocketPoller.cpp b/src/Nazara/Network/SocketPoller.cpp index fa5aa837e..43250a84f 100644 --- a/src/Nazara/Network/SocketPoller.cpp +++ b/src/Nazara/Network/SocketPoller.cpp @@ -142,13 +142,15 @@ namespace Nz } /*! - * \brief Wait until any registered socket switches to a ready state + * \brief Wait until any registered socket switches to a ready state. * * Waits a specific/undetermined amount of time until at least one socket part of the SocketPoller becomes ready. * To query the ready state of the registered socket, use the IsReady function. * * \param msTimeout Maximum time to wait in milliseconds, 0 for infinity * + * \return True if at least one socket registered to the poller is ready. + * * \remark It is an error to try to unregister a non-registered socket from a SocketPoller. * * \see IsReady From 9c7b2ed4b841b22ba83a7d57af44bc87b4dfbcf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 8 Mar 2017 15:52:59 +0100 Subject: [PATCH 17/25] Sdk/World: Fix entity ids being reused before destruction --- SDK/src/NDK/World.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index 545fab499..cad4660d4 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -185,12 +185,12 @@ namespace Ndk NazaraAssert(entity.IsValid(), "Entity must be valid"); - // Send back the identifier of the entity to the free queue - m_freeIdList.push_back(entity.GetId()); - // Destruction of the entity (invalidation of handle by the same way) entity.Destroy(); + // Send back the identifier of the entity to the free queue + m_freeIdList.push_back(entity.GetId()); + // We take out the handle from the list of alive entities // With the idiom swap and pop From 0818a2187bb9cdd9445ad4a2124d09f48e3f2b20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 8 Mar 2017 16:32:08 +0100 Subject: [PATCH 18/25] Sdk/Entity: Fix OnDetached being called after OnEntityRemove when destructing --- SDK/src/NDK/Entity.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/SDK/src/NDK/Entity.cpp b/SDK/src/NDK/Entity.cpp index ae5743163..29b8f75df 100644 --- a/SDK/src/NDK/Entity.cpp +++ b/SDK/src/NDK/Entity.cpp @@ -152,6 +152,10 @@ namespace Ndk for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i)) m_components[i]->OnEntityDestruction(); + // Detach components while they're still attached to systems + for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i)) + m_components[i]->SetEntity(nullptr); + // We alert each system for (std::size_t index = m_systemBits.FindFirst(); index != m_systemBits.npos; index = m_systemBits.FindNext(index)) { @@ -165,10 +169,7 @@ namespace Ndk } m_systemBits.Clear(); - // We properly destroy each component - for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i)) - m_components[i]->SetEntity(nullptr); - + // Destroy components m_components.clear(); m_componentBits.Reset(); From 4ea43e0b0b35d78c9205380c20570b858415ddee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 8 Mar 2017 17:36:13 +0100 Subject: [PATCH 19/25] Sdk/Entity: Fix problem when moving entities --- SDK/src/NDK/Entity.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SDK/src/NDK/Entity.cpp b/SDK/src/NDK/Entity.cpp index 29b8f75df..7cdc87d07 100644 --- a/SDK/src/NDK/Entity.cpp +++ b/SDK/src/NDK/Entity.cpp @@ -30,6 +30,7 @@ namespace Ndk m_enabled(entity.m_enabled), m_valid(entity.m_valid) { + entity.m_world = nullptr; } /*! @@ -53,7 +54,8 @@ namespace Ndk Entity::~Entity() { - Destroy(); + if (m_world) + Destroy(); } /*! From cdf7c11ef854d5c004e8830db04836f2d6c28c22 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 9 Mar 2017 18:20:18 +0100 Subject: [PATCH 20/25] Fix crash when RigidBody2D is moved while having poststeps --- SDK/src/NDK/Components/PhysicsComponent3D.cpp | 1 - include/Nazara/Physics2D/PhysWorld2D.hpp | 2 +- src/Nazara/Physics2D/PhysWorld2D.cpp | 2 +- src/Nazara/Physics2D/RigidBody2D.cpp | 18 +++++++++--------- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/SDK/src/NDK/Components/PhysicsComponent3D.cpp b/SDK/src/NDK/Components/PhysicsComponent3D.cpp index e0a22d08f..31b3fb6ac 100644 --- a/SDK/src/NDK/Components/PhysicsComponent3D.cpp +++ b/SDK/src/NDK/Components/PhysicsComponent3D.cpp @@ -92,7 +92,6 @@ namespace Ndk { // Kill rigid body before entity destruction to force contact callbacks to be called while the entity is still valid m_object.reset(); - } ComponentIndex PhysicsComponent3D::componentIndex; diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index c3858dc1a..7b31d9743 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -91,7 +91,7 @@ namespace Nz private: void InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks); - using PostStep = std::function; + using PostStep = std::function; void OnRigidBodyMoved(RigidBody2D* oldPointer, RigidBody2D* newPointer); void OnRigidBodyRelease(RigidBody2D* rigidBody); diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index f3dcba77d..f77c509ed 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -169,7 +169,7 @@ namespace Nz for (const auto& pair : m_rigidPostSteps) { for (const auto& step : pair.second.funcs) - step(); + step(pair.first); } m_rigidPostSteps.clear(); diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index 8bf713402..f31e9ef54 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -245,24 +245,24 @@ namespace Nz { if (mass > 0.f) { - m_world->RegisterPostStep(this, [this, mass]() + m_world->RegisterPostStep(this, [mass](Nz::RigidBody2D* body) { - cpBodySetMass(m_handle, mass); - cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + cpBodySetMass(body->GetHandle(), mass); + cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeInertialMatrix(mass)); }); } else - m_world->RegisterPostStep(this, [this]() { cpBodySetType(m_handle, CP_BODY_TYPE_STATIC); } ); + m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body) { cpBodySetType(body->GetHandle(), CP_BODY_TYPE_STATIC); } ); } else if (mass > 0.f) { - m_world->RegisterPostStep(this, [this, mass]() + m_world->RegisterPostStep(this, [mass](Nz::RigidBody2D* body) { - if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC) + if (cpBodyGetType(body->GetHandle()) == CP_BODY_TYPE_STATIC) { - cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC); - cpBodySetMass(m_handle, mass); - cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + cpBodySetType(body->GetHandle(), CP_BODY_TYPE_DYNAMIC); + cpBodySetMass(body->GetHandle(), mass); + cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeInertialMatrix(mass)); } }); } From ef474fc3a40d200cad317d81eb48af2e1cc650af Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 9 Mar 2017 18:21:07 +0100 Subject: [PATCH 21/25] Physics2D/PhysWorld2D: Fix compilation --- src/Nazara/Physics2D/PhysWorld2D.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index f77c509ed..e56749d66 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -294,7 +294,7 @@ namespace Nz // If space isn't locked, no need to wait if (!cpSpaceIsLocked(m_handle)) { - func(); + func(rigidBody); return; } From 353ade3efd2be0195e26b7ecf6f9b3f3d98cb8f8 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 10 Mar 2017 11:36:48 +0100 Subject: [PATCH 22/25] Core/Signal: Make movement noexcept --- include/Nazara/Core/Signal.hpp | 14 +++++++------- include/Nazara/Core/Signal.inl | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/Nazara/Core/Signal.hpp b/include/Nazara/Core/Signal.hpp index c325b40ce..0dfff4a1e 100644 --- a/include/Nazara/Core/Signal.hpp +++ b/include/Nazara/Core/Signal.hpp @@ -69,7 +69,7 @@ namespace Nz SlotListIndex index; }; - void Disconnect(const SlotPtr& slot); + void Disconnect(const SlotPtr& slot) noexcept; SlotList m_slots; mutable SlotListIndex m_slotIterator; @@ -84,17 +84,17 @@ namespace Nz public: Connection() = default; Connection(const Connection& connection) = default; - Connection(Connection&& connection) = default; + Connection(Connection&& connection) noexcept = default; ~Connection() = default; template void Connect(BaseClass& signal, ConnectArgs&&... args); - void Disconnect(); + void Disconnect() noexcept; bool IsConnected() const; Connection& operator=(const Connection& connection) = default; - Connection& operator=(Connection&& connection) = default; + Connection& operator=(Connection&& connection) noexcept = default; private: Connection(const SlotPtr& slot); @@ -113,12 +113,12 @@ namespace Nz ConnectionGuard(const Connection& connection); ConnectionGuard(const ConnectionGuard& connection) = delete; ConnectionGuard(Connection&& connection); - ConnectionGuard(ConnectionGuard&& connection) = default; + ConnectionGuard(ConnectionGuard&& connection) noexcept = default; ~ConnectionGuard(); template void Connect(BaseClass& signal, ConnectArgs&&... args); - void Disconnect(); + void Disconnect() noexcept; Connection& GetConnection(); @@ -127,7 +127,7 @@ namespace Nz ConnectionGuard& operator=(const Connection& connection); ConnectionGuard& operator=(const ConnectionGuard& connection) = delete; ConnectionGuard& operator=(Connection&& connection); - ConnectionGuard& operator=(ConnectionGuard&& connection); + ConnectionGuard& operator=(ConnectionGuard&& connection) noexcept; private: Connection m_connection; diff --git a/include/Nazara/Core/Signal.inl b/include/Nazara/Core/Signal.inl index 9e711a65f..65df55712 100644 --- a/include/Nazara/Core/Signal.inl +++ b/include/Nazara/Core/Signal.inl @@ -205,7 +205,7 @@ namespace Nz */ template - void Signal::Disconnect(const SlotPtr& slot) + void Signal::Disconnect(const SlotPtr& slot) noexcept { NazaraAssert(slot, "Invalid slot pointer"); NazaraAssert(slot->index < m_slots.size(), "Invalid slot index"); @@ -277,7 +277,7 @@ namespace Nz */ template - void Signal::Connection::Disconnect() + void Signal::Connection::Disconnect() noexcept { if (SlotPtr ptr = m_ptr.lock()) ptr->signal->Disconnect(ptr); @@ -353,7 +353,7 @@ namespace Nz */ template - void Signal::ConnectionGuard::Disconnect() + void Signal::ConnectionGuard::Disconnect() noexcept { m_connection.Disconnect(); } @@ -420,7 +420,7 @@ namespace Nz */ template - typename Signal::ConnectionGuard& Signal::ConnectionGuard::operator=(ConnectionGuard&& connection) + typename Signal::ConnectionGuard& Signal::ConnectionGuard::operator=(ConnectionGuard&& connection) noexcept { m_connection.Disconnect(); m_connection = std::move(connection.m_connection); From 4d932e93170852598dbf13d8e14928326fa6c9d9 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 10 Mar 2017 11:36:58 +0100 Subject: [PATCH 23/25] PhysWorld2D: Ensure PostStepContainer is move-constructible noexcept --- include/Nazara/Physics2D/PhysWorld2D.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index 7b31d9743..52db98189 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -106,6 +106,8 @@ namespace Nz std::vector funcs; }; + static_assert(std::is_nothrow_move_constructible::value, "PostStepContainer should be noexcept MoveConstructible"); + std::unordered_map> m_callbacks; std::unordered_map m_rigidPostSteps; cpSpace* m_handle; From 9531edfffc01363ee67dc0025919382498da3ddd Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 10 Mar 2017 17:07:40 +0100 Subject: [PATCH 24/25] Core/Signal: Fix move behaviour with GCC 4.9 .... --- include/Nazara/Core/Signal.inl | 38 ++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/include/Nazara/Core/Signal.inl b/include/Nazara/Core/Signal.inl index 65df55712..d71388c94 100644 --- a/include/Nazara/Core/Signal.inl +++ b/include/Nazara/Core/Signal.inl @@ -246,6 +246,18 @@ namespace Nz * \brief Core class that represents a connection attached to a signal */ + /*! + * \brief Constructs a Signal::Connection object with by move semantic + * + * \param connection Connection object to move + */ + template + Signal::Connection::Connection(Connection&& connection) noexcept : + m_ptr(std::move(connection.m_ptr)) + { + connection.m_ptr.reset(); //< Fuck you GCC 4.9 + } + /*! * \brief Constructs a Signal::Connection object with a slot * @@ -294,6 +306,18 @@ namespace Nz return !m_ptr.expired(); } + /*! + * \brief Constructs a Signal::ConnectionGuard object by move semantic + * + * \param connection Connection to move + */ + template + typename Signal::Connection& Signal::Connection::operator=(Connection&& connection) noexcept + { + m_ptr = std::move(connection.m_ptr); + connection.m_ptr.reset(); //< Fuck you GCC 4.9 + } + /*! * \class Nz::Signal::ConnectionGuard * \brief Core class that represents a RAII for a connection attached to a signal @@ -406,8 +430,11 @@ namespace Nz template typename Signal::ConnectionGuard& Signal::ConnectionGuard::operator=(Connection&& connection) { - m_connection.Disconnect(); - m_connection = std::move(connection); + if (&connection != this) + { + m_connection.Disconnect(); + m_connection = std::move(connection); + } return *this; } @@ -422,8 +449,11 @@ namespace Nz template typename Signal::ConnectionGuard& Signal::ConnectionGuard::operator=(ConnectionGuard&& connection) noexcept { - m_connection.Disconnect(); - m_connection = std::move(connection.m_connection); + if (&connection != this) + { + m_connection.Disconnect(); + m_connection = std::move(connection.m_connection); + } return *this; } From 82edb5c7cb55b4c520be1815ebd9992b4d819c35 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 10 Mar 2017 17:10:11 +0100 Subject: [PATCH 25/25] Core/Signal: Fix compilation --- include/Nazara/Core/Signal.hpp | 4 ++-- include/Nazara/Core/Signal.inl | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/Nazara/Core/Signal.hpp b/include/Nazara/Core/Signal.hpp index 0dfff4a1e..1569c5d0e 100644 --- a/include/Nazara/Core/Signal.hpp +++ b/include/Nazara/Core/Signal.hpp @@ -84,7 +84,7 @@ namespace Nz public: Connection() = default; Connection(const Connection& connection) = default; - Connection(Connection&& connection) noexcept = default; + Connection(Connection&& connection) noexcept; ~Connection() = default; template @@ -94,7 +94,7 @@ namespace Nz bool IsConnected() const; Connection& operator=(const Connection& connection) = default; - Connection& operator=(Connection&& connection) noexcept = default; + Connection& operator=(Connection&& connection) noexcept; private: Connection(const SlotPtr& slot); diff --git a/include/Nazara/Core/Signal.inl b/include/Nazara/Core/Signal.inl index d71388c94..c4e89bd40 100644 --- a/include/Nazara/Core/Signal.inl +++ b/include/Nazara/Core/Signal.inl @@ -316,6 +316,8 @@ namespace Nz { m_ptr = std::move(connection.m_ptr); connection.m_ptr.reset(); //< Fuck you GCC 4.9 + + return *this; } /*!