// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using System.Collections.Generic; using System.Linq; using FlaxEngine; namespace FlaxEditor.CustomEditors { /// /// Synchronizes objects modifications and records undo operations. /// Allows to override undo action target objects for the part of the custom editors hierarchy. /// /// [HideInEditor] public class SyncPointEditor : CustomEditor { private object[] _snapshotUndoInternal; /// /// The 'is dirty' flag. /// protected bool _isDirty; /// /// The cached token used by the value setter to support batching Undo actions (eg. for sliders or color pickers). /// protected object _setValueToken; /// /// Gets the undo objects used to record undo operation changes. /// public virtual IEnumerable UndoObjects => Presenter.GetUndoObjects(Presenter); /// /// Gets the undo. /// public virtual Undo Undo => Presenter.Undo; /// public override void Initialize(LayoutElementsContainer layout) { _isDirty = false; } /// protected override void Deinitialize() { EndUndoRecord(); base.Deinitialize(); } internal override void RefreshInternal() { bool isDirty = _isDirty; _isDirty = false; // If any UI control has been modified we should try to record selected objects change if (isDirty && Undo != null && Undo.Enabled) { string actionName = "Edit object(s)"; // Check if use token if (_setValueToken != null) { // Check if record start if (_snapshotUndoInternal == null) { // Record undo action start only (end called in EndUndoRecord) _snapshotUndoInternal = UndoObjects.ToArray(); Undo.RecordMultiBegin(_snapshotUndoInternal, actionName); } Refresh(); } else { // Normal undo action recording using (new UndoMultiBlock(Undo, UndoObjects, actionName)) Refresh(); } } else { Refresh(); } if (isDirty) OnModified(); } /// public override void Refresh() { base.Refresh(); RefreshRoot(); } /// /// Called when data gets modified by the custom editors. /// protected virtual void OnModified() { var parent = ParentEditor; while (parent != null) { if (parent is SyncPointEditor syncPointEditor) { syncPointEditor.OnModified(); break; } parent = parent.ParentEditor; } } /// protected override bool OnDirty(CustomEditor editor, object value, object token = null) { // End any active Undo action batching if (token != _setValueToken) EndUndoRecord(); _setValueToken = token; // Mark as modified and don't pass event further to the higher editors (don't call parent) _isDirty = true; return true; } /// protected override void ClearToken() { EndUndoRecord(); } /// /// Ends the undo recording if started with custom token (eg. by value slider). /// protected void EndUndoRecord() { if (_snapshotUndoInternal != null) { Undo.RecordMultiEnd(_snapshotUndoInternal); _snapshotUndoInternal = null; } // Clear token _setValueToken = null; } } }