public void RebuildPhysicalRepresentation(bool keepSelectedStatuses, Action actionWhileNoPhysActor)
{
// long lock or array copy? in this case lets try array
SceneObjectPart[] parts;
SceneObjectPart part;
int i;
lock (m_partsLock)//Force the root to be deleted last
parts = m_partsList.OrderBy((sop)=>-sop.LinkNum).ToArray();
if (RootPart.PhysActor != null)
RootPart.PhysActor.BlockPhysicalReconstruction = true;
for (i = 0; i < parts.Length; i++)
{
part = parts[i];
// PhysicsObject oldActor = part.PhysActor;
// PrimitiveBaseShape pbs = part.Shape;
if (part.PhysActor != null)
{
part.PhysActor.RotationalVelocity = Vector3.Zero;
part.m_hasSubscribedToCollisionEvent = false;
part.PhysActor.OnRequestTerseUpdate -= part.PhysicsRequestingTerseUpdate;
part.PhysActor.OnSignificantMovement -= part.ParentGroup.CheckForSignificantMovement;
part.PhysActor.OnOutOfBounds -= part.PhysicsOutOfBounds;
//part.PhysActor.delink ();
//Remove the old one so that we don't have more than we should,
// as when we copy, it readds it to the PhysicsScene somehow
//if (part.IsRoot)//The root removes all children
m_scene.PhysicsScene.RemovePrim(part.PhysActor);
part.FireOnRemovedPhysics();
part.PhysActor = null;
}
//Reset any old data that we have
part.Velocity = Vector3.Zero;
part.AngularVelocity = Vector3.Zero;
part.Acceleration = Vector3.Zero;
part.GenerateRotationalVelocityFromOmega();
}
if(actionWhileNoPhysActor != null)
actionWhileNoPhysActor();
//Check for meshes and stuff
CheckSculptAndLoad();
// check root part setting that make the entire object not having physics rep
if (RootPart.PhysicsType == (byte)PhysicsShapeType.None ||
((RootPart.Flags & PrimFlags.Phantom) == PrimFlags.Phantom && !RootPart.VolumeDetectActive))
{
Scene.UniverseEventManager.FireGenericEventHandler("ObjectChangedPhysicalStatus", this);
if (OnFinishedPhysicalRepresentationBuilding != null)
OnFinishedPhysicalRepresentationBuilding();
OnFinishedPhysicalRepresentationBuilding = null;
return;
}
// create the root part
bool isPhysical = ((RootPart.Flags & PrimFlags.Physics) != 0);
bool isPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
bool physical = isPhysical & !isPhantom;
RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(RootPart.UUID, RootPart.LocalId, RootPart.Name, RootPart.PhysicsType,
RootPart.Shape, RootPart.AbsolutePosition, RootPart.Scale, RootPart.GetWorldRotation(), physical, RootPart.Material,
RootPart.Friction, RootPart.Restitution, RootPart.GravityMultiplier, RootPart.Density);
if (RootPart.PhysActor == null)
return;
//Don't let it rebuild it until we have all the links done
RootPart.PhysActor.VolumeDetect = RootPart.VolumeDetectActive;
//Add collision updates
//part.PhysActor.OnCollisionUpdate += RootPart.PhysicsCollision;
RootPart.PhysActor.OnRequestTerseUpdate += RootPart.PhysicsRequestingTerseUpdate;
RootPart.PhysActor.OnSignificantMovement += RootPart.ParentGroup.CheckForSignificantMovement;
RootPart.PhysActor.OnOutOfBounds += RootPart.PhysicsOutOfBounds;
RootPart.FireOnAddedPhysics();
RootPart.aggregateScriptEvents();
PhysicsActor[] actors = new PhysicsActor[parts.Length - 1];
for (i = 0; i < parts.Length; i++)
{
part = parts[i];
if (part == RootPart ||
part.PhysicsType == (byte)PhysicsShapeType.None ||
((part.Flags & PrimFlags.Phantom) == PrimFlags.Phantom && !part.VolumeDetectActive))
{
continue; // ignore phantom prims
}
//Now read the physics actor to the physics scene
isPhysical = ((part.ParentEntity.RootChild.Flags & PrimFlags.Physics) != 0);
isPhantom = ((part.ParentEntity.RootChild.Flags & PrimFlags.Phantom) != 0);
physical = isPhysical & !isPhantom;
part.PhysActor = m_scene.PhysicsScene.AddPrimShape(part.UUID, part.LocalId, part.Name, RootPart.PhysicsType,
part.Shape, part.AbsolutePosition, part.Scale, part.GetWorldRotation(), physical, part.Material,
part.Friction, part.Restitution, part.GravityMultiplier, part.Density);
if (part.PhysActor == null)
continue;
// part.PhysActor.BuildingRepresentation = true;
// if(part.IsRoot)
//Don't let it rebuild it until we have all the links done
part.PhysActor.VolumeDetect = part.VolumeDetectActive;
//Add collision updates
part.PhysActor.OnRequestTerseUpdate += part.PhysicsRequestingTerseUpdate;
part.PhysActor.OnSignificantMovement += part.ParentGroup.CheckForSignificantMovement;
part.PhysActor.OnOutOfBounds += part.PhysicsOutOfBounds;
part.FireOnAddedPhysics();
part.aggregateScriptEvents();
actors[i] = part.PhysActor;
if(!m_scene.PhysicsScene.AllowGroupLink)
part.PhysActor.Link(RootPart.PhysActor);
}
if (m_scene.PhysicsScene.AllowGroupLink)
RootPart.PhysActor.LinkGroupToThis(actors);
Scene.UniverseEventManager.FireGenericEventHandler("ObjectChangedPhysicalStatus", this);
FixVehicleParams(RootPart);
/*if (physical != RootPart.PhysActor.IsPhysical)
{
RootPart.PhysActor.IsPhysical = physical;
foreach (SceneObjectPart p in parts)
{
if(!p.IsRoot)
p.PhysActor.IsPhysical = physical;
}
}*/
//Force deselection here so that it isn't stuck forever
IsSelected = keepSelectedStatuses && IsSelected;
if (OnFinishedPhysicalRepresentationBuilding != null)
OnFinishedPhysicalRepresentationBuilding();
OnFinishedPhysicalRepresentationBuilding = null;
}