186 lines
3.9 KiB
C#
186 lines
3.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using MyUtility;
|
|
using UnityEngine;
|
|
|
|
namespace UndoRedo
|
|
{
|
|
public class UR_CommandMgr
|
|
{
|
|
private static UR_CommandMgr s_instance;
|
|
|
|
private List<UR_ICommand> m_undoCommands = new List<UR_ICommand>();
|
|
|
|
private List<UR_ICommand> m_redoCommands = new List<UR_ICommand>();
|
|
|
|
private UtilityOnDestroyHandler m_sceneDestroyHandler;
|
|
|
|
private long m_commandsStoredBytesLimit = 134217728L;
|
|
|
|
private long m_commandsStoredBytes;
|
|
|
|
public static UR_CommandMgr Instance
|
|
{
|
|
get
|
|
{
|
|
return (s_instance != null) ? s_instance : (s_instance = new UR_CommandMgr());
|
|
}
|
|
}
|
|
|
|
public bool IsDestroyedOnSceneLoad
|
|
{
|
|
get
|
|
{
|
|
return m_sceneDestroyHandler != null;
|
|
}
|
|
set
|
|
{
|
|
if (value)
|
|
{
|
|
if (m_sceneDestroyHandler == null)
|
|
{
|
|
GameObject gameObject = new GameObject("UR_CommandMgrSceneDestroyHandler");
|
|
m_sceneDestroyHandler = gameObject.AddComponent<UtilityOnDestroyHandler>();
|
|
UtilityOnDestroyHandler sceneDestroyHandler = m_sceneDestroyHandler;
|
|
sceneDestroyHandler.m_onDestroy = (Action)Delegate.Combine(sceneDestroyHandler.m_onDestroy, new Action(Reset));
|
|
}
|
|
}
|
|
else if (m_sceneDestroyHandler != null)
|
|
{
|
|
m_sceneDestroyHandler.DestroyWithoutHandling();
|
|
m_sceneDestroyHandler = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public long StoredBytesLimit
|
|
{
|
|
get
|
|
{
|
|
return m_commandsStoredBytesLimit;
|
|
}
|
|
set
|
|
{
|
|
m_commandsStoredBytesLimit = value;
|
|
LimitMemoryUsage();
|
|
}
|
|
}
|
|
|
|
public long StoredBytes
|
|
{
|
|
get
|
|
{
|
|
return m_commandsStoredBytes;
|
|
}
|
|
}
|
|
|
|
public bool IsRedoable
|
|
{
|
|
get
|
|
{
|
|
return m_redoCommands.Count > 0;
|
|
}
|
|
}
|
|
|
|
public bool IsUndoable
|
|
{
|
|
get
|
|
{
|
|
return m_undoCommands.Count > 0;
|
|
}
|
|
}
|
|
|
|
public void Add(UR_ICommand p_cmd, bool p_isAlreadyExecuted)
|
|
{
|
|
if (p_cmd != null)
|
|
{
|
|
if (!p_isAlreadyExecuted)
|
|
{
|
|
p_cmd.Execute();
|
|
}
|
|
if (m_undoCommands.Count > 0)
|
|
{
|
|
UR_ICommand uR_ICommand = m_undoCommands[m_undoCommands.Count - 1];
|
|
long storedBytes = uR_ICommand.GetStoredBytes();
|
|
if (uR_ICommand.CombineWithNext(p_cmd))
|
|
{
|
|
ClearRedoCommands();
|
|
m_commandsStoredBytes += uR_ICommand.GetStoredBytes() - storedBytes;
|
|
LimitMemoryUsage();
|
|
return;
|
|
}
|
|
}
|
|
m_undoCommands.Add(p_cmd);
|
|
ClearRedoCommands();
|
|
m_commandsStoredBytes += p_cmd.GetStoredBytes();
|
|
LimitMemoryUsage();
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("UR_CommandMgr: Add: p_cmd is null!");
|
|
}
|
|
}
|
|
|
|
public void Execute(UR_ICommand p_cmd)
|
|
{
|
|
Add(p_cmd, false);
|
|
}
|
|
|
|
public bool Redo()
|
|
{
|
|
if (IsRedoable)
|
|
{
|
|
UR_ICommand uR_ICommand = m_redoCommands[m_redoCommands.Count - 1];
|
|
m_redoCommands.RemoveAt(m_redoCommands.Count - 1);
|
|
m_commandsStoredBytes -= uR_ICommand.GetStoredBytes();
|
|
uR_ICommand.Execute();
|
|
m_commandsStoredBytes += uR_ICommand.GetStoredBytes();
|
|
m_undoCommands.Add(uR_ICommand);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool Undo()
|
|
{
|
|
if (IsUndoable)
|
|
{
|
|
UR_ICommand uR_ICommand = m_undoCommands[m_undoCommands.Count - 1];
|
|
m_undoCommands.RemoveAt(m_undoCommands.Count - 1);
|
|
m_commandsStoredBytes -= uR_ICommand.GetStoredBytes();
|
|
uR_ICommand.Rollback();
|
|
m_commandsStoredBytes += uR_ICommand.GetStoredBytes();
|
|
m_redoCommands.Add(uR_ICommand);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
m_undoCommands.Clear();
|
|
m_redoCommands.Clear();
|
|
m_commandsStoredBytes = 0L;
|
|
}
|
|
|
|
private void ClearRedoCommands()
|
|
{
|
|
for (int i = 0; i < m_redoCommands.Count; i++)
|
|
{
|
|
m_commandsStoredBytes -= m_redoCommands[i].GetStoredBytes();
|
|
}
|
|
m_redoCommands.Clear();
|
|
}
|
|
|
|
private void LimitMemoryUsage()
|
|
{
|
|
while (m_commandsStoredBytes > m_commandsStoredBytesLimit && m_undoCommands.Count > 0)
|
|
{
|
|
UR_ICommand uR_ICommand = m_undoCommands[0];
|
|
m_undoCommands.RemoveAt(0);
|
|
m_commandsStoredBytes -= uR_ICommand.GetStoredBytes();
|
|
}
|
|
}
|
|
}
|
|
}
|