Extend the Godot Editor with custom plugins using the EditorPlugin class
Editor plugins allow you to extend the functionality of the Godot Editor. Plugins can add custom tools, importers, export functionality, and modify the editor interface.
@toolextends EditorPlugin# Called when plugin is enabledfunc _enable_plugin(): print("Plugin enabled")# Called when plugin is disabledfunc _disable_plugin(): print("Plugin disabled")# Called before project runsfunc _build(): print("Building project") return true # Return false to abort run# Save external datafunc _save_external_data(): print("Saving external data")# Apply pending changesfunc _apply_changes(): print("Applying changes")
Create plugins that edit specific node or resource types:
@toolextends EditorPluginvar edited_object# Return true if this plugin handles the object typefunc _handles(object): return object is MyCustomNode# Called when an object should be editedfunc _edit(object): edited_object = object if object: print("Editing: ", object.name) else: print("Clearing editor")# Clear editing statefunc _clear(): edited_object = null# Control visibilityfunc _make_visible(visible): # Show/hide your custom UI if custom_control: custom_control.visible = visible
@toolextends EditorPluginvar dockfunc _enter_tree(): # Create dock dock = preload("res://addons/my_plugin/dock.tscn").instantiate() # Add to editor (modern approach) var editor_dock = EditorDock.new() editor_dock.dock_slot = EditorPlugin.DOCK_SLOT_LEFT_UR editor_dock.add_child(dock) add_dock(editor_dock)func _exit_tree(): # Remove and free the dock if dock: remove_dock(dock.get_parent()) # Remove EditorDock dock.queue_free()
Tool scripts run in the editor and can be used for editor automation:
@toolextends Node@export var auto_update := false: set(value): auto_update = value if value and Engine.is_editor_hint(): _update_in_editor()func _update_in_editor(): # This runs in the editor print("Updating in editor")func _ready(): if Engine.is_editor_hint(): print("Running in editor") else: print("Running in game")
Always check Engine.is_editor_hint() before running editor-specific code to prevent issues at runtime.
@toolextends EditorScript# EditorScript provides a simple way to run code in the editorfunc _run(): var scene = get_scene() print("Current scene: ", scene.name) # Modify scene for node in scene.get_children(): if node is Sprite2D: node.modulate = Color.RED
# Check if plugin is enabledif EditorInterface.is_plugin_enabled("my_plugin"): print("Plugin is active")# Enable/disable pluginEditorInterface.set_plugin_enabled("my_plugin", true)# Get plugin versionvar version = get_plugin_version()print("Plugin version: ", version)
Handle input and draw overlays in the 2D/3D viewports:
@toolextends EditorPluginfunc _forward_3d_gui_input(camera, event): if event is InputEventMouseButton: if event.pressed and event.button_index == MOUSE_BUTTON_LEFT: print("Clicked in 3D viewport") return EditorPlugin.AFTER_GUI_INPUT_STOP return EditorPlugin.AFTER_GUI_INPUT_PASSfunc _forward_3d_draw_over_viewport(overlay): # Draw a circle at cursor position overlay.draw_circle(overlay.get_local_mouse_position(), 64, Color.WHITE)func _forward_canvas_gui_input(event): if event is InputEventMouseMotion: update_overlays() return true return falsefunc _forward_canvas_draw_over_viewport(overlay): # Draw in 2D viewport overlay.draw_circle(overlay.get_local_mouse_position(), 64, Color.WHITE)