Files
FlaxEngine/Source/Editor/Undo/Actions/DeleteActorsAction.cs
2021-01-02 14:28:49 +01:00

155 lines
4.6 KiB
C#

// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.SceneGraph;
using FlaxEngine;
namespace FlaxEditor.Actions
{
/// <summary>
/// Implementation of <see cref="IUndoAction"/> used to delete a selection of <see cref="ActorNode"/>.
/// </summary>
/// <seealso cref="FlaxEditor.IUndoAction" />
[Serializable]
class DeleteActorsAction : IUndoAction
{
[Serialize]
private byte[] _data;
[Serialize]
private Guid[] _prefabIds;
[Serialize]
private Guid[] _prefabObjectIds;
[Serialize]
private bool _isInverted;
/// <summary>
/// The node parents.
/// </summary>
[Serialize]
protected List<ActorNode> _nodeParents;
/// <summary>
/// Initializes a new instance of the <see cref="DeleteActorsAction"/> class.
/// </summary>
/// <param name="objects">The objects.</param>
/// <param name="isInverted">If set to <c>true</c> action will be inverted - instead of delete it will be create actors.</param>
internal DeleteActorsAction(List<SceneGraphNode> objects, bool isInverted = false)
{
_isInverted = isInverted;
_nodeParents = new List<ActorNode>(objects.Count);
var actorNodes = new List<ActorNode>(objects.Count);
var actors = new List<Actor>(objects.Count);
for (int i = 0; i < objects.Count; i++)
{
if (objects[i] is ActorNode node)
{
actorNodes.Add(node);
actors.Add(node.Actor);
}
}
actorNodes.BuildNodesParents(_nodeParents);
_data = Actor.ToBytes(actors.ToArray());
_prefabIds = new Guid[actors.Count];
_prefabObjectIds = new Guid[actors.Count];
for (int i = 0; i < actors.Count; i++)
{
_prefabIds[i] = actors[i].PrefabID;
_prefabObjectIds[i] = actors[i].PrefabObjectID;
}
}
/// <inheritdoc />
public string ActionString => _isInverted ? "Create actors" : "Delete actors";
/// <inheritdoc />
public void Do()
{
if (_isInverted)
Create();
else
Delete();
}
/// <inheritdoc />
public void Undo()
{
if (_isInverted)
Delete();
else
Create();
}
/// <inheritdoc />
public void Dispose()
{
_data = null;
_prefabIds = null;
_prefabObjectIds = null;
}
/// <summary>
/// Deletes the objects.
/// </summary>
protected virtual void Delete()
{
// Remove objects
for (int i = 0; i < _nodeParents.Count; i++)
{
var node = _nodeParents[i];
Editor.Instance.Scene.MarkSceneEdited(node.ParentScene);
node.Delete();
}
_nodeParents.Clear();
}
/// <summary>
/// Gets the node.
/// </summary>
/// <param name="id">The actor id.</param>
/// <returns>The scene graph node.</returns>
protected virtual SceneGraphNode GetNode(Guid id)
{
return SceneGraphFactory.FindNode(id);
}
/// <summary>
/// Creates the removed objects (from data).
/// </summary>
protected virtual void Create()
{
// Restore objects
var actors = Actor.FromBytes(_data);
if (actors == null)
return;
for (int i = 0; i < actors.Length; i++)
{
Guid prefabId = _prefabIds[i];
if (prefabId != Guid.Empty)
{
Actor.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(actors[i]), ref prefabId, ref _prefabObjectIds[i]);
}
}
var actorNodes = new List<ActorNode>(actors.Length);
for (int i = 0; i < actors.Length; i++)
{
var foundNode = GetNode(actors[i].ID);
if (foundNode is ActorNode node)
{
actorNodes.Add(node);
}
}
actorNodes.BuildNodesParents(_nodeParents);
for (int i = 0; i < _nodeParents.Count; i++)
{
Editor.Instance.Scene.MarkSceneEdited(_nodeParents[i].ParentScene);
}
}
}
}