Files
sbox-public/game/editor/ActionGraph/Code/UndoStack.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

90 lines
1.7 KiB
C#

using System;
using System.Collections.Generic;
namespace Editor.ActionGraphs;
public class UndoStack
{
private record struct Frame( string Name, string State );
private readonly List<Frame> _stack = new();
private int _index;
public bool CanUndo => _index > 0;
public bool CanRedo => _index < _stack.Count - 1;
public string UndoName => CanUndo ? $"Undo {_stack[_index - 1].Name}" : null;
public string RedoName => CanRedo ? $"Redo {_stack[_index].Name}" : null;
private readonly Func<string> _captureStateFunc;
public UndoStack( Func<string> captureStateFunc )
{
_captureStateFunc = captureStateFunc;
}
public void Push( string name )
{
var state = _captureStateFunc();
if ( _index > 0 && _stack[_index - 1].State.Equals( state, StringComparison.Ordinal ) )
{
_stack[_index - 1] = new Frame( name, state );
return;
}
if ( _index != _stack.Count )
{
_stack.RemoveRange( _index, _stack.Count - _index );
}
_stack.Add( new Frame( name, state ) );
_index = _stack.Count;
}
public string Undo()
{
if ( !CanUndo )
{
throw new InvalidOperationException();
}
if ( _index == _stack.Count )
{
// Add a restore point if we're at the top of the undo stack
_stack.Add( new Frame( null, _captureStateFunc() ) );
}
--_index;
return _stack[_index].State;
}
public string Redo()
{
if ( !CanRedo )
{
throw new InvalidOperationException();
}
++_index;
var frame = _stack[_index];
if ( frame.Name == null && _index == _stack.Count - 1 )
{
// We've reached the top of the stack, get rid of the restore point
_stack.RemoveAt( _index );
}
return frame.State;
}
public void Clear()
{
_stack.Clear();
_index = 0;
}
}