Physics2D/PhysWorld2D: Fix SetMass calls during callbacks
This commit is contained in:
parent
ede6dd90b8
commit
78d6a69bcb
|
|
@ -11,6 +11,7 @@
|
|||
#include <Nazara/Core/Signal.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Physics2D/Config.hpp>
|
||||
#include <Nazara/Physics2D/RigidBody2D.hpp>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
|
|
@ -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()>;
|
||||
|
||||
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<PostStep> funcs;
|
||||
};
|
||||
|
||||
std::unordered_map<cpCollisionHandler*, std::unique_ptr<Callback>> m_callbacks;
|
||||
std::unordered_map<RigidBody2D*, PostStepContainer> m_rigidPostSteps;
|
||||
cpSpace* m_handle;
|
||||
float m_stepSize;
|
||||
float m_timestepAccumulator;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue