Show added and removed actors in prefab diff view.

This commit is contained in:
Chandler Cox
2025-06-03 15:25:45 -05:00
parent fa89e710d8
commit 71991ff8c7

View File

@@ -240,6 +240,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)
{
@@ -295,11 +301,35 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Not used
}
}
private class RemovedActorDummy : CustomEditor
{
/// <summary>
/// The removed prefab object (from the prefab default instance).
/// </summary>
public Actor PrefabObject;
/// <summary>
/// The prefab instance's parent.
/// </summary>
public Actor ParentActor;
/// <summary>
/// The order of the removed actor in the parent.
/// </summary>
public int OrderInParent;
/// <inheritdoc />
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
@@ -359,6 +389,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;
}
@@ -459,6 +524,25 @@ 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);
if (Presenter.Owner is PropertiesWindow propertiesWindow)
Editor.Instance.SceneEditing.Spawn(restored, parentActor, removedActor.OrderInParent);
else if (Presenter.Owner is PrefabWindow prefabWindow)
prefabWindow.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)
{
@@ -470,6 +554,27 @@ 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.
if (Presenter.Owner is PropertiesWindow propertiesWindow)
{
var editorInstance = Editor.Instance.SceneEditing;
editorInstance.Select(a);
editorInstance.Delete();
}
else if (Presenter.Owner is PrefabWindow prefabWindow)
{
prefabWindow.Select(prefabWindow.Graph.Root.Find(a));
prefabWindow.Delete();
}
return;
}
editor.RevertToReferenceValue();
}