mirror of
https://github.com/love2d/love.git
synced 2026-08-19 12:14:20 +02:00
Import box2d-contacts branch from love-experiments
Fix issues with Contact lifetime, based on the work of Matteo "teomat" Goggi
This commit is contained in:
@@ -39,7 +39,21 @@ Contact::Contact(b2Contact *contact)
|
|||||||
|
|
||||||
Contact::~Contact()
|
Contact::~Contact()
|
||||||
{
|
{
|
||||||
Memoizer::remove(contact);
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Contact::invalidate()
|
||||||
|
{
|
||||||
|
if (contact != NULL)
|
||||||
|
{
|
||||||
|
Memoizer::remove(contact);
|
||||||
|
contact = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Contact::isValid()
|
||||||
|
{
|
||||||
|
return contact != NULL ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Contact::getPositions(lua_State *L)
|
int Contact::getPositions(lua_State *L)
|
||||||
|
|||||||
@@ -59,6 +59,18 @@ public:
|
|||||||
|
|
||||||
virtual ~Contact();
|
virtual ~Contact();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the b2Contact pointer from Memoizer and sets it
|
||||||
|
* to null on the Contact.
|
||||||
|
**/
|
||||||
|
void invalidate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the Contact still points to a valid b2Contact.
|
||||||
|
* @return True if the contact is still valid or false if it has been destroyed.
|
||||||
|
**/
|
||||||
|
bool isValid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the position of each point of contact.
|
* Gets the position of each point of contact.
|
||||||
* @return The position along the x-axis.
|
* @return The position along the x-axis.
|
||||||
|
|||||||
@@ -77,9 +77,13 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse
|
|||||||
throw love::Exception("A fixture has escaped Memoizer!");
|
throw love::Exception("A fixture has escaped Memoizer!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Contact *c = new Contact(contact);
|
Contact *cobj = (Contact *)Memoizer::find(contact);
|
||||||
|
if (!cobj)
|
||||||
|
cobj = new Contact(contact);
|
||||||
|
else
|
||||||
|
cobj->retain();
|
||||||
|
|
||||||
luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void *)c);
|
luax_newtype(L, "Contact", (PHYSICS_CONTACT_T), (void *)cobj);
|
||||||
|
|
||||||
int args = 3;
|
int args = 3;
|
||||||
if (impulse)
|
if (impulse)
|
||||||
@@ -117,12 +121,12 @@ bool World::ContactFilter::process(Fixture *a, Fixture *b)
|
|||||||
a->getFilterData(filterA);
|
a->getFilterData(filterA);
|
||||||
b->getFilterData(filterB);
|
b->getFilterData(filterB);
|
||||||
|
|
||||||
if (filterA[2] != 0 && // 0 is the default group, so this does not count
|
if (filterA[2] != 0 && // 0 is the default group, so this does not count
|
||||||
filterA[2] == filterB[2]) // if they are in the same group
|
filterA[2] == filterB[2]) // if they are in the same group
|
||||||
return filterA[2] > 0; // Negative indexes mean you don't collide
|
return filterA[2] > 0; // Negative indexes mean you don't collide
|
||||||
|
|
||||||
if ((filterA[1] & filterB[0]) == 0 ||
|
if ((filterA[1] & filterB[0]) == 0 ||
|
||||||
(filterB[1] & filterA[0]) == 0)
|
(filterB[1] & filterA[0]) == 0)
|
||||||
return false; // A and B aren't set to collide
|
return false; // A and B aren't set to collide
|
||||||
|
|
||||||
if (ref != 0)
|
if (ref != 0)
|
||||||
@@ -290,6 +294,11 @@ void World::BeginContact(b2Contact *contact)
|
|||||||
void World::EndContact(b2Contact *contact)
|
void World::EndContact(b2Contact *contact)
|
||||||
{
|
{
|
||||||
end.process(contact);
|
end.process(contact);
|
||||||
|
|
||||||
|
// Letting the Contact know that the b2Contact will be destroyed any second.
|
||||||
|
Contact *c = (Contact *)Memoizer::find(contact);
|
||||||
|
if (c != NULL)
|
||||||
|
c->invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::PreSolve(b2Contact *contact, const b2Manifold *oldManifold)
|
void World::PreSolve(b2Contact *contact, const b2Manifold *oldManifold)
|
||||||
@@ -332,19 +341,19 @@ int World::setCallbacks(lua_State *L)
|
|||||||
case 4:
|
case 4:
|
||||||
if (postsolve.ref)
|
if (postsolve.ref)
|
||||||
delete postsolve.ref;
|
delete postsolve.ref;
|
||||||
postsolve.ref = luax_refif (L, LUA_TFUNCTION);
|
postsolve.ref = luax_refif(L, LUA_TFUNCTION);
|
||||||
case 3:
|
case 3:
|
||||||
if (presolve.ref)
|
if (presolve.ref)
|
||||||
delete presolve.ref;
|
delete presolve.ref;
|
||||||
presolve.ref = luax_refif (L, LUA_TFUNCTION);
|
presolve.ref = luax_refif(L, LUA_TFUNCTION);
|
||||||
case 2:
|
case 2:
|
||||||
if (end.ref)
|
if (end.ref)
|
||||||
delete end.ref;
|
delete end.ref;
|
||||||
end.ref = luax_refif (L, LUA_TFUNCTION);
|
end.ref = luax_refif(L, LUA_TFUNCTION);
|
||||||
case 1:
|
case 1:
|
||||||
if (begin.ref)
|
if (begin.ref)
|
||||||
delete begin.ref;
|
delete begin.ref;
|
||||||
begin.ref = luax_refif (L, LUA_TFUNCTION);
|
begin.ref = luax_refif(L, LUA_TFUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -364,7 +373,7 @@ int World::setContactFilter(lua_State *L)
|
|||||||
luax_assert_argc(L, 1);
|
luax_assert_argc(L, 1);
|
||||||
if (filter.ref)
|
if (filter.ref)
|
||||||
delete filter.ref;
|
delete filter.ref;
|
||||||
filter.ref = luax_refif (L, LUA_TFUNCTION);
|
filter.ref = luax_refif(L, LUA_TFUNCTION);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,8 +477,10 @@ int World::getContactList(lua_State *L) const
|
|||||||
{
|
{
|
||||||
if (!c) break;
|
if (!c) break;
|
||||||
Contact *contact = (Contact *)Memoizer::find(c);
|
Contact *contact = (Contact *)Memoizer::find(c);
|
||||||
if (!contact) throw love::Exception("A contact has escaped Memoizer!");
|
if (!contact)
|
||||||
contact->retain();
|
contact = new Contact(c);
|
||||||
|
else
|
||||||
|
contact->retain();
|
||||||
luax_newtype(L, "Contact", PHYSICS_CONTACT_T, (void *)contact);
|
luax_newtype(L, "Contact", PHYSICS_CONTACT_T, (void *)contact);
|
||||||
lua_rawseti(L, -2, i);
|
lua_rawseti(L, -2, i);
|
||||||
i++;
|
i++;
|
||||||
@@ -494,7 +505,7 @@ int World::queryBoundingBox(lua_State *L)
|
|||||||
box.lowerBound = Physics::scaleDown(b2Vec2(lx, ly));
|
box.lowerBound = Physics::scaleDown(b2Vec2(lx, ly));
|
||||||
box.upperBound = Physics::scaleDown(b2Vec2(ux, uy));
|
box.upperBound = Physics::scaleDown(b2Vec2(ux, uy));
|
||||||
if (query.ref) delete query.ref;
|
if (query.ref) delete query.ref;
|
||||||
query.ref = luax_refif (L, LUA_TFUNCTION);
|
query.ref = luax_refif(L, LUA_TFUNCTION);
|
||||||
world->QueryAABB(&query, box);
|
world->QueryAABB(&query, box);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -510,7 +521,7 @@ int World::rayCast(lua_State *L)
|
|||||||
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
|
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
|
||||||
if (raycast.ref)
|
if (raycast.ref)
|
||||||
delete raycast.ref;
|
delete raycast.ref;
|
||||||
raycast.ref = luax_refif (L, LUA_TFUNCTION);
|
raycast.ref = luax_refif(L, LUA_TFUNCTION);
|
||||||
world->RayCast(&raycast, v1, v2);
|
world->RayCast(&raycast, v1, v2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ namespace box2d
|
|||||||
|
|
||||||
Contact *luax_checkcontact(lua_State *L, int idx)
|
Contact *luax_checkcontact(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
return luax_checktype<Contact>(L, idx, "Contact", PHYSICS_CONTACT_T);
|
Contact *c = luax_checktype<Contact>(L, idx, "Contact", PHYSICS_CONTACT_T);
|
||||||
|
if (!c->isValid())
|
||||||
|
luaL_error(L, "Attempt to use destroyed contact.");
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_Contact_getPositions(lua_State *L)
|
int w_Contact_getPositions(lua_State *L)
|
||||||
|
|||||||
Reference in New Issue
Block a user