// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.History;
using FlaxEditor.Options;
using FlaxEngine;
namespace FlaxEditor
{
///
/// Implementation of customized for the .
///
///
public class EditorUndo : Undo
{
private readonly Editor _editor;
internal EditorUndo(Editor editor)
: base(500)
{
_editor = editor;
editor.Options.OptionsChanged += OnOptionsChanged;
}
private void OnOptionsChanged(EditorOptions options)
{
Capacity = options.General.UndoActionsCapacity;
}
///
public override bool Enabled
{
get => _editor.StateMachine.CurrentState.CanUseUndoRedo;
set => throw new AccessViolationException("Cannot change enabled state of the editor main undo.");
}
///
protected override void OnAction(IUndoAction action)
{
CheckSceneEdited(action);
base.OnAction(action);
}
///
protected override void OnUndo(IUndoAction action)
{
CheckSceneEdited(action);
base.OnUndo(action);
}
///
protected override void OnRedo(IUndoAction action)
{
CheckSceneEdited(action);
base.OnRedo(action);
}
///
/// Checks if the any scene has been edited after performing the given action.
///
/// The action.
private void CheckSceneEdited(IUndoAction action)
{
// Note: this is automatic tracking system to check if undo action modifies scene objects
// Skip if all scenes are already modified
if (Editor.Instance.Scene.IsEverySceneEdited())
return;
// ReSharper disable once SuspiciousTypeConversion.Global
if (action is ISceneEditAction sceneEditAction)
{
sceneEditAction.MarkSceneEdited(Editor.Instance.Scene);
}
else if (action is UndoActionObject undoActionObject)
{
var data = undoActionObject.PrepareData();
if (data.TargetInstance is SceneGraph.SceneGraphNode node)
{
Editor.Instance.Scene.MarkSceneEdited(node.ParentScene);
}
else if (data.TargetInstance is Actor actor)
{
Editor.Instance.Scene.MarkSceneEdited(actor.Scene);
}
else if (data.TargetInstance is Script script && script.Actor != null)
{
Editor.Instance.Scene.MarkSceneEdited(script.Actor.Scene);
}
}
else if (action is MultiUndoAction multiUndoAction)
{
// Process child actions
for (int i = 0; i < multiUndoAction.Actions.Length; i++)
{
CheckSceneEdited(multiUndoAction.Actions[i]);
}
}
}
}
}