From cdca5b4a2896fbc3cd4150da2d5afa0406de1c44 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 8 Aug 2021 18:38:26 +0200 Subject: [PATCH] Fix undo for missing actor children and scripts when doing Convert action --- Source/Editor/Modules/SceneEditingModule.cs | 44 ++++++++----------- Source/Editor/SceneGraph/SceneGraphTools.cs | 28 ++++++++++++ .../Editor/Undo/Actions/DeleteActorsAction.cs | 1 + 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/Source/Editor/Modules/SceneEditingModule.cs b/Source/Editor/Modules/SceneEditingModule.cs index 021817945..a3f23f775 100644 --- a/Source/Editor/Modules/SceneEditingModule.cs +++ b/Source/Editor/Modules/SceneEditingModule.cs @@ -303,26 +303,28 @@ namespace FlaxEditor.Modules { if (!Editor.SceneEditing.HasSthSelected || !(Editor.SceneEditing.Selection[0] is ActorNode)) return; - if (Level.IsAnySceneLoaded == false) throw new InvalidOperationException("Cannot spawn actor when no scene is loaded."); var actionList = new IUndoAction[4]; - Actor old = ((ActorNode)Editor.SceneEditing.Selection[0]).Actor; - Actor actor = (Actor)FlaxEngine.Object.New(to); + var oldNode = (ActorNode)Editor.SceneEditing.Selection[0]; + var old = oldNode.Actor; + var actor = (Actor)FlaxEngine.Object.New(to); var parent = old.Parent; var orderInParent = old.OrderInParent; + // Steps: + // - deselect old actor + // - destroy old actor + // - spawn new actor + // - select new actor + SelectionDeleteBegin?.Invoke(); actionList[0] = new SelectionChangeAction(Selection.ToArray(), new SceneGraphNode[0], OnSelectionUndo); actionList[0].Do(); - actionList[1] = new DeleteActorsAction(new List - { - Editor.Instance.Scene.GetActorNode(old) - }); - actionList[1].Do(); + actionList[1] = new DeleteActorsAction(oldNode.BuildAllNodes().Where(x => x.CanDelete).ToList()); SelectionDeleteEnd?.Invoke(); @@ -345,17 +347,12 @@ namespace FlaxEditor.Modules actor.StaticFlags = StaticFlags.None; // Move children - for (var i = old.ScriptsCount - 1; i >= 0; i--) - { - var script = old.Scripts[i]; - script.Actor = actor; - Guid newid = Guid.NewGuid(); - FlaxEngine.Object.Internal_ChangeID(FlaxEngine.Object.GetUnmanagedPtr(script), ref newid); - } - for (var i = old.Children.Length - 1; i >= 0; i--) - { - old.Children[i].Parent = actor; - } + var scripts = old.Scripts; + for (var i = scripts.Length - 1; i >= 0; i--) + scripts[i].Actor = actor; + var children = old.Children; + for (var i = children.Length - 1; i >= 0; i--) + children[i].Parent = actor; var actorNode = Editor.Instance.Scene.GetActorNode(actor); if (actorNode == null) @@ -364,16 +361,13 @@ namespace FlaxEditor.Modules actorNode.PostSpawn(); Editor.Scene.MarkSceneEdited(actor.Scene); - actionList[2] = new DeleteActorsAction(new List - { - actorNode - }, true); + actionList[1].Do(); + actionList[2] = new DeleteActorsAction(actorNode.BuildAllNodes().Where(x => x.CanDelete).ToList(), true); actionList[3] = new SelectionChangeAction(new SceneGraphNode[0], new SceneGraphNode[] { actorNode }, OnSelectionUndo); actionList[3].Do(); - var actions = new MultiUndoAction(actionList); - Undo.AddAction(actions); + Undo.AddAction(new MultiUndoAction(actionList, "Convert actor")); SpawnEnd?.Invoke(); diff --git a/Source/Editor/SceneGraph/SceneGraphTools.cs b/Source/Editor/SceneGraph/SceneGraphTools.cs index b20303a14..1416e379b 100644 --- a/Source/Editor/SceneGraph/SceneGraphTools.cs +++ b/Source/Editor/SceneGraph/SceneGraphTools.cs @@ -125,5 +125,33 @@ namespace FlaxEditor.SceneGraph FillTree(target, result); } } + + /// + /// Builds the list made of all nodes in the input scene tree root and child tree. The result collection contains all nodes in the tree. + /// + /// The node. + /// The result. + public static List BuildAllNodes(this T node) + where T : SceneGraphNode + { + var list = new List(); + BuildAllNodes(node, list); + return list; + } + + /// + /// Builds the list made of all nodes in the input scene tree root and child tree. The result collection contains all nodes in the tree. + /// + /// The node. + /// The result. + public static void BuildAllNodes(this T node, List result) + where T : SceneGraphNode + { + if (node == null || result == null) + throw new ArgumentNullException(); + result.Clear(); + result.Add(node); + FillTree(node, result); + } } } diff --git a/Source/Editor/Undo/Actions/DeleteActorsAction.cs b/Source/Editor/Undo/Actions/DeleteActorsAction.cs index 41dac3ccc..3dc7b77cf 100644 --- a/Source/Editor/Undo/Actions/DeleteActorsAction.cs +++ b/Source/Editor/Undo/Actions/DeleteActorsAction.cs @@ -135,6 +135,7 @@ namespace FlaxEditor.Actions node.Delete(); } _nodeParents.Clear(); + FlaxEngine.Scripting.FlushRemovedObjects(); } ///