Extending the Godot editor to work for you: creating EditorPlugins, @tool scripts that run inside the editor, custom inspectors with EditorInspectorPlugin, and asset pipeline automation and reusable editor utilities for the whole team.

In episode 14, you made a fast, measurable game. Now it's time to speed up the other side: your own workflow. Godot differs from many engines — the entire editor is built on the same nodes as your game, so you can write your own tools that run inside the editor. Episode 15 covers custom tools & editor plugins.
This episode's roadmap: the anatomy of EditorPlugin, creating your first editor menu and dock panel, @tool scripts that run in the editor, custom inspectors with EditorInspectorPlugin, asset pipeline automation, and finishing with reusable editor utility patterns.
All editor extensions are rooted in one class: EditorPlugin. It's the entry point into the editor: from there you can add menus, create dock panels, register inspector plugins, and connect to editor signals. Plugins are declared through a plugin.cfg file in the addons/ folder:
[plugin]
name="Level Builder"
description="Alat untuk menyusun level lebih cepat"
author="Arman Dwi Pangestu"
version="1.0"
script="plugin.gd"Once this file is created and its script filled in, enable the plugin via the Project → Project Settings → Plugins menu. Godot loads and runs that script inside the editor. Its two required functions are _enter_tree and _exit_tree:
@tool
extends EditorPlugin
func _enter_tree() -> void:
add_tool_menu_item("Buat Level Baru", _buat_level)
func _exit_tree() -> void:
remove_tool_menu_item("Buat Level Baru")add_tool_menu_item adds an entry to the Tool menu in the editor. Because plugins run inside the editor, they have access to EditorInterface — the gateway to the currently open scene, the FileSystem, and much more.
A tool menu is enough for one-click actions, but for tools used repeatedly, create a dock panel — a window that can be pinned to the side of the editor. The process: create a regular UI scene, save it as panel.tscn, then register it via add_control_to_dock:
@tool
extends EditorPlugin
var panel: Control
func _enter_tree() -> void:
panel = preload("res://addons/level_builder/panel.tscn").instantiate()
add_control_to_dock(DOCK_SLOT_LEFT_UL, panel)
func _exit_tree() -> void:
if panel:
remove_control_from_dock(panel)
panel.queue_free()Because a panel is just a regular Control node, you build it exactly like game UI: buttons, labels, and containers. The difference: it lives inside the editor and can read the currently open scene via EditorInterface.
Godot's most powerful feature for tooling is the @tool annotation (in Godot 3, the keyword is tool). Regular scripts only run while the game runs; @tool scripts also execute inside the editor. This opens the door for nodes that compute their own visuals when a scene is opened.
A classic example: a marker node that draws its radius circle directly in the editor, so level designers see the area without running the game:
@tool
extends Node2D
@export var radius: float = 100.0
func _ready() -> void:
if Engine.is_editor_hint():
queue_redraw()
func _draw() -> void:
draw_circle(Vector2.ZERO, radius, Color(0.4, 0.8, 1.0, 0.3))The Engine.is_editor_hint() pattern is a must-know: it tells you whether the script is being run in the editor. Use it to protect code that only makes sense when the game runs — like accessing autoloads or input — so the editor doesn't error when opening scenes.
Info
When creating @tool scripts, always ask: does this function need to run in the editor, or is running in the game enough? Careful @tool code (protected by is_editor_hint()) saves the team from confusing editor errors.
Often what you need isn't a big panel, but better controls in the Inspector. @export_custom lets you provide your own control for a property:
@export_custom(ProceduralType)
var tipe: ProceduralType = ProceduralType.HILL
func _validate_property(property: Dictionary) -> void:
if property.name == "tipe":
property.hint = PROPERTY_HINT_ENUM
property.hint_string = "Bukit, Lembah, Gunung"_validate_property gives you full control over how a property appears in the Inspector. For truly custom controls — color sliders, graphs, action buttons — use EditorInspectorPlugin: create a subclass, register it via add_inspector_plugin(), and in parse_property you can add custom controls to the Inspector of any node of a matching type.
Editor plugins can also be pipeline automation: repetitive work that shouldn't be done by hand. A common pattern is processing assets when they're imported. Godot provides the filesystem_changed and scene_imported signals, which you can connect from a plugin to run post-processing steps.
A concrete example: a plugin that reads all level configuration files in the levels/ folder, validates their IDs, then writes the level list to a JSON file when the editor closes:
func _on_filesystem_changed() -> void:
var daftar: Array = []
var dir := DirAccess.open("res://levels")
if dir:
for nama in dir.get_files():
if nama.ends_with(".tscn"):
daftar.append(nama.trim_suffix(".tscn"))
var file := FileAccess.open("res://levels/index.json", FileAccess.WRITE)
file.store_string(JSON.stringify(daftar))With patterns like this, designers add levels without touching code — the plugin keeps the index in sync. That's the essence of workflow automation: shifting mechanical work from humans to the editor.
A good plugin doesn't just solve one problem; it solves recurring problems for the whole team. Some patterns worth making into plugins:
To keep plugins maintainable, store them per-feature in the addons/ folder and use version control. A clean structure looks like this:
addons/level_builder/
├── plugin.cfg
├── plugin.gd
└── panel.tscnYou can now extend the Godot editor: EditorPlugin as the entry point for menus, docks, and inspectors, @tool scripts that run in the editor for direct visualization, @export_custom and EditorInspectorPlugin for clean Inspector controls, asset pipeline automation through editor signals and file IO, and small plugin patterns reusable by the whole team.
The key takeaways:
plugin.cfg and an extends EditorPlugin script in the addons/ folder.add_control_to_dock.@tool runs scripts in the editor; Engine.is_editor_hint() protects game-only code.@export_custom and EditorInspectorPlugin give full control over the Inspector.In episode 16, you touch the most visual layer of a game: shaders & visual effects — Godot's shader language and material workflow, fragment shaders for 2D, spatial materials for 3D, and combining shaders with particles for stunning VFX. All the cool effects you see in commercial games start from a single shader file.