Add support for custom duplicate of SceneGraphNode

This commit is contained in:
Wojtek Figat
2021-02-01 16:03:33 +01:00
parent d69b005792
commit b22805f866
7 changed files with 103 additions and 18 deletions

View File

@@ -358,7 +358,15 @@ namespace FlaxEditor.Modules
var pasteAction = PasteActorsAction.Paste(data, pasteTargetActor?.ID ?? Guid.Empty);
if (pasteAction != null)
{
OnPasteAction(pasteAction);
pasteAction.Do(out _, out var nodeParents);
// Select spawned objects (parents only)
var selectAction = new SelectionChangeAction(Selection.ToArray(), nodeParents.Cast<SceneGraphNode>().ToArray(), OnSelectionUndo);
selectAction.Do();
// Build single compound undo action that pastes the actors and selects the created objects (parents only)
Undo.AddAction(new MultiUndoAction(pasteAction, selectAction));
OnSelectionChanged();
}
}
@@ -377,12 +385,57 @@ namespace FlaxEditor.Modules
public void Duplicate()
{
// Peek things that can be copied (copy all actors)
var objects = Selection.Where(x => x.CanCopyPaste).ToList().BuildAllNodes().Where(x => x.CanCopyPaste && x is ActorNode).ToList();
if (objects.Count == 0)
var nodes = Selection.Where(x => x.CanDuplicate).ToList().BuildAllNodes();
if (nodes.Count == 0)
return;
var actors = new List<Actor>();
var newSelection = new List<SceneGraphNode>();
List<IUndoAction> customUndoActions = null;
foreach (var node in nodes)
{
if (node.CanDuplicate)
{
if (node is ActorNode actorNode)
{
actors.Add(actorNode.Actor);
}
else
{
var customDuplicatedObject = node.Duplicate(out var customUndoAction);
if (customDuplicatedObject != null)
newSelection.Add(customDuplicatedObject);
if (customUndoAction != null)
{
if (customUndoActions == null)
customUndoActions = new List<IUndoAction>();
customUndoActions.Add(customUndoAction);
}
}
}
}
if (actors.Count == 0)
{
// Duplicate custom scene graph nodes only without actors
if (newSelection.Count != 0)
{
// Select spawned objects (parents only)
var selectAction = new SelectionChangeAction(Selection.ToArray(), newSelection.ToArray(), OnSelectionUndo);
selectAction.Do();
// Build a single compound undo action that pastes the actors, pastes custom stuff (scene graph extension) and selects the created objects (parents only)
var customUndoActionsCount = customUndoActions?.Count ?? 0;
var undoActions = new IUndoAction[1 + customUndoActionsCount];
for (int i = 0; i < customUndoActionsCount; i++)
undoActions[i] = customUndoActions[i];
undoActions[undoActions.Length - 1] = selectAction;
Undo.AddAction(new MultiUndoAction(undoActions));
OnSelectionChanged();
}
return;
}
// Serialize actors
var actors = objects.ConvertAll(x => ((ActorNode)x).Actor);
var data = Actor.ToBytes(actors.ToArray());
if (data == null)
{
@@ -394,22 +447,26 @@ namespace FlaxEditor.Modules
var pasteAction = PasteActorsAction.Duplicate(data, Guid.Empty);
if (pasteAction != null)
{
OnPasteAction(pasteAction);
pasteAction.Do(out _, out var nodeParents);
// Select spawned objects (parents only)
newSelection.AddRange(nodeParents);
var selectAction = new SelectionChangeAction(Selection.ToArray(), newSelection.ToArray(), OnSelectionUndo);
selectAction.Do();
// Build a single compound undo action that pastes the actors, pastes custom stuff (scene graph extension) and selects the created objects (parents only)
var customUndoActionsCount = customUndoActions?.Count ?? 0;
var undoActions = new IUndoAction[2 + customUndoActionsCount];
undoActions[0] = pasteAction;
for (int i = 0; i < customUndoActionsCount; i++)
undoActions[i + 1] = customUndoActions[i];
undoActions[undoActions.Length - 1] = selectAction;
Undo.AddAction(new MultiUndoAction(undoActions));
OnSelectionChanged();
}
}
private void OnPasteAction(PasteActorsAction pasteAction)
{
pasteAction.Do(out _, out var nodeParents);
// Select spawned objects
var selectAction = new SelectionChangeAction(Selection.ToArray(), nodeParents.Cast<SceneGraphNode>().ToArray(), OnSelectionUndo);
selectAction.Do();
Undo.AddAction(new MultiUndoAction(pasteAction, selectAction));
OnSelectionChanged();
}
/// <summary>
/// Called when selection gets changed. Invokes the other events and updates editor. Call it when you manually modify selected objects collection.
/// </summary>

View File

@@ -63,6 +63,9 @@ namespace FlaxEditor.SceneGraph
/// <inheritdoc />
public override bool CanCopyPaste => false;
/// <inheritdoc />
public override bool CanDuplicate => false;
/// <inheritdoc />
public override bool CanDrag => false;

View File

@@ -182,6 +182,9 @@ namespace FlaxEditor.SceneGraph
/// <inheritdoc />
public override bool CanCopyPaste => (_actor.HideFlags & HideFlags.HideInHierarchy) == 0;
/// <inheritdoc />
public override bool CanDuplicate => (_actor.HideFlags & HideFlags.HideInHierarchy) == 0;
/// <inheritdoc />
public override bool IsActive => _actor.IsActive;

View File

@@ -57,6 +57,9 @@ namespace FlaxEditor.SceneGraph.Actors
/// <inheritdoc />
public override bool CanCopyPaste => false;
/// <inheritdoc />
public override bool CanDuplicate => false;
/// <inheritdoc />
public override bool CanDelete => false;

View File

@@ -56,6 +56,9 @@ namespace FlaxEditor.SceneGraph
/// <inheritdoc />
public override bool CanCopyPaste => false;
/// <inheritdoc />
public override bool CanDuplicate => false;
/// <inheritdoc />
public override bool CanDelete => false;

View File

@@ -65,6 +65,11 @@ namespace FlaxEditor.SceneGraph
/// </summary>
public virtual bool CanCopyPaste => true;
/// <summary>
/// Gets a value indicating whether this instance can be duplicated by the user.
/// </summary>
public virtual bool CanDuplicate => true;
/// <summary>
/// Gets a value indicating whether this node can be deleted by the user.
/// </summary>
@@ -359,6 +364,17 @@ namespace FlaxEditor.SceneGraph
{
}
/// <summary>
/// Duplicates this object. Valid only if <see cref="CanDuplicate"/> returns true.
/// </summary>
/// <param name="undoAction">The undo action that duplicated the object (already performed), null if skip it.</param>
/// <returns>The duplicated object node.</returns>
public virtual SceneGraphNode Duplicate(out IUndoAction undoAction)
{
undoAction = null;
return null;
}
/// <summary>
/// Releases the node and the child tree. Disposed all GUI parts and used resources.
/// </summary>

View File

@@ -159,7 +159,7 @@ namespace FlaxEditor.Windows.Assets
public void Duplicate()
{
// Peek things that can be copied (copy all actors)
var objects = Selection.Where(x => x.CanCopyPaste && x != Graph.Main).ToList().BuildAllNodes().Where(x => x.CanCopyPaste && x is ActorNode).ToList();
var objects = Selection.Where(x => x.CanDuplicate && x != Graph.Main).ToList().BuildAllNodes().Where(x => x.CanDuplicate && x is ActorNode).ToList();
if (objects.Count == 0)
return;