// Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback) { if (body.ptr == IntPtr.Zero) { return; } lock (m_collectionActivityLock) { BodyDesc bodyDesc; if (Bodies.TryGetValue(body.ID, out bodyDesc)) { bodyDesc.referenceCount--; bodyDesc.lastReferenced = System.DateTime.Now; Bodies[body.ID] = bodyDesc; DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); // If body is no longer being used, free it -- bodies are never shared. if (bodyDesc.referenceCount == 0) { Bodies.Remove(body.ID); BSScene.TaintCallback removeOperation = delegate() { DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", body.ID, body.ptr.ToString("X")); // If the caller needs to know, pass the event up. if (bodyCallback != null) { bodyCallback(body); } // Zero any reference to the shape so it is not freed when the body is deleted. BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); // It may have already been removed from the world in which case the next is a NOOP. BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); }; // If already in taint-time, do the operations now. Otherwise queue for later. if (inTaintTime) { removeOperation(); } else { PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); } } } else { DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount); } } }