From fe2b044d38f3bd3aa669334d34567fd991a67b3e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 3 Jul 2010 06:10:55 -0700 Subject: [PATCH] Fix Undo! Made a lot of changes to Undo state saving; it now considers that groups of objects can be moved and not just individual prims.. --- .../Framework/Scenes/SceneObjectGroup.cs | 39 +++++++++---- .../Framework/Scenes/SceneObjectPart.cs | 16 +++++- OpenSim/Region/Framework/Scenes/UndoState.cs | 55 +++++++++++++++---- 3 files changed, 87 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c48ce3baa5..da664dac40 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -349,7 +349,21 @@ namespace OpenSim.Region.Framework.Scenes public virtual Quaternion Rotation { get { return m_rotation; } - set { m_rotation = value; } + set { + lockPartsForRead(true); + try + { + foreach(SceneObjectPart p in m_parts.Values) + { + p.StoreUndoState(true); + } + } + finally + { + lockPartsForRead(false); + } + m_rotation = value; + } } public Quaternion GroupRotation @@ -421,6 +435,7 @@ namespace OpenSim.Region.Framework.Scenes get { return m_rootPart.GroupPosition; } set { + Vector3 val = value; if ((m_scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || m_scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) @@ -431,7 +446,10 @@ namespace OpenSim.Region.Framework.Scenes } lockPartsForRead(true); - + foreach (SceneObjectPart part in m_parts.Values) + { + part.IgnoreUndoUpdate = true; + } if (RootPart.GetStatusSandbox()) { if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) @@ -443,12 +461,12 @@ namespace OpenSim.Region.Framework.Scenes return; } } - foreach (SceneObjectPart part in m_parts.Values) { + part.IgnoreUndoUpdate = false; + part.StoreUndoState(true); part.GroupPosition = val; } - lockPartsForRead(false); //if (m_rootPart.PhysActor != null) @@ -724,7 +742,6 @@ namespace OpenSim.Region.Framework.Scenes { foreach (SceneObjectPart part in m_parts.Values) { - Vector3 partscale = part.Scale; Vector3 partoffset = part.OffsetPosition; @@ -3132,7 +3149,6 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = GetChildPart(localID); if (part != null) { - part.IgnoreUndoUpdate = true; if (scale.X > m_scene.m_maxNonphys) scale.X = m_scene.m_maxNonphys; if (scale.Y > m_scene.m_maxNonphys) @@ -3218,8 +3234,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - obPart.IgnoreUndoUpdate = false; - obPart.StoreUndoState(); + } } } @@ -3229,13 +3244,17 @@ namespace OpenSim.Region.Framework.Scenes Vector3 prevScale = part.Scale; prevScale.X *= x; prevScale.Y *= y; - prevScale.Z *= z; + prevScale.Z *= z;; + part.IgnoreUndoUpdate = true; part.Resize(prevScale); + part.IgnoreUndoUpdate = false; lockPartsForRead(true); { foreach (SceneObjectPart obPart in m_parts.Values) { + obPart.IgnoreUndoUpdate = false; + obPart.StoreUndoState(true); obPart.IgnoreUndoUpdate = true; if (obPart.UUID != m_rootPart.UUID) { @@ -3251,7 +3270,6 @@ namespace OpenSim.Region.Framework.Scenes obPart.UpdateOffSet(currentpos); } obPart.IgnoreUndoUpdate = false; - obPart.StoreUndoState(); } } lockPartsForRead(false); @@ -3263,7 +3281,6 @@ namespace OpenSim.Region.Framework.Scenes } part.IgnoreUndoUpdate = false; - part.StoreUndoState(); HasGroupChanged = true; ScheduleGroupForTerseUpdate(); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 5b007e603f..72ad281944 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3504,8 +3504,11 @@ namespace OpenSim.Region.Framework.Scenes m_parentGroup.ScheduleGroupForTerseUpdate(); //m_parentGroup.ScheduleGroupForFullUpdate(); } - public void StoreUndoState() + { + StoreUndoState(false); + } + public void StoreUndoState(bool group) { if (!Undoing) { @@ -3528,7 +3531,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_parentGroup.GetSceneMaxUndo() > 0) { UndoState nUndo = new UndoState(this); - + nUndo.GroupChange = group; m_undo.Push(nUndo); } @@ -4010,6 +4013,15 @@ namespace OpenSim.Region.Framework.Scenes nUndo = new UndoState(this); } UndoState goback = m_undo.Pop(); + m_log.Debug("Got goback"); + if (goback == null) + { + m_log.Debug("it's null"); + } + else + { + m_log.Debug(goback.GroupPosition.ToString()); + } if (goback != null) { goback.PlaybackState(this); diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index 55e407ec5f..77381ab7d9 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs @@ -35,6 +35,10 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 Position = Vector3.Zero; public Vector3 Scale = Vector3.Zero; public Quaternion Rotation = Quaternion.Identity; + public bool GroupChange = false; + public Vector3 GroupPosition = Vector3.Zero; + public Quaternion GroupRotation = Quaternion.Identity; + public Vector3 GroupScale = Vector3.Zero; public UndoState(SceneObjectPart part) { @@ -42,12 +46,24 @@ namespace OpenSim.Region.Framework.Scenes { if (part.ParentID == 0) { - Position = part.ParentGroup.AbsolutePosition; + GroupScale = part.Shape.Scale; + + //FUBAR WARNING: Do NOT get the group's absoluteposition here + //or you'll experience a loop and/or a stack issue + GroupPosition = part.ParentGroup.RootPart.AbsolutePosition; + GroupRotation = part.ParentGroup.Rotation; + Position = part.ParentGroup.RootPart.AbsolutePosition; Rotation = part.RotationOffset; Scale = part.Shape.Scale; } else { + GroupScale = part.Shape.Scale; + + //FUBAR WARNING: Do NOT get the group's absoluteposition here + //or you'll experience a loop and/or a stack issue + GroupPosition = part.ParentGroup.RootPart.AbsolutePosition; + GroupRotation = part.ParentGroup.Rotation; Position = part.OffsetPosition; Rotation = part.RotationOffset; Scale = part.Shape.Scale; @@ -61,14 +77,14 @@ namespace OpenSim.Region.Framework.Scenes { if (part.ParentID == 0) { - if (Position == part.ParentGroup.AbsolutePosition && Rotation == part.ParentGroup.Rotation) + if (Position == part.ParentGroup.RootPart.AbsolutePosition && Rotation == part.ParentGroup.Rotation && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale) return true; else return false; } else { - if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale) + if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale) return true; else return false; @@ -84,10 +100,10 @@ namespace OpenSim.Region.Framework.Scenes { part.Undoing = true; - if (part.ParentID == 0) + if (part.ParentID == 0 && GroupChange == false) { if (Position != Vector3.Zero) - part.ParentGroup.AbsolutePosition = Position; + part.ParentGroup.AbsolutePosition = Position; part.RotationOffset = Rotation; if (Scale != Vector3.Zero) part.Resize(Scale); @@ -95,11 +111,30 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (Position != Vector3.Zero) - part.OffsetPosition = Position; - part.UpdateRotation(Rotation); - if (Scale != Vector3.Zero) - part.Resize(Scale); part.ScheduleTerseUpdate(); + if (GroupChange) + { + if (Position != Vector3.Zero) + { + //Calculate the scale... + Vector3 gs = part.Shape.Scale; + float scale = GroupScale.Z / gs.Z; + + //Scale first since it can affect our position + part.ParentGroup.GroupResize(gs * scale, part.LocalId); + part.ParentGroup.AbsolutePosition = GroupPosition; + part.ParentGroup.Rotation = GroupRotation; + + } + } + else + { + if (Position != Vector3.Zero) //We can use this for all the updates since all are set + { + part.OffsetPosition = Position; + part.UpdateRotation(Rotation); + part.Resize(Scale); part.ScheduleTerseUpdate(); + } + } } part.Undoing = false;