Changed undo redo internals. moved exec code to UndoState.cs from sop that now only sees a unified UndoRedoStore class, added size limit on buffers so only last 5 undo/redo are kept. (5 is hardcode like it was ) ***UNTESTED***

avinationmerge
UbitUmarov 2012-03-11 00:36:34 +00:00
parent 908abb1c3d
commit ab235abc46
2 changed files with 195 additions and 136 deletions

View File

@ -263,8 +263,7 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_occupied; // KF if any av is sitting on this prim private bool m_occupied; // KF if any av is sitting on this prim
private string m_text = String.Empty; private string m_text = String.Empty;
private string m_touchName = String.Empty; private string m_touchName = String.Empty;
private Stack<UndoState> m_undo = new Stack<UndoState>(5); private UndoRedoState m_UndoRedo = new UndoRedoState(5);
private Stack<UndoState> m_redo = new Stack<UndoState>(5);
private bool m_passTouches; private bool m_passTouches;
@ -1709,8 +1708,8 @@ namespace OpenSim.Region.Framework.Scenes
dupe.Category = Category; dupe.Category = Category;
dupe.m_rezzed = m_rezzed; dupe.m_rezzed = m_rezzed;
dupe.m_undo = new Stack<UndoState>(5); dupe.m_UndoRedo = new UndoRedoState(5);
dupe.m_redo = new Stack<UndoState>(5);
dupe.IgnoreUndoUpdate = false; dupe.IgnoreUndoUpdate = false;
dupe.Undoing = false; dupe.Undoing = false;
@ -3657,82 +3656,14 @@ namespace OpenSim.Region.Framework.Scenes
ParentGroup.ScheduleGroupForTerseUpdate(); ParentGroup.ScheduleGroupForTerseUpdate();
//ParentGroup.ScheduleGroupForFullUpdate(); //ParentGroup.ScheduleGroupForFullUpdate();
} }
/*
public void StoreUndoState()
{
StoreUndoState(false);
}
public void StoreUndoState(bool forGroup)
{
if (!Undoing && !IgnoreUndoUpdate) // just to read better - undo is in progress, or suspended
{
if (ParentGroup != null)
{
lock (m_undo)
{
if (m_undo.Count > 0)
{
// see if we had a change
UndoState last = m_undo.Peek();
if (last != null)
{
if (last.Compare(this, forGroup))
{
return;
}
}
}
if (ParentGroup.GetSceneMaxUndo() > 0)
{
UndoState nUndo = new UndoState(this, forGroup);
m_undo.Push(nUndo);
if (m_redo.Count > 0)
m_redo.Clear();
}
}
}
}
}
*/
public void StoreUndoState(ObjectChangeWhat what) public void StoreUndoState(ObjectChangeWhat what)
{ {
if (!Undoing && !IgnoreUndoUpdate) // just to read better - undo is in progress, or suspended lock (m_UndoRedo)
{ {
if (ParentGroup != null) if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
{ {
lock (m_undo) m_UndoRedo.StoreUndo(this, what);
{
if (m_undo.Count > 0)
{
// see if we had a change
UndoState last = m_undo.Peek();
if (last != null)
{
if (last.Compare(this, what))
{
return;
}
}
}
if (ParentGroup.GetSceneMaxUndo() > 0)
{
UndoState nUndo = new UndoState(this, what);
m_undo.Push(nUndo);
if (m_redo.Count > 0)
m_redo.Clear();
}
}
} }
} }
} }
@ -3744,84 +3675,42 @@ namespace OpenSim.Region.Framework.Scenes
{ {
get get
{ {
lock (m_undo) lock (m_UndoRedo)
return m_undo.Count; return m_UndoRedo.Count;
} }
} }
public void Undo() public void Undo()
{ {
lock (m_undo) lock (m_UndoRedo)
{ {
// m_log.DebugFormat( if (Undoing || ParentGroup == null)
// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}", return;
// Name, LocalId, m_undo.Count);
if (m_undo.Count > 0) Undoing = true;
{ m_UndoRedo.Undo(this);
UndoState goback = m_undo.Pop(); Undoing = false;
if (goback != null)
{
UndoState nUndo = null;
if (ParentGroup.GetSceneMaxUndo() > 0)
{
nUndo = new UndoState(this, goback.data.what);
}
goback.PlayState(this);
if (nUndo != null)
m_redo.Push(nUndo);
}
}
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}",
// Name, LocalId, m_undo.Count);
} }
} }
public void Redo() public void Redo()
{ {
lock (m_undo) lock (m_UndoRedo)
{ {
// m_log.DebugFormat( if (Undoing || ParentGroup == null)
// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}", return;
// Name, LocalId, m_redo.Count);
if (m_redo.Count > 0) Undoing = true;
{ m_UndoRedo.Redo(this);
UndoState gofwd = m_redo.Pop(); Undoing = false;
if (gofwd != null)
{
if (ParentGroup.GetSceneMaxUndo() > 0)
{
UndoState nUndo = new UndoState(this, gofwd.data.what);
m_undo.Push(nUndo);
}
gofwd.PlayState(this);
}
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}",
// Name, LocalId, m_redo.Count);
}
} }
} }
public void ClearUndoState() public void ClearUndoState()
{ {
// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); lock (m_UndoRedo)
lock (m_undo)
{ {
m_undo.Clear(); m_UndoRedo.Clear();
m_redo.Clear();
} }
} }

View File

@ -27,6 +27,7 @@
using System; using System;
using System.Reflection; using System.Reflection;
using System.Collections.Generic;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
@ -34,6 +35,8 @@ using System;
namespace OpenSim.Region.Framework.Scenes namespace OpenSim.Region.Framework.Scenes
{ {
/*
[Flags] [Flags]
public enum UndoType public enum UndoType
{ {
@ -48,7 +51,7 @@ namespace OpenSim.Region.Framework.Scenes
STATE_ALL = 63 STATE_ALL = 63
} }
/*
public class UndoState public class UndoState
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -194,7 +197,10 @@ namespace OpenSim.Region.Framework.Scenes
*/ */
public class UndoState public class UndoState
{ {
const int UNDOEXPIRESECONDS = 300; // undo expire time (nice to have it came from a ini later)
public ObjectChangeData data; public ObjectChangeData data;
public DateTime creationtime;
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
@ -204,8 +210,8 @@ namespace OpenSim.Region.Framework.Scenes
public UndoState(SceneObjectPart part, ObjectChangeWhat what) public UndoState(SceneObjectPart part, ObjectChangeWhat what)
{ {
data = new ObjectChangeData(); data = new ObjectChangeData();
data.what = what; data.what = what;
creationtime = DateTime.UtcNow;
if (part.ParentGroup.RootPart == part) if (part.ParentGroup.RootPart == part)
{ {
@ -227,12 +233,25 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public bool checkExpire()
{
TimeSpan t = DateTime.UtcNow - creationtime;
if (t.Seconds > UNDOEXPIRESECONDS)
return true;
return false;
}
public void updateExpire()
{
creationtime = DateTime.UtcNow;
}
/// <summary> /// <summary>
/// Compare the relevant state in the given part to this state. /// Compare the relevant state in the given part to this state.
/// </summary> /// </summary>
/// <param name="part"></param> /// <param name="part"></param>
/// <returns>true if both the part's position, rotation and scale match those in this undo state. False otherwise.</returns> /// <returns>true if both the part's position, rotation and scale match those in this undo state. False otherwise.</returns>
public bool Compare(SceneObjectPart part, ObjectChangeWhat what) public bool Compare(SceneObjectPart part, ObjectChangeWhat what)
{ {
if (data.what != what) // if diferent targets, then they are diferent if (data.what != what) // if diferent targets, then they are diferent
return false; return false;
@ -274,6 +293,157 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public class UndoRedoState
{
int size;
public LinkedList<UndoState> m_redo = new LinkedList<UndoState>();
public LinkedList<UndoState> m_undo = new LinkedList<UndoState>();
public UndoRedoState()
{
size = 5;
}
public UndoRedoState(int _size)
{
if (_size < 3)
size = 3;
else
size = _size;
}
public int Count
{
get { return m_undo.Count; }
}
public void Clear()
{
m_undo.Clear();
m_redo.Clear();
}
public void StoreUndo(SceneObjectPart part, ObjectChangeWhat what)
{
lock (m_undo)
{
UndoState last;
if (m_redo.Count > 0) // last code seems to clear redo on every new undo
{
m_redo.Clear();
}
if (m_undo.Count > 0)
{
// check expired entry
last = m_undo.First.Value;
if (last != null && last.checkExpire())
m_undo.Clear();
else
{
// see if we actually have a change
if (last != null)
{
if (last.Compare(part, what))
return;
}
}
}
// limite size
while (m_undo.Count >= size)
m_undo.RemoveLast();
UndoState nUndo = new UndoState(part, what);
m_undo.AddFirst(nUndo);
}
}
public void Undo(SceneObjectPart part)
{
lock (m_undo)
{
UndoState nUndo;
// expire redo
if (m_redo.Count > 0)
{
nUndo = m_redo.First.Value;
if (nUndo != null && nUndo.checkExpire())
m_redo.Clear();
}
if (m_undo.Count > 0)
{
UndoState goback = m_undo.First.Value;
// check expired
if (goback != null && goback.checkExpire())
{
m_undo.Clear();
return;
}
if (goback != null)
{
m_undo.RemoveFirst();
// redo limite size
while (m_redo.Count >= size)
m_redo.RemoveLast();
nUndo = new UndoState(part, goback.data.what); // new value in part should it be full goback copy?
m_redo.AddFirst(nUndo);
goback.PlayState(part);
}
}
}
}
public void Redo(SceneObjectPart part)
{
lock (m_undo)
{
UndoState nUndo;
// expire undo
if (m_undo.Count > 0)
{
nUndo = m_undo.First.Value;
if (nUndo != null && nUndo.checkExpire())
m_undo.Clear();
}
if (m_redo.Count > 0)
{
UndoState gofwd = m_redo.First.Value;
// check expired
if (gofwd != null && gofwd.checkExpire())
{
m_redo.Clear();
return;
}
if (gofwd != null)
{
m_redo.RemoveFirst();
// limite undo size
while (m_undo.Count >= size)
m_undo.RemoveLast();
nUndo = new UndoState(part, gofwd.data.what); // new value in part should it be full gofwd copy?
m_undo.AddFirst(nUndo);
gofwd.PlayState(part);
}
}
}
}
}
public class LandUndoState public class LandUndoState
{ {