From 430a4aeba8e98b8285ea3ebdf264baf429a55e22 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 19 Jul 2011 03:01:54 +0100 Subject: [PATCH] Fix undo for resizing linksets This involves implementing a boolean in UndoState to signal whether the undo needs to be done for an entire group/linkset or just a single prim Resizing individual components of linksets is still dodgy. Resizing still has to be down twice, since for some reason the client is sending two multiobjectupdate packets on every resize except the very first. This applies to single prims and linksets. Need to look into this. --- .../ClientStack/Linden/UDP/LLClientView.cs | 37 ++++++++++------ .../Framework/Scenes/SceneObjectGroup.cs | 23 ++++++---- .../Framework/Scenes/SceneObjectPart.cs | 42 +++++++++++-------- OpenSim/Region/Framework/Scenes/UndoState.cs | 24 +++++++++-- 4 files changed, 85 insertions(+), 41 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index fa35bd81c6..4c0b53ca53 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11220,8 +11220,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet) { MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; - if (multipleupdate.AgentData.SessionID != SessionId) return false; - // m_log.Debug("new multi update packet " + multipleupdate.ToString()); + + if (multipleupdate.AgentData.SessionID != SessionId) + return false; + +// m_log.DebugFormat( +// "[CLIENT]: Incoming MultipleObjectUpdatePacket contained {0} blocks", multipleupdate.ObjectData.Length); + Scene tScene = (Scene)m_scene; for (int i = 0; i < multipleupdate.ObjectData.Length; i++) @@ -11242,15 +11247,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - // Do this once since fetch parts creates a new array. - SceneObjectPart[] parts = part.ParentGroup.Parts; - for (int j = 0; j < parts.Length; j++) - { - part.StoreUndoState(); - parts[j].IgnoreUndoUpdate = true; - } +// m_log.DebugFormat( +// "[CLIENT]: Processing block {0} type {1} for {2} {3}", +// i, block.Type, part.Name, part.LocalId); + +// // Do this once since fetch parts creates a new array. +// SceneObjectPart[] parts = part.ParentGroup.Parts; +// for (int j = 0; j < parts.Length; j++) +// { +// part.StoreUndoState(); +// parts[j].IgnoreUndoUpdate = true; +// } - // UUID partId = part.UUID; UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; switch (block.Type) @@ -11394,6 +11402,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerUpdatePrimGroupScale != null) { // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); + part.StoreUndoState(true); + part.IgnoreUndoUpdate = true; handlerUpdatePrimGroupScale(localId, scale5, this); handlerUpdateVector = OnUpdatePrimGroupPosition; @@ -11401,7 +11411,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { handlerUpdateVector(localId, pos5, this); } + + part.IgnoreUndoUpdate = false; } + break; case 21: @@ -11426,8 +11439,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP break; } - for (int j = 0; j < parts.Length; j++) - parts[j].IgnoreUndoUpdate = false; +// for (int j = 0; j < parts.Length; j++) +// parts[j].IgnoreUndoUpdate = false; } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 7254992ca0..3bbf76c8fc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2624,6 +2624,8 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); + RootPart.StoreUndoState(true); + scale.X = Math.Min(scale.X, Scene.m_maxNonphys); scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); @@ -2722,16 +2724,20 @@ namespace OpenSim.Region.Framework.Scenes prevScale.X *= x; prevScale.Y *= y; prevScale.Z *= z; + +// RootPart.IgnoreUndoUpdate = true; RootPart.Resize(prevScale); +// RootPart.IgnoreUndoUpdate = false; parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; -// obPart.IgnoreUndoUpdate = true; if (obPart.UUID != m_rootPart.UUID) { + obPart.IgnoreUndoUpdate = true; + Vector3 currentpos = new Vector3(obPart.OffsetPosition); currentpos.X *= x; currentpos.Y *= y; @@ -2741,12 +2747,11 @@ namespace OpenSim.Region.Framework.Scenes newSize.X *= x; newSize.Y *= y; newSize.Z *= z; - - obPart.Resize(newSize); - obPart.IgnoreUndoUpdate = true; + obPart.Resize(newSize); obPart.UpdateOffSet(currentpos); - obPart.IgnoreUndoUpdate = false; + + obPart.IgnoreUndoUpdate = false; } // obPart.IgnoreUndoUpdate = false; @@ -2769,9 +2774,11 @@ namespace OpenSim.Region.Framework.Scenes { // m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos); - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - parts[i].StoreUndoState(); + RootPart.StoreUndoState(true); + +// SceneObjectPart[] parts = m_parts.GetArray(); +// for (int i = 0; i < parts.Length; i++) +// parts[i].StoreUndoState(); if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 44d7ce3505..5414cf2377 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3664,6 +3664,11 @@ namespace OpenSim.Region.Framework.Scenes } public void StoreUndoState() + { + StoreUndoState(false); + } + + public void StoreUndoState(bool forGroup) { if (!Undoing) { @@ -3678,6 +3683,7 @@ namespace OpenSim.Region.Framework.Scenes UndoState last = m_undo.Peek(); if (last != null) { + // TODO: May need to fix for group comparison if (last.Compare(this)) { // m_log.DebugFormat( @@ -3690,12 +3696,12 @@ namespace OpenSim.Region.Framework.Scenes } // m_log.DebugFormat( -// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, initial stack size {2}", -// Name, LocalId, m_undo.Count); +// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", +// Name, LocalId, forGroup, m_undo.Count); if (m_parentGroup.GetSceneMaxUndo() > 0) { - UndoState nUndo = new UndoState(this); + UndoState nUndo = new UndoState(this, forGroup); m_undo.Push(nUndo); @@ -3740,17 +3746,17 @@ namespace OpenSim.Region.Framework.Scenes if (m_undo.Count > 0) { - UndoState nUndo = null; - - if (m_parentGroup.GetSceneMaxUndo() > 0) - { - nUndo = new UndoState(this); - } - UndoState goback = m_undo.Pop(); if (goback != null) { + UndoState nUndo = null; + + if (m_parentGroup.GetSceneMaxUndo() > 0) + { + nUndo = new UndoState(this, goback.ForGroup); + } + goback.PlaybackState(this); if (nUndo != null) @@ -3772,17 +3778,19 @@ namespace OpenSim.Region.Framework.Scenes // "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}", // Name, LocalId, m_redo.Count); - if (m_parentGroup.GetSceneMaxUndo() > 0) - { - UndoState nUndo = new UndoState(this); - - m_undo.Push(nUndo); - } - UndoState gofwd = m_redo.Pop(); if (gofwd != null) + { + if (m_parentGroup.GetSceneMaxUndo() > 0) + { + UndoState nUndo = new UndoState(this, gofwd.ForGroup); + + m_undo.Push(nUndo); + } + gofwd.PlayfwdState(this); + } // m_log.DebugFormat( // "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index 38bbeb0d34..1fa8ee2dba 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs @@ -41,11 +41,17 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 Scale = Vector3.Zero; public Quaternion Rotation = Quaternion.Identity; + /// + /// Is this undo state for an entire group? + /// + public bool ForGroup; + /// /// Constructor. /// /// - public UndoState(SceneObjectPart part) + /// True if the undo is for an entire group + public UndoState(SceneObjectPart part, bool forGroup) { if (part != null) { @@ -62,6 +68,8 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[UNDO STATE]: Storing undo scale {0} for root part", part.Shape.Scale); Scale = part.Shape.Scale; + + ForGroup = forGroup; } else { @@ -141,7 +149,10 @@ namespace OpenSim.Region.Framework.Scenes // "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", // part.Shape.Scale, Scale, part.Name, part.LocalId); - part.Resize(Scale); + if (ForGroup) + part.ParentGroup.GroupResize(Scale); + else + part.Resize(Scale); } part.ParentGroup.ScheduleGroupForTerseUpdate(); @@ -194,7 +205,12 @@ namespace OpenSim.Region.Framework.Scenes part.UpdateRotation(Rotation); if (Scale != Vector3.Zero) - part.Resize(Scale); + { + if (ForGroup) + part.ParentGroup.GroupResize(Scale); + else + part.Resize(Scale); + } part.ParentGroup.ScheduleGroupForTerseUpdate(); } @@ -241,4 +257,4 @@ namespace OpenSim.Region.Framework.Scenes m_terrainModule.UndoTerrain(m_terrainChannel); } } -} +} \ No newline at end of file