You can @export a Callable, but it won’t be pickable through the editor. It would be a nice feature, it does raise tough questions and could be difficult to implement while satisfying all use cases.
You could also export a node path and a string to call, which is certainly uglier and doesn’t autocomplete.
@export var caller: Node
@export var function_name: String
###
caller.call(function_name)
@tool
extends Node
@export var move_left_action = ""
@export_custom(PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY) var move_left_method:String
@export_tool_button("Choose method") var choose_move_left = choose_move.bind("move_left")
var editor_interface
func _init() -> void:
# EditorInterface isn't available on exported projects so
# we need to load it dynamically and only when the script
# is running inside the editor.
if Engine.is_editor_hint():
editor_interface = Engine.get_singleton("EditorInterface")
func _ready() -> void:
printt(move_left_action, move_left_method)
func choose_move(option:String) -> void:
if not Engine.is_editor_hint() or editor_interface == null:
return
editor_interface.popup_node_selector(func(node_path:NodePath):
if node_path.is_empty():
return
else:
var node = editor_interface.get_edited_scene_root().get_node(node_path)
editor_interface.popup_method_selector(node, func(method:String):
match option:
"move_left":
move_left_method = method
)
)
It’s really easy using signals to do what you want without exporting a method. At some point signals started showing up in the editor when you create them.
Based on your screenshots, do something like this:
class_name InputComponent extends Node
signal input_received(direction: Vector2)
func _physics_process(delta: float) -> void:
var direction := vector2.ZERO
var direction2 = Input.get_vector("move_left", "move_right","move_up","move_down")
input_received.emit(direction)
class_name MoveComponenet extends Node
@export var actor: Node2D
@export var speed := 1.0
func _on_input_received(direction: Vector2) -> void:
actor.position += direction * speed
Then you can hook it up in the editor like any other signal, or add this to you MoveComponent code:
@onready var input_component = "$../InputComponent"
func _ready() -> void:
input_component.input_received.connect(_on_input_received)
Personally, I add a parent component that handles all the signals like a switchboard. But you may be doing something slightly different than I am, as I have the inputs inside each state, and if the state isn’t in the tree, that things can’t be done.
@hexgrid I’m actually avoiding calling the method in the script, I was looking for a more generic approach. @gertkeno don’t worry, that’s not ugly and it is generic just like I need it. @mrcdk it was exactly what I was looking for, thanks. @dragonforge-dev good point, will try this approach too.