Skip to content

Instantly share code, notes, and snippets.

@hanya
Last active September 19, 2023 09:54
Show Gist options
  • Save hanya/dde0de19cdff66260ca6d970975cfb15 to your computer and use it in GitHub Desktop.
Save hanya/dde0de19cdff66260ca6d970975cfb15 to your computer and use it in GitHub Desktop.
Example Editor Inspector plugin for Godot

This inspector plugin provides way to set property of NodePath type under ItemMenu (VBoxContainer) node. Children must be instance of Button. This plugin helps to choose siblings of the button in focus entries.

CustomNodeSelector.gd: Specifies handled objects and property type.

NodeSelector.gd: Set property value and execute dialog to choose one of the siblings.

Selector.gd: Sibling chooser in list.

See official document of the inspector plugin for more detail.

extends EditorInspectorPlugin
var NodeSelector = preload("res://addons/custom_node_selector/NodeSelector.gd")
var Selector = preload("res://addons/custom_node_selector/Selector.gd")
func can_handle(object):
# only ItemMenu / SomeButton buttons are handled
if object.get_class() == "Button":
var parent = object.get_parent()
if parent:
return parent.get_class() == "VBoxContainer" and \
parent.name == "ItemMenu"
return false
func parse_property(object, type, path, hint, hint_text, usage):
# only NodePath type is parsed
if type == TYPE_NODE_PATH:
var selector = Selector.new()
var node_selector = NodeSelector.new()
node_selector.set_selector(selector)
add_custom_control(selector)
add_property_editor(path, node_selector)
return true
else:
return false
extends EditorProperty
var _selector = null
var _property_control = Button.new()
var _current_path = NodePath()
var _updating = false
func _init():
add_child(_property_control)
#add_focusable(property_control)
refresh_control_text()
_property_control.connect("pressed", self, "_on_button_pressed")
func _on_button_pressed():
if _updating:
return
var obj = get_edited_object()
_selector.set_parent(obj.get_parent())
_selector.popup_centered()
# Set selector.
func set_selector(selector):
_selector = selector
_selector.connect("select_node", self, "_on_set")
# Takes path of selected node in the selector.
func _on_set(path):
_updating = true
_current_path = path
refresh_control_text()
_updating = false
# tells change of the property value
emit_changed(get_edited_property(), _current_path)
func update_property():
var new_value = get_edited_object()[get_edited_property()]
if new_value == _current_path:
return
_updating = true
_current_path = new_value
refresh_control_text()
_updating = false
func refresh_control_text():
var count = _current_path.get_name_count()
if count > 0:
_property_control.text = _current_path.get_name(count - 1)
else:
_property_control.text = ""
[plugin]
name="CustomNodeSelector"
description="Allow to select node which contains specific child."
author="h"
version="0.0.1"
script="plugin.gd"
extends AcceptDialog
# Signal to tell new node is selected.
signal select_node(path)
var _parent:Node = null
var _item_list:ItemList = null
func _init():
window_title = "Select Node"
popup_exclusive = true
func _ready():
connect("confirmed", self, "_on_confirmed")
# add cancel button and its signal
add_button("Cancel", false, "cancel")
connect("custom_action", self, "_on_custom_action")
var vbox = VBoxContainer.new()
add_child(vbox)
_item_list = ItemList.new()
_item_list.rect_min_size = Vector2(200, 300)
vbox.add_child(_item_list)
_item_list.grab_focus()
# Set parent node which its children are shown in the list
func set_parent(node:Node):
_parent = node
_update_list(_parent)
# OK button action.
func _on_confirmed():
var items = _item_list.get_selected_items()
if items:
var child = _parent.get_child(items[0])
var path = child.get_path()
var parent_path = child.get_path_to(_parent)
# construct path such as ../NAME
var this_path = String(parent_path) + "/" + child.get_path().get_name(path.get_name_count() - 1)
# tells the new value selected
emit_signal("select_node", NodePath(this_path))
# Button action for additional buttons.
func _on_custom_action(action):
if action == "cancel":
# hide selector
visible = false
# Fills node list.
func _update_list(parent:Node):
_item_list.clear()
if not parent:
return
for index in range(0, parent.get_child_count()):
var child = parent.get_child(index)
_item_list.add_item(child.name, null, true)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment