diff --git a/src/modules/physics/box2d/Body.cpp b/src/modules/physics/box2d/Body.cpp index 8c786a3be..cf6ff1166 100644 --- a/src/modules/physics/box2d/Body.cpp +++ b/src/modules/physics/box2d/Body.cpp @@ -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 diff --git a/src/modules/physics/box2d/Body.h b/src/modules/physics/box2d/Body.h index cecabcdfe..57aa4916b 100644 --- a/src/modules/physics/box2d/Body.h +++ b/src/modules/physics/box2d/Body.h @@ -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(); diff --git a/src/modules/physics/box2d/DistanceJoint.cpp b/src/modules/physics/box2d/DistanceJoint.cpp index 02ece9c91..d08cd402b 100644 --- a/src/modules/physics/box2d/DistanceJoint.cpp +++ b/src/modules/physics/box2d/DistanceJoint.cpp @@ -42,8 +42,6 @@ namespace box2d DistanceJoint::~DistanceJoint() { - destroyJoint(joint); - joint = 0; } void DistanceJoint::setLength(float length) diff --git a/src/modules/physics/box2d/Fixture.cpp b/src/modules/physics/box2d/Fixture.cpp index 38e49949e..641cc5107 100644 --- a/src/modules/physics/box2d/Fixture.cpp +++ b/src/modules/physics/box2d/Fixture.cpp @@ -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 diff --git a/src/modules/physics/box2d/Fixture.h b/src/modules/physics/box2d/Fixture.h index 0d875d2a6..4a39fbfef 100644 --- a/src/modules/physics/box2d/Fixture.h +++ b/src/modules/physics/box2d/Fixture.h @@ -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 diff --git a/src/modules/physics/box2d/FrictionJoint.cpp b/src/modules/physics/box2d/FrictionJoint.cpp index c6ee5f43d..705480943 100644 --- a/src/modules/physics/box2d/FrictionJoint.cpp +++ b/src/modules/physics/box2d/FrictionJoint.cpp @@ -45,8 +45,6 @@ namespace box2d FrictionJoint::~FrictionJoint() { - destroyJoint(joint); - joint = 0; } void FrictionJoint::setMaxForce(float force) diff --git a/src/modules/physics/box2d/GearJoint.cpp b/src/modules/physics/box2d/GearJoint.cpp index 1e2d5f10e..a182ee016 100644 --- a/src/modules/physics/box2d/GearJoint.cpp +++ b/src/modules/physics/box2d/GearJoint.cpp @@ -46,8 +46,6 @@ namespace box2d GearJoint::~GearJoint() { - destroyJoint(joint); - joint = 0; } void GearJoint::setRatio(float ratio) diff --git a/src/modules/physics/box2d/Joint.cpp b/src/modules/physics/box2d/Joint.cpp index 2c4cee80b..c01ead763 100644 --- a/src/modules/physics/box2d/Joint.cpp +++ b/src/modules/physics/box2d/Joint.cpp @@ -23,11 +23,15 @@ // STD #include +// LOVE +#include + // 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 diff --git a/src/modules/physics/box2d/Joint.h b/src/modules/physics/box2d/Joint.h index 3eaabc655..726e1a9a9 100644 --- a/src/modules/physics/box2d/Joint.h +++ b/src/modules/physics/box2d/Joint.h @@ -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 diff --git a/src/modules/physics/box2d/MouseJoint.cpp b/src/modules/physics/box2d/MouseJoint.cpp index 958a7bd8d..b285750c9 100644 --- a/src/modules/physics/box2d/MouseJoint.cpp +++ b/src/modules/physics/box2d/MouseJoint.cpp @@ -45,8 +45,6 @@ namespace box2d MouseJoint::~MouseJoint() { - destroyJoint(joint); - joint = 0; } void MouseJoint::setTarget(float x, float y) diff --git a/src/modules/physics/box2d/PrismaticJoint.cpp b/src/modules/physics/box2d/PrismaticJoint.cpp index 52db2c1d1..093a7748c 100644 --- a/src/modules/physics/box2d/PrismaticJoint.cpp +++ b/src/modules/physics/box2d/PrismaticJoint.cpp @@ -47,8 +47,6 @@ namespace box2d PrismaticJoint::~PrismaticJoint() { - destroyJoint(joint); - joint = 0; } float PrismaticJoint::getJointTranslation() const diff --git a/src/modules/physics/box2d/PulleyJoint.cpp b/src/modules/physics/box2d/PulleyJoint.cpp index ef43d3ec4..2e77b7f95 100644 --- a/src/modules/physics/box2d/PulleyJoint.cpp +++ b/src/modules/physics/box2d/PulleyJoint.cpp @@ -44,8 +44,6 @@ namespace box2d PulleyJoint::~PulleyJoint() { - destroyJoint(joint); - joint = 0; } int PulleyJoint::getGroundAnchors(lua_State * L) diff --git a/src/modules/physics/box2d/RevoluteJoint.cpp b/src/modules/physics/box2d/RevoluteJoint.cpp index 34621ce23..baf1a39e0 100644 --- a/src/modules/physics/box2d/RevoluteJoint.cpp +++ b/src/modules/physics/box2d/RevoluteJoint.cpp @@ -44,8 +44,6 @@ namespace box2d RevoluteJoint::~RevoluteJoint() { - destroyJoint(joint); - joint = 0; } float RevoluteJoint::getJointAngle() const diff --git a/src/modules/physics/box2d/RopeJoint.cpp b/src/modules/physics/box2d/RopeJoint.cpp index 183677f0b..780fcc862 100644 --- a/src/modules/physics/box2d/RopeJoint.cpp +++ b/src/modules/physics/box2d/RopeJoint.cpp @@ -46,8 +46,6 @@ namespace box2d RopeJoint::~RopeJoint() { - destroyJoint(joint); - joint = 0; } float RopeJoint::getMaxLength() const diff --git a/src/modules/physics/box2d/WeldJoint.cpp b/src/modules/physics/box2d/WeldJoint.cpp index 87b4c9539..5890c944f 100644 --- a/src/modules/physics/box2d/WeldJoint.cpp +++ b/src/modules/physics/box2d/WeldJoint.cpp @@ -45,8 +45,6 @@ namespace box2d WeldJoint::~WeldJoint() { - destroyJoint(joint); - joint = 0; } void WeldJoint::setFrequency(float hz) diff --git a/src/modules/physics/box2d/WheelJoint.cpp b/src/modules/physics/box2d/WheelJoint.cpp index c3e16e428..85c1dc518 100644 --- a/src/modules/physics/box2d/WheelJoint.cpp +++ b/src/modules/physics/box2d/WheelJoint.cpp @@ -44,8 +44,6 @@ namespace box2d WheelJoint::~WheelJoint() { - destroyJoint(joint); - joint = 0; } float WheelJoint::getJointTranslation() const diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index fbe95b133..6ad8c146d 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -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::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::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::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 diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index aa307a26c..eab6bb848 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -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 destructBodies; + std::vector destructFixtures; + std::vector 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(); }; diff --git a/src/modules/physics/box2d/wrap_Body.cpp b/src/modules/physics/box2d/wrap_Body.cpp index 89a0a11fc..915698115 100644 --- a/src/modules/physics/box2d/wrap_Body.cpp +++ b/src/modules/physics/box2d/wrap_Body.cpp @@ -28,7 +28,10 @@ namespace box2d { Body * luax_checkbody(lua_State * L, int idx) { - return luax_checktype(L, idx, "Body", PHYSICS_BODY_T); + Body * b = luax_checktype(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; } diff --git a/src/modules/physics/box2d/wrap_DistanceJoint.cpp b/src/modules/physics/box2d/wrap_DistanceJoint.cpp index f7618ecfc..db5304a00 100644 --- a/src/modules/physics/box2d/wrap_DistanceJoint.cpp +++ b/src/modules/physics/box2d/wrap_DistanceJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { DistanceJoint * luax_checkdistancejoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T); + DistanceJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_Fixture.cpp b/src/modules/physics/box2d/wrap_Fixture.cpp index 8555811f6..5236ac55b 100644 --- a/src/modules/physics/box2d/wrap_Fixture.cpp +++ b/src/modules/physics/box2d/wrap_Fixture.cpp @@ -29,7 +29,10 @@ namespace box2d { Fixture * luax_checkfixture(lua_State * L, int idx) { - return luax_checktype(L, idx, "Fixture", PHYSICS_FIXTURE_T); + Fixture * f = luax_checktype(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; } diff --git a/src/modules/physics/box2d/wrap_FrictionJoint.cpp b/src/modules/physics/box2d/wrap_FrictionJoint.cpp index 74de2a0e0..1f972d474 100644 --- a/src/modules/physics/box2d/wrap_FrictionJoint.cpp +++ b/src/modules/physics/box2d/wrap_FrictionJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { FrictionJoint * luax_checkfrictionjoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "FrictionJoint", PHYSICS_FRICTION_JOINT_T); + FrictionJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_GearJoint.cpp b/src/modules/physics/box2d/wrap_GearJoint.cpp index 68217f834..aa664d87b 100644 --- a/src/modules/physics/box2d/wrap_GearJoint.cpp +++ b/src/modules/physics/box2d/wrap_GearJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { GearJoint * luax_checkgearjoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "GearJoint", PHYSICS_GEAR_JOINT_T); + GearJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_Joint.cpp b/src/modules/physics/box2d/wrap_Joint.cpp index 3c45a60fb..13fb4cf88 100644 --- a/src/modules/physics/box2d/wrap_Joint.cpp +++ b/src/modules/physics/box2d/wrap_Joint.cpp @@ -30,7 +30,10 @@ namespace box2d { Joint * luax_checkjoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "Joint", PHYSICS_JOINT_T); + Joint * t = luax_checktype(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; } diff --git a/src/modules/physics/box2d/wrap_MouseJoint.cpp b/src/modules/physics/box2d/wrap_MouseJoint.cpp index 5a21ab93d..5267fe0d7 100644 --- a/src/modules/physics/box2d/wrap_MouseJoint.cpp +++ b/src/modules/physics/box2d/wrap_MouseJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { MouseJoint * luax_checkmousejoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "MouseJoint", PHYSICS_MOUSE_JOINT_T); + MouseJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_Physics.cpp b/src/modules/physics/box2d/wrap_Physics.cpp index c872b737d..9b9d02a04 100644 --- a/src/modules/physics/box2d/wrap_Physics.cpp +++ b/src/modules/physics/box2d/wrap_Physics.cpp @@ -378,7 +378,7 @@ namespace box2d { Physics::setMeter(arg1); } - catch (love::Exception e) + catch (love::Exception & e) { return luaL_error(L, e.what()); } diff --git a/src/modules/physics/box2d/wrap_PrismaticJoint.cpp b/src/modules/physics/box2d/wrap_PrismaticJoint.cpp index ddde69574..ed0df4e52 100644 --- a/src/modules/physics/box2d/wrap_PrismaticJoint.cpp +++ b/src/modules/physics/box2d/wrap_PrismaticJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { PrismaticJoint * luax_checkprismaticjoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T); + PrismaticJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_PulleyJoint.cpp b/src/modules/physics/box2d/wrap_PulleyJoint.cpp index eec714590..f956cf699 100644 --- a/src/modules/physics/box2d/wrap_PulleyJoint.cpp +++ b/src/modules/physics/box2d/wrap_PulleyJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { PulleyJoint * luax_checkpulleyjoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "PulleyJoint", PHYSICS_PULLEY_JOINT_T); + PulleyJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_RevoluteJoint.cpp b/src/modules/physics/box2d/wrap_RevoluteJoint.cpp index 901dd7bb1..c52e9b443 100644 --- a/src/modules/physics/box2d/wrap_RevoluteJoint.cpp +++ b/src/modules/physics/box2d/wrap_RevoluteJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { RevoluteJoint * luax_checkrevolutejoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T); + RevoluteJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_RopeJoint.cpp b/src/modules/physics/box2d/wrap_RopeJoint.cpp index 04c1c0092..e6e6d4dc9 100644 --- a/src/modules/physics/box2d/wrap_RopeJoint.cpp +++ b/src/modules/physics/box2d/wrap_RopeJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { RopeJoint * luax_checkropejoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "RopeJoint", PHYSICS_ROPE_JOINT_T); + RopeJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_WeldJoint.cpp b/src/modules/physics/box2d/wrap_WeldJoint.cpp index d15fa68ee..6fc934992 100644 --- a/src/modules/physics/box2d/wrap_WeldJoint.cpp +++ b/src/modules/physics/box2d/wrap_WeldJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { WeldJoint * luax_checkweldjoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "WeldJoint", PHYSICS_WELD_JOINT_T); + WeldJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_WheelJoint.cpp b/src/modules/physics/box2d/wrap_WheelJoint.cpp index b5d48723a..a9ab98afd 100644 --- a/src/modules/physics/box2d/wrap_WheelJoint.cpp +++ b/src/modules/physics/box2d/wrap_WheelJoint.cpp @@ -28,7 +28,10 @@ namespace box2d { WheelJoint * luax_checkwheeljoint(lua_State * L, int idx) { - return luax_checktype(L, idx, "WheelJoint", PHYSICS_WHEEL_JOINT_T); + WheelJoint * j = luax_checktype(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) diff --git a/src/modules/physics/box2d/wrap_World.cpp b/src/modules/physics/box2d/wrap_World.cpp index c509a2c7c..af373d24e 100644 --- a/src/modules/physics/box2d/wrap_World.cpp +++ b/src/modules/physics/box2d/wrap_World.cpp @@ -29,7 +29,10 @@ namespace box2d World * luax_checkworld(lua_State * L, int idx) { - return luax_checktype(L, idx, "World", PHYSICS_WORLD_T); + World * w = luax_checktype(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 } }; diff --git a/src/modules/physics/box2d/wrap_World.h b/src/modules/physics/box2d/wrap_World.h index 64c9fdfcc..ad1835957 100644 --- a/src/modules/physics/box2d/wrap_World.h +++ b/src/modules/physics/box2d/wrap_World.h @@ -23,6 +23,7 @@ // LOVE #include +#include #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