I've created a custom Node2D that draws a circle. I've marked it as a [Tool] so that I can create and use instances of it in the editor.

When I add an instance of it to my project, the only part of it that is pickabler is the origin point gizmo. I'd like the user to be able to select it if they click anywhere in the circular area. Is there a way to do this?


using Godot;
using System;

[Tool]
public class Circle : Node2D
{
    private float _radius = 40;
    [Export] public float radius {
        get { return _radius; }
        set { _radius = value; Update(); }
    }

    private Color _color = new Color(1, 1, 1);
    [Export] public Color color {
        get { return _color; }
        set { _color = value; Update(); }
    }

    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {        
    }

    public override void _Draw()
    {
        DrawCircle(new Vector2(), radius, color);
    }
}

I actually had put it in plugin script but don't see how that helps. None of the methods in EditorPlugin seem related to picking with the mouse.

Editor plugins get access to things such as the editor viewport and it's sub-areas. So you can add tool icons/buttons and options there.

Not sure but I imagine it might also give access to tools such as the different pickers and transform tools on the editor viewport header.

I was looking to see if there is a way to set the AABB (or Rect2 in this case) for a CanvasItem node so you could just expand the clickable area relative to the circle, but I couldn't find anything. There is a signal called item_rect_changed (source code) that seems to update the Rect2, but I'm not sure how you set the Rect2 itself. That might be a way to get a larger mouse selection there without needing to make too many modifications, if you can find a way to set the Rect2 for the node.

I'd like to be able to pick the actual shape, not just the bounding box. I think just extending a Control would give you the bounding box.

@kitfox said: I actually had put it in plugin script but don't see how that helps. None of the methods in EditorPlugin seem related to picking with the mouse.

EditorPlugin inherits from Node. It will receive mouse events. Simply make a mouse click event handler that'll walk through all the relevant nodes in the scene and check if mouse position is inside any of the circles. When such node is found, use EditorPlugin's functionality to select the node.

Here's an example. I don't have C# so it's GDScript, but there should be no difference.

tool
extends EditorPlugin

func get_all_children(node, array):
	for n in node.get_children():
		array.push_back(n)
		get_all_children(n, array)
	return array
	
func get_hit_node(nodes, position):
	for n in nodes:
		if n.has_method("hit"):
			if n.hit(position):
				return n
	return null

func _input(event):
	if event is InputEventMouseButton and event.is_pressed() and event.button_index == 2:
		var interface = get_editor_interface()
		var selection = interface.get_selection()
		var root = interface.get_edited_scene_root()

		var all_nodes = get_all_children(root, [])
		
		var hit_node = get_hit_node(all_nodes, event.position)
		if hit_node:
			selection.clear()
			selection.add_node(hit_node)
			interface.edit_node(hit_node)
			get_tree().set_input_as_handled()

Selectables don't even need to be of a special class or tool scripts. They just need to implement hit(position) method that returns true if position is in their hit area.

The event handler in the example works on right mouse click to avoid messing the editor gui up when testing.

a year later