AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Addon Development

skill-jame581-godotprompter-addon-development · by jame581

Use when creating Godot editor plugins — EditorPlugin, @tool scripts, custom inspectors, and dock panels

No reviews yet
0 installs
36 views
0.0% view→install

Install

$ agentstack add skill-jame581-godotprompter-addon-development

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-jame581-godotprompter-addon-development)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Addon Development? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Addon Development in Godot 4.3+

Editor plugins extend the Godot editor itself: custom node types, inspector panels, dock widgets, 3D gizmos, and toolbar buttons. All examples target Godot 4.3+ with no deprecated APIs.

> Related skills: resource-pattern for custom Resource editors, godot-ui for editor panel UI, csharp-godot for C# plugin development.


1. Plugin Structure

Every plugin lives inside addons/ at the project root. Godot discovers plugins by scanning for plugin.cfg files.

res://
└── addons/
    └── my_plugin/
        ├── plugin.cfg          # required — plugin metadata
        ├── plugin.gd           # main EditorPlugin script (named in plugin.cfg)
        ├── my_inspector.gd     # optional — EditorInspectorPlugin
        ├── my_dock.tscn        # optional — dock panel scene
        └── icons/
            └── my_node.svg     # optional — custom node icons

plugin.cfg is a plain INI file. Godot reads it when scanning addons/. The script key must point to the main plugin script relative to the plugin folder.

Enable the plugin: Project → Project Settings → Plugins → tick the checkbox next to your plugin name.


2. @tool Annotation

@tool makes a GDScript (or its C# equivalent) run inside the editor process as well as at runtime. Without it, the script only runs when the game is playing.

GDScript

@tool
extends Sprite2D

# Engine.is_editor_hint() is true when running inside the editor,
# false during a running game. Use it to guard editor-only logic.
func _process(delta: float) -> void:
    if Engine.is_editor_hint():
        # This block runs in the editor viewport — safe to call editor APIs.
        update_configuration_warnings()
    else:
        # Normal game logic here.
        pass

# _get_configuration_warnings() returns an array of strings shown as
# yellow warning icons on the node in the Scene panel.
func _get_configuration_warnings() -> PackedStringArray:
    var warnings := PackedStringArray()
    if texture == null:
        warnings.append("Texture is not set. Assign a Texture2D in the Inspector.")
    return warnings

C#

#if TOOLS
using Godot;

[Tool]
public partial class MyToolSprite : Sprite2D
{
    public override void _Process(double delta)
    {
        if (Engine.IsEditorHint())
        {
            // Editor-only logic — safe to call editor APIs here.
            UpdateConfigurationWarnings();
        }
        else
        {
            // Normal game logic.
        }
    }

    public override string[] _GetConfigurationWarnings()
    {
        if (Texture == null)
            return new[] { "Texture is not set. Assign a Texture2D in the Inspector." };
        return System.Array.Empty();
    }
}
#endif

> Wrap C# tool scripts in #if TOOLS / #endif to prevent the class from being included in exported builds. GDScript @tool scripts are excluded from exports automatically.

Key rules:

  • Add @tool / [Tool] at the top of every script that needs editor access.
  • Always guard runtime-only code with Engine.is_editor_hint() to avoid crashing the editor when processing begins before the scene is fully loaded.
  • Call update_configuration_warnings() whenever a property changes that might affect the warning state.

3. EditorPlugin Base

The main plugin script extends EditorPlugin. Godot calls _enter_tree() when the plugin is enabled and _exit_tree() when it is disabled or the project is closed. Everything added in _enter_tree() must be removed in _exit_tree().

GDScript

# plugin.gd
@tool
extends EditorPlugin

func _enter_tree() -> void:
    # Register a custom node type. The editor shows MyNode in the
    # "Add Node" dialog under the chosen base class, with a custom icon.
    add_custom_type(
        "MyNode",                              # name shown in editor
        "Node2D",                              # base class to extend
        preload("res://addons/my_plugin/my_node.gd"),
        preload("res://addons/my_plugin/icons/my_node.svg")
    )

    # Add a menu item to the Project menu (top toolbar).
    add_tool_menu_item("My Plugin Action", _on_tool_menu_item)

func _exit_tree() -> void:
    remove_custom_type("MyNode")
    remove_tool_menu_item("My Plugin Action")

func _on_tool_menu_item() -> void:
    print("My Plugin Action triggered")

C#

// Plugin.cs
#if TOOLS
using Godot;

[Tool]
public partial class MyPlugin : EditorPlugin
{
    public override void _EnterTree()
    {
        AddCustomType(
            "MyNode",
            "Node2D",
            GD.Load("res://addons/my_plugin/MyNode.cs"),
            GD.Load("res://addons/my_plugin/icons/my_node.svg")
        );

        AddToolMenuItem("My Plugin Action", new Callable(this, MethodName.OnToolMenuAction));
    }

    public override void _ExitTree()
    {
        RemoveCustomType("MyNode");
        RemoveToolMenuItem("My Plugin Action");
    }

    private void OnToolMenuAction()
    {
        GD.Print("My Plugin Action triggered");
    }
}
#endif

addcustomtype parameters:

| Parameter | Description | |---|---| | name | The name shown in the Add Node dialog | | base | String name of the Godot base class | | script | The GDScript / C# script resource | | icon | A Texture2D, typically a 16×16 SVG |

addtoolmenu_item adds an entry under Project in the top menu bar. Pass a Callable that takes no arguments.


4. Custom Inspector Plugin

When you want a custom widget for an exported property of a specific type, register an EditorInspectorPlugin from your main EditorPlugin. The inspector plugin overrides _can_handle to opt in and _parse_property (or _parse_begin) to inject custom widgets. Pair with an EditorProperty subclass for the actual UI.

> See [references/inspector-plugins.md](references/inspector-plugins.md) for the full GDScript and C# scaffold (custom inspector + EditorProperty + registration boilerplate).


5. Custom Dock Panel

Add a custom dock to the editor by calling add_control_to_dock(slot, control) from your EditorPlugin._enter_tree. Free the control on _exit_tree. Useful for project-wide tooling UIs (level browser, asset summary, build dashboard).

> See [references/dock-panels.md](references/dock-panels.md) for the full GDScript and C# dock scaffold.


6. Custom Resource Editors

EditorResourcePicker lets you constrain a property to a specific Resource subclass with a tooltip and base-type filter. EditorResourcePreviewGenerator provides custom thumbnails for resources in the FileSystem dock and Inspector.

> See [references/inspector-plugins.md](references/inspector-plugins.md) for the full GDScript and C# EditorResourcePicker and EditorResourcePreviewGenerator scaffolds.


7. Gizmos

EditorNode3DGizmoPlugin adds visual handles for 3D nodes in the editor — wireframe shapes, draggable handles, rotation rings. Implement _init (materials), _get_gizmo_name, _has_gizmo, _redraw (draw lines/handles), and _get_handle_value / _set_handle / _commit_handle for interactive editing.

> See [references/gizmos-deep-dive.md](references/gizmos-deep-dive.md) for the full GDScript and C# gizmo plugin (with undo/redo wiring for handle commits).


8. Testing Plugins

Reloading a plugin in the editor

The fastest way to reload plugin code without restarting Godot:

  1. Project → Project Settings → Plugins → untick the plugin → tick it again.
  2. Alternatively, run this from Editor → Execute Script or the editor console:
var plugin_name := "my_plugin"
ProjectSettings.set_setting("editor_plugins/enabled", [])
ProjectSettings.save()
# Re-enable via the Plugins dialog.

For quicker iteration, save the plugin script — Godot hot-reloads @tool scripts automatically. Complex changes (new class registrations, dock changes) require a full disable/enable cycle.

Debugging with print

print() and push_error() / push_warning() output to the Godot Output panel and the OS console when Godot is launched from a terminal.

func _enter_tree() -> void:
    print("[my_plugin] _enter_tree called")   # Output panel
    push_warning("[my_plugin] something unexpected")
    push_error("[my_plugin] something failed")  # also shown as red in Output
// C# equivalent — same Output panel, same OS console.
#if TOOLS
public override void _EnterTree()
{
    GD.Print("[my_plugin] _EnterTree called");      // Output panel
    GD.PushWarning("[my_plugin] something unexpected");
    GD.PushError("[my_plugin] something failed");   // also shown as red in Output
}
#endif

> C# plugin reload caveat: Unlike GDScript, C# plugins require recompilation. After editing C# plugin source, the editor must rebuild the assembly before re-enabling. If the plugin fails to load with Could not find type "Plugin", the C# project failed to compile — check the MSBuild Panel at the bottom of the editor for compilation errors. Programmatic plugin reload from a [Tool] script:

#if TOOLS
[Tool]
public partial class PluginReloader : EditorScript
{
    public override void _Run()
    {
        var pluginName = "my_plugin";
        // Disable then re-enable to force a clean reload cycle.
        EditorInterface.Singleton.SetPluginEnabled(pluginName, false);
        EditorInterface.Singleton.SetPluginEnabled(pluginName, true);
        GD.Print($"Plugin {pluginName} reloaded.");
    }
}
#endif

To launch with the OS console visible on Windows:

godot.exe --editor --path /path/to/project

Plugin lifecycle gotchas

| Situation | What happens | Fix | |---|---|---| | Plugin enabled but _enter_tree crashes | Plugin remains enabled but broken; editor may be unstable | Disable, fix, re-enable | | Forgot to remove a dock in _exit_tree | Dock orphan survives disable; duplicate docks appear on next enable | Always null-check and queue_free() in _exit_tree | | Custom type still listed after removal | Stale entry in the project's plugin_types cache | Restart the editor once after remove_custom_type | | @tool script crashes on property set | Editor shows the error but the script stops updating | Guard with if Engine.is_editor_hint() and validate inputs | | C# plugin not compiling | Entire plugin silently fails to load | Check the Mono → Build Project output and fix C# errors first | | add_inspector_plugin called twice | Inspector plugin fires twice per property | Track and guard with a null-check before add_inspector_plugin |


9. plugin.cfg Format

plugin.cfg is a plain INI file placed at the root of the plugin folder. All fields in the [plugin] section are required except dependencies and installs.

[plugin]

name="My Plugin"
description="Adds MyNode, a custom inspector, and a dock panel to the editor."
author="Your Name"
version="1.0.0"
script="plugin.gd"

Field reference:

| Key | Type | Description | |---|---|---| | name | String | Display name shown in Project Settings → Plugins | | description | String | Short summary shown in the Plugins panel | | author | String | Author name or organisation | | version | String | Semantic version string (e.g. "1.2.0") | | script | String | Path to the main EditorPlugin script, relative to the plugin folder |

Complete example with all optional fields:

[plugin]

name="My Plugin"
description="Adds MyNode, a custom inspector, and a dock panel to the editor."
author="Your Name"
version="1.0.0"
script="plugin.gd"

> There are no other standard keys in Godot 4.x plugin.cfg. Dependency management is handled externally (e.g., by the Asset Library or manual installation instructions).


10. Checklist

  • [ ] addons//plugin.cfg exists with name, description, author, version, script
  • [ ] Main script extends EditorPlugin and is decorated with @tool (GDScript) or [Tool] inside #if TOOLS (C#)
  • [ ] Everything registered in _enter_tree() is unregistered in _exit_tree()
  • [ ] Custom node types use add_custom_type / remove_custom_type with a matching icon SVG
  • [ ] @tool scripts guard editor-only code with Engine.is_editor_hint()
  • [ ] _get_configuration_warnings() returns non-empty array when node is misconfigured
  • [ ] Inspector plugins implement _can_handle to avoid handling unintended types
  • [ ] _parse_property returns true only for properties that need a custom editor
  • [ ] Dock scenes have a Custom Minimum Size set so the panel is usable at default dock widths
  • [ ] Dock Control is freed with queue_free() in _exit_tree()
  • [ ] EditorResourcePreviewGenerator is both added and removed via EditorInterface.get_resource_previewer()
  • [ ] Gizmo plugin implements _commit_handle with get_undo_redo() so handle drags are undoable
  • [ ] Plugin tested by full disable/enable cycle after each structural change
  • [ ] push_error() used instead of silent failures in all _enter_tree setup paths
  • [ ] C# plugin scripts wrapped in #if TOOLS / #endif

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.