From e61faae0897c2899194b51d1e64d4b932ca931ec Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 15 Apr 2019 16:25:40 +0200 Subject: [PATCH] Physics2D/PhysWorld2D: Fix multiple calls to RegisterCallbacks with the same collision id --- ChangeLog.md | 1 + SDK/src/NDK/Systems/PhysicsSystem2D.cpp | 2 +- include/Nazara/Physics2D/PhysWorld2D.hpp | 8 +-- src/Nazara/Physics2D/PhysWorld2D.cpp | 71 ++++++++++++++++++------ 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index f35121273..37cb5f5c0 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -183,6 +183,7 @@ Nazara Engine: - ⚠ Renamed TextStyleFlags enum to TextStyle, introduced Flags specialization of TextStyle as TextStyleFlags - ⚠ Font, FontData and SimpleTextDrawer now use a proper TextStyleFlags instead of a UInt32 - Almost all Math algorithms are now constexpr +- PhysWorld2D: Fixed callbacks not properly replacing each others when registering twice with the same collisionId (pair) Nazara Development Kit: - Added ImageWidget (#139) diff --git a/SDK/src/NDK/Systems/PhysicsSystem2D.cpp b/SDK/src/NDK/Systems/PhysicsSystem2D.cpp index 1273d66bc..8cce2e9aa 100644 --- a/SDK/src/NDK/Systems/PhysicsSystem2D.cpp +++ b/SDK/src/NDK/Systems/PhysicsSystem2D.cpp @@ -287,7 +287,7 @@ namespace Ndk void PhysicsSystem2D::RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, Callback callbacks) { - Nz::PhysWorld2D::Callback worldCallbacks{}; + Nz::PhysWorld2D::Callback worldCallbacks; if (callbacks.endCallback) { diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index 42e9288a1..86de8f003 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -69,8 +69,8 @@ namespace Nz void RegionQuery(const Nz::Rectf& boundingBox, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector* bodies); - void RegisterCallbacks(unsigned int collisionId, const Callback& callbacks); - void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, const Callback& callbacks); + void RegisterCallbacks(unsigned int collisionId, Callback callbacks); + void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, Callback callbacks); void SetDamping(float dampingValue); void SetGravity(const Vector2f& gravity); @@ -91,7 +91,7 @@ namespace Nz ContactPreSolveCallback preSolveCallback = nullptr; ContactPostSolveCallback postSolveCallback = nullptr; ContactStartCallback startCallback = nullptr; - void* userdata; + void* userdata = nullptr; }; struct DebugDrawOptions @@ -130,7 +130,7 @@ namespace Nz NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/, float /*invStepCount*/); private: - void InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks); + void InitCallbacks(cpCollisionHandler* handler, Callback callbacks); using PostStep = std::function; diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index 7383510f8..319a10582 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -273,14 +273,14 @@ namespace Nz cpSpaceBBQuery(m_handle, cpBBNew(boundingBox.x, boundingBox.y, boundingBox.x + boundingBox.width, boundingBox.y + boundingBox.height), filter, callback, bodies); } - void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, const Callback& callbacks) + void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, Callback callbacks) { - InitCallbacks(cpSpaceAddWildcardHandler(m_handle, collisionId), callbacks); + InitCallbacks(cpSpaceAddWildcardHandler(m_handle, collisionId), std::move(callbacks)); } - void PhysWorld2D::RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, const Callback& callbacks) + void PhysWorld2D::RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, Callback callbacks) { - InitCallbacks(cpSpaceAddCollisionHandler(m_handle, collisionIdA, collisionIdB), callbacks); + InitCallbacks(cpSpaceAddCollisionHandler(m_handle, collisionIdA, collisionIdB), std::move(callbacks)); } void PhysWorld2D::SetDamping(float dampingValue) @@ -341,15 +341,20 @@ namespace Nz cpSpaceUseSpatialHash(m_handle, cpFloat(cellSize), int(entityCount)); } - void PhysWorld2D::InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks) + void PhysWorld2D::InitCallbacks(cpCollisionHandler* handler, Callback callbacks) { - auto it = m_callbacks.emplace(handler, std::make_unique(callbacks)).first; + auto it = m_callbacks.find(handler); + if (it == m_callbacks.end()) + it = m_callbacks.emplace(handler, std::make_unique(std::move(callbacks))).first; + else + it->second = std::make_unique(std::move(callbacks)); - handler->userData = it->second.get(); + Callback* callbackFunctions = it->second.get(); + handler->userData = callbackFunctions; - if (callbacks.startCallback) + if (callbackFunctions->startCallback) { - handler->beginFunc = [](cpArbiter* arb, cpSpace* space, void *data) -> cpBool + handler->beginFunc = [](cpArbiter* arb, cpSpace* space, void*) -> cpBool { cpBody* firstBody; cpBody* secondBody; @@ -372,10 +377,19 @@ namespace Nz return cpFalse; }; } - - if (callbacks.endCallback) + else { - handler->separateFunc = [](cpArbiter* arb, cpSpace* space, void *data) + handler->beginFunc = [](cpArbiter* arb, cpSpace* space, void*) -> cpBool + { + cpBool retA = cpArbiterCallWildcardBeginA(arb, space); + cpBool retB = cpArbiterCallWildcardBeginB(arb, space); + return retA && retB; + }; + } + + if (callbackFunctions->endCallback) + { + handler->separateFunc = [](cpArbiter* arb, cpSpace* space, void*) { cpBody* firstBody; cpBody* secondBody; @@ -394,10 +408,18 @@ namespace Nz cpArbiterCallWildcardSeparateB(arb, space); }; } - - if (callbacks.preSolveCallback) + else { - handler->preSolveFunc = [](cpArbiter* arb, cpSpace* space, void *data) -> cpBool + handler->separateFunc = [](cpArbiter* arb, cpSpace* space, void*) + { + cpArbiterCallWildcardSeparateA(arb, space); + cpArbiterCallWildcardSeparateB(arb, space); + }; + } + + if (callbackFunctions->preSolveCallback) + { + handler->preSolveFunc = [](cpArbiter* arb, cpSpace* space, void* data) -> cpBool { cpBody* firstBody; cpBody* secondBody; @@ -420,8 +442,17 @@ namespace Nz return cpFalse; }; } + else + { + handler->preSolveFunc = [](cpArbiter* arb, cpSpace* space, void* data) -> cpBool + { + cpBool retA = cpArbiterCallWildcardPreSolveA(arb, space); + cpBool retB = cpArbiterCallWildcardPreSolveB(arb, space); + return retA && retB; + }; + } - if (callbacks.postSolveCallback) + if (callbackFunctions->postSolveCallback) { handler->postSolveFunc = [](cpArbiter* arb, cpSpace* space, void *data) { @@ -442,6 +473,14 @@ namespace Nz cpArbiterCallWildcardPostSolveB(arb, space); }; } + else + { + handler->postSolveFunc = [](cpArbiter* arb, cpSpace* space, void* data) + { + cpArbiterCallWildcardPostSolveA(arb, space); + cpArbiterCallWildcardPostSolveB(arb, space); + }; + } } void PhysWorld2D::OnRigidBodyMoved(RigidBody2D* oldPointer, RigidBody2D* newPointer)