diff --git a/Source/Editor/Modules/SceneEditingModule.cs b/Source/Editor/Modules/SceneEditingModule.cs
index 8c0914d58..3f3c4cb70 100644
--- a/Source/Editor/Modules/SceneEditingModule.cs
+++ b/Source/Editor/Modules/SceneEditingModule.cs
@@ -259,6 +259,97 @@ namespace FlaxEditor.Modules
}
}
+ ///
+ /// Converts the selected actor to another type.
+ ///
+ /// The type to convert in.
+ public void Convert(Type to)
+ {
+ 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 List();
+
+ Actor old = ((ActorNode)Editor.SceneEditing.Selection[0]).Actor;
+ Actor actor = (Actor)FlaxEngine.Object.New(to);
+
+ actionList.Add(new SelectionChangeAction(Selection.ToArray(), new SceneGraphNode[0], OnSelectionUndo));
+ actionList[0].Do();
+ actionList.Add(new DeleteActorsAction(new List
+ {
+ Editor.Instance.Scene.GetActorNode(old)
+ }));
+ SelectionDeleteBegin?.Invoke();
+ actionList[1].Do();
+ SelectionDeleteEnd?.Invoke();
+
+ bool isPlayMode = Editor.StateMachine.IsPlayMode;
+
+ SpawnBegin?.Invoke();
+
+ actor.Transform = old.Transform;
+ if (old.Parent != null)
+ actor.Parent = old.Parent;
+ actor.StaticFlags = old.StaticFlags;
+ actor.HideFlags = old.HideFlags;
+ actor.Layer = old.Layer;
+ actor.Tag = old.Tag;
+ actor.Name = old.Name;
+ actor.IsActive = old.IsActive;
+ 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;
+ }
+
+ Level.SpawnActor(actor, actor.Parent);
+
+ if (isPlayMode)
+ actor.StaticFlags = StaticFlags.None;
+
+ var actorNode = Editor.Instance.Scene.GetActorNode(actor);
+ if (actorNode == null)
+ throw new InvalidOperationException("Failed to create scene node for the spawned actor.");
+
+ actorNode.PostSpawn();
+ Editor.Scene.MarkSceneEdited(actor.Scene);
+
+ actionList.Add(new DeleteActorsAction(new List
+ {
+ actorNode
+ }, true));
+ actionList.Add(new SelectionChangeAction(new SceneGraphNode[0], new SceneGraphNode[]{actorNode}, OnSelectionUndo));
+ actionList[3].Do();
+ var actions = new MultiUndoAction(actionList);
+ Undo.AddAction(actions);
+ SpawnEnd?.Invoke();
+
+ var options = Editor.Options.Options;
+
+ // Auto CSG mesh rebuild
+ if (!isPlayMode && options.General.AutoRebuildCSG)
+ {
+ if (actor is BoxBrush && actor.Scene)
+ actor.Scene.BuildCSG(options.General.AutoRebuildCSGTimeoutMs);
+ }
+
+ // Auto NavMesh rebuild
+ if (!isPlayMode && options.General.AutoRebuildNavMesh && actor.Scene && (actor.StaticFlags & StaticFlags.Navigation) == StaticFlags.Navigation)
+ {
+ var bounds = actor.BoxWithChildren;
+ Navigation.BuildNavMesh(actor.Scene, bounds, options.General.AutoRebuildNavMeshTimeoutMs);
+ }
+ }
+
///
/// Deletes the selected objects. Supports undo/redo.
///
diff --git a/Source/Editor/Windows/SceneTreeWindow.ContextMenu.cs b/Source/Editor/Windows/SceneTreeWindow.ContextMenu.cs
index f407017df..262bfd0bb 100644
--- a/Source/Editor/Windows/SceneTreeWindow.ContextMenu.cs
+++ b/Source/Editor/Windows/SceneTreeWindow.ContextMenu.cs
@@ -56,6 +56,30 @@ namespace FlaxEditor.Windows
b = contextMenu.AddButton("Duplicate", Editor.SceneEditing.Duplicate);
b.Enabled = hasSthSelected;
+ if (Editor.SceneEditing.SelectionCount == 1)
+ {
+ var convertMenu = contextMenu.AddChildMenu("Convert");
+ var convertActorCm = convertMenu.ContextMenu;
+ for (int i = 0; i < SpawnActorsGroups.Length; i++)
+ {
+ var group = SpawnActorsGroups[i];
+
+ if (group.Types.Length == 1)
+ {
+ var type = group.Types[0].Value;
+ convertActorCm.AddButton(group.Types[0].Key, () => Editor.SceneEditing.Convert(type));
+ }
+ else
+ {
+ var groupCm = convertActorCm.AddChildMenu(group.Name).ContextMenu;
+ for (int j = 0; j < group.Types.Length; j++)
+ {
+ var type = group.Types[j].Value;
+ groupCm.AddButton(group.Types[j].Key, () => Editor.SceneEditing.Convert(type));
+ }
+ }
+ }
+ }
b = contextMenu.AddButton("Delete", Editor.SceneEditing.Delete);
b.Enabled = hasSthSelected;