using System; using System.Collections.Generic; using UnityEngine; using UNEB.Utility; namespace UNEB { /// /// Handles execution of actions, undo, and redo. /// public class ActionManager { private NodeEditorWindow _window; private FiniteStack _undoStack; private Stack _redoStack; // Caches the current multi-stage action that is currently executing. private MultiStageAction _activeMultiAction = null; public event Action OnUndo; public event Action OnRedo; public ActionManager(NodeEditorWindow w) { _undoStack = new FiniteStack(100); _redoStack = new Stack(); _window = w; // Makes sure that the action cleans up after itself // when it is removed from the undo buffer. _undoStack.OnRemoveBottomItem += (action) => { action.OnDestroy(); }; } public void Update() { if (IsRunningAction) { _activeMultiAction.Do(); } } public bool IsRunningAction { get { return _activeMultiAction != null; } } /// /// Runs an action and stores it in the undo stack. /// /// public void RunUndoableAction() where T : UndoableAction, new() { T action = new T(); action.manager = this; if (action.Init()) { clearRedoStack(); _undoStack.Push(action); action.Do(); } } /// /// Starts a multi stage action but does not record it in the undo stack. /// /// public void StartMultiStageAction() where T : MultiStageAction, new() { // Only run 1 multi-action at a time. if (_activeMultiAction != null) { return; } T action = new T(); action.manager = this; if (action.Init()) { _activeMultiAction = action; _activeMultiAction.OnActionStart(); } } /// /// Records the multi-stage action in the undo stack. /// /// /// public void FinishMultiStageAction() { if (_activeMultiAction == null) { return; } // We check if the action ended properly so it can be stored in undo. if (_activeMultiAction.OnActionEnd()) { clearRedoStack(); _undoStack.Push(_activeMultiAction); } // There is no longer an active multi-stage action. _activeMultiAction = null; } public void UndoAction() { if (_undoStack.Count != 0) { var action = _undoStack.Pop(); _redoStack.Push(action); action.Undo(); if (OnUndo != null) OnUndo(); } } public void RedoAction() { if (_redoStack.Count != 0) { var action = _redoStack.Pop(); _undoStack.Push(action); action.Redo(); if (OnRedo != null) OnRedo(); } } public void Reset() { _activeMultiAction = null; clearUndoStack(); clearRedoStack(); } private void clearRedoStack() { foreach (var action in _redoStack) { action.OnDestroy(); } _redoStack.Clear(); } private void clearUndoStack() { foreach (var action in _undoStack) { action.OnDestroy(); } _undoStack.Clear(); } public NodeEditorWindow window { get { return _window; } } } }