mirror of
https://github.com/love2d/love.git
synced 2026-08-15 15:51:12 +02:00
Use Box2D's callbacks for destruction of physics objects and wait until the end of the timestep before destroying them.
Merge of box2d-id2 from love-experiments
This commit is contained in:
@@ -41,6 +41,8 @@ namespace box2d
|
||||
b2BodyDef def;
|
||||
def.position = Physics::scaleDown(p);
|
||||
body = world->world->CreateBody(&def);
|
||||
// Box2D body holds a reference to the love Body.
|
||||
this->retain();
|
||||
this->setType(type);
|
||||
Memoizer::add(body, this);
|
||||
}
|
||||
@@ -50,13 +52,13 @@ namespace box2d
|
||||
{
|
||||
world = (World *)Memoizer::find(b->GetWorld());
|
||||
world->retain();
|
||||
// Box2D body holds a reference to the love Body.
|
||||
this->retain();
|
||||
Memoizer::add(body, this);
|
||||
}
|
||||
|
||||
Body::~Body()
|
||||
{
|
||||
Memoizer::remove(body);
|
||||
world->world->DestroyBody(body);
|
||||
world->release();
|
||||
body = 0;
|
||||
}
|
||||
@@ -148,7 +150,8 @@ namespace box2d
|
||||
|
||||
Body::Type Body::getType() const
|
||||
{
|
||||
switch (body->GetType()) {
|
||||
switch (body->GetType())
|
||||
{
|
||||
case b2_staticBody:
|
||||
return BODY_STATIC;
|
||||
break;
|
||||
@@ -266,7 +269,8 @@ namespace box2d
|
||||
|
||||
void Body::setType(Body::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
switch (type)
|
||||
{
|
||||
case Body::BODY_STATIC:
|
||||
body->SetType(b2_staticBody);
|
||||
break;
|
||||
@@ -403,9 +407,11 @@ namespace box2d
|
||||
b2Fixture * f = body->GetFixtureList();
|
||||
int i = 1;
|
||||
do {
|
||||
if (!f) break;
|
||||
if (!f)
|
||||
break;
|
||||
Fixture * fixture = (Fixture *)Memoizer::find(f);
|
||||
if (!fixture) throw love::Exception("A fixture has escaped Memoizer!");
|
||||
if (!fixture)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
fixture->retain();
|
||||
luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void*)fixture);
|
||||
lua_rawseti(L, -2, i);
|
||||
@@ -431,7 +437,20 @@ namespace box2d
|
||||
|
||||
void Body::destroy()
|
||||
{
|
||||
world->destroyBody(this);
|
||||
if (world->world->IsLocked())
|
||||
{
|
||||
// Called during time step. Save reference for destruction afterwards.
|
||||
this->retain();
|
||||
world->destructBodies.push_back(this);
|
||||
return;
|
||||
}
|
||||
|
||||
world->world->DestroyBody(body);
|
||||
Memoizer::remove(body);
|
||||
body = NULL;
|
||||
|
||||
// Box2D body destroyed. Release its reference to the love Body.
|
||||
this->release();
|
||||
}
|
||||
|
||||
} // box2d
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace box2d
|
||||
friend class CircleShape;
|
||||
friend class PolygonShape;
|
||||
friend class Shape;
|
||||
friend class Fixture;
|
||||
|
||||
private:
|
||||
|
||||
@@ -386,7 +387,7 @@ namespace box2d
|
||||
int getFixtureList(lua_State * L) const;
|
||||
|
||||
/**
|
||||
* Mark the body for destruction
|
||||
* Destroy this body.
|
||||
**/
|
||||
void destroy();
|
||||
|
||||
|
||||
@@ -42,8 +42,6 @@ namespace box2d
|
||||
|
||||
DistanceJoint::~DistanceJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
void DistanceJoint::setLength(float length)
|
||||
|
||||
@@ -39,7 +39,6 @@ namespace box2d
|
||||
Fixture::Fixture(Body * body, Shape * shape, float density)
|
||||
: body(body), fixture(NULL)
|
||||
{
|
||||
body->retain();
|
||||
data = new fixtureudata();
|
||||
data->ref = 0;
|
||||
b2FixtureDef def;
|
||||
@@ -47,6 +46,7 @@ namespace box2d
|
||||
def.userData = (void *)data;
|
||||
def.density = density;
|
||||
fixture = body->body->CreateFixture(&def);
|
||||
this->retain();
|
||||
Memoizer::add(fixture, this);
|
||||
}
|
||||
|
||||
@@ -55,8 +55,9 @@ namespace box2d
|
||||
{
|
||||
data = (fixtureudata *)f->GetUserData();
|
||||
body = (Body *)Memoizer::find(f->GetBody());
|
||||
if (!body) body = new Body(f->GetBody());
|
||||
else body->retain();
|
||||
if (!body)
|
||||
body = new Body(f->GetBody());
|
||||
this->retain();
|
||||
Memoizer::add(fixture, this);
|
||||
}
|
||||
|
||||
@@ -66,13 +67,9 @@ namespace box2d
|
||||
delete data->ref;
|
||||
|
||||
delete data;
|
||||
data = 0;
|
||||
data = NULL;
|
||||
|
||||
if (fixture)
|
||||
body->body->DestroyFixture(fixture);
|
||||
fixture = 0;
|
||||
|
||||
body->release();
|
||||
fixture = NULL;
|
||||
}
|
||||
|
||||
Shape::Type Fixture::getType() const
|
||||
@@ -127,12 +124,19 @@ namespace box2d
|
||||
|
||||
Shape * Fixture::getShape() const
|
||||
{
|
||||
if (!fixture->GetShape()) return NULL;
|
||||
if (!fixture->GetShape())
|
||||
return NULL;
|
||||
Shape * s = (Shape *)Memoizer::find(fixture->GetShape());
|
||||
if (!s) s = new Shape(fixture->GetShape());
|
||||
if (!s)
|
||||
s = new Shape(fixture->GetShape());
|
||||
return s;
|
||||
}
|
||||
|
||||
bool Fixture::isValid() const
|
||||
{
|
||||
return fixture != 0;
|
||||
}
|
||||
|
||||
void Fixture::setFilterData(int * v)
|
||||
{
|
||||
b2Filter f;
|
||||
@@ -300,6 +304,24 @@ namespace box2d
|
||||
return 4;
|
||||
}
|
||||
|
||||
void Fixture::destroy(bool implicit)
|
||||
{
|
||||
if (body->world->world->IsLocked())
|
||||
{
|
||||
// Called during time step. Save reference for destruction afterwards.
|
||||
this->retain();
|
||||
body->world->destructFixtures.push_back(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!implicit && fixture != 0)
|
||||
body->body->DestroyFixture(fixture);
|
||||
Memoizer::remove(fixture);
|
||||
fixture = NULL;
|
||||
|
||||
// Box2D fixture destroyed. Release its reference to the love Fixture.
|
||||
this->release();
|
||||
}
|
||||
|
||||
} // box2d
|
||||
} // physics
|
||||
|
||||
@@ -62,8 +62,8 @@ namespace box2d
|
||||
protected:
|
||||
|
||||
Body * body;
|
||||
b2Fixture * fixture;
|
||||
fixtureudata * data;
|
||||
b2Fixture * fixture;
|
||||
|
||||
public:
|
||||
|
||||
@@ -90,6 +90,11 @@ namespace box2d
|
||||
**/
|
||||
Shape * getShape() const;
|
||||
|
||||
/**
|
||||
* Returns true if the fixture is active in a Box2D world.
|
||||
**/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Checks whether this Fixture acts as a sensor.
|
||||
* @return True if sensor, false otherwise.
|
||||
@@ -206,6 +211,11 @@ namespace box2d
|
||||
* This operation may be expensive.
|
||||
**/
|
||||
int getMassData(lua_State * L) const;
|
||||
|
||||
/**
|
||||
* Destroys this fixture.
|
||||
**/
|
||||
void destroy(bool implicit = false);
|
||||
};
|
||||
|
||||
} // box2d
|
||||
|
||||
@@ -45,8 +45,6 @@ namespace box2d
|
||||
|
||||
FrictionJoint::~FrictionJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
void FrictionJoint::setMaxForce(float force)
|
||||
|
||||
@@ -46,8 +46,6 @@ namespace box2d
|
||||
|
||||
GearJoint::~GearJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
void GearJoint::setRatio(float ratio)
|
||||
|
||||
@@ -23,11 +23,15 @@
|
||||
// STD
|
||||
#include <bitset>
|
||||
|
||||
// LOVE
|
||||
#include <common/Memoizer.h>
|
||||
|
||||
// Module
|
||||
#include "Body.h"
|
||||
#include "World.h"
|
||||
#include "Physics.h"
|
||||
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace physics
|
||||
@@ -37,24 +41,15 @@ namespace box2d
|
||||
Joint::Joint(Body * body1)
|
||||
: body1(body1), body2(0), world(body1->world)
|
||||
{
|
||||
body1->retain();
|
||||
}
|
||||
|
||||
Joint::Joint(Body * body1, Body * body2)
|
||||
: body1(body1), body2(body2), world(body1->world)
|
||||
{
|
||||
body1->retain();
|
||||
body2->retain();
|
||||
}
|
||||
|
||||
Joint::~Joint()
|
||||
{
|
||||
if (body1 != 0)
|
||||
body1->release();
|
||||
if (body2 != 0)
|
||||
body2->release();
|
||||
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
Joint::Type Joint::getType() const
|
||||
@@ -86,6 +81,11 @@ namespace box2d
|
||||
}
|
||||
}
|
||||
|
||||
bool Joint::isValid() const
|
||||
{
|
||||
return joint != 0;
|
||||
}
|
||||
|
||||
int Joint::getAnchors(lua_State * L)
|
||||
{
|
||||
lua_pushnumber(L, Physics::scaleUp(joint->GetAnchorA().x));
|
||||
@@ -112,13 +112,28 @@ namespace box2d
|
||||
b2Joint * Joint::createJoint(b2JointDef * def)
|
||||
{
|
||||
joint = world->world->CreateJoint(def);
|
||||
Memoizer::add(joint, this);
|
||||
// Box2D joint has a reference to this love Joint.
|
||||
this->retain();
|
||||
return joint;
|
||||
}
|
||||
|
||||
void Joint::destroyJoint(b2Joint * joint)
|
||||
void Joint::destroyJoint(bool implicit)
|
||||
{
|
||||
if (joint != NULL)
|
||||
if (world->world->IsLocked())
|
||||
{
|
||||
// Called during time step. Save reference for destruction afterwards.
|
||||
this->retain();
|
||||
world->destructJoints.push_back(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!implicit && joint != 0)
|
||||
world->world->DestroyJoint(joint);
|
||||
Memoizer::remove(joint);
|
||||
joint = NULL;
|
||||
// Release the reference of the Box2D joint.
|
||||
this->release();
|
||||
}
|
||||
|
||||
bool Joint::isActive() const
|
||||
|
||||
@@ -78,6 +78,12 @@ namespace box2d
|
||||
|
||||
virtual ~Joint();
|
||||
|
||||
/**
|
||||
* Returns true if the joint is active in a Box2D world.
|
||||
**/
|
||||
bool isValid() const;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the type of joint.
|
||||
**/
|
||||
@@ -103,25 +109,27 @@ namespace box2d
|
||||
|
||||
bool getCollideConnected() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Joints require pointers to a Box2D joint objects at
|
||||
* different polymorphic levels, which is why these function
|
||||
* were created.
|
||||
**/
|
||||
|
||||
/**
|
||||
* Destroys the joint. This function was created just to
|
||||
* get some cinsistency.
|
||||
**/
|
||||
void destroyJoint(bool implicit = false);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Creates a Joint, and ensures that the parent class
|
||||
* gets a copy of the pointer.
|
||||
**/
|
||||
b2Joint * createJoint(b2JointDef * def);
|
||||
|
||||
/**
|
||||
* Destroys the joint. This function was created just to
|
||||
* get some cinsistency.
|
||||
**/
|
||||
void destroyJoint(b2Joint * joint);
|
||||
|
||||
};
|
||||
|
||||
} // box2d
|
||||
|
||||
@@ -45,8 +45,6 @@ namespace box2d
|
||||
|
||||
MouseJoint::~MouseJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
void MouseJoint::setTarget(float x, float y)
|
||||
|
||||
@@ -47,8 +47,6 @@ namespace box2d
|
||||
|
||||
PrismaticJoint::~PrismaticJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
float PrismaticJoint::getJointTranslation() const
|
||||
|
||||
@@ -44,8 +44,6 @@ namespace box2d
|
||||
|
||||
PulleyJoint::~PulleyJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
int PulleyJoint::getGroundAnchors(lua_State * L)
|
||||
|
||||
@@ -44,8 +44,6 @@ namespace box2d
|
||||
|
||||
RevoluteJoint::~RevoluteJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
float RevoluteJoint::getJointAngle() const
|
||||
|
||||
@@ -46,8 +46,6 @@ namespace box2d
|
||||
|
||||
RopeJoint::~RopeJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
float RopeJoint::getMaxLength() const
|
||||
|
||||
@@ -45,8 +45,6 @@ namespace box2d
|
||||
|
||||
WeldJoint::~WeldJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
void WeldJoint::setFrequency(float hz)
|
||||
|
||||
@@ -44,8 +44,6 @@ namespace box2d
|
||||
|
||||
WheelJoint::~WheelJoint()
|
||||
{
|
||||
destroyJoint(joint);
|
||||
joint = 0;
|
||||
}
|
||||
|
||||
float WheelJoint::getJointTranslation() const
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace box2d
|
||||
|
||||
Contact * c = new Contact(contact);
|
||||
|
||||
luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void*)c, true);
|
||||
luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void*)c);
|
||||
|
||||
int args = 3;
|
||||
if (impulse)
|
||||
@@ -97,7 +97,7 @@ namespace box2d
|
||||
}
|
||||
|
||||
World::ContactFilter::ContactFilter()
|
||||
: ref(0)
|
||||
: ref(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace box2d
|
||||
}
|
||||
|
||||
World::QueryCallback::QueryCallback()
|
||||
: ref(0)
|
||||
: ref(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -139,7 +139,8 @@ namespace box2d
|
||||
lua_State * L = ref->getL();
|
||||
ref->push();
|
||||
Fixture * f = (Fixture *)Memoizer::find(fixture);
|
||||
if (!f) throw love::Exception("A fixture has escaped Memoizer!");
|
||||
if (!f)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
f->retain();
|
||||
luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void*)f);
|
||||
lua_call(L, 1, 1);
|
||||
@@ -166,7 +167,8 @@ namespace box2d
|
||||
lua_State * L = ref->getL();
|
||||
ref->push();
|
||||
Fixture * f = (Fixture *)Memoizer::find(fixture);
|
||||
if (!f) throw love::Exception("A fixture has escaped Memoizer!");
|
||||
if (!f)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
f->retain();
|
||||
luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void*)f);
|
||||
b2Vec2 scaledPoint = Physics::scaleUp(point);
|
||||
@@ -182,23 +184,42 @@ namespace box2d
|
||||
return 0;
|
||||
}
|
||||
|
||||
void World::SayGoodbye(b2Fixture* fixture)
|
||||
{
|
||||
Fixture * f = (Fixture *)Memoizer::find(fixture);
|
||||
// Hint implicit destruction with true.
|
||||
if (f) f->destroy(true);
|
||||
}
|
||||
|
||||
void World::SayGoodbye(b2Joint* joint)
|
||||
{
|
||||
Joint * j = (Joint *)Memoizer::find(joint);
|
||||
// Hint implicit destruction with true.
|
||||
if (j) j->destroyJoint(true);
|
||||
}
|
||||
|
||||
World::World()
|
||||
: world(NULL)
|
||||
: world(NULL), destructWorld(false)
|
||||
{
|
||||
world = new b2World(b2Vec2(0,0));
|
||||
this->retain(); // The Box2D world holds a reference to this World.
|
||||
world->SetAllowSleeping(true);
|
||||
world->SetContactListener(this);
|
||||
world->SetDestructionListener(this);
|
||||
b2BodyDef def;
|
||||
groundBody = world->CreateBody(&def);
|
||||
Memoizer::add(world, this);
|
||||
}
|
||||
|
||||
World::World(b2Vec2 gravity, bool sleep)
|
||||
: world(NULL)
|
||||
: world(NULL), destructWorld(false)
|
||||
{
|
||||
world = new b2World(Physics::scaleDown(gravity));
|
||||
// The Box2D world holds a reference to this World.
|
||||
this->retain();
|
||||
world->SetAllowSleeping(sleep);
|
||||
world->SetContactListener(this);
|
||||
world->SetDestructionListener(this);
|
||||
b2BodyDef def;
|
||||
groundBody = world->CreateBody(&def);
|
||||
Memoizer::add(world, this);
|
||||
@@ -206,22 +227,43 @@ namespace box2d
|
||||
|
||||
World::~World()
|
||||
{
|
||||
world->DestroyBody(groundBody);
|
||||
Memoizer::remove(world);
|
||||
delete world;
|
||||
}
|
||||
|
||||
void World::update(float dt)
|
||||
{
|
||||
world->Step(dt, 8, 6);
|
||||
|
||||
// Really destroy all marked bodies.
|
||||
// Destroy all objects marked during the time step.
|
||||
if (destructWorld)
|
||||
{
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::vector<Body*>::iterator i = destructBodies.begin(); i < destructBodies.end(); i++)
|
||||
{
|
||||
Body * b = *i;
|
||||
if (b->body != 0) b->destroy();
|
||||
// Release for reference in vector.
|
||||
b->release();
|
||||
}
|
||||
for (std::vector<Fixture*>::iterator i = destructFixtures.begin(); i < destructFixtures.end(); i++)
|
||||
{
|
||||
Fixture * f = *i;
|
||||
if (f->isValid()) f->destroy();
|
||||
// Release for reference in vector.
|
||||
f->release();
|
||||
}
|
||||
for (std::vector<Joint*>::iterator i = destructJoints.begin(); i < destructJoints.end(); i++)
|
||||
{
|
||||
Joint * j = *i;
|
||||
if (j->isValid()) j->destroyJoint();
|
||||
// Release for reference in vector.
|
||||
j->release();
|
||||
}
|
||||
destructBodies.clear();
|
||||
destructFixtures.clear();
|
||||
destructJoints.clear();
|
||||
}
|
||||
|
||||
void World::BeginContact(b2Contact* contact)
|
||||
@@ -249,14 +291,21 @@ namespace box2d
|
||||
{
|
||||
// Fixtures should be memoized, if we created them
|
||||
Fixture * a = (Fixture *)Memoizer::find(fixtureA);
|
||||
if (!a) throw love::Exception("A fixture has escaped Memoizer!");
|
||||
if (!a)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
a->retain();
|
||||
Fixture * b = (Fixture *)Memoizer::find(fixtureB);
|
||||
if (!b) throw love::Exception("A fixture has escaped Memoizer!");
|
||||
if (!b)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
b->retain();
|
||||
return filter.process(a, b);
|
||||
}
|
||||
|
||||
bool World::isValid() const
|
||||
{
|
||||
return world != 0;
|
||||
}
|
||||
|
||||
int World::setCallbacks(lua_State * L)
|
||||
{
|
||||
int n = lua_gettop(L);
|
||||
@@ -265,16 +314,20 @@ namespace box2d
|
||||
switch(n)
|
||||
{
|
||||
case 4:
|
||||
if (postsolve.ref) delete postsolve.ref;
|
||||
if (postsolve.ref)
|
||||
delete postsolve.ref;
|
||||
postsolve.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
case 3:
|
||||
if (presolve.ref) delete presolve.ref;
|
||||
if (presolve.ref)
|
||||
delete presolve.ref;
|
||||
presolve.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
case 2:
|
||||
if (end.ref) delete end.ref;
|
||||
if (end.ref)
|
||||
delete end.ref;
|
||||
end.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
case 1:
|
||||
if (begin.ref) delete begin.ref;
|
||||
if (begin.ref)
|
||||
delete begin.ref;
|
||||
begin.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
}
|
||||
|
||||
@@ -293,7 +346,8 @@ namespace box2d
|
||||
int World::setContactFilter(lua_State * L)
|
||||
{
|
||||
luax_assert_argc(L, 1);
|
||||
if (filter.ref) delete filter.ref;
|
||||
if (filter.ref)
|
||||
delete filter.ref;
|
||||
filter.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
return 0;
|
||||
}
|
||||
@@ -353,10 +407,13 @@ namespace box2d
|
||||
b2Body * b = world->GetBodyList();
|
||||
int i = 1;
|
||||
do {
|
||||
if (!b) break;
|
||||
if (b == groundBody) continue;
|
||||
if (!b)
|
||||
break;
|
||||
if (b == groundBody)
|
||||
continue;
|
||||
Body * body = (Body *)Memoizer::find(b);
|
||||
if (!body) throw love::Exception("A body has escaped Memoizer!");
|
||||
if (!body)
|
||||
throw love::Exception("A body has escaped Memoizer!");
|
||||
body->retain();
|
||||
luax_newtype(L, "Body", PHYSICS_BODY_T, (void*)body);
|
||||
lua_rawseti(L, -2, i);
|
||||
@@ -429,15 +486,42 @@ namespace box2d
|
||||
float y2 = (float)luaL_checknumber(L, 4);
|
||||
b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1));
|
||||
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
|
||||
if (raycast.ref) delete raycast.ref;
|
||||
if (raycast.ref)
|
||||
delete raycast.ref;
|
||||
raycast.ref = luax_refif(L, LUA_TFUNCTION);
|
||||
world->RayCast(&raycast, v1, v2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void World::destroyBody(Body * b)
|
||||
void World::destroy()
|
||||
{
|
||||
destructBodies.push_back(b);
|
||||
if (world->IsLocked())
|
||||
{
|
||||
destructWorld = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Cleaning up the world.
|
||||
b2Body * b = world->GetBodyList();
|
||||
while (b)
|
||||
{
|
||||
b2Body * t = b;
|
||||
b = b->GetNext();
|
||||
if (t == groundBody)
|
||||
continue;
|
||||
Body * body = (Body *)Memoizer::find(t);
|
||||
if (!body)
|
||||
throw love::Exception("A body has escaped Memoizer!");
|
||||
body->destroy();
|
||||
}
|
||||
|
||||
world->DestroyBody(groundBody);
|
||||
Memoizer::remove(world);
|
||||
delete world;
|
||||
world = 0;
|
||||
|
||||
// Box2D world destroyed. Release its reference.
|
||||
this->release();
|
||||
}
|
||||
|
||||
} // box2d
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace box2d
|
||||
class Contact;
|
||||
class Body;
|
||||
class Fixture;
|
||||
class Joint;
|
||||
|
||||
/**
|
||||
* The World is the "God" container class,
|
||||
@@ -54,13 +55,14 @@ namespace box2d
|
||||
* The world also controls global parameters, like
|
||||
* gravity.
|
||||
**/
|
||||
class World : public Object, public b2ContactListener, public b2ContactFilter
|
||||
class World : public Object, public b2ContactListener, public b2ContactFilter, public b2DestructionListener
|
||||
{
|
||||
// Friends.
|
||||
friend class Joint;
|
||||
friend class DistanceJoint;
|
||||
friend class MouseJoint;
|
||||
friend class Body;
|
||||
friend class Fixture;
|
||||
|
||||
public:
|
||||
|
||||
@@ -110,6 +112,9 @@ namespace box2d
|
||||
|
||||
// The list of to be destructed bodies.
|
||||
std::vector<Body*> destructBodies;
|
||||
std::vector<Fixture*> destructFixtures;
|
||||
std::vector<Joint*> destructJoints;
|
||||
bool destructWorld;
|
||||
|
||||
// Contact callbacks.
|
||||
ContactCallback begin, end, presolve, postsolve;
|
||||
@@ -152,6 +157,15 @@ namespace box2d
|
||||
// From b2ContactFilter
|
||||
bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB);
|
||||
|
||||
// From b2DestructionListener
|
||||
void SayGoodbye(b2Fixture* fixture);
|
||||
void SayGoodbye(b2Joint* joint);
|
||||
|
||||
/**
|
||||
* Returns true if the Box2D world is alive.
|
||||
**/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Receives up to four Lua functions as arguments. Each function is
|
||||
* collision callback for the four events (in order): begin, end,
|
||||
@@ -261,10 +275,9 @@ namespace box2d
|
||||
int rayCast(lua_State * L);
|
||||
|
||||
/**
|
||||
* Mark a body for destruction.
|
||||
* To be called from Body
|
||||
* Destroy this world.
|
||||
**/
|
||||
void destroyBody(Body * b);
|
||||
void destroy();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
Body * luax_checkbody(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<Body>(L, idx, "Body", PHYSICS_BODY_T);
|
||||
Body * b = luax_checktype<Body>(L, idx, "Body", PHYSICS_BODY_T);
|
||||
if (b->body == 0)
|
||||
luaL_error(L, "Attempt to use destroyed body.");
|
||||
return b;
|
||||
}
|
||||
|
||||
int w_Body_getX(lua_State * L)
|
||||
@@ -509,12 +512,15 @@ namespace box2d
|
||||
|
||||
int w_Body_destroy(lua_State * L)
|
||||
{
|
||||
Proxy * p = (Proxy *)lua_touserdata(L, 1);
|
||||
p->own = false;
|
||||
|
||||
Body * t = (Body *)p->data;
|
||||
t->destroy();
|
||||
|
||||
Body * t = luax_checkbody(L, 1);
|
||||
try
|
||||
{
|
||||
t->destroy();
|
||||
}
|
||||
catch (love::Exception & e)
|
||||
{
|
||||
luaL_error(L, "%s", e.what());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
DistanceJoint * luax_checkdistancejoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<DistanceJoint>(L, idx, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T);
|
||||
DistanceJoint * j = luax_checktype<DistanceJoint>(L, idx, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_DistanceJoint_setLength(lua_State * L)
|
||||
|
||||
@@ -29,7 +29,10 @@ namespace box2d
|
||||
{
|
||||
Fixture * luax_checkfixture(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<Fixture>(L, idx, "Fixture", PHYSICS_FIXTURE_T);
|
||||
Fixture * f = luax_checktype<Fixture>(L, idx, "Fixture", PHYSICS_FIXTURE_T);
|
||||
if (!f->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed fixture.");
|
||||
return f;
|
||||
}
|
||||
|
||||
int w_Fixture_getType(lua_State * L)
|
||||
@@ -251,11 +254,15 @@ namespace box2d
|
||||
|
||||
int w_Fixture_destroy(lua_State * L)
|
||||
{
|
||||
Proxy * p = (Proxy *)lua_touserdata(L, 1);
|
||||
p->own = false;
|
||||
|
||||
Fixture * t = (Fixture *)p->data;
|
||||
t->release();
|
||||
Fixture * t = luax_checkfixture(L, 1);
|
||||
try
|
||||
{
|
||||
t->destroy();
|
||||
}
|
||||
catch (love::Exception & e)
|
||||
{
|
||||
luaL_error(L, "%s", e.what());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
FrictionJoint * luax_checkfrictionjoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<FrictionJoint>(L, idx, "FrictionJoint", PHYSICS_FRICTION_JOINT_T);
|
||||
FrictionJoint * j = luax_checktype<FrictionJoint>(L, idx, "FrictionJoint", PHYSICS_FRICTION_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_FrictionJoint_setMaxForce(lua_State * L)
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
GearJoint * luax_checkgearjoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<GearJoint>(L, idx, "GearJoint", PHYSICS_GEAR_JOINT_T);
|
||||
GearJoint * j = luax_checktype<GearJoint>(L, idx, "GearJoint", PHYSICS_GEAR_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_GearJoint_setRatio(lua_State * L)
|
||||
|
||||
@@ -30,7 +30,10 @@ namespace box2d
|
||||
{
|
||||
Joint * luax_checkjoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<Joint>(L, idx, "Joint", PHYSICS_JOINT_T);
|
||||
Joint * t = luax_checktype<Joint>(L, idx, "Joint", PHYSICS_JOINT_T);
|
||||
if (!t->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return t;
|
||||
}
|
||||
|
||||
int w_Joint_getType(lua_State * L)
|
||||
@@ -73,12 +76,15 @@ namespace box2d
|
||||
|
||||
int w_Joint_destroy(lua_State * L)
|
||||
{
|
||||
Proxy * p = (Proxy *)lua_touserdata(L, 1);
|
||||
p->own = false;
|
||||
|
||||
Joint * t = (Joint *)p->data;
|
||||
t->release();
|
||||
|
||||
Joint * t = luax_checkjoint(L, 1);
|
||||
try
|
||||
{
|
||||
t->destroyJoint();
|
||||
}
|
||||
catch (love::Exception & e)
|
||||
{
|
||||
luaL_error(L, "%s", e.what());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
MouseJoint * luax_checkmousejoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<MouseJoint>(L, idx, "MouseJoint", PHYSICS_MOUSE_JOINT_T);
|
||||
MouseJoint * j = luax_checktype<MouseJoint>(L, idx, "MouseJoint", PHYSICS_MOUSE_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_MouseJoint_setTarget(lua_State * L)
|
||||
|
||||
@@ -378,7 +378,7 @@ namespace box2d
|
||||
{
|
||||
Physics::setMeter(arg1);
|
||||
}
|
||||
catch (love::Exception e)
|
||||
catch (love::Exception & e)
|
||||
{
|
||||
return luaL_error(L, e.what());
|
||||
}
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
PrismaticJoint * luax_checkprismaticjoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<PrismaticJoint>(L, idx, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T);
|
||||
PrismaticJoint * j = luax_checktype<PrismaticJoint>(L, idx, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_PrismaticJoint_getJointTranslation(lua_State * L)
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
PulleyJoint * luax_checkpulleyjoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<PulleyJoint>(L, idx, "PulleyJoint", PHYSICS_PULLEY_JOINT_T);
|
||||
PulleyJoint * j = luax_checktype<PulleyJoint>(L, idx, "PulleyJoint", PHYSICS_PULLEY_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_PulleyJoint_getGroundAnchors(lua_State * L)
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
RevoluteJoint * luax_checkrevolutejoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<RevoluteJoint>(L, idx, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T);
|
||||
RevoluteJoint * j = luax_checktype<RevoluteJoint>(L, idx, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_RevoluteJoint_getJointAngle(lua_State * L)
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
RopeJoint * luax_checkropejoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<RopeJoint>(L, idx, "RopeJoint", PHYSICS_ROPE_JOINT_T);
|
||||
RopeJoint * j = luax_checktype<RopeJoint>(L, idx, "RopeJoint", PHYSICS_ROPE_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_RopeJoint_getMaxLength(lua_State * L)
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
WeldJoint * luax_checkweldjoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<WeldJoint>(L, idx, "WeldJoint", PHYSICS_WELD_JOINT_T);
|
||||
WeldJoint * j = luax_checktype<WeldJoint>(L, idx, "WeldJoint", PHYSICS_WELD_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_WeldJoint_setFrequency(lua_State * L)
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace box2d
|
||||
{
|
||||
WheelJoint * luax_checkwheeljoint(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<WheelJoint>(L, idx, "WheelJoint", PHYSICS_WHEEL_JOINT_T);
|
||||
WheelJoint * j = luax_checktype<WheelJoint>(L, idx, "WheelJoint", PHYSICS_WHEEL_JOINT_T);
|
||||
if (!j->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed joint.");
|
||||
return j;
|
||||
}
|
||||
|
||||
int w_WheelJoint_getJointTranslation(lua_State * L)
|
||||
|
||||
@@ -29,7 +29,10 @@ namespace box2d
|
||||
|
||||
World * luax_checkworld(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<World>(L, idx, "World", PHYSICS_WORLD_T);
|
||||
World * w = luax_checktype<World>(L, idx, "World", PHYSICS_WORLD_T);
|
||||
if (!w->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed world.");
|
||||
return w;
|
||||
}
|
||||
|
||||
int w_World_update(lua_State * L)
|
||||
@@ -162,6 +165,21 @@ namespace box2d
|
||||
ASSERT_GUARD(return t->rayCast(L);)
|
||||
}
|
||||
|
||||
int w_World_destroy(lua_State * L)
|
||||
{
|
||||
World * t = luax_checkworld(L, 1);
|
||||
try
|
||||
{
|
||||
t->destroy();
|
||||
}
|
||||
catch (love::Exception & e)
|
||||
{
|
||||
luaL_error(L, "%s", e.what());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg functions[] = {
|
||||
{ "update", w_World_update },
|
||||
{ "setCallbacks", w_World_setCallbacks },
|
||||
@@ -181,6 +199,7 @@ namespace box2d
|
||||
{ "getContactList", w_World_getContactList },
|
||||
{ "queryBoundingBox", w_World_queryBoundingBox },
|
||||
{ "rayCast", w_World_rayCast },
|
||||
{ "destroy", w_World_destroy },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
// LOVE
|
||||
#include <common/runtime.h>
|
||||
#include <common/Exception.h>
|
||||
#include "World.h"
|
||||
#include "wrap_Physics.h"
|
||||
|
||||
@@ -51,6 +52,7 @@ namespace box2d
|
||||
int w_World_getContactList(lua_State * L);
|
||||
int w_World_queryBoundingBox(lua_State * L);
|
||||
int w_World_rayCast(lua_State * L);
|
||||
int w_World_destroy(lua_State * L);
|
||||
extern "C" int luaopen_world(lua_State * L);
|
||||
|
||||
} // box2d
|
||||
|
||||
Reference in New Issue
Block a user