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.