From 1fb54b074c243bab1964b4a568d672e87d18655f Mon Sep 17 00:00:00 2001
From: Teravus Ovares
Date: Mon, 28 Apr 2008 01:48:21 +0000
Subject: * Added basic 3-5 level undo on prim position/rotation/scale. * In
the future this should be a config option... and, hopefully this tides the
builders over for a little while.
---
OpenSim/Region/ClientStack/ClientView.cs | 19 ++++
OpenSim/Region/Environment/Scenes/InnerScene.cs | 14 +++
OpenSim/Region/Environment/Scenes/Scene.cs | 2 +
.../Region/Environment/Scenes/SceneObjectGroup.cs | 25 ++++-
.../Region/Environment/Scenes/SceneObjectPart.cs | 69 +++++++++++-
OpenSim/Region/Environment/Scenes/UndoState.cs | 118 +++++++++++++++++++++
.../Region/Examples/SimpleModule/MyNpcCharacter.cs | 1 +
7 files changed, 240 insertions(+), 8 deletions(-)
create mode 100644 OpenSim/Region/Environment/Scenes/UndoState.cs
(limited to 'OpenSim/Region')
diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs
index 94de013..aac96d1 100644
--- a/OpenSim/Region/ClientStack/ClientView.cs
+++ b/OpenSim/Region/ClientStack/ClientView.cs
@@ -238,6 +238,7 @@ namespace OpenSim.Region.ClientStack
private ScriptAnswer handlerScriptAnswer = null;
private RequestPayPrice handlerRequestPayPrice = null;
private ObjectDeselect handlerObjectDetach = null;
+ private AgentSit handlerOnUndo = null;
/* Properties */
@@ -799,6 +800,7 @@ namespace OpenSim.Region.ClientStack
public event ScriptAnswer OnScriptAnswer;
public event RequestPayPrice OnRequestPayPrice;
+ public event AgentSit OnUndo;
#region Scene/Avatar to Client
@@ -3884,6 +3886,23 @@ namespace OpenSim.Region.ClientStack
// That means multiple object perms may be updated in a single packet.
break;
+
+ case PacketType.Undo:
+ UndoPacket undoitem = (UndoPacket)Pack;
+ if (undoitem.ObjectData.Length > 0)
+ {
+ for (int i = 0; i < undoitem.ObjectData.Length; i++)
+ {
+ LLUUID objiD = undoitem.ObjectData[i].ObjectID;
+ handlerOnUndo = OnUndo;
+ if (handlerOnUndo != null)
+ {
+ handlerOnUndo(this, objiD);
+ }
+
+ }
+ }
+ break;
case PacketType.ObjectDuplicateOnRay:
ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack;
diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs
index d00f601..8a48f6e 100644
--- a/OpenSim/Region/Environment/Scenes/InnerScene.cs
+++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs
@@ -312,6 +312,20 @@ namespace OpenSim.Region.Environment.Scenes
}
}
+
+ public void HandleUndo(IClientAPI remoteClient, LLUUID primId)
+ {
+ if (primId != LLUUID.Zero)
+ {
+ SceneObjectPart part = m_parentScene.GetSceneObjectPart(primId);
+ if (part != null)
+ part.Undo();
+
+ }
+
+
+ }
+
///
/// Event Handling routine for Attach Object
///
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
index a517e69..de4270f 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -78,6 +78,7 @@ namespace OpenSim.Region.Environment.Scenes
private readonly Mutex updateLock;
public bool m_physicalPrim;
public bool m_seeIntoRegionFromNeighbor;
+ public int MaxUndoCount = 5;
private int m_RestartTimerCounter;
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
private int m_incrementsof15seconds = 0;
@@ -1628,6 +1629,7 @@ namespace OpenSim.Region.Environment.Scenes
client.OnTeleportHomeRequest += TeleportClientHome;
client.OnSetStartLocationRequest += SetHomeRezPoint;
+ client.OnUndo += m_innerScene.HandleUndo;
EventManager.TriggerOnNewClient(client);
}
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
index ba318a8..4711701 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -378,6 +378,7 @@ namespace OpenSim.Region.Environment.Scenes
part.RegionHandle = m_regionHandle;
part.TrimPermissions();
+ part.StoreUndoState();
}
break;
case XmlNodeType.EndElement:
@@ -436,6 +437,7 @@ namespace OpenSim.Region.Environment.Scenes
{
SceneObjectPart Part = SceneObjectPart.FromXml(reader);
AddPart(Part);
+ Part.StoreUndoState();
}
else
{
@@ -703,6 +705,8 @@ namespace OpenSim.Region.Environment.Scenes
m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_scene.m_physicalPrim);
AttachToBackup();
m_rootPart.ScheduleFullUpdate();
+ m_rootPart.ClearUndoState();
+
}
public void DetachToInventoryPrep()
{
@@ -731,6 +735,7 @@ namespace OpenSim.Region.Environment.Scenes
private void SetPartAsNonRoot(SceneObjectPart part)
{
part.ParentID = m_rootPart.LocalId;
+ part.ClearUndoState();
}
///
@@ -783,6 +788,7 @@ namespace OpenSim.Region.Environment.Scenes
try
{
m_parts.Add(part.UUID, part);
+
}
catch (Exception e)
{
@@ -803,6 +809,7 @@ namespace OpenSim.Region.Environment.Scenes
if (part.UUID != m_rootPart.UUID)
{
part.ParentID = m_rootPart.LocalId;
+
}
}
}
@@ -815,10 +822,17 @@ namespace OpenSim.Region.Environment.Scenes
foreach (SceneObjectPart part in m_parts.Values)
{
part.UUID = LLUUID.Random();
+
}
}
}
-
+ // helper provided for parts.
+ public int GetSceneMaxUndo()
+ {
+ if (m_scene != null)
+ return m_scene.MaxUndoCount;
+ return 5;
+ }
public void ResetChildPrimPhysicsPositions()
{
AbsolutePosition = AbsolutePosition;
@@ -845,12 +859,15 @@ namespace OpenSim.Region.Environment.Scenes
{
SceneObjectPart part = GetChildPart(localId);
OnGrabPart(part, offsetPos, remoteClient);
+
}
}
public virtual void OnGrabPart(SceneObjectPart part, LLVector3 offsetPos, IClientAPI remoteClient)
{
+ part.StoreUndoState();
part.OnGrab(offsetPos, remoteClient);
+
}
public virtual void OnGrabGroup(LLVector3 offsetPos, IClientAPI remoteClient)
@@ -1382,8 +1399,9 @@ namespace OpenSim.Region.Environment.Scenes
{
m_parts.Add(newPart.UUID, newPart);
}
-
+
SetPartAsNonRoot(newPart);
+
}
///
@@ -1758,6 +1776,7 @@ namespace OpenSim.Region.Environment.Scenes
{
LinkNonRootPart(part, oldGroupPosition, oldRootRotation);
}
+ part.ClearUndoState();
}
DetachFromBackup(objectGroup);
@@ -1781,7 +1800,7 @@ namespace OpenSim.Region.Environment.Scenes
public void DelinkFromGroup(uint partID)
{
SceneObjectPart linkPart = GetChildPart(partID);
-
+ linkPart.ClearUndoState();
if (null != linkPart)
{
// m_log.DebugFormat(
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index 0db9b91..6cfe3e9 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -26,6 +26,7 @@
*/
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.Serialization;
@@ -106,6 +107,8 @@ namespace OpenSim.Region.Environment.Scenes
[XmlIgnore] public LLVector3 m_attachedPos = LLVector3.Zero;
[XmlIgnore] public LLUUID fromAssetID = LLUUID.Zero;
+ [XmlIgnore] public bool m_undoing = false;
+
public Int32 CreationDate;
public uint ParentID = 0;
@@ -123,6 +126,8 @@ namespace OpenSim.Region.Environment.Scenes
public uint EveryoneMask = (uint)PermissionMask.None;
public uint NextOwnerMask = (uint)PermissionMask.All;
+ private UndoStack m_undo = new UndoStack(5);
+
public LLObject.ObjectFlags Flags = LLObject.ObjectFlags.None;
public uint ObjectFlags
@@ -266,6 +271,40 @@ namespace OpenSim.Region.Environment.Scenes
//return new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w);
}
+
+ public void StoreUndoState()
+ {
+ if (!m_undoing)
+ {
+ if (m_parentGroup != null)
+ {
+ if (m_undo.Count > 0)
+ {
+ UndoState last = m_undo.Peek();
+ if (last != null)
+ {
+ if (last.Compare(this))
+ return;
+ }
+ }
+
+
+ if (m_parentGroup.GetSceneMaxUndo() > 0)
+ {
+ UndoState nUndo = new UndoState(this);
+
+ m_undo.Push(nUndo);
+
+ }
+ }
+ }
+ }
+
+ public void ClearUndoState()
+ {
+ m_undo.Clear();
+ StoreUndoState();
+ }
public LLVector3 GroupPosition
{
@@ -290,7 +329,9 @@ namespace OpenSim.Region.Environment.Scenes
return m_groupPosition;
}
set
- {
+ {
+ StoreUndoState();
+
m_groupPosition = value;
if (PhysActor != null)
@@ -334,7 +375,10 @@ namespace OpenSim.Region.Environment.Scenes
public LLVector3 OffsetPosition
{
get { return m_offsetPosition; }
- set { m_offsetPosition = value;
+ set
+ {
+ StoreUndoState();
+ m_offsetPosition = value;
try
{
// Hack to get the child prim to update world positions in the physics engine
@@ -380,6 +424,7 @@ namespace OpenSim.Region.Environment.Scenes
}
set
{
+ StoreUndoState();
m_rotationOffset = value;
if (PhysActor != null)
@@ -650,7 +695,8 @@ namespace OpenSim.Region.Environment.Scenes
{
get { return m_shape.Scale; }
set
- {
+ {
+ StoreUndoState();
m_shape.Scale = value;
TriggerScriptChangedEvent(Changed.SCALE);
}
@@ -759,7 +805,8 @@ namespace OpenSim.Region.Environment.Scenes
LLObject.ObjectFlags.CreateSelected;
TrimPermissions();
-
+ //m_undo = new UndoStack(ParentGroup.GetSceneMaxUndo());
+
ScheduleFullUpdate();
}
@@ -802,7 +849,7 @@ namespace OpenSim.Region.Environment.Scenes
TrimPermissions();
// ApplyPhysics();
-
+
ScheduleFullUpdate();
}
@@ -1982,6 +2029,7 @@ namespace OpenSim.Region.Environment.Scenes
public void UpdateRotation(LLQuaternion rot)
{
+ //StoreUndoState();
RotationOffset = new LLQuaternion(rot.X, rot.Y, rot.Z, rot.W);
ScheduleTerseUpdate();
}
@@ -2097,6 +2145,7 @@ namespace OpenSim.Region.Environment.Scenes
///
public void Resize(LLVector3 scale)
{
+ StoreUndoState();
m_shape.Scale = scale;
ScheduleFullUpdate();
@@ -2522,5 +2571,15 @@ namespace OpenSim.Region.Environment.Scenes
info.AddValue("PayPrice", PayPrice);
}
+
+ public void Undo()
+ {
+ if (m_undo.Count > 0)
+ {
+ UndoState goback = m_undo.Pop();
+ if (goback != null)
+ goback.PlaybackState(this);
+ }
+ }
}
}
diff --git a/OpenSim/Region/Environment/Scenes/UndoState.cs b/OpenSim/Region/Environment/Scenes/UndoState.cs
new file mode 100644
index 0000000..65c8669
--- /dev/null
+++ b/OpenSim/Region/Environment/Scenes/UndoState.cs
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSim Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using libsecondlife;
+
+namespace OpenSim.Region.Environment.Scenes
+{
+ public class UndoState
+ {
+ public LLVector3 Position = LLVector3.Zero;
+ public LLVector3 Scale = LLVector3.Zero;
+ public LLQuaternion Rotation = LLQuaternion.Identity;
+
+ public UndoState(LLVector3 pos, LLQuaternion rot, LLVector3 scale)
+ {
+ Position = pos;
+ Rotation = rot;
+ Scale = scale;
+ }
+
+ public UndoState(SceneObjectPart part)
+ {
+ if (part != null)
+ {
+ if (part.ParentID == 0)
+ {
+ Position = part.AbsolutePosition;
+ Rotation = part.RotationOffset;
+
+ }
+ else
+ {
+ Position = part.GroupPosition;
+ Rotation = part.RotationOffset;
+ Scale = part.Shape.Scale;
+
+ }
+ }
+ }
+
+ public bool Compare(SceneObjectPart part)
+ {
+ if (part != null)
+ {
+ if (part.ParentID == 0)
+ {
+ if (Position == part.AbsolutePosition && Rotation == part.RotationOffset)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ if (Position == part.GroupPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale)
+ return true;
+ else
+ return false;
+
+ }
+ }
+ return false;
+ }
+
+ public void PlaybackState(SceneObjectPart part)
+ {
+ if (part != null)
+ {
+ part.m_undoing = true;
+
+ if (part.ParentID == 0)
+ {
+ part.ParentGroup.AbsolutePosition = Position;
+ part.UpdateRotation(Rotation);
+ part.ParentGroup.ScheduleGroupForTerseUpdate();
+ }
+ else
+ {
+ part.OffsetPosition = Position;
+ part.UpdateRotation(Rotation);
+ part.Resize(Scale);
+ part.ScheduleTerseUpdate();
+ }
+ part.m_undoing = false;
+
+ }
+ }
+
+ public UndoState()
+ {
+ }
+ }
+}
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 9e57da5..59a2fd8 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -171,6 +171,7 @@ namespace OpenSim.Region.Examples.SimpleModule
public event ScriptAnswer OnScriptAnswer;
public event RequestPayPrice OnRequestPayPrice;
+ public event AgentSit OnUndo;
#pragma warning restore 67
--
cgit v1.1