private void ContactProcess(object sender, Game.Newt.v1.NewtonDynamics1.Api.CContactProcessEventArgs e) { #region Get Keys string key = _currentCollidingKey; if (key == null) { throw new ApplicationException("ContactProcess was called before ContactBegin"); } else if (!_collisionListeners.ContainsKey(key)) { throw new ApplicationException("There is no listener for this material pair, but how did this callback get set up???: " + key); } #endregion // See if I should duck out early CollisionEventProps eventProps = _collisionListeners[key]; if (eventProps.HasRaisedContactEvent || eventProps.HasContactCancelled) // if they cancelled in the begin event, but for some reason this process event still fires, I don't want them to see it { if (eventProps.HasContactCancelled) { e.AllowCollision = false; } return; } // Remember that I've raised the event to the outside (so they only get informed once) eventProps.HasRaisedContactEvent = true; // Validate if (eventProps.CollisionBody1 == null || eventProps.CollisionBody2 == null) { throw new ApplicationException("Received a collision contact event without the start event"); } if (eventProps.CollisionEnd != null) { // Raise an event to the outside CollisionEndEventArgs args = new CollisionEndEventArgs(e.Material, e.Contact, eventProps.Material1, eventProps.Material2); args.Body1 = eventProps.CollisionBody1; args.Body2 = eventProps.CollisionBody2; eventProps.CollisionEnd(this, args); e.AllowCollision = args.AllowCollision; } if (!e.AllowCollision) { eventProps.HasContactCancelled = true; } }
private void ContactBegin(object sender, Game.Newt.v1.NewtonDynamics1.Api.CContactBeginEventArgs e) { #region Get Keys // Get the entry for this material pair string key = GetMaterialComboHash(e.Body0.MaterialGroupID, e.Body1.MaterialGroupID); if (!_collisionListeners.ContainsKey(key)) { throw new ApplicationException("There is no listener for this material pair, but how did this callback get set up???: " + key); } // Just to complicate things, the contact process callback doesn't give me bodies, and e.Material is different, so I have store the key, // and trust everything is called in order _currentCollidingKey = key; #endregion // Reset for this current collision between these two bodies CollisionEventProps eventProps = _collisionListeners[key]; eventProps.CollisionBody1 = e.Body0.UserData; eventProps.CollisionBody2 = e.Body1.UserData; eventProps.Material1 = _materials[e.Body0.MaterialGroupID]; eventProps.Material2 = _materials[e.Body1.MaterialGroupID]; eventProps.HasRaisedContactEvent = false; eventProps.HasContactCancelled = false; if (eventProps.CollisionStart != null) { // Raise an event to the outside CollisionStartEventArgs args = new CollisionStartEventArgs(); args.Body1 = e.Body0.UserData; args.Body2 = e.Body1.UserData; eventProps.CollisionStart(this, args); // Tell the caller what the user decided e.AllowCollision = args.AllowCollision; // This shouldn't matter, because the ContactProcess shouldn't be called if they cancelled, but I'm just being safe if (!args.AllowCollision) { eventProps.HasContactCancelled = true; } } }
/// <summary> /// This lets the consumer get notified when two bodies of the material type are colliding /// NOTE: Currently, only one listener per matieral pair is supported /// </summary> public void SetCollisionCallback(int material1, int material2, CollisionStartHandler collisionStart, CollisionEndHandler collisionEnd) { string key = GetMaterialComboHash(material1, material2); if (_collisionListeners.ContainsKey(key)) { // Newton 2.0 has a much better collision event system (when listening to the ContactProcess event, all I have is the material, not // bodies, so I have to keep track of bodies by material to make it easier on the consumer. This is all based on the fact that I receive // all contact events in order for the current collision of two bodies, then I'll get a different ContactBegin/ContactProcess set for another // two bodies) throw new ApplicationException("Currently, only one event listener is allowed for each material pair -- upgrade to newton 2"); } // Store the delegates for this material pair CollisionEventProps eventProps = new CollisionEventProps(); eventProps.CollisionStart = collisionStart; eventProps.CollisionEnd = collisionEnd; _collisionListeners.Add(key, eventProps); // Set up a callback for this material pair //NOTE: The callback goes to my event listener. I then make the args easier for the consumer, and call the delegates that were passed in _materialHelper.SetCollisionCallback(_materials[material1], _materials[material2], null, ContactBegin, ContactProcess, null); }
/// <summary> /// This lets the consumer get notified when two bodies of the material type are colliding /// NOTE: Currently, only one listener per matieral pair is supported /// </summary> public void SetCollisionCallback(int material1, int material2, CollisionStartHandler collisionStart, CollisionEndHandler collisionEnd) { string key = GetMaterialComboHash(material1, material2); if (_collisionListeners.ContainsKey(key)) { // Newton 2.0 has a much better collision event system (when listening to the ContactProcess event, all I have is the material, not // bodies, so I have to keep track of bodies by material to make it easier on the consumer. This is all based on the fact that I receive // all contact events in order for the current collision of two bodies, then I'll get a different ContactBegin/ContactProcess set for another // two bodies) throw new ApplicationException("Currently, only one event listener is allowed for each material pair -- upgrade to newton 2"); } // Store the delegates for this material pair CollisionEventProps eventProps = new CollisionEventProps(); eventProps.CollisionStart = collisionStart; eventProps.CollisionEnd = collisionEnd; _collisionListeners.Add(key, eventProps); // Set up a callback for this material pair //NOTE: The callback goes to my event listener. I then make the args easier for the consumer, and call the delegates that were passed in _materialHelper.SetCollisionCallback(_materials[material1], _materials[material2], null, ContactBegin, ContactProcess, null); }