Browse Source

Added Contact:getFixtures and Body:getContactList (see issue #905).

The list of Contacts associated with bodies changes during World:update (potentially multiple times), so you might miss collisions if you don't use the World callbacks at all.
Alex Szpakowski 11 years ago
parent
commit
9ab9a393d5

+ 24 - 0
src/modules/physics/box2d/Body.cpp

@@ -444,6 +444,30 @@ int Body::getFixtureList(lua_State *L) const
 	return 1;
 	return 1;
 }
 }
 
 
+int Body::getContactList(lua_State *L) const
+{
+	lua_newtable(L);
+	const b2ContactEdge *ce = body->GetContactList();
+	int i = 1;
+	do
+	{
+		if (!ce)
+			break;
+
+		Contact *contact = (Contact *) Memoizer::find(ce->contact);
+		if (!contact)
+			contact = new Contact(ce->contact);
+		else
+			contact->retain();
+		
+		luax_pushtype(L, "Contact", PHYSICS_CONTACT_T, contact);
+		lua_rawseti(L, -2, i);
+		i++;
+	}
+	while ((ce = ce->next));
+	return 1;
+}
+
 b2Vec2 Body::getVector(lua_State *L)
 b2Vec2 Body::getVector(lua_State *L)
 {
 {
 	love::luax_assert_argc(L, 2, 2);
 	love::luax_assert_argc(L, 2, 2);

+ 7 - 0
src/modules/physics/box2d/Body.h

@@ -393,6 +393,13 @@ public:
 	 **/
 	 **/
 	int getFixtureList(lua_State *L) const;
 	int getFixtureList(lua_State *L) const;
 
 
+	/**
+	 * Get an array of all active Contacts attached to this Body.
+	 * This list changes during World:update and you may miss some collisions
+	 * if you don't use the collision callbacks.
+	 **/
+	int getContactList(lua_State *L) const;
+
 	/**
 	/**
 	 * Destroy this body.
 	 * Destroy this body.
 	 **/
 	 **/

+ 9 - 0
src/modules/physics/box2d/Contact.cpp

@@ -142,6 +142,15 @@ void Contact::getChildren(int &childA, int &childB)
 	childB = contact->GetChildIndexB();
 	childB = contact->GetChildIndexB();
 }
 }
 
 
+void Contact::getFixtures(Fixture *&fixtureA, Fixture *&fixtureB)
+{
+	fixtureA = (Fixture *) Memoizer::find(contact->GetFixtureA());
+	fixtureB = (Fixture *) Memoizer::find(contact->GetFixtureB());
+
+	if (!fixtureA || !fixtureB)
+		throw love::Exception("A fixture has escaped Memoizer!");
+}
+
 } // box2d
 } // box2d
 } // physics
 } // physics
 } // love
 } // love

+ 5 - 0
src/modules/physics/box2d/Contact.h

@@ -148,6 +148,11 @@ public:
 
 
 	void getChildren(int &childA, int &childB);
 	void getChildren(int &childA, int &childB);
 
 
+	/**
+	 * Gets the Fixtures associated with this Contact.
+	 **/
+	void getFixtures(Fixture *&fixtureA, Fixture *&fixtureB);
+
 private:
 private:
 
 
 	// The Box2D contact.
 	// The Box2D contact.

+ 1 - 3
src/modules/physics/box2d/World.cpp

@@ -318,10 +318,8 @@ bool World::ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB)
 {
 {
 	// Fixtures should be memoized, if we created them
 	// Fixtures should be memoized, if we created them
 	Fixture *a = (Fixture *)Memoizer::find(fixtureA);
 	Fixture *a = (Fixture *)Memoizer::find(fixtureA);
-	if (!a)
-		throw love::Exception("A fixture has escaped Memoizer!");
 	Fixture *b = (Fixture *)Memoizer::find(fixtureB);
 	Fixture *b = (Fixture *)Memoizer::find(fixtureB);
-	if (!b)
+	if (!a || !b)
 		throw love::Exception("A fixture has escaped Memoizer!");
 		throw love::Exception("A fixture has escaped Memoizer!");
 	return filter.process(a, b);
 	return filter.process(a, b);
 }
 }

+ 10 - 0
src/modules/physics/box2d/wrap_Body.cpp

@@ -540,6 +540,15 @@ int w_Body_getFixtureList(lua_State *L)
 	return n;
 	return n;
 }
 }
 
 
+int w_Body_getContactList(lua_State *L)
+{
+	Body *t = luax_checkbody(L, 1);
+	lua_remove(L, 1);
+	int n = 0;
+	luax_catchexcept(L, [&](){ n = t->getContactList(L); });
+	return n;
+}
+
 int w_Body_destroy(lua_State *L)
 int w_Body_destroy(lua_State *L)
 {
 {
 	Body *t = luax_checkbody(L, 1);
 	Body *t = luax_checkbody(L, 1);
@@ -615,6 +624,7 @@ static const luaL_Reg functions[] =
 	{ "isFixedRotation", w_Body_isFixedRotation },
 	{ "isFixedRotation", w_Body_isFixedRotation },
 	{ "getWorld", w_Body_getWorld },
 	{ "getWorld", w_Body_getWorld },
 	{ "getFixtureList", w_Body_getFixtureList },
 	{ "getFixtureList", w_Body_getFixtureList },
+	{ "getContactList", w_Body_getContactList },
 	{ "destroy", w_Body_destroy },
 	{ "destroy", w_Body_destroy },
 	{ "setUserData", w_Body_setUserData },
 	{ "setUserData", w_Body_setUserData },
 	{ "getUserData", w_Body_getUserData },
 	{ "getUserData", w_Body_getUserData },

+ 1 - 0
src/modules/physics/box2d/wrap_Body.h

@@ -85,6 +85,7 @@ int w_Body_setFixedRotation(lua_State *L);
 int w_Body_isFixedRotation(lua_State *L);
 int w_Body_isFixedRotation(lua_State *L);
 int w_Body_getWorld(lua_State *L);
 int w_Body_getWorld(lua_State *L);
 int w_Body_getFixtureList(lua_State *L);
 int w_Body_getFixtureList(lua_State *L);
+int w_Body_getContactList(lua_State *L);
 int w_Body_destroy(lua_State *L);
 int w_Body_destroy(lua_State *L);
 int w_Body_setUserData(lua_State *L);
 int w_Body_setUserData(lua_State *L);
 int w_Body_getUserData(lua_State *L);
 int w_Body_getUserData(lua_State *L);

+ 16 - 0
src/modules/physics/box2d/wrap_Contact.cpp

@@ -19,6 +19,7 @@
  **/
  **/
 
 
 #include "wrap_Contact.h"
 #include "wrap_Contact.h"
+#include "Fixture.h"
 
 
 namespace love
 namespace love
 {
 {
@@ -138,6 +139,20 @@ int w_Contact_getChildren(lua_State *L)
 	return 2;
 	return 2;
 }
 }
 
 
+int w_Contact_getFixtures(lua_State *L)
+{
+	Contact *t = luax_checkcontact(L, 1);
+	Fixture *a = nullptr;
+	Fixture *b = nullptr;
+	luax_catchexcept(L, [&](){ t->getFixtures(a, b); });
+
+	a->retain();
+	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, a);
+	b->retain();
+	luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, b);
+	return 2;
+}
+
 extern "C" int luaopen_contact(lua_State *L)
 extern "C" int luaopen_contact(lua_State *L)
 {
 {
 	static const luaL_Reg functions[] =
 	static const luaL_Reg functions[] =
@@ -156,6 +171,7 @@ extern "C" int luaopen_contact(lua_State *L)
 		{ "setTangentSpeed", w_Contact_setTangentSpeed },
 		{ "setTangentSpeed", w_Contact_setTangentSpeed },
 		{ "getTangentSpeed", w_Contact_getTangentSpeed },
 		{ "getTangentSpeed", w_Contact_getTangentSpeed },
 		{ "getChildren", w_Contact_getChildren },
 		{ "getChildren", w_Contact_getChildren },
+		{ "getFixtures", w_Contact_getFixtures },
 		{ 0, 0 }
 		{ 0, 0 }
 	};
 	};
 
 

+ 1 - 0
src/modules/physics/box2d/wrap_Contact.h

@@ -47,6 +47,7 @@ int w_Contact_resetRestitution(lua_State *L);
 int w_Contact_setTangentSpeed(lua_State *L);
 int w_Contact_setTangentSpeed(lua_State *L);
 int w_Contact_getTangentSpeed(lua_State *L);
 int w_Contact_getTangentSpeed(lua_State *L);
 int w_Contact_getChildren(lua_State *L);
 int w_Contact_getChildren(lua_State *L);
+int w_Contact_getFixtures(lua_State *L);
 extern "C" int luaopen_contact(lua_State *L);
 extern "C" int luaopen_contact(lua_State *L);
 
 
 } // box2d
 } // box2d