While running a test case I had written to pursue problems with

llDie() not always completely working, I discovered I was
  getting a lot (60+ over 6000 iterations of the test case)
  null pointer exceptions in various physics related checks in
  SceneObjectPart. It was apparent that the (frequent) checks for
  PhysActor being non-null is an insufficient protection in a
  highly asynchronous environment. The null reference exceptions
  are one example of failure, but it could also happen that a
  sequence started with one instance of a PhysicsActor might
  finish with another?
  Anyway, I have implemented a safer mechanism that should
  stop the errors. I re-ran my test case with the fix in place,
  and completed nearly 1000 iterations without a single occurrence.

  SceneObjectPart is seriously in need of rejigging, if not for
  this reason, then for its ridiculous size.

Signed-off-by: dr scofield (aka dirk husemann) <drscofield@xyzzyxyzzy.net>
prioritization
Alan M Webb 2009-09-16 17:31:14 -04:00 committed by dr scofield (aka dirk husemann)
parent 69ef95693a
commit 88294d9ebf
1 changed files with 152 additions and 113 deletions

View File

@ -415,9 +415,10 @@ namespace OpenSim.Region.Framework.Scenes
set set
{ {
m_name = value; m_name = value;
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.SOPName = value; pa.SOPName = value;
} }
} }
} }
@ -427,10 +428,11 @@ namespace OpenSim.Region.Framework.Scenes
get { return (byte) m_material; } get { return (byte) m_material; }
set set
{ {
PhysicsActor pa = PhysActor;
m_material = (Material)value; m_material = (Material)value;
if (PhysActor != null) if (pa != null)
{ {
PhysActor.SetMaterial((int)value); pa.SetMaterial((int)value);
} }
} }
} }
@ -501,11 +503,12 @@ namespace OpenSim.Region.Framework.Scenes
get get
{ {
// If this is a linkset, we don't want the physics engine mucking up our group position here. // If this is a linkset, we don't want the physics engine mucking up our group position here.
if (PhysActor != null && _parentID == 0) PhysicsActor pa = PhysActor;
if (pa != null && _parentID == 0)
{ {
m_groupPosition.X = PhysActor.Position.X; m_groupPosition.X = pa.Position.X;
m_groupPosition.Y = PhysActor.Position.Y; m_groupPosition.Y = pa.Position.Y;
m_groupPosition.Z = PhysActor.Position.Z; m_groupPosition.Z = pa.Position.Z;
} }
if (IsAttachment) if (IsAttachment)
@ -525,26 +528,27 @@ namespace OpenSim.Region.Framework.Scenes
m_groupPosition = value; m_groupPosition = value;
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
try try
{ {
// Root prim actually goes at Position // Root prim actually goes at Position
if (_parentID == 0) if (_parentID == 0)
{ {
PhysActor.Position = new PhysicsVector(value.X, value.Y, value.Z); pa.Position = new PhysicsVector(value.X, value.Y, value.Z);
} }
else else
{ {
// To move the child prim in respect to the group position and rotation we have to calculate // To move the child prim in respect to the group position and rotation we have to calculate
Vector3 resultingposition = GetWorldPosition(); Vector3 resultingposition = GetWorldPosition();
PhysActor.Position = new PhysicsVector(resultingposition.X, resultingposition.Y, resultingposition.Z); pa.Position = new PhysicsVector(resultingposition.X, resultingposition.Y, resultingposition.Z);
Quaternion resultingrot = GetWorldRotation(); Quaternion resultingrot = GetWorldRotation();
PhysActor.Orientation = resultingrot; pa.Orientation = resultingrot;
} }
// Tell the physics engines that this prim changed. // Tell the physics engines that this prim changed.
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
} }
catch (Exception e) catch (Exception e)
{ {
@ -577,15 +581,16 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentGroup != null && !ParentGroup.IsDeleted) if (ParentGroup != null && !ParentGroup.IsDeleted)
{ {
if (_parentID != 0 && PhysActor != null) PhysicsActor pa = PhysActor;
if (_parentID != 0 && pa != null)
{ {
Vector3 resultingposition = GetWorldPosition(); Vector3 resultingposition = GetWorldPosition();
PhysActor.Position = new PhysicsVector(resultingposition.X, resultingposition.Y, resultingposition.Z); pa.Position = new PhysicsVector(resultingposition.X, resultingposition.Y, resultingposition.Z);
Quaternion resultingrot = GetWorldRotation(); Quaternion resultingrot = GetWorldRotation();
PhysActor.Orientation = resultingrot; pa.Orientation = resultingrot;
// Tell the physics engines that this prim changed. // Tell the physics engines that this prim changed.
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
} }
} }
} }
@ -595,13 +600,14 @@ namespace OpenSim.Region.Framework.Scenes
{ {
get get
{ {
PhysicsActor pa = PhysActor;
// We don't want the physics engine mucking up the rotations in a linkset // We don't want the physics engine mucking up the rotations in a linkset
if ((_parentID == 0) && (Shape.PCode != 9 || Shape.State == 0) && (PhysActor != null)) if ((_parentID == 0) && (Shape.PCode != 9 || Shape.State == 0) && (pa != null))
{ {
if (PhysActor.Orientation.X != 0 || PhysActor.Orientation.Y != 0 if (pa.Orientation.X != 0 || pa.Orientation.Y != 0
|| PhysActor.Orientation.Z != 0 || PhysActor.Orientation.W != 0) || pa.Orientation.Z != 0 || pa.Orientation.W != 0)
{ {
m_rotationOffset = PhysActor.Orientation; m_rotationOffset = pa.Orientation;
} }
} }
@ -610,27 +616,28 @@ namespace OpenSim.Region.Framework.Scenes
set set
{ {
PhysicsActor pa = PhysActor;
StoreUndoState(); StoreUndoState();
m_rotationOffset = value; m_rotationOffset = value;
if (PhysActor != null) if (pa != null)
{ {
try try
{ {
// Root prim gets value directly // Root prim gets value directly
if (_parentID == 0) if (_parentID == 0)
{ {
PhysActor.Orientation = value; pa.Orientation = value;
//m_log.Info("[PART]: RO1:" + PhysActor.Orientation.ToString()); //m_log.Info("[PART]: RO1:" + PhysActor.Orientation.ToString());
} }
else else
{ {
// Child prim we have to calculate it's world rotationwel // Child prim we have to calculate it's world rotationwel
Quaternion resultingrotation = GetWorldRotation(); Quaternion resultingrotation = GetWorldRotation();
PhysActor.Orientation = resultingrotation; pa.Orientation = resultingrotation;
//m_log.Info("[PART]: RO2:" + PhysActor.Orientation.ToString()); //m_log.Info("[PART]: RO2:" + PhysActor.Orientation.ToString());
} }
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
//} //}
} }
catch (Exception ex) catch (Exception ex)
@ -650,13 +657,14 @@ namespace OpenSim.Region.Framework.Scenes
//if (PhysActor.Velocity.X != 0 || PhysActor.Velocity.Y != 0 //if (PhysActor.Velocity.X != 0 || PhysActor.Velocity.Y != 0
//|| PhysActor.Velocity.Z != 0) //|| PhysActor.Velocity.Z != 0)
//{ //{
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
if (PhysActor.IsPhysical) if (pa.IsPhysical)
{ {
m_velocity.X = PhysActor.Velocity.X; m_velocity.X = pa.Velocity.X;
m_velocity.Y = PhysActor.Velocity.Y; m_velocity.Y = pa.Velocity.Y;
m_velocity.Z = PhysActor.Velocity.Z; m_velocity.Z = pa.Velocity.Z;
} }
} }
@ -666,12 +674,13 @@ namespace OpenSim.Region.Framework.Scenes
set set
{ {
m_velocity = value; m_velocity = value;
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
if (PhysActor.IsPhysical) if (pa.IsPhysical)
{ {
PhysActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z); pa.Velocity = new PhysicsVector(value.X, value.Y, value.Z);
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
} }
} }
} }
@ -688,9 +697,10 @@ namespace OpenSim.Region.Framework.Scenes
{ {
get get
{ {
if ((PhysActor != null) && PhysActor.IsPhysical) PhysicsActor pa = PhysActor;
if ((pa != null) && pa.IsPhysical)
{ {
m_angularVelocity.FromBytes(PhysActor.RotationalVelocity.GetBytes(), 0); m_angularVelocity.FromBytes(pa.RotationalVelocity.GetBytes(), 0);
} }
return m_angularVelocity; return m_angularVelocity;
} }
@ -709,10 +719,11 @@ namespace OpenSim.Region.Framework.Scenes
get { return m_description; } get { return m_description; }
set set
{ {
PhysicsActor pa = PhysActor;
m_description = value; m_description = value;
if (PhysActor != null) if (pa != null)
{ {
PhysActor.SOPDescription = value; pa.SOPDescription = value;
} }
} }
} }
@ -806,14 +817,15 @@ namespace OpenSim.Region.Framework.Scenes
if (m_shape != null) { if (m_shape != null) {
m_shape.Scale = value; m_shape.Scale = value;
if (PhysActor != null && m_parentGroup != null) PhysicsActor pa = PhysActor;
if (pa != null && m_parentGroup != null)
{ {
if (m_parentGroup.Scene != null) if (m_parentGroup.Scene != null)
{ {
if (m_parentGroup.Scene.PhysicsScene != null) if (m_parentGroup.Scene.PhysicsScene != null)
{ {
PhysActor.Size = new PhysicsVector(m_shape.Scale.X, m_shape.Scale.Y, m_shape.Scale.Z); pa.Size = new PhysicsVector(m_shape.Scale.X, m_shape.Scale.Y, m_shape.Scale.Z);
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
} }
} }
} }
@ -1343,13 +1355,14 @@ if (m_shape != null) {
RigidBody); RigidBody);
// Basic Physics returns null.. joy joy joy. // Basic Physics returns null.. joy joy joy.
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.SOPName = this.Name; // save object name and desc into the PhysActor so ODE internals know the joint/body info pa.SOPName = this.Name; // save object name and desc into the PhysActor so ODE internals know the joint/body info
PhysActor.SOPDescription = this.Description; pa.SOPDescription = this.Description;
PhysActor.LocalID = LocalId; pa.LocalID = LocalId;
DoPhysicsPropertyUpdate(RigidBody, true); DoPhysicsPropertyUpdate(RigidBody, true);
PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
} }
} }
} }
@ -1563,23 +1576,24 @@ if (m_shape != null) {
} }
else else
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
if (UsePhysics != PhysActor.IsPhysical || isNew) if (UsePhysics != pa.IsPhysical || isNew)
{ {
if (PhysActor.IsPhysical) // implies UsePhysics==false for this block if (pa.IsPhysical) // implies UsePhysics==false for this block
{ {
if (!isNew) if (!isNew)
ParentGroup.Scene.RemovePhysicalPrim(1); ParentGroup.Scene.RemovePhysicalPrim(1);
PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; pa.OnOutOfBounds -= PhysicsOutOfBounds;
PhysActor.delink(); pa.delink();
if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew))
{ {
// destroy all joints connected to this now deactivated body // destroy all joints connected to this now deactivated body
m_parentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(PhysActor); m_parentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
} }
// stop client-side interpolation of all joint proxy objects that have just been deleted // stop client-side interpolation of all joint proxy objects that have just been deleted
@ -1598,7 +1612,7 @@ if (m_shape != null) {
//RotationalVelocity = new Vector3(0, 0, 0); //RotationalVelocity = new Vector3(0, 0, 0);
} }
PhysActor.IsPhysical = UsePhysics; pa.IsPhysical = UsePhysics;
// If we're not what we're supposed to be in the physics scene, recreate ourselves. // If we're not what we're supposed to be in the physics scene, recreate ourselves.
@ -1612,19 +1626,19 @@ if (m_shape != null) {
{ {
ParentGroup.Scene.AddPhysicalPrim(1); ParentGroup.Scene.AddPhysicalPrim(1);
PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
PhysActor.OnOutOfBounds += PhysicsOutOfBounds; pa.OnOutOfBounds += PhysicsOutOfBounds;
if (_parentID != 0 && _parentID != LocalId) if (_parentID != 0 && _parentID != LocalId)
{ {
if (ParentGroup.RootPart.PhysActor != null) if (ParentGroup.RootPart.PhysActor != null)
{ {
PhysActor.link(ParentGroup.RootPart.PhysActor); pa.link(ParentGroup.RootPart.PhysActor);
} }
} }
} }
} }
} }
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
} }
} }
} }
@ -1690,9 +1704,10 @@ if (m_shape != null) {
public Vector3 GetGeometricCenter() public Vector3 GetGeometricCenter()
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
return new Vector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z); return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z);
} }
else else
{ {
@ -1702,9 +1717,10 @@ if (m_shape != null) {
public float GetMass() public float GetMass()
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
return PhysActor.Mass; return pa.Mass;
} }
else else
{ {
@ -1714,8 +1730,9 @@ if (m_shape != null) {
public PhysicsVector GetForce() public PhysicsVector GetForce()
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
return PhysActor.Force; if (pa != null)
return pa.Force;
else else
return new PhysicsVector(); return new PhysicsVector();
} }
@ -2094,11 +2111,15 @@ if (m_shape != null) {
public void PhysicsRequestingTerseUpdate() public void PhysicsRequestingTerseUpdate()
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0); Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
if (m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.N) | m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.S) | m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.E) | m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) if (m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.N) |
m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.S) |
m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.E) |
m_parentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
{ {
m_parentGroup.AbsolutePosition = newpos; m_parentGroup.AbsolutePosition = newpos;
return; return;
@ -2294,14 +2315,15 @@ if (m_shape != null) {
if (texture != null) if (texture != null)
m_shape.SculptData = texture.Data; m_shape.SculptData = texture.Data;
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
// Tricks physics engine into thinking we've changed the part shape. // Tricks physics engine into thinking we've changed the part shape.
PrimitiveBaseShape m_newshape = m_shape.Copy(); PrimitiveBaseShape m_newshape = m_shape.Copy();
PhysActor.Shape = m_newshape; pa.Shape = m_newshape;
m_shape = m_newshape; m_shape = m_newshape;
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
} }
} }
} }
@ -2520,9 +2542,10 @@ if (m_shape != null) {
public void SetBuoyancy(float fvalue) public void SetBuoyancy(float fvalue)
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.Buoyancy = fvalue; pa.Buoyancy = fvalue;
} }
} }
@ -2538,56 +2561,62 @@ if (m_shape != null) {
public void SetFloatOnWater(int floatYN) public void SetFloatOnWater(int floatYN)
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
if (floatYN == 1) if (floatYN == 1)
{ {
PhysActor.FloatOnWater = true; pa.FloatOnWater = true;
} }
else else
{ {
PhysActor.FloatOnWater = false; pa.FloatOnWater = false;
} }
} }
} }
public void SetForce(PhysicsVector force) public void SetForce(PhysicsVector force)
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.Force = force; pa.Force = force;
} }
} }
public void SetVehicleType(int type) public void SetVehicleType(int type)
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.VehicleType = type; pa.VehicleType = type;
} }
} }
public void SetVehicleFloatParam(int param, float value) public void SetVehicleFloatParam(int param, float value)
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.VehicleFloatParam(param, value); pa.VehicleFloatParam(param, value);
} }
} }
public void SetVehicleVectorParam(int param, PhysicsVector value) public void SetVehicleVectorParam(int param, PhysicsVector value)
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.VehicleVectorParam(param, value); pa.VehicleVectorParam(param, value);
} }
} }
public void SetVehicleRotationParam(int param, Quaternion rotation) public void SetVehicleRotationParam(int param, Quaternion rotation)
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.VehicleRotationParam(param, rotation); pa.VehicleRotationParam(param, rotation);
} }
} }
@ -2615,10 +2644,11 @@ if (m_shape != null) {
public void SetPhysicsAxisRotation() public void SetPhysicsAxisRotation()
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.LockAngularMotion(RotationAxis); pa.LockAngularMotion(RotationAxis);
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
} }
} }
@ -3350,8 +3380,9 @@ if (m_shape != null) {
{ {
IsVD = false; // Switch it of for the course of this routine IsVD = false; // Switch it of for the course of this routine
VolumeDetectActive = false; // and also permanently VolumeDetectActive = false; // and also permanently
if (PhysActor != null) PhysicsActor pa = PhysActor;
PhysActor.SetVolumeDetect(0); // Let physics know about it too if (pa != null)
pa.SetVolumeDetect(0); // Let physics know about it too
} }
else else
{ {
@ -3399,18 +3430,21 @@ if (m_shape != null) {
if (IsPhantom || IsAttachment) // note: this may have been changed above in the case of joints if (IsPhantom || IsAttachment) // note: this may have been changed above in the case of joints
{ {
AddFlag(PrimFlags.Phantom); AddFlag(PrimFlags.Phantom);
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); m_parentGroup.Scene.PhysicsScene.RemovePrim(pa);
/// that's not wholesome. Had to make Scene public /// that's not wholesome. Had to make Scene public
PhysActor = null; pa = null;
} }
} }
else // Not phantom else // Not phantom
{ {
RemFlag(PrimFlags.Phantom); RemFlag(PrimFlags.Phantom);
if (PhysActor == null) // This is NOT safe!!
PhysicsActor pa = PhysActor;
if (pa == null)
{ {
// It's not phantom anymore. So make sure the physics engine get's knowledge of it // It's not phantom anymore. So make sure the physics engine get's knowledge of it
PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
@ -3421,9 +3455,9 @@ if (m_shape != null) {
RotationOffset, RotationOffset,
UsePhysics); UsePhysics);
if (PhysActor != null) if (pa != null)
{ {
PhysActor.LocalID = LocalId; pa.LocalID = LocalId;
DoPhysicsPropertyUpdate(UsePhysics, true); DoPhysicsPropertyUpdate(UsePhysics, true);
if (m_parentGroup != null) if (m_parentGroup != null)
{ {
@ -3442,14 +3476,14 @@ if (m_shape != null) {
(CollisionSound != UUID.Zero) (CollisionSound != UUID.Zero)
) )
{ {
PhysActor.OnCollisionUpdate += PhysicsCollision; pa.OnCollisionUpdate += PhysicsCollision;
PhysActor.SubscribeEvents(1000); pa.SubscribeEvents(1000);
} }
} }
} }
else // it already has a physical representation else // it already has a physical representation
{ {
PhysActor.IsPhysical = UsePhysics; pa.IsPhysical = UsePhysics;
DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
if (m_parentGroup != null) if (m_parentGroup != null)
@ -3472,9 +3506,10 @@ if (m_shape != null) {
// Defensive programming calls for a check here. // Defensive programming calls for a check here.
// Better would be throwing an exception that could be catched by a unit test as the internal // Better would be throwing an exception that could be catched by a unit test as the internal
// logic should make sure, this Physactor is always here. // logic should make sure, this Physactor is always here.
if (this.PhysActor != null) PhysicsActor pa = this.PhysActor;
if (pa != null)
{ {
PhysActor.SetVolumeDetect(1); pa.SetVolumeDetect(1);
AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
this.VolumeDetectActive = true; this.VolumeDetectActive = true;
} }
@ -3482,10 +3517,11 @@ if (m_shape != null) {
} }
else else
{ // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like { // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
// (mumbles, well, at least if you have infinte CPU powers :-)) // (mumbles, well, at least if you have infinte CPU powers :-) )
if (this.PhysActor != null) PhysicsActor pa = this.PhysActor;
if (pa != null)
{ {
PhysActor.SetVolumeDetect(0); pa.SetVolumeDetect(0);
} }
this.VolumeDetectActive = false; this.VolumeDetectActive = false;
} }
@ -3543,10 +3579,11 @@ if (m_shape != null) {
m_shape.PathTaperY = shapeBlock.PathTaperY; m_shape.PathTaperY = shapeBlock.PathTaperY;
m_shape.PathTwist = shapeBlock.PathTwist; m_shape.PathTwist = shapeBlock.PathTwist;
m_shape.PathTwistBegin = shapeBlock.PathTwistBegin; m_shape.PathTwistBegin = shapeBlock.PathTwistBegin;
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.Shape = m_shape; pa.Shape = m_shape;
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
} }
// This is what makes vehicle trailers work // This is what makes vehicle trailers work
@ -3647,19 +3684,21 @@ if (m_shape != null) {
) )
{ {
// subscribe to physics updates. // subscribe to physics updates.
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.OnCollisionUpdate += PhysicsCollision; pa.OnCollisionUpdate += PhysicsCollision;
PhysActor.SubscribeEvents(1000); pa.SubscribeEvents(1000);
} }
} }
else else
{ {
if (PhysActor != null) PhysicsActor pa = PhysActor;
if (pa != null)
{ {
PhysActor.UnSubscribeEvents(); pa.UnSubscribeEvents();
PhysActor.OnCollisionUpdate -= PhysicsCollision; pa.OnCollisionUpdate -= PhysicsCollision;
} }
} }