#Undo Redo Scene Tree Modification Failure

1 messages · Page 1 of 1 (latest)

clear sable
#

The current implementation

To achieve this goal, I tried using the undo_redo feature of the editor. So far, I have made the code to add the dialogue box as a sibling of the original node in the tree.
To that end, I produced the following three scripts...
The main plugin script:

@tool
extends EditorPlugin

func enter_tree():
    add_custom_type("Dialogue", "MarginContainer", preload("res://addons/arta_vn/nodes/dialogue_template.gd"), preload("res://Assets/icon.svg"))

func exit_tree():
    remove_custom_type("Dialogue")

The dialogue node that you can add to a scene:

@tool
class_name Dialogue
extends MarginContainer

const SceneTemplate = preload("res://addons/arta_vn/nodes/dialogue_scene.tscn")

# Replace self with scene instance
func _enter_tree():
    NodeUtil.replace_with_scene(self, SceneTemplate)

And the actual replacement code, which for now just replaces the original Dialogue node with an instantiated scene for the purposes of testing:

#
@tool
class_name NodeUtil

static func replace_with_scene(node: Node, scene: PackedScene) -> void:
    if not is_instance_valid(node):
        push_warning("Invalid node passed to NodeUtil.print_node_info()")
        return
    if not Engine.is_editor_hint():
        return

    var scene_instance = scene.instantiate()
    var undo_redo = EditorInterface.get_editor_undo_redo()

    var parent = node.get_parent()
    if parent:
        var parent_path = parent.get_path()
        var scene_name = scene_instance.name
        var edited_scene_root = parent.get_tree().edited_scene_root

        undo_redo.create_action("Add scene")

        # Store references
        undo_redo.add_do_reference(parent)
        undo_redo.add_do_reference(scene_instance)
        undo_redo.add_undo_reference(parent)
        undo_redo.add_undo_reference(scene_instance)

        # Add the scene instance
        undo_redo.add_do_method(parent, "add_child", scene_instance)

        # Set the owner, forcing an update
        undo_redo.add_do_property(scene_instance, "owner", edited_scene_root)

        # Set the name that was lost in the process
        undo_redo.add_do_property(scene_instance, "name", scene_name)

        # Revert actions
        undo_redo.add_undo_property(scene_instance, "name", scene_name)
        undo_redo.add_undo_property(scene_instance, "owner", edited_scene_root)
        undo_redo.add_undo_method(parent, "remove_child", scene_instance)

        # Commit the action of adding the scene
        undo_redo.commit_action()

This kind of works. Indeed, the packed scene is added to the tree, and everything updates properly with no errors, but the main issue I'm facing right now is the undo_redo does not really seem to function properly with this code.
When I add the Dialogue node the following two actions are committed to history: