diff --git a/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs index d1d318c562..4455df49a6 100755 --- a/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs @@ -29,6 +29,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; +using System.Threading; using OpenSim.Framework; using OpenSim.Region.CoreModules; @@ -198,7 +199,33 @@ public class ExtendedPhysics : INonSharedRegionModule Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor; if (rootPhysActor != null) { - ret = (int)rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType); + if (rootPhysActor.IsPhysical) + { + // Change a physical linkset by making non-physical, waiting for one heartbeat so all + // the prim and linkset state is updated, changing the type and making the + // linkset physical again. + containingGroup.ScriptSetPhysicsStatus(false); + Thread.Sleep(150); // longer than one heartbeat tick + + // A kludge for the moment. + // Since compound linksets move the children but don't generate position updates to the + // simulator, it is possible for compound linkset children to have out-of-sync simulator + // and physical positions. The following causes the simulator to push the real child positions + // down into the physics engine to get everything synced. + containingGroup.UpdateGroupPosition(containingGroup.AbsolutePosition); + containingGroup.UpdateGroupRotationR(containingGroup.GroupRotation); + + ret = (int)rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType); + Thread.Sleep(150); // longer than one heartbeat tick + + containingGroup.ScriptSetPhysicsStatus(true); + } + else + { + // Non-physical linksets don't have a physical instantiation so there is no state to + // worry about being updated. + ret = (int)rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType); + } } else { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3afd52e142..a051002b39 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -148,7 +148,7 @@ public abstract class BSLinkset // Returns a new linkset for the child which is a linkset of one (just the // orphened child). // Called at runtime. - public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child) + public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child, bool inTaintTime) { lock (m_linksetActivityLock) { @@ -157,7 +157,7 @@ public abstract class BSLinkset // Cannot remove the root from a linkset. return this; } - RemoveChildFromLinkset(child); + RemoveChildFromLinkset(child, inTaintTime); LinksetMass = ComputeLinksetMass(); } @@ -255,7 +255,7 @@ public abstract class BSLinkset // I am the root of a linkset and one of my children is being removed. // Safe to call even if the child is not really in my linkset. - protected abstract void RemoveChildFromLinkset(BSPrimLinkable child); + protected abstract void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime); // When physical properties are changed the linkset needs to recalculate // its internal properties. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 085d195d83..47ab8424b4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -242,7 +242,7 @@ public sealed class BSLinksetCompound : BSLinkset { bool ret = false; - DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", + DetailLog("{0},BSLinksetCompound.RemoveDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child)); ScheduleRebuild(child); @@ -270,7 +270,7 @@ public sealed class BSLinksetCompound : BSLinkset // Remove the specified child from the linkset. // Safe to call even if the child is not really in the linkset. - protected override void RemoveChildFromLinkset(BSPrimLinkable child) + protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime) { child.ClearDisplacement(); @@ -282,12 +282,12 @@ public sealed class BSLinksetCompound : BSLinkset child.LocalID, child.PhysBody.AddrString); // Cause the child's body to be rebuilt and thus restored to normal operation - child.ForceBodyShapeRebuild(false); + child.ForceBodyShapeRebuild(inTaintTime); if (!HasAnyChildren) { // The linkset is now empty. The root needs rebuilding. - LinksetRoot.ForceBodyShapeRebuild(false); + LinksetRoot.ForceBodyShapeRebuild(inTaintTime); } else { @@ -318,10 +318,10 @@ public sealed class BSLinksetCompound : BSLinkset // being destructed and going non-physical. LinksetRoot.ForceBodyShapeRebuild(true); - // There is no reason to build all this physical stuff for a non-physical linkset. - if (!LinksetRoot.IsPhysicallyActive) + // There is no reason to build all this physical stuff for a non-physical or empty linkset. + if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren) { - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID); + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID); return; // Note the 'finally' clause at the botton which will get executed. } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 4bac222ab2..d4ee27d31d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -224,7 +224,7 @@ public sealed class BSLinksetConstraints : BSLinkset // Remove the specified child from the linkset. // Safe to call even if the child is not really in my linkset. - protected override void RemoveChildFromLinkset(BSPrimLinkable child) + protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime) { if (m_children.Remove(child)) { @@ -236,7 +236,7 @@ public sealed class BSLinksetConstraints : BSLinkset rootx.LocalID, rootx.PhysBody.AddrString, childx.LocalID, childx.PhysBody.AddrString); - m_physicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() + m_physicsScene.TaintedObject(inTaintTime, "BSLinksetConstraints.RemoveChildFromLinkset", delegate() { PhysicallyUnlinkAChildFromRoot(rootx, childx); }); @@ -382,9 +382,9 @@ public sealed class BSLinksetConstraints : BSLinkset Rebuilding = true; // There is no reason to build all this physical stuff for a non-physical linkset. - if (!LinksetRoot.IsPhysicallyActive) + if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren) { - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID); + DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID); return; // Note the 'finally' clause at the botton which will get executed. } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs index 7179a6d571..38d1f88053 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs @@ -66,7 +66,7 @@ public class BSPrimLinkable : BSPrimDisplaced public override void Destroy() { - Linkset = Linkset.RemoveMeFromLinkset(this); + Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime */); base.Destroy(); } @@ -94,7 +94,7 @@ public class BSPrimLinkable : BSPrimDisplaced BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG int childrenBefore = Linkset.NumberOfChildren; // DEBUG - Linkset = Linkset.RemoveMeFromLinkset(this); + Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime*/); DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); @@ -240,6 +240,8 @@ public class BSPrimLinkable : BSPrimDisplaced bool ret = false; if (LinksetType != newType) { + DetailLog("{0},BSPrimLinkset.ConvertLinkset,oldT={1},newT={2}", LocalID, LinksetType, newType); + // Set the implementation type first so the call to BSLinkset.Factory gets the new type. this.LinksetType = newType; @@ -263,7 +265,10 @@ public class BSPrimLinkable : BSPrimDisplaced // Remove the children from the old linkset and add to the new (will be a new instance from the factory) foreach (BSPrimLinkable child in children) { - oldLinkset.RemoveMeFromLinkset(child); + oldLinkset.RemoveMeFromLinkset(child, true /*inTaintTime*/); + } + foreach (BSPrimLinkable child in children) + { newLinkset.AddMeToLinkset(child); child.Linkset = newLinkset; }