From 19ab4c950880beb3ac88a172b775c3973782ec3d Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 16:52:03 -0700 Subject: [PATCH] Fix a rather nasty issue where the Backup() process causes objects and avatars sitting on them to be pushed to the corner of the sim. --- .../Framework/Scenes/SceneObjectGroup.cs | 199 ++++++++++-------- .../Framework/Scenes/SceneObjectPart.cs | 25 ++- 2 files changed, 120 insertions(+), 104 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a8281271fa..0d15cb45d5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -317,8 +317,8 @@ namespace OpenSim.Region.Framework.Scenes private bool m_scriptListens_notAtTarget = false; private bool m_scriptListens_atRotTarget = false; - private bool m_scriptListens_notAtRotTarget = false; - + private bool m_scriptListens_notAtRotTarget = false; + public bool m_dupeInProgress = false; internal Dictionary m_savedScriptState = null; #region Properties @@ -475,16 +475,21 @@ namespace OpenSim.Region.Framework.Scenes { part.IgnoreUndoUpdate = false; part.StoreUndoState(UndoType.STATE_GROUP_POSITION); - part.GroupPosition = val; - part.TriggerScriptChangedEvent(Changed.POSITION); - } - - foreach (ScenePresence av in m_linkedAvatars) - { - Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; - av.AbsolutePosition += offset; - av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition - av.SendFullUpdateToAllClients(); + part.GroupPosition = val; + if (!m_dupeInProgress) + { + part.TriggerScriptChangedEvent(Changed.POSITION); + } + } + if (!m_dupeInProgress) + { + foreach (ScenePresence av in m_linkedAvatars) + { + Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; + av.AbsolutePosition += offset; + av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition + av.SendFullUpdateToAllClients(); + } } //if (m_rootPart.PhysActor != null) @@ -1800,88 +1805,96 @@ namespace OpenSim.Region.Framework.Scenes /// True if the duplicate will immediately be in the scene, false otherwise /// public SceneObjectGroup Copy(bool userExposed) - { - SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); - dupe.m_isBackedUp = false; - dupe.m_parts = new Dictionary(); - - // Warning, The following code related to previousAttachmentStatus is needed so that clones of - // attachments do not bordercross while they're being duplicated. This is hacktastic! - // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! - // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state - // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, - // then restore it's attachment state - - // This is only necessary when userExposed is false! - - bool previousAttachmentStatus = dupe.RootPart.IsAttachment; - - if (!userExposed) - dupe.RootPart.IsAttachment = true; - - dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); - - if (!userExposed) - { - dupe.RootPart.IsAttachment = previousAttachmentStatus; + { + SceneObjectGroup dupe; + try + { + m_dupeInProgress = true; + dupe = (SceneObjectGroup)MemberwiseClone(); + dupe.m_isBackedUp = false; + dupe.m_parts = new Dictionary(); + + // Warning, The following code related to previousAttachmentStatus is needed so that clones of + // attachments do not bordercross while they're being duplicated. This is hacktastic! + // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! + // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state + // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, + // then restore it's attachment state + + // This is only necessary when userExposed is false! + + bool previousAttachmentStatus = dupe.RootPart.IsAttachment; + + if (!userExposed) + dupe.RootPart.IsAttachment = true; + + dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); + + if (!userExposed) + { + dupe.RootPart.IsAttachment = previousAttachmentStatus; + } + + dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); + dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; + + if (userExposed) + dupe.m_rootPart.TrimPermissions(); + + /// may need to create a new Physics actor. + if (dupe.RootPart.PhysActor != null && userExposed) + { + PrimitiveBaseShape pbs = dupe.RootPart.Shape; + + dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( + dupe.RootPart.Name, + pbs, + dupe.RootPart.AbsolutePosition, + dupe.RootPart.Scale, + dupe.RootPart.RotationOffset, + dupe.RootPart.PhysActor.IsPhysical); + + dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; + dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); + } + + List partList; + + lockPartsForRead(true); + + partList = new List(m_parts.Values); + + lockPartsForRead(false); + + partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) + { + return p1.LinkNum.CompareTo(p2.LinkNum); + } + ); + + foreach (SceneObjectPart part in partList) + { + if (part.UUID != m_rootPart.UUID) + { + SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); + + newPart.LinkNum = part.LinkNum; + } + } + + if (userExposed) + { + dupe.UpdateParentIDs(); + dupe.HasGroupChanged = true; + dupe.AttachToBackup(); + + ScheduleGroupForFullUpdate(); + } + } + finally + { + m_dupeInProgress = false; } - - dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); - dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; - - if (userExposed) - dupe.m_rootPart.TrimPermissions(); - - /// may need to create a new Physics actor. - if (dupe.RootPart.PhysActor != null && userExposed) - { - PrimitiveBaseShape pbs = dupe.RootPart.Shape; - - dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( - dupe.RootPart.Name, - pbs, - dupe.RootPart.AbsolutePosition, - dupe.RootPart.Scale, - dupe.RootPart.RotationOffset, - dupe.RootPart.PhysActor.IsPhysical); - - dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; - dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); - } - - List partList; - - lockPartsForRead(true); - - partList = new List(m_parts.Values); - - lockPartsForRead(false); - - partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) - { - return p1.LinkNum.CompareTo(p2.LinkNum); - } - ); - - foreach (SceneObjectPart part in partList) - { - if (part.UUID != m_rootPart.UUID) - { - SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); - - newPart.LinkNum = part.LinkNum; - } - } - - if (userExposed) - { - dupe.UpdateParentIDs(); - dupe.HasGroupChanged = true; - dupe.AttachToBackup(); - - ScheduleGroupForFullUpdate(); - } - return dupe; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b0ce450b9b..77581af6ac 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -718,17 +718,20 @@ namespace OpenSim.Region.Framework.Scenes // Tell the physics engines that this prim changed. m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); - } - - List avs = ParentGroup.GetLinkedAvatars(); - foreach (ScenePresence av in avs) - { - if (av.LinkedPrim == m_uuid) - { - Vector3 offset = (m_offsetPosition - oldpos); - av.OffsetPosition += offset; - av.SendFullUpdateToAllClients(); - } + } + + if (!m_parentGroup.m_dupeInProgress) + { + List avs = ParentGroup.GetLinkedAvatars(); + foreach (ScenePresence av in avs) + { + if (av.LinkedPrim == m_uuid) + { + Vector3 offset = (m_offsetPosition - oldpos); + av.OffsetPosition += offset; + av.SendFullUpdateToAllClients(); + } + } } } TriggerScriptChangedEvent(Changed.POSITION);