How do I export a clickable button to the inspector (for one-time actions)?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Calinou

I want to export a button that can be clicked in the inspector without having to create an editor plugin. For instance, a “Generate Points” button that will fill an array with random points.

1 Like
:bust_in_silhouette: Reply From: Calinou

Godot currently doesn’t expose a way to expose a clickable action within the
Inspector. While you could create an editor plugin, you can also expose a
boolean property with a setter that performs the desired action. The setter
should be made to keep the variable’s original value at all times, which means
the checkbox will always remain unchecked. The user will still be able to press
it to trigger the desired action.

The script must be in tool mode for this to work.
Otherwise, the setter won’t be run while in the editor.
See Running code in the editor for more information.

This can be useful to create editor tooling when you’re in a hurry:

# Notice the setter method.
export var bake_shadows = false setget do_bake_shadows


# In GDScript, setters always need to accept at least one parameter.
# To make it easier to call this method from code, you can make the parameter optional
# by giving it a default value.
func do_bake_shadows(_p_bake_shadows = null):
    print("Do stuff here...")

    # Notice how we never set the variable of `bake_shadows` in this method.
    # Therefore, `bake_shadows` will always remain set to `false` when changed externally.
    # Since exported variables will trigger the setter when modifying the value
    # from the inspector, this `do_bake_shadows()` method will be called
    # whenever the user tries to enable the "Bake Shadows" property.

One issue I’ve noticed with this approach is that code changes to the script are not always detected (I’m using an external editor). You can add prints to your setter to verify your changes are detected. Delete the node and re-add it (or detach and attach the script) to force a code refresh.

idbrii | 2022-12-16 19:29

:bust_in_silhouette: Reply From: idbrii

I too hit this issue so I created EditorScript Launcher. It adds a hotbar with buttons for each of your editor scripts so you can write scripts to speed up your Godot development. Scripts can specify custom UI so you can pass parameters.

After install, you’ll get a new “Script Launcher” button on the bottom toolbar that incldues buttons for all of your scripts:

While Godot has built-in EditorScript, you have to open them in the code editor to run which means you can’t see the scene and can’t run when using an external editor.

Scripts look similar to EditorScript but they’re static:

tool
extends LaunchableScript

static func run_script(ed: EditorInterface, ui_root: Control):
	var selection := LaunchableScript.get_selection_or_children(ed)
	var name_of_first = selection[0].name.rstrip(" 0123456789")
	for item in selection:
		item.name = name_of_first
:bust_in_silhouette: Reply From: insanecake

C# version (for Godot4) of workaround by Calinou:
When you click checkbox in editor it runs setter with your code and in Editor UI it always be unchecked

using Godot;

[Tool]
public partial class SampleTool : Node3D
{
    [Export]
    public bool ResetPositions
    {
        get => false;
        set
        {
            if (value)
            {
                GD.Print("Resetting positions...");
            }
        }
    }
}
1 Like