aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorTeravus Ovares2008-04-28 01:48:21 +0000
committerTeravus Ovares2008-04-28 01:48:21 +0000
commit1fb54b074c243bab1964b4a568d672e87d18655f (patch)
tree1a9a113d09b94a10e5113e1b2e613039029d52a7
parent* Added String(FileExtension) property to ITerrainLoader to allow us to deter... (diff)
downloadopensim-SC_OLD-1fb54b074c243bab1964b4a568d672e87d18655f.zip
opensim-SC_OLD-1fb54b074c243bab1964b4a568d672e87d18655f.tar.gz
opensim-SC_OLD-1fb54b074c243bab1964b4a568d672e87d18655f.tar.bz2
opensim-SC_OLD-1fb54b074c243bab1964b4a568d672e87d18655f.tar.xz
* 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.
-rw-r--r--OpenSim/Framework/IClientAPI.cs2
-rw-r--r--OpenSim/Framework/UndoStack.cs128
-rw-r--r--OpenSim/Region/ClientStack/ClientView.cs19
-rw-r--r--OpenSim/Region/Environment/Scenes/InnerScene.cs14
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.cs2
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs25
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectPart.cs69
-rw-r--r--OpenSim/Region/Environment/Scenes/UndoState.cs118
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs1
9 files changed, 370 insertions, 8 deletions
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index fb32397..985e085 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -570,6 +570,8 @@ namespace OpenSim.Framework
570 event UUIDNameRequest OnTeleportHomeRequest; 570 event UUIDNameRequest OnTeleportHomeRequest;
571 571
572 event ScriptAnswer OnScriptAnswer; 572 event ScriptAnswer OnScriptAnswer;
573
574 event AgentSit OnUndo;
573 575
574 LLVector3 StartPos { get; set; } 576 LLVector3 StartPos { get; set; }
575 577
diff --git a/OpenSim/Framework/UndoStack.cs b/OpenSim/Framework/UndoStack.cs
new file mode 100644
index 0000000..0b97644
--- /dev/null
+++ b/OpenSim/Framework/UndoStack.cs
@@ -0,0 +1,128 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31
32namespace OpenSim.Framework
33{
34 /// <summary>
35 /// Undo stack. Deletes entries beyond a certain capacity
36 /// </summary>
37 /// <typeparam name="T"></typeparam>
38 [Serializable]
39 public class UndoStack<T>
40 {
41
42 private int m_new = 1;
43 private int m_old = 0;
44 private T[] m_Undos;
45
46 public bool IsFull
47 {
48 get
49 {
50 return m_new == m_old;
51 }
52 }
53
54
55 public int Capacity
56 {
57 get
58 {
59 return m_Undos.Length - 1;
60 }
61 }
62
63
64 public UndoStack(int capacity)
65 {
66 m_Undos = new T[capacity + 1];
67 }
68
69 public void Push(T item)
70 {
71 if (IsFull)
72 {
73 m_old++;
74 if (m_old >= m_Undos.Length)
75 m_old -= m_Undos.Length;
76 }
77 if (++m_new >= m_Undos.Length)
78 m_new -= m_Undos.Length;
79 m_Undos[m_new] = item;
80 }
81
82 public T Pop()
83 {
84 if (Count > 0)
85 {
86 T deleted = m_Undos[m_new];
87 m_Undos[m_new--] = default(T);
88 if (m_new < 0)
89 m_new += m_Undos.Length;
90 return deleted;
91 }
92 else
93 throw new InvalidOperationException("Cannot pop from emtpy stack");
94 }
95
96 public int Count
97 {
98 get
99 {
100 int count = m_new - m_old - 1;
101 if (count < 0)
102 count += m_Undos.Length;
103 return count;
104 }
105 }
106
107
108 public T Peek()
109 {
110 return m_Undos[m_new];
111 }
112
113
114 public void Clear()
115 {
116 if (Count > 0)
117 {
118 for (int i = 0; i < m_Undos.Length; i++)
119 {
120 m_Undos[i] = default(T);
121 }
122 m_new = 1;
123 m_old = 0;
124 }
125 }
126
127 }
128} \ No newline at end of file
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
238 private ScriptAnswer handlerScriptAnswer = null; 238 private ScriptAnswer handlerScriptAnswer = null;
239 private RequestPayPrice handlerRequestPayPrice = null; 239 private RequestPayPrice handlerRequestPayPrice = null;
240 private ObjectDeselect handlerObjectDetach = null; 240 private ObjectDeselect handlerObjectDetach = null;
241 private AgentSit handlerOnUndo = null;
241 242
242 /* Properties */ 243 /* Properties */
243 244
@@ -799,6 +800,7 @@ namespace OpenSim.Region.ClientStack
799 800
800 public event ScriptAnswer OnScriptAnswer; 801 public event ScriptAnswer OnScriptAnswer;
801 public event RequestPayPrice OnRequestPayPrice; 802 public event RequestPayPrice OnRequestPayPrice;
803 public event AgentSit OnUndo;
802 804
803 #region Scene/Avatar to Client 805 #region Scene/Avatar to Client
804 806
@@ -3884,6 +3886,23 @@ namespace OpenSim.Region.ClientStack
3884 // That means multiple object perms may be updated in a single packet. 3886 // That means multiple object perms may be updated in a single packet.
3885 3887
3886 break; 3888 break;
3889
3890 case PacketType.Undo:
3891 UndoPacket undoitem = (UndoPacket)Pack;
3892 if (undoitem.ObjectData.Length > 0)
3893 {
3894 for (int i = 0; i < undoitem.ObjectData.Length; i++)
3895 {
3896 LLUUID objiD = undoitem.ObjectData[i].ObjectID;
3897 handlerOnUndo = OnUndo;
3898 if (handlerOnUndo != null)
3899 {
3900 handlerOnUndo(this, objiD);
3901 }
3902
3903 }
3904 }
3905 break;
3887 case PacketType.ObjectDuplicateOnRay: 3906 case PacketType.ObjectDuplicateOnRay:
3888 ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack; 3907 ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack;
3889 3908
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
312 } 312 }
313 313
314 } 314 }
315
316 public void HandleUndo(IClientAPI remoteClient, LLUUID primId)
317 {
318 if (primId != LLUUID.Zero)
319 {
320 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primId);
321 if (part != null)
322 part.Undo();
323
324 }
325
326
327 }
328
315 /// <summary> 329 /// <summary>
316 /// Event Handling routine for Attach Object 330 /// Event Handling routine for Attach Object
317 /// </summary> 331 /// </summary>
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
78 private readonly Mutex updateLock; 78 private readonly Mutex updateLock;
79 public bool m_physicalPrim; 79 public bool m_physicalPrim;
80 public bool m_seeIntoRegionFromNeighbor; 80 public bool m_seeIntoRegionFromNeighbor;
81 public int MaxUndoCount = 5;
81 private int m_RestartTimerCounter; 82 private int m_RestartTimerCounter;
82 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 83 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
83 private int m_incrementsof15seconds = 0; 84 private int m_incrementsof15seconds = 0;
@@ -1628,6 +1629,7 @@ namespace OpenSim.Region.Environment.Scenes
1628 client.OnTeleportHomeRequest += TeleportClientHome; 1629 client.OnTeleportHomeRequest += TeleportClientHome;
1629 1630
1630 client.OnSetStartLocationRequest += SetHomeRezPoint; 1631 client.OnSetStartLocationRequest += SetHomeRezPoint;
1632 client.OnUndo += m_innerScene.HandleUndo;
1631 1633
1632 EventManager.TriggerOnNewClient(client); 1634 EventManager.TriggerOnNewClient(client);
1633 } 1635 }
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
378 part.RegionHandle = m_regionHandle; 378 part.RegionHandle = m_regionHandle;
379 379
380 part.TrimPermissions(); 380 part.TrimPermissions();
381 part.StoreUndoState();
381 } 382 }
382 break; 383 break;
383 case XmlNodeType.EndElement: 384 case XmlNodeType.EndElement:
@@ -436,6 +437,7 @@ namespace OpenSim.Region.Environment.Scenes
436 { 437 {
437 SceneObjectPart Part = SceneObjectPart.FromXml(reader); 438 SceneObjectPart Part = SceneObjectPart.FromXml(reader);
438 AddPart(Part); 439 AddPart(Part);
440 Part.StoreUndoState();
439 } 441 }
440 else 442 else
441 { 443 {
@@ -703,6 +705,8 @@ namespace OpenSim.Region.Environment.Scenes
703 m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_scene.m_physicalPrim); 705 m_rootPart.ApplyPhysics(m_rootPart.ObjectFlags, m_scene.m_physicalPrim);
704 AttachToBackup(); 706 AttachToBackup();
705 m_rootPart.ScheduleFullUpdate(); 707 m_rootPart.ScheduleFullUpdate();
708 m_rootPart.ClearUndoState();
709
706 } 710 }
707 public void DetachToInventoryPrep() 711 public void DetachToInventoryPrep()
708 { 712 {
@@ -731,6 +735,7 @@ namespace OpenSim.Region.Environment.Scenes
731 private void SetPartAsNonRoot(SceneObjectPart part) 735 private void SetPartAsNonRoot(SceneObjectPart part)
732 { 736 {
733 part.ParentID = m_rootPart.LocalId; 737 part.ParentID = m_rootPart.LocalId;
738 part.ClearUndoState();
734 } 739 }
735 740
736 /// <summary> 741 /// <summary>
@@ -783,6 +788,7 @@ namespace OpenSim.Region.Environment.Scenes
783 try 788 try
784 { 789 {
785 m_parts.Add(part.UUID, part); 790 m_parts.Add(part.UUID, part);
791
786 } 792 }
787 catch (Exception e) 793 catch (Exception e)
788 { 794 {
@@ -803,6 +809,7 @@ namespace OpenSim.Region.Environment.Scenes
803 if (part.UUID != m_rootPart.UUID) 809 if (part.UUID != m_rootPart.UUID)
804 { 810 {
805 part.ParentID = m_rootPart.LocalId; 811 part.ParentID = m_rootPart.LocalId;
812
806 } 813 }
807 } 814 }
808 } 815 }
@@ -815,10 +822,17 @@ namespace OpenSim.Region.Environment.Scenes
815 foreach (SceneObjectPart part in m_parts.Values) 822 foreach (SceneObjectPart part in m_parts.Values)
816 { 823 {
817 part.UUID = LLUUID.Random(); 824 part.UUID = LLUUID.Random();
825
818 } 826 }
819 } 827 }
820 } 828 }
821 829 // helper provided for parts.
830 public int GetSceneMaxUndo()
831 {
832 if (m_scene != null)
833 return m_scene.MaxUndoCount;
834 return 5;
835 }
822 public void ResetChildPrimPhysicsPositions() 836 public void ResetChildPrimPhysicsPositions()
823 { 837 {
824 AbsolutePosition = AbsolutePosition; 838 AbsolutePosition = AbsolutePosition;
@@ -845,12 +859,15 @@ namespace OpenSim.Region.Environment.Scenes
845 { 859 {
846 SceneObjectPart part = GetChildPart(localId); 860 SceneObjectPart part = GetChildPart(localId);
847 OnGrabPart(part, offsetPos, remoteClient); 861 OnGrabPart(part, offsetPos, remoteClient);
862
848 } 863 }
849 } 864 }
850 865
851 public virtual void OnGrabPart(SceneObjectPart part, LLVector3 offsetPos, IClientAPI remoteClient) 866 public virtual void OnGrabPart(SceneObjectPart part, LLVector3 offsetPos, IClientAPI remoteClient)
852 { 867 {
868 part.StoreUndoState();
853 part.OnGrab(offsetPos, remoteClient); 869 part.OnGrab(offsetPos, remoteClient);
870
854 } 871 }
855 872
856 public virtual void OnGrabGroup(LLVector3 offsetPos, IClientAPI remoteClient) 873 public virtual void OnGrabGroup(LLVector3 offsetPos, IClientAPI remoteClient)
@@ -1382,8 +1399,9 @@ namespace OpenSim.Region.Environment.Scenes
1382 { 1399 {
1383 m_parts.Add(newPart.UUID, newPart); 1400 m_parts.Add(newPart.UUID, newPart);
1384 } 1401 }
1385 1402
1386 SetPartAsNonRoot(newPart); 1403 SetPartAsNonRoot(newPart);
1404
1387 } 1405 }
1388 1406
1389 /// <summary> 1407 /// <summary>
@@ -1758,6 +1776,7 @@ namespace OpenSim.Region.Environment.Scenes
1758 { 1776 {
1759 LinkNonRootPart(part, oldGroupPosition, oldRootRotation); 1777 LinkNonRootPart(part, oldGroupPosition, oldRootRotation);
1760 } 1778 }
1779 part.ClearUndoState();
1761 } 1780 }
1762 1781
1763 DetachFromBackup(objectGroup); 1782 DetachFromBackup(objectGroup);
@@ -1781,7 +1800,7 @@ namespace OpenSim.Region.Environment.Scenes
1781 public void DelinkFromGroup(uint partID) 1800 public void DelinkFromGroup(uint partID)
1782 { 1801 {
1783 SceneObjectPart linkPart = GetChildPart(partID); 1802 SceneObjectPart linkPart = GetChildPart(partID);
1784 1803 linkPart.ClearUndoState();
1785 if (null != linkPart) 1804 if (null != linkPart)
1786 { 1805 {
1787// m_log.DebugFormat( 1806// 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 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Drawing; 31using System.Drawing;
31using System.Runtime.Serialization; 32using System.Runtime.Serialization;
@@ -106,6 +107,8 @@ namespace OpenSim.Region.Environment.Scenes
106 [XmlIgnore] public LLVector3 m_attachedPos = LLVector3.Zero; 107 [XmlIgnore] public LLVector3 m_attachedPos = LLVector3.Zero;
107 [XmlIgnore] public LLUUID fromAssetID = LLUUID.Zero; 108 [XmlIgnore] public LLUUID fromAssetID = LLUUID.Zero;
108 109
110 [XmlIgnore] public bool m_undoing = false;
111
109 public Int32 CreationDate; 112 public Int32 CreationDate;
110 public uint ParentID = 0; 113 public uint ParentID = 0;
111 114
@@ -123,6 +126,8 @@ namespace OpenSim.Region.Environment.Scenes
123 public uint EveryoneMask = (uint)PermissionMask.None; 126 public uint EveryoneMask = (uint)PermissionMask.None;
124 public uint NextOwnerMask = (uint)PermissionMask.All; 127 public uint NextOwnerMask = (uint)PermissionMask.All;
125 128
129 private UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
130
126 public LLObject.ObjectFlags Flags = LLObject.ObjectFlags.None; 131 public LLObject.ObjectFlags Flags = LLObject.ObjectFlags.None;
127 132
128 public uint ObjectFlags 133 public uint ObjectFlags
@@ -266,6 +271,40 @@ namespace OpenSim.Region.Environment.Scenes
266 //return new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w); 271 //return new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w);
267 272
268 } 273 }
274
275 public void StoreUndoState()
276 {
277 if (!m_undoing)
278 {
279 if (m_parentGroup != null)
280 {
281 if (m_undo.Count > 0)
282 {
283 UndoState last = m_undo.Peek();
284 if (last != null)
285 {
286 if (last.Compare(this))
287 return;
288 }
289 }
290
291
292 if (m_parentGroup.GetSceneMaxUndo() > 0)
293 {
294 UndoState nUndo = new UndoState(this);
295
296 m_undo.Push(nUndo);
297
298 }
299 }
300 }
301 }
302
303 public void ClearUndoState()
304 {
305 m_undo.Clear();
306 StoreUndoState();
307 }
269 308
270 public LLVector3 GroupPosition 309 public LLVector3 GroupPosition
271 { 310 {
@@ -290,7 +329,9 @@ namespace OpenSim.Region.Environment.Scenes
290 return m_groupPosition; 329 return m_groupPosition;
291 } 330 }
292 set 331 set
293 { 332 {
333 StoreUndoState();
334
294 m_groupPosition = value; 335 m_groupPosition = value;
295 336
296 if (PhysActor != null) 337 if (PhysActor != null)
@@ -334,7 +375,10 @@ namespace OpenSim.Region.Environment.Scenes
334 public LLVector3 OffsetPosition 375 public LLVector3 OffsetPosition
335 { 376 {
336 get { return m_offsetPosition; } 377 get { return m_offsetPosition; }
337 set { m_offsetPosition = value; 378 set
379 {
380 StoreUndoState();
381 m_offsetPosition = value;
338 try 382 try
339 { 383 {
340 // Hack to get the child prim to update world positions in the physics engine 384 // Hack to get the child prim to update world positions in the physics engine
@@ -380,6 +424,7 @@ namespace OpenSim.Region.Environment.Scenes
380 } 424 }
381 set 425 set
382 { 426 {
427 StoreUndoState();
383 m_rotationOffset = value; 428 m_rotationOffset = value;
384 429
385 if (PhysActor != null) 430 if (PhysActor != null)
@@ -650,7 +695,8 @@ namespace OpenSim.Region.Environment.Scenes
650 { 695 {
651 get { return m_shape.Scale; } 696 get { return m_shape.Scale; }
652 set 697 set
653 { 698 {
699 StoreUndoState();
654 m_shape.Scale = value; 700 m_shape.Scale = value;
655 TriggerScriptChangedEvent(Changed.SCALE); 701 TriggerScriptChangedEvent(Changed.SCALE);
656 } 702 }
@@ -759,7 +805,8 @@ namespace OpenSim.Region.Environment.Scenes
759 LLObject.ObjectFlags.CreateSelected; 805 LLObject.ObjectFlags.CreateSelected;
760 806
761 TrimPermissions(); 807 TrimPermissions();
762 808 //m_undo = new UndoStack<UndoState>(ParentGroup.GetSceneMaxUndo());
809
763 ScheduleFullUpdate(); 810 ScheduleFullUpdate();
764 } 811 }
765 812
@@ -802,7 +849,7 @@ namespace OpenSim.Region.Environment.Scenes
802 849
803 TrimPermissions(); 850 TrimPermissions();
804 // ApplyPhysics(); 851 // ApplyPhysics();
805 852
806 ScheduleFullUpdate(); 853 ScheduleFullUpdate();
807 } 854 }
808 855
@@ -1982,6 +2029,7 @@ namespace OpenSim.Region.Environment.Scenes
1982 2029
1983 public void UpdateRotation(LLQuaternion rot) 2030 public void UpdateRotation(LLQuaternion rot)
1984 { 2031 {
2032 //StoreUndoState();
1985 RotationOffset = new LLQuaternion(rot.X, rot.Y, rot.Z, rot.W); 2033 RotationOffset = new LLQuaternion(rot.X, rot.Y, rot.Z, rot.W);
1986 ScheduleTerseUpdate(); 2034 ScheduleTerseUpdate();
1987 } 2035 }
@@ -2097,6 +2145,7 @@ namespace OpenSim.Region.Environment.Scenes
2097 /// <param name="scale"></param> 2145 /// <param name="scale"></param>
2098 public void Resize(LLVector3 scale) 2146 public void Resize(LLVector3 scale)
2099 { 2147 {
2148 StoreUndoState();
2100 m_shape.Scale = scale; 2149 m_shape.Scale = scale;
2101 2150
2102 ScheduleFullUpdate(); 2151 ScheduleFullUpdate();
@@ -2522,5 +2571,15 @@ namespace OpenSim.Region.Environment.Scenes
2522 info.AddValue("PayPrice", PayPrice); 2571 info.AddValue("PayPrice", PayPrice);
2523 } 2572 }
2524 2573
2574
2575 public void Undo()
2576 {
2577 if (m_undo.Count > 0)
2578 {
2579 UndoState goback = m_undo.Pop();
2580 if (goback != null)
2581 goback.PlaybackState(this);
2582 }
2583 }
2525 } 2584 }
2526} 2585}
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 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using libsecondlife;
31
32namespace OpenSim.Region.Environment.Scenes
33{
34 public class UndoState
35 {
36 public LLVector3 Position = LLVector3.Zero;
37 public LLVector3 Scale = LLVector3.Zero;
38 public LLQuaternion Rotation = LLQuaternion.Identity;
39
40 public UndoState(LLVector3 pos, LLQuaternion rot, LLVector3 scale)
41 {
42 Position = pos;
43 Rotation = rot;
44 Scale = scale;
45 }
46
47 public UndoState(SceneObjectPart part)
48 {
49 if (part != null)
50 {
51 if (part.ParentID == 0)
52 {
53 Position = part.AbsolutePosition;
54 Rotation = part.RotationOffset;
55
56 }
57 else
58 {
59 Position = part.GroupPosition;
60 Rotation = part.RotationOffset;
61 Scale = part.Shape.Scale;
62
63 }
64 }
65 }
66
67 public bool Compare(SceneObjectPart part)
68 {
69 if (part != null)
70 {
71 if (part.ParentID == 0)
72 {
73 if (Position == part.AbsolutePosition && Rotation == part.RotationOffset)
74 return true;
75 else
76 return false;
77 }
78 else
79 {
80 if (Position == part.GroupPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale)
81 return true;
82 else
83 return false;
84
85 }
86 }
87 return false;
88 }
89
90 public void PlaybackState(SceneObjectPart part)
91 {
92 if (part != null)
93 {
94 part.m_undoing = true;
95
96 if (part.ParentID == 0)
97 {
98 part.ParentGroup.AbsolutePosition = Position;
99 part.UpdateRotation(Rotation);
100 part.ParentGroup.ScheduleGroupForTerseUpdate();
101 }
102 else
103 {
104 part.OffsetPosition = Position;
105 part.UpdateRotation(Rotation);
106 part.Resize(Scale);
107 part.ScheduleTerseUpdate();
108 }
109 part.m_undoing = false;
110
111 }
112 }
113
114 public UndoState()
115 {
116 }
117 }
118}
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
171 171
172 public event ScriptAnswer OnScriptAnswer; 172 public event ScriptAnswer OnScriptAnswer;
173 public event RequestPayPrice OnRequestPayPrice; 173 public event RequestPayPrice OnRequestPayPrice;
174 public event AgentSit OnUndo;
174 175
175 176
176#pragma warning restore 67 177#pragma warning restore 67