From c561d684eba1e0cea290b5d07a2b2603132bce72 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 6 Mar 2024 19:01:36 +0100 Subject: [PATCH] Refactor undo logic for actors reparenting in Editor #1741 --- Source/Editor/SceneGraph/ActorNode.cs | 36 +-- Source/Editor/SceneGraph/GUI/ActorTreeNode.cs | 221 +++++------------- .../Editor/Undo/Actions/ParentActorsAction.cs | 199 ++++++++++++++++ .../Editor/Undo/Actions/PasteActorsAction.cs | 1 - 4 files changed, 257 insertions(+), 200 deletions(-) create mode 100644 Source/Editor/Undo/Actions/ParentActorsAction.cs diff --git a/Source/Editor/SceneGraph/ActorNode.cs b/Source/Editor/SceneGraph/ActorNode.cs index 5c6adb055..91bf26103 100644 --- a/Source/Editor/SceneGraph/ActorNode.cs +++ b/Source/Editor/SceneGraph/ActorNode.cs @@ -316,41 +316,7 @@ namespace FlaxEditor.SceneGraph { base.OnParentChanged(); - // Update UI (special case if actor is spawned and added to existing scene tree) - var parentTreeNode = (parentNode as ActorNode)?.TreeNode; - if (parentTreeNode != null && !parentTreeNode.IsLayoutLocked) - { - parentTreeNode.IsLayoutLocked = true; - _treeNode.Parent = parentTreeNode; - _treeNode.IndexInParent = _actor.OrderInParent; - parentTreeNode.IsLayoutLocked = false; - - // Skip UI update if node won't be in a view - if (parentTreeNode.IsCollapsed) - { - TreeNode.UnlockChildrenRecursive(); - } - else - { - // Try to perform layout at the level where it makes it the most performant (the least computations) - var tree = parentTreeNode.ParentTree; - if (tree != null) - { - if (tree.Parent is FlaxEngine.GUI.Panel treeParent) - treeParent.PerformLayout(); - else - tree.PerformLayout(); - } - else - { - parentTreeNode.PerformLayout(); - } - } - } - else - { - _treeNode.Parent = parentTreeNode; - } + _treeNode.OnParentChanged(_actor, parentNode as ActorNode); } /// diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs index 270647433..6056cf68b 100644 --- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs +++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; +using FlaxEditor.Actions; using FlaxEditor.Content; using FlaxEditor.GUI; using FlaxEditor.GUI.Drag; @@ -14,7 +15,6 @@ using FlaxEditor.Windows.Assets; using FlaxEngine; using FlaxEngine.GUI; using FlaxEngine.Utilities; -using Object = FlaxEngine.Object; namespace FlaxEditor.SceneGraph.GUI { @@ -82,8 +82,51 @@ namespace FlaxEditor.SceneGraph.GUI UpdateText(); } + internal void OnParentChanged(Actor actor, ActorNode parentNode) + { + // Update cached value + _orderInParent = actor.OrderInParent; + + // Update UI (special case if actor is spawned and added to existing scene tree) + var parentTreeNode = parentNode?.TreeNode; + if (parentTreeNode != null && !parentTreeNode.IsLayoutLocked) + { + parentTreeNode.IsLayoutLocked = true; + Parent = parentTreeNode; + IndexInParent = _orderInParent; + parentTreeNode.IsLayoutLocked = false; + + // Skip UI update if node won't be in a view + if (parentTreeNode.IsCollapsed) + { + UnlockChildrenRecursive(); + } + else + { + // Try to perform layout at the level where it makes it the most performant (the least computations) + var tree = parentTreeNode.ParentTree; + if (tree != null) + { + if (tree.Parent is Panel treeParent) + treeParent.PerformLayout(); + else + tree.PerformLayout(); + } + else + { + parentTreeNode.PerformLayout(); + } + } + } + else + { + Parent = parentTreeNode; + } + } + internal void OnOrderInParentChanged() { + // Use cached value to check if we need to update UI layout (and update siblings order at once) if (Parent is ActorTreeNode parent) { var anyChanged = false; @@ -419,134 +462,6 @@ namespace FlaxEditor.SceneGraph.GUI _dragHandlers.OnDragLeave(); } - [Serializable] - private class ReparentAction : IUndoAction - { - [Serialize] - private Guid[] _ids; - - [Serialize] - private int _actorsCount; - - [Serialize] - private Guid[] _prefabIds; - - [Serialize] - private Guid[] _prefabObjectIds; - - public ReparentAction(Actor actor) - : this(new List { actor }) - { - } - - public ReparentAction(List actors) - { - var allActors = new List(Mathf.NextPowerOfTwo(actors.Count)); - - for (int i = 0; i < actors.Count; i++) - { - GetAllActors(allActors, actors[i]); - } - - var allScripts = new List