diff --git a/Source/Editor/CustomEditors/CustomEditorPresenter.cs b/Source/Editor/CustomEditors/CustomEditorPresenter.cs
index 1030abfda..ccf712904 100644
--- a/Source/Editor/CustomEditors/CustomEditorPresenter.cs
+++ b/Source/Editor/CustomEditors/CustomEditorPresenter.cs
@@ -63,6 +63,11 @@ namespace FlaxEditor.CustomEditors
/// Indication of if the properties window is locked on specific objects.
///
public bool LockSelection { get; set; }
+
+ ///
+ /// Gets the scene editing context.
+ ///
+ public ISceneEditingContext SceneContext { get; }
}
///
diff --git a/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs b/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs
index 62985fe30..ecdc1f7db 100644
--- a/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/ActorEditor.cs
@@ -1,8 +1,5 @@
// Copyright (c) Wojciech Figat. All rights reserved.
-using System;
-using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.Actions;
using FlaxEditor.CustomEditors.Editors;
using FlaxEditor.CustomEditors.Elements;
@@ -10,10 +7,14 @@ using FlaxEditor.GUI;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Scripting;
+using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
using FlaxEngine.Utilities;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace FlaxEditor.CustomEditors.Dedicated
{
@@ -238,6 +239,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
node.TextColor = Color.OrangeRed;
node.Text = Utilities.Utils.GetPropertyNameUI(removed.PrefabObject.GetType().Name);
}
+ // Removed Actor
+ else if (editor is RemovedActorDummy removedActor)
+ {
+ node.TextColor = Color.OrangeRed;
+ node.Text = $"{removedActor.PrefabObject.Name} ({Utilities.Utils.GetPropertyNameUI(removedActor.PrefabObject.GetType().Name)})";
+ }
// Actor or Script
else if (editor.Values[0] is SceneObject sceneObject)
{
@@ -293,11 +300,35 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Not used
}
}
+
+ private class RemovedActorDummy : CustomEditor
+ {
+ ///
+ /// The removed prefab object (from the prefab default instance).
+ ///
+ public Actor PrefabObject;
+
+ ///
+ /// The prefab instance's parent.
+ ///
+ public Actor ParentActor;
+
+ ///
+ /// The order of the removed actor in the parent.
+ ///
+ public int OrderInParent;
+
+ ///
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ // Not used
+ }
+ }
private TreeNode ProcessDiff(CustomEditor editor, bool skipIfNotModified = true)
{
- // Special case for new Script added to actor
- if (editor.Values[0] is Script script && !script.HasPrefabLink)
+ // Special case for new Script or child actor added to actor
+ if ((editor.Values[0] is Script script && !script.HasPrefabLink) || (editor.Values[0] is Actor a && !a.HasPrefabLink))
return CreateDiffNode(editor);
// Skip if no change detected
@@ -357,6 +388,41 @@ namespace FlaxEditor.CustomEditors.Dedicated
}
}
+ // Compare child actors for removed actors.
+ if (editor is ActorEditor && editor.Values.HasReferenceValue && editor.Values.ReferenceValue is Actor prefabObjectActor)
+ {
+ var thisActor = editor.Values[0] as Actor;
+ for (int i = 0; i < prefabObjectActor.ChildrenCount; i++)
+ {
+ var prefabActorChild = prefabObjectActor.Children[i];
+ if (thisActor == null)
+ continue;
+ bool isRemoved = true;
+ for (int j = 0; j < thisActor.ChildrenCount; j++)
+ {
+ var actorChild = thisActor.Children[j];
+ if (actorChild.PrefabObjectID == prefabActorChild.PrefabObjectID)
+ {
+ isRemoved = false;
+ break;
+ }
+ }
+ if (isRemoved)
+ {
+ var dummy = new RemovedActorDummy
+ {
+ PrefabObject = prefabActorChild,
+ ParentActor = thisActor,
+ OrderInParent = prefabActorChild.OrderInParent,
+ };
+ var child = CreateDiffNode(dummy);
+ if (result == null)
+ result = CreateDiffNode(editor);
+ result.AddChild(child);
+ }
+ }
+ }
+
return result;
}
@@ -466,6 +532,22 @@ namespace FlaxEditor.CustomEditors.Dedicated
return;
}
+ // Special case for reverting removed Actors
+ if (editor is RemovedActorDummy removedActor)
+ {
+ Editor.Log("Reverting removed actor changes to prefab (adding it)");
+
+ var parentActor = removedActor.ParentActor;
+ var restored = parentActor.AddChild(removedActor.PrefabObject.GetType());
+ var prefabId = parentActor.PrefabID;
+ var prefabObjectId = removedActor.PrefabObject.PrefabObjectID;
+ string data = JsonSerializer.Serialize(removedActor.PrefabObject);
+ JsonSerializer.Deserialize(restored, data);
+ Presenter.Owner.SceneContext.Spawn(restored, parentActor, removedActor.OrderInParent);
+ Actor.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), ref prefabId, ref prefabObjectId);
+ return;
+ }
+
// Special case for new Script added to actor
if (editor.Values[0] is Script script && !script.HasPrefabLink)
{
@@ -477,6 +559,19 @@ namespace FlaxEditor.CustomEditors.Dedicated
return;
}
+
+ // Special case for new Actor added to actor
+ if (editor.Values[0] is Actor a && !a.HasPrefabLink)
+ {
+ Editor.Log("Reverting added actor changes to prefab (removing it)");
+
+ // TODO: Keep previous selection.
+ var context = Presenter.Owner.SceneContext;
+ context.Select(SceneGraph.SceneGraphFactory.FindNode(a.ID));
+ context.DeleteSelection();
+
+ return;
+ }
if (Presenter.Undo != null && Presenter.Undo.Enabled)
{
diff --git a/Source/Editor/SceneGraph/ISceneEditingContext.cs b/Source/Editor/SceneGraph/ISceneEditingContext.cs
index d480ceba5..cc750d854 100644
--- a/Source/Editor/SceneGraph/ISceneEditingContext.cs
+++ b/Source/Editor/SceneGraph/ISceneEditingContext.cs
@@ -1,8 +1,9 @@
// Copyright (c) Wojciech Figat. All rights reserved.
-using System.Collections.Generic;
using FlaxEditor.SceneGraph;
using FlaxEditor.Viewport;
+using FlaxEngine;
+using System.Collections.Generic;
namespace FlaxEditor
{
@@ -39,9 +40,23 @@ namespace FlaxEditor
///
void RenameSelection();
+ ///
+ /// Deletes selected objects.
+ ///
+ void DeleteSelection();
+
///
/// Focuses selected objects.
///
void FocusSelection();
+
+ ///
+ /// Spawns the specified actor to the game (with undo).
+ ///
+ /// The actor.
+ /// The parent actor. Set null as default.
+ /// The order under the parent to put the spawned actor.
+ /// True if automatically select the spawned actor, otherwise false.
+ void Spawn(Actor actor, Actor parent = null, int orderInParent = -1, bool autoSelect = true);
}
}
diff --git a/Source/Editor/SceneGraph/RootNode.cs b/Source/Editor/SceneGraph/RootNode.cs
index 1a3e47be8..71a9dc83a 100644
--- a/Source/Editor/SceneGraph/RootNode.cs
+++ b/Source/Editor/SceneGraph/RootNode.cs
@@ -175,7 +175,7 @@ namespace FlaxEditor.SceneGraph
public List Selection => SceneContext.Selection;
///
- /// Gets the list of selected scene graph nodes in the editor context.
+ /// Gets the scene editing context.
///
public abstract ISceneEditingContext SceneContext { get; }
}
diff --git a/Source/Editor/Windows/Assets/BehaviorTreeWindow.cs b/Source/Editor/Windows/Assets/BehaviorTreeWindow.cs
index 2b86664f2..03ba26fc8 100644
--- a/Source/Editor/Windows/Assets/BehaviorTreeWindow.cs
+++ b/Source/Editor/Windows/Assets/BehaviorTreeWindow.cs
@@ -641,5 +641,8 @@ namespace FlaxEditor.Windows.Assets
///
public bool LockSelection { get; set; }
+
+ ///
+ public ISceneEditingContext SceneContext => null;
}
}
diff --git a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
index 24854afb9..0eecc4861 100644
--- a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
+++ b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
@@ -430,6 +430,12 @@ namespace FlaxEditor.Windows.Assets
}
}
+ ///
+ public void DeleteSelection()
+ {
+ Delete();
+ }
+
///
public void FocusSelection()
{
@@ -488,7 +494,8 @@ namespace FlaxEditor.Windows.Assets
/// The actor.
/// The parent.
/// The order of the actor under the parent.
- public void Spawn(Actor actor, Actor parent, int orderInParent = -1)
+ /// True if automatically select the spawned actor, otherwise false.
+ public void Spawn(Actor actor, Actor parent, int orderInParent = -1, bool autoSelect = true)
{
if (actor == null)
throw new ArgumentNullException(nameof(actor));
@@ -514,8 +521,11 @@ namespace FlaxEditor.Windows.Assets
// Create undo action
var action = new CustomDeleteActorsAction(new List(1) { actorNode }, true);
Undo.AddAction(action);
- Focus();
- Select(actorNode);
+ if (autoSelect)
+ {
+ Focus();
+ Select(actorNode);
+ }
}
private void OnTreeRightClick(TreeNode node, Float2 location)
diff --git a/Source/Editor/Windows/Assets/PrefabWindow.cs b/Source/Editor/Windows/Assets/PrefabWindow.cs
index 44c21d863..7f17053ac 100644
--- a/Source/Editor/Windows/Assets/PrefabWindow.cs
+++ b/Source/Editor/Windows/Assets/PrefabWindow.cs
@@ -91,6 +91,9 @@ namespace FlaxEditor.Windows.Assets
}
}
+ ///
+ public ISceneEditingContext SceneContext => this;
+
///
/// Gets or sets a value indicating whether use live reloading for the prefab changes (applies prefab changes on modification by auto).
///
diff --git a/Source/Editor/Windows/PropertiesWindow.cs b/Source/Editor/Windows/PropertiesWindow.cs
index e90003038..03316a221 100644
--- a/Source/Editor/Windows/PropertiesWindow.cs
+++ b/Source/Editor/Windows/PropertiesWindow.cs
@@ -58,6 +58,9 @@ namespace FlaxEditor.Windows
}
}
+ ///
+ public ISceneEditingContext SceneContext => Editor.Windows.EditWin;
+
///
/// Initializes a new instance of the class.
///
diff --git a/Source/Editor/Windows/SceneEditorWindow.cs b/Source/Editor/Windows/SceneEditorWindow.cs
index e3c72d069..888cb0888 100644
--- a/Source/Editor/Windows/SceneEditorWindow.cs
+++ b/Source/Editor/Windows/SceneEditorWindow.cs
@@ -26,12 +26,24 @@ namespace FlaxEditor.Windows
FlaxEditor.Utilities.Utils.SetupCommonInputActions(this);
}
+ ///
+ public void DeleteSelection()
+ {
+ Editor.SceneEditing.Delete();
+ }
+
///
public void FocusSelection()
{
Editor.Windows.EditWin.Viewport.FocusSelection();
}
+ ///
+ public void Spawn(Actor actor, Actor parent = null, int orderInParent = -1, bool autoSelect = true)
+ {
+ Editor.SceneEditing.Spawn(actor, parent, orderInParent, autoSelect);
+ }
+
///
public EditorViewport Viewport => Editor.Windows.EditWin.Viewport;