GraphEdit nodes deletion error

Godot Version

v4.4.stable.official [4c311cbee]

Question

Hello! I am writing editor plugin for my project and I had been faced with this problem.
It is a GraphEdit inheritor. And I have this code:

@tool
class_name GraphDataEdit

extends GraphEdit

@export var graph_data: GraphData
@export var node_template: PackedScene

var undo_redo: UndoRedo = UndoRedo.new()

func _delete_selected_nodes() -> void:
    undo_redo.create_action("Delete Nodes")
    var selected_nodes := _collect_selected_nodes()
    for node in selected_nodes:
        undo_redo.add_do_method(graph_data.nodes.erase.bind(node.data))
        undo_redo.add_do_method(node.queue_free)
        undo_redo.add_undo_method(graph_data.nodes.append.bind(node.data))
        undo_redo.add_undo_method(self._restore_node.bind(node))
    undo_redo.add_do_method(graph_data.update_connections.bind(get_connection_list()))
    undo_redo.add_undo_method(graph_data.update_connections.bind(get_connection_list()))
    undo_redo.commit_action()
    graph_data.update_connections(get_connection_list())

# GraphDataNode is GraphNode inheritor, GraphNodeData is a Resource with node data
func create_node(node_data: GraphNodeData, first_load: bool = false) -> GraphDataNode:
    var node: GraphDataNode = node_template.instantiate()
    var node_name = str(node_data.node_id)
    node.initialize(node_name, node_data, undo_redo)
    if not first_load:
        undo_redo.create_action("Create Node")
        undo_redo.add_do_method(add_child.bind(node))
        undo_redo.add_undo_method(remove_child.bind(node))
        undo_redo.commit_action()
        node.selected = true
    else:
        add_child(node)
    node.tree_entered.connect(_on_node_entered_tree.bind(node))
    return node


func _on_node_entered_tree(node) -> void:
    node.owner = self.owner


func _collect_selected_nodes() -> Array[GraphDataNode]:
    var result: Array[GraphDataNode] = []
    for child in get_children():
        if child is not GraphDataNode:
            continue
        if child.selected:
            result.append(child as GraphDataNode)
    return result

And when I am calling _delete_selected_nodes() this thing happening:

  ERROR: Attempt to disconnect a nonexistent connection from '87490663:<GraphNode#16684907847369>'. Signal: 'item_rect_changed', callable: 'CanvasItem::queue_redraw'.

So, it handles node to delete corretly, but when queue_free() called, it trying to disconnect node from connection that I have never used. I am out of ideas what to do.

Will appreciate any help with this)

I had a sleep and got an idea how to solve this problem. And it kinda worked.

I noticed that there is no problem with removing nodes from grid when they were created. As I use same function in loading and creating nodes anew, there is some differences. How I see this situation:

  1. I am creating my node from template and initializing it with data
  2. If this node is new, I am using UndoRedo and action do_method not called. But node is adding to canvas when node.tree_entered invoked and all is going good.
  3. If this is loading case, I just called add_child(node) and something gone wrong when I tried to delete it. Problem was resolved when I changed immediate add_child call with call_deferred
func create_node(node_data: GraphNodeData, first_load: bool = false) -> GraphDataNode:
    var node: GraphDataNode = node_template.instantiate()
    var node_name = str(node_data.node_id)
    node.initialize(node_name, node_data, undo_redo)
    if not first_load:
        undo_redo.create_action("Create Node")
        undo_redo.add_do_method(add_child.bind(node))
        undo_redo.add_undo_method(remove_child.bind(node))
        undo_redo.commit_action()
        node.selected = true
    else:
        call_deferred("add_child", node)
    node.tree_entered.connect(_on_node_entered_tree.bind(node))
    return node

I am still curious about how this works and why after 1-frame-delay I don’t have any problems with signals disconnection. But my initial problem is solved :upside_down_face: