Merge branch 'convertactor' of git://github.com/jb-perrier/FlaxEngine into jb-perrier-convertactor

This commit is contained in:
Wojtek Figat
2021-02-18 10:18:25 +01:00
2 changed files with 115 additions and 0 deletions

View File

@@ -259,6 +259,97 @@ namespace FlaxEditor.Modules
}
}
/// <summary>
/// Converts the selected actor to another type.
/// </summary>
/// <param name="to">The type to convert in.</param>
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<IUndoAction>();
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<SceneGraphNode>
{
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<SceneGraphNode>
{
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);
}
}
/// <summary>
/// Deletes the selected objects. Supports undo/redo.
/// </summary>

View File

@@ -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;