Browse Source

Add ContactFilter callback to World

--HG--
branch : box2d-update
Bill Meltsner 14 years ago
parent
commit
7e039dd1ef

+ 49 - 0
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)
 	{

+ 25 - 1
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.

+ 16 - 0
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 },

+ 2 - 0
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);