diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index d7423e9f9..dc368517f 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -117,6 +117,31 @@ namespace box2d } } + + World::ContactFilter::ContactFilter() + : ref(0) + { + } + + World::ContactFilter::~ContactFilter() + { + if(ref != 0) + delete ref; + } + + bool World::ContactFilter::process(Fixture * a, Fixture * b) + { + if (ref != 0) + { + lua_State * L = ref->getL(); + ref->push(); + luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void*)a); + luax_newtype(L, "Fixture", PHYSICS_FIXTURE_T, (void*)b); + lua_call(L, 2, 1); + return luax_toboolean(L, -1); + } + return true; + } World::World() : world(NULL) @@ -178,6 +203,16 @@ namespace box2d { postsolve.add(contact, impulse); } + + bool World::ShouldCollide(b2Fixture * fixtureA, b2Fixture * fixtureB) + { + // Fixtures should be memoized, if we created them + Fixture * a = (Fixture *)Memoizer::find(fixtureA); + if (!a) throw love::Exception("A fixture has escaped Memoizer!"); + Fixture * b = (Fixture *)Memoizer::find(fixtureB); + if (!b) throw love::Exception("A fixture has escaped Memoizer!"); + return filter.process(a, b); + } int World::setCallbacks(lua_State * L) { @@ -211,6 +246,20 @@ namespace box2d postsolve.ref ? postsolve.ref->push() : lua_pushnil(L); return lua_gettop(L); } + + int World::setContactFilter(lua_State * L) + { + luax_assert_argc(L, 1); + if (filter.ref) delete filter.ref; + filter.ref = luax_refif(L, LUA_TFUNCTION); + return 0; + } + + int World::getContactFilter(lua_State * L) + { + filter.ref ? filter.ref->push() : lua_pushnil(L); + return lua_gettop(L); + } void World::setGravity(float x, float y) { diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index b76eee41c..1798372af 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -40,6 +40,7 @@ namespace box2d { class Contact; + class Fixture; /** * The World is the "God" container class, @@ -52,7 +53,7 @@ namespace box2d * The world also controls global parameters, like * gravity. **/ - class World : public Object, public b2ContactListener + class World : public Object, public b2ContactListener, public b2ContactFilter { // Friends. friend class Joint; @@ -76,6 +77,15 @@ namespace box2d void add(b2Contact* contact, const b2ContactImpulse* impulse); void process(); }; + + class ContactFilter + { + public: + Reference * ref; + ContactFilter(); + ~ContactFilter(); + bool process(Fixture * a, Fixture * b); + }; private: @@ -87,6 +97,7 @@ namespace box2d // Contact callbacks. ContactCallback begin, end, presolve, postsolve; + ContactFilter filter; public: @@ -119,6 +130,9 @@ namespace box2d void EndContact(b2Contact* contact); void PreSolve(b2Contact* contact, const b2Manifold* oldManifold); void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse); + + // From b2ContactFilter + bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB); /** * Receives up to four Lua functions as arguments. Each function is @@ -132,6 +146,16 @@ namespace box2d * Returns the functions previously set by setCallbacks. **/ int getCallbacks(lua_State * L); + + /** + * Sets the ContactFilter callback. + **/ + int setContactFilter(lua_State * L); + + /** + * Gets the ContactFilter callback. + **/ + int getContactFilter(lua_State * L); /** * Sets the current gravity of the World. diff --git a/src/modules/physics/box2d/wrap_World.cpp b/src/modules/physics/box2d/wrap_World.cpp index 4e8f14dc9..febfcfcb4 100644 --- a/src/modules/physics/box2d/wrap_World.cpp +++ b/src/modules/physics/box2d/wrap_World.cpp @@ -53,6 +53,20 @@ namespace box2d lua_remove(L, 1); return t->getCallbacks(L); } + + int w_World_setContactFilter(lua_State * L) + { + World * t = luax_checkworld(L, 1); + lua_remove(L, 1); + return t->setContactFilter(L); + } + + int w_World_getContactFilter(lua_State * L) + { + World * t = luax_checkworld(L, 1); + lua_remove(L, 1); + return t->getContactFilter(L); + } int w_World_setGravity(lua_State * L) { @@ -103,6 +117,8 @@ namespace box2d { "update", w_World_update }, { "setCallbacks", w_World_setCallbacks }, { "getCallbacks", w_World_getCallbacks }, + { "setContactFilter", w_World_setContactFilter }, + { "getContactFilter", w_World_getContactFilter }, { "setGravity", w_World_setGravity }, { "getGravity", w_World_getGravity }, { "setAllowSleeping", w_World_setAllowSleeping }, diff --git a/src/modules/physics/box2d/wrap_World.h b/src/modules/physics/box2d/wrap_World.h index 7f99a7449..372928c22 100644 --- a/src/modules/physics/box2d/wrap_World.h +++ b/src/modules/physics/box2d/wrap_World.h @@ -35,6 +35,8 @@ namespace box2d int w_World_update(lua_State * L); int w_World_setCallbacks(lua_State * L); int w_World_getCallbacks(lua_State * L); + int w_World_setContactFilter(lua_State * L); + int w_World_getContactFilter(lua_State * L); int w_World_setGravity(lua_State * L); int w_World_getGravity(lua_State * L); int w_World_setAllowSleeping(lua_State * L);