internal void update( ContactManager contactManager )
{
var bodyA = fixtureA.body;
var bodyB = fixtureB.body;
if( fixtureA == null || fixtureB == null )
return;
var oldManifold = manifold;
// Re-enable this contact.
enabled = true;
bool touching;
var wasTouching = isTouching;
var sensor = fixtureA.isSensor || fixtureB.isSensor;
// Is this contact a sensor?
if( sensor )
{
var shapeA = fixtureA.shape;
var shapeB = fixtureB.shape;
touching = Collision.Collision.testOverlap( shapeA, childIndexA, shapeB, childIndexB, ref bodyA._xf, ref bodyB._xf );
// Sensors don't generate manifolds.
manifold.pointCount = 0;
}
else
{
evaluate( ref manifold, ref bodyA._xf, ref bodyB._xf );
touching = manifold.pointCount > 0;
// Match old contact ids to new contact ids and copy the
// stored impulses to warm start the solver.
for( int i = 0; i < manifold.pointCount; ++i )
{
var mp2 = manifold.points[i];
mp2.normalImpulse = 0.0f;
mp2.tangentImpulse = 0.0f;
var id2 = mp2.id;
for( int j = 0; j < oldManifold.pointCount; ++j )
{
var mp1 = oldManifold.points[j];
if( mp1.id.key == id2.key )
{
mp2.normalImpulse = mp1.normalImpulse;
mp2.tangentImpulse = mp1.tangentImpulse;
break;
}
}
manifold.points[i] = mp2;
}
if( touching != wasTouching )
{
bodyA.isAwake = true;
bodyB.isAwake = true;
}
}
isTouching = touching;
if( wasTouching == false )
{
if( touching )
{
if( Settings.allCollisionCallbacksAgree )
{
bool enabledA = true, enabledB = true;
// Report the collision to both participants. Track which ones returned true so we can
// later call OnSeparation if the contact is disabled for a different reason.
if( fixtureA.onCollision != null )
foreach( OnCollisionEventHandler handler in fixtureA.onCollision.GetInvocationList() )
enabledA = handler( fixtureA, fixtureB, this ) && enabledA;
// Reverse the order of the reported fixtures. The first fixture is always the one that the
// user subscribed to.
if( fixtureB.onCollision != null )
foreach( OnCollisionEventHandler handler in fixtureB.onCollision.GetInvocationList() )
enabledB = handler( fixtureB, fixtureA, this ) && enabledB;
enabled = enabledA && enabledB;
// BeginContact can also return false and disable the contact
if( enabledA && enabledB && contactManager.onBeginContact != null )
enabled = contactManager.onBeginContact( this );
}
else
{
// Report the collision to both participants:
if( fixtureA.onCollision != null )
foreach( OnCollisionEventHandler handler in fixtureA.onCollision.GetInvocationList() )
enabled = handler( fixtureA, fixtureB, this );
//Reverse the order of the reported fixtures. The first fixture is always the one that the
//user subscribed to.
if( fixtureB.onCollision != null )
foreach( OnCollisionEventHandler handler in fixtureB.onCollision.GetInvocationList() )
enabled = handler( fixtureB, fixtureA, this );
//BeginContact can also return false and disable the contact
if( contactManager.onBeginContact != null )
enabled = contactManager.onBeginContact( this );
}
// If the user disabled the contact (needed to exclude it in TOI solver) at any point by
// any of the callbacks, we need to mark it as not touching and call any separation
// callbacks for fixtures that didn't explicitly disable the collision.
if( !enabled )
isTouching = false;
}
}
else
{
if( touching == false )
{
// Report the separation to both participants:
if( fixtureA != null && fixtureA.onSeparation != null )
fixtureA.onSeparation( fixtureA, fixtureB );
//Reverse the order of the reported fixtures. The first fixture is always the one that the
//user subscribed to.
if( fixtureB != null && fixtureB.onSeparation != null )
fixtureB.onSeparation( fixtureB, fixtureA );
if( contactManager.onEndContact != null )
contactManager.onEndContact( this );
}
}
if( sensor )
return;
if( contactManager.onPreSolve != null )
contactManager.onPreSolve( this, ref oldManifold );
}