OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
UndoState.cs
Go to the documentation of this file.
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 OpenSimulator 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 
28 using System;
29 using System.Reflection;
30 using System.Collections.Generic;
31 using log4net;
32 using OpenMetaverse;
33 using OpenSim.Framework;
34 using OpenSim.Region.Framework.Interfaces;
35 
36 namespace OpenSim.Region.Framework.Scenes
37 {
38  public class UndoState
39  {
40  const int UNDOEXPIRESECONDS = 300; // undo expire time (nice to have it came from a ini later)
41 
43  public DateTime creationtime;
51  {
52  data = new ObjectChangeData();
53  data.change = change;
54  creationtime = DateTime.UtcNow;
55 
56  if (part.ParentGroup.RootPart == part)
57  {
58  if ((change & ObjectChangeType.Position) != 0)
59  data.position = part.ParentGroup.AbsolutePosition;
60  if ((change & ObjectChangeType.Rotation) != 0)
61  data.rotation = part.RotationOffset;
62  if ((change & ObjectChangeType.Scale) != 0)
63  data.scale = part.Shape.Scale;
64  }
65  else
66  {
67  if ((change & ObjectChangeType.Position) != 0)
68  data.position = part.OffsetPosition;
69  if ((change & ObjectChangeType.Rotation) != 0)
70  data.rotation = part.RotationOffset;
71  if ((change & ObjectChangeType.Scale) != 0)
72  data.scale = part.Shape.Scale;
73  }
74  }
78 
79  public bool checkExpire()
80  {
81  TimeSpan t = DateTime.UtcNow - creationtime;
82  if (t.Seconds > UNDOEXPIRESECONDS)
83  return true;
84  return false;
85  }
86 
90  public void updateExpire()
91  {
92  creationtime = DateTime.UtcNow;
93  }
94 
101  public bool Compare(SceneObjectPart part, ObjectChangeType change)
102  {
103  if (data.change != change) // if diferent targets, then they are diferent
104  return false;
105 
106  if (part != null)
107  {
108  if (part.ParentID == 0)
109  {
110  if ((change & ObjectChangeType.Position) != 0 && data.position != part.ParentGroup.AbsolutePosition)
111  return false;
112  }
113  else
114  {
115  if ((change & ObjectChangeType.Position) != 0 && data.position != part.OffsetPosition)
116  return false;
117  }
118 
119  if ((change & ObjectChangeType.Rotation) != 0 && data.rotation != part.RotationOffset)
120  return false;
121  if ((change & ObjectChangeType.Rotation) != 0 && data.scale == part.Shape.Scale)
122  return false;
123  return true;
124 
125  }
126  return false;
127  }
128 
134 
135  public void PlayState(SceneObjectPart part)
136  {
137  part.Undoing = true;
138 
139  SceneObjectGroup grp = part.ParentGroup;
140 
141  if (grp != null)
142  {
143  grp.doChangeObject(part, data);
144  }
145  part.Undoing = false;
146  }
147  }
148 
149  public class UndoRedoState
150  {
151  int size;
152  public LinkedList<UndoState> m_redo = new LinkedList<UndoState>();
153  public LinkedList<UndoState> m_undo = new LinkedList<UndoState>();
154 
158 
159  public UndoRedoState()
160  {
161  size = 5;
162  }
163 
168 
169  public UndoRedoState(int _size)
170  {
171  if (_size < 3)
172  size = 3;
173  else
174  size = _size;
175  }
176 
180 
181  public int Count
182  {
183  get { return m_undo.Count; }
184  }
185 
189 
190  public void Clear()
191  {
192  m_undo.Clear();
193  m_redo.Clear();
194  }
195 
201 
202  public void StoreUndo(SceneObjectPart part, ObjectChangeType change)
203  {
204  lock (m_undo)
205  {
206  UndoState last;
207 
208  if (m_redo.Count > 0) // last code seems to clear redo on every new undo
209  {
210  m_redo.Clear();
211  }
212 
213  if (m_undo.Count > 0)
214  {
215  // check expired entry
216  last = m_undo.First.Value;
217  if (last != null && last.checkExpire())
218  m_undo.Clear();
219  else
220  {
221  // see if we actually have a change
222  if (last != null)
223  {
224  if (last.Compare(part, change))
225  return;
226  }
227  }
228  }
229 
230  // limite size
231  while (m_undo.Count >= size)
232  m_undo.RemoveLast();
233 
234  UndoState nUndo = new UndoState(part, change);
235  m_undo.AddFirst(nUndo);
236  }
237  }
238 
244 
245  public void Undo(SceneObjectPart part)
246  {
247  lock (m_undo)
248  {
249  UndoState nUndo;
250 
251  // expire redo
252  if (m_redo.Count > 0)
253  {
254  nUndo = m_redo.First.Value;
255  if (nUndo != null && nUndo.checkExpire())
256  m_redo.Clear();
257  }
258 
259  if (m_undo.Count > 0)
260  {
261  UndoState goback = m_undo.First.Value;
262  // check expired
263  if (goback != null && goback.checkExpire())
264  {
265  m_undo.Clear();
266  return;
267  }
268 
269  if (goback != null)
270  {
271  m_undo.RemoveFirst();
272 
273  // redo limite size
274  while (m_redo.Count >= size)
275  m_redo.RemoveLast();
276 
277  nUndo = new UndoState(part, goback.data.change); // new value in part should it be full goback copy?
278  m_redo.AddFirst(nUndo);
279 
280  goback.PlayState(part);
281  }
282  }
283  }
284  }
285 
291 
292  public void Redo(SceneObjectPart part)
293  {
294  lock (m_undo)
295  {
296  UndoState nUndo;
297 
298  // expire undo
299  if (m_undo.Count > 0)
300  {
301  nUndo = m_undo.First.Value;
302  if (nUndo != null && nUndo.checkExpire())
303  m_undo.Clear();
304  }
305 
306  if (m_redo.Count > 0)
307  {
308  UndoState gofwd = m_redo.First.Value;
309  // check expired
310  if (gofwd != null && gofwd.checkExpire())
311  {
312  m_redo.Clear();
313  return;
314  }
315 
316  if (gofwd != null)
317  {
318  m_redo.RemoveFirst();
319 
320  // limite undo size
321  while (m_undo.Count >= size)
322  m_undo.RemoveLast();
323 
324  nUndo = new UndoState(part, gofwd.data.change); // new value in part should it be full gofwd copy?
325  m_undo.AddFirst(nUndo);
326 
327  gofwd.PlayState(part);
328  }
329  }
330  }
331  }
332  }
333 
334  public class LandUndoState
335  {
338 
339  public LandUndoState(ITerrainModule terrainModule, ITerrainChannel terrainChannel)
340  {
341  m_terrainModule = terrainModule;
342  m_terrainChannel = terrainChannel;
343  }
344 
345  public bool Compare(ITerrainChannel terrainChannel)
346  {
347  return m_terrainChannel == terrainChannel;
348  }
349 
350  public void PlaybackState()
351  {
352  m_terrainModule.UndoTerrain(m_terrainChannel);
353  }
354  }
355 }
void updateExpire()
updates undo or redo creation time to now
Definition: UndoState.cs:90
LandUndoState(ITerrainModule terrainModule, ITerrainChannel terrainChannel)
Definition: UndoState.cs:339
void StoreUndo(SceneObjectPart part, ObjectChangeType change)
adds a new state undo to part or its group, with changes indicated by what bits
Definition: UndoState.cs:202
A scene object group is conceptually an object in the scene. The object is constituted of SceneObject...
void PlayState(SceneObjectPart part)
executes the undo or redo to a part or its group
Definition: UndoState.cs:135
UndoRedoState(int _size)
creates a new UndoRedoState with states memory having indicated size
Definition: UndoState.cs:169
UndoRedoState()
creates a new UndoRedoState with default states memory size
Definition: UndoState.cs:159
void Undo(SceneObjectPart part)
executes last state undo to part or its group current state is pushed into redo
Definition: UndoState.cs:245
bool checkExpire()
check if undo or redo is too old
Definition: UndoState.cs:79
uint ParentID
The parent ID of this part.
override Vector3 AbsolutePosition
The absolute position of this scene object in the scene
void Redo(SceneObjectPart part)
executes last state redo to part or its group current state is pushed into undo
Definition: UndoState.cs:292
UndoState(SceneObjectPart part, ObjectChangeType change)
Constructor.
Definition: UndoState.cs:50
bool Compare(SceneObjectPart part, ObjectChangeType change)
Compare the relevant state in the given part to this state.
Definition: UndoState.cs:101
void Clear()
clears all undo and redo entries
Definition: UndoState.cs:190
bool Compare(ITerrainChannel terrainChannel)
Definition: UndoState.cs:345