Physics2D: Add support for trigger and callbacks

This commit is contained in:
Jérôme Leclercq
2017-02-21 15:58:31 +01:00
parent c2e4ccaf72
commit 7b47a6ad2e
6 changed files with 179 additions and 2 deletions

View File

@@ -11,6 +11,18 @@ namespace Nz
{
Collider2D::~Collider2D() = default;
std::vector<cpShape*> Collider2D::GenerateShapes(RigidBody2D* body) const
{
std::vector<cpShape*> shapes = CreateShapes(body);
for (cpShape* shape : shapes)
{
cpShapeSetCollisionType(shape, m_collisionId);
cpShapeSetSensor(shape, (m_trigger) ? cpTrue : cpFalse);
}
return shapes;
}
/******************************** BoxCollider2D *********************************/
BoxCollider2D::BoxCollider2D(const Vector2f& size, float radius) :

View File

@@ -37,6 +37,16 @@ namespace Nz
return m_stepSize;
}
void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, const Callback& callbacks)
{
InitCallbacks(cpSpaceAddWildcardHandler(m_handle, collisionId), callbacks);
}
void PhysWorld2D::RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, const Callback& callbacks)
{
InitCallbacks(cpSpaceAddCollisionHandler(m_handle, collisionIdA, collisionIdB), callbacks);
}
void PhysWorld2D::SetGravity(const Vector2f& gravity)
{
cpSpaceSetGravity(m_handle, cpv(gravity.x, gravity.y));
@@ -57,4 +67,99 @@ namespace Nz
m_timestepAccumulator -= m_stepSize;
}
}
void PhysWorld2D::InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks)
{
auto it = m_callbacks.emplace(handler, std::make_unique<Callback>(callbacks)).first;
handler->userData = &it->second;
if (callbacks.startCallback)
{
handler->beginFunc = [](cpArbiter* arb, cpSpace* space, void *data) -> cpBool
{
cpBody* firstBody;
cpBody* secondBody;
cpArbiterGetBodies(arb, &firstBody, &secondBody);
PhysWorld2D* world = static_cast<PhysWorld2D*>(cpSpaceGetUserData(space));
RigidBody2D* firstRigidBody = static_cast<RigidBody2D*>(cpBodyGetUserData(firstBody));
RigidBody2D* secondRigidBody = static_cast<RigidBody2D*>(cpBodyGetUserData(secondBody));
const Callback* customCallbacks = static_cast<const Callback*>(data);
if (customCallbacks->startCallback(*world, *firstRigidBody, *secondRigidBody, customCallbacks->userdata))
{
cpBool retA = cpArbiterCallWildcardBeginA(arb, space);
cpBool retB = cpArbiterCallWildcardBeginB(arb, space);
return retA && retB;
}
else
return cpFalse;
};
}
if (callbacks.endCallback)
{
handler->separateFunc = [](cpArbiter* arb, cpSpace* space, void *data)
{
cpBody* firstBody;
cpBody* secondBody;
cpArbiterGetBodies(arb, &firstBody, &secondBody);
PhysWorld2D* world = static_cast<PhysWorld2D*>(cpSpaceGetUserData(space));
RigidBody2D* firstRigidBody = static_cast<RigidBody2D*>(cpBodyGetUserData(firstBody));
RigidBody2D* secondRigidBody = static_cast<RigidBody2D*>(cpBodyGetUserData(secondBody));
const Callback* customCallbacks = static_cast<const Callback*>(data);
customCallbacks->endCallback(*world, *firstRigidBody, *secondRigidBody, customCallbacks->userdata);
cpArbiterCallWildcardSeparateA(arb, space);
cpArbiterCallWildcardSeparateB(arb, space);
};
}
if (callbacks.preSolveCallback)
{
handler->preSolveFunc = [](cpArbiter* arb, cpSpace* space, void *data) -> cpBool
{
cpBody* firstBody;
cpBody* secondBody;
cpArbiterGetBodies(arb, &firstBody, &secondBody);
PhysWorld2D* world = static_cast<PhysWorld2D*>(cpSpaceGetUserData(space));
RigidBody2D* firstRigidBody = static_cast<RigidBody2D*>(cpBodyGetUserData(firstBody));
RigidBody2D* secondRigidBody = static_cast<RigidBody2D*>(cpBodyGetUserData(secondBody));
const Callback* customCallbacks = static_cast<const Callback*>(data);
if (customCallbacks->preSolveCallback(*world, *firstRigidBody, *secondRigidBody, customCallbacks->userdata))
{
cpBool retA = cpArbiterCallWildcardPreSolveA(arb, space);
cpBool retB = cpArbiterCallWildcardPreSolveB(arb, space);
return retA && retB;
}
else
return cpFalse;
};
}
if (callbacks.postSolveCallback)
{
handler->postSolveFunc = [](cpArbiter* arb, cpSpace* space, void *data)
{
cpBody* firstBody;
cpBody* secondBody;
cpArbiterGetBodies(arb, &firstBody, &secondBody);
PhysWorld2D* world = static_cast<PhysWorld2D*>(cpSpaceGetUserData(space));
RigidBody2D* firstRigidBody = static_cast<RigidBody2D*>(cpBodyGetUserData(firstBody));
RigidBody2D* secondRigidBody = static_cast<RigidBody2D*>(cpBodyGetUserData(secondBody));
const Callback* customCallbacks = static_cast<const Callback*>(data);
customCallbacks->postSolveCallback(*world, *firstRigidBody, *secondRigidBody, customCallbacks->userdata);
cpArbiterCallWildcardPostSolveA(arb, space);
cpArbiterCallWildcardPostSolveB(arb, space);
};
}
}
}

View File

@@ -190,7 +190,7 @@ namespace Nz
else
m_geom = NullCollider2D::New();
m_shapes = m_geom->CreateShapes(this);
m_shapes = m_geom->GenerateShapes(this);
cpSpace* space = m_world->GetHandle();
for (cpShape* shape : m_shapes)