How to change GraphNode position within the GraphEditor via script?

Godot Version

v4.3.stable.mono.official [77dcf97d8]

Question

I’m trying to make a tool to make graphs to hopefully use for a dialog system. I set up a GraphEdit scene, and I made a drop down menu to pick nodes to add to the graph. The menu appears when I right click, its position is set to the mouse position, and it’s added to the scene as a child of the GraphEdit. This works, the menu is created like I want, where I want. The problem is when I actually pick a node from the menu.

When I pick a node, I instantiate it as a child of GraphEdit, and then set its global position to the menu global position, but the position it appears is is always the center of the GraphEdit, despite the fact that debugging shows that the global position is indeed changed. I assume this is a problem of the global position being different from the position within the grapEdit, but I don’t know how to fix this.

This is the menu script:

public partial class DialogNodePicker : Control
{
    [Export] Godot.Collections.Array<PackedScene> dialogNodes = new Godot.Collections.Array<PackedScene>();
    [Export] PackedScene PickerButton;

    public override void _Ready()
    {
        Control grid = GetNode<Control>("%GridContainer");
        foreach(PackedScene node in dialogNodes)
        {
            var dialogNode = node.Instantiate<GraphNode>();
            
            var button = PickerButton.Instantiate<DialogNodePickerButton>();
            button.DialogNode = node;
            var label = button.GetNode<Label>("Label");
            label.Text = "Add " + dialogNode.Title + " node";
            button.NodePicked += OnNodePicked;
            grid.AddChild(button);
            dialogNode.QueueFree();
        }
    }

    public void OnNodePicked(PackedScene node)
    {
        var dialogNode = node.Instantiate<GraphNode>();
        GetParent().AddChild(dialogNode);
        dialogNode.GlobalPosition = GlobalPosition;
        GD.Print(dialogNode.GlobalPosition);
        QueueFree();
    }
    
    public void OnClose() 
    {
        QueueFree();
    }
}

How can I make it so the node appears where I want?

To make the node appear where you want, you have to use the position_offset property instead of position or global_position. The property is inherited from the GraphElement class and I think it should work with any other graph element.

Thanks that seems to work in changing where the node spawns. However since the node picker is not a graphelement I can’t just set the PositionOffset to the picker’s position. Do you know if there’s a way to get the picker’s position within the graph? Feels like I could use the GraphEdit’s ScrollOffset to calculate it, but I can’t figure it out lol

1 Like

In case you still need this, or in case someone else does…

I was attempting to add a node to the graph in the connection_to_empty event handler. You must consider both the scroll offset and the zoom

new_node.position_offset = (release_position + graph_edit.scroll_offset) / graph_edit.zoom