This page documents the 3D editor gizmo system: the EditorNode3DGizmoPlugin and EditorNode3DGizmo classes, how they relate to Node3D nodes in the editor, and how to implement custom gizmos with handles and subgizmos.
For general 3D editor viewport behavior and camera navigation, see the Node3D Editor. For the 2D equivalent (CanvasItem overlays), see the CanvasItem Editor.
Gizmos are the interactive overlays drawn on top of Node3D objects in the 3D editor viewport. They display visual cues (lines, meshes, billboards) and provide draggable handles that let the user edit node properties directly in the viewport without touching the Inspector.
The system has two primary classes:
| Class | Role |
|---|---|
Node3DGizmo | Abstract base; bridges Node3D ↔ editor |
EditorNode3DGizmo | Concrete gizmo instance attached to a specific Node3D |
EditorNode3DGizmoPlugin | Factory and behavior handler; creates and manages gizmo instances |
Sources: doc/classes/Node3DGizmo.xml1-12 doc/classes/EditorNode3DGizmo.xml1-8 doc/classes/EditorNode3DGizmoPlugin.xml1-9
Diagram: Gizmo System Class Hierarchy
Sources: doc/classes/Node3DGizmo.xml1-12 doc/classes/EditorNode3DGizmo.xml1-218 doc/classes/EditorNode3DGizmoPlugin.xml1-218
There are two implementation paths, depending on complexity:
| Approach | When to use | How |
|---|---|---|
| Plugin-only (simple) | Gizmo needs no per-instance state or custom logic | Extend EditorNode3DGizmoPlugin, override virtual methods that receive a gizmo parameter |
| Custom gizmo class | Per-instance state, complex interaction logic | Override both EditorNode3DGizmoPlugin._create_gizmo() and extend EditorNode3DGizmo |
Both require registering the plugin via EditorPlugin.add_node_3d_gizmo_plugin().
EditorNode3DGizmoPlugin is a Resource that acts as a factory and behavior delegator for a family of gizmos. One plugin instance manages all active gizmo instances of its type.
Diagram: Plugin Lifecycle
Sources: doc/classes/EditorNode3DGizmoPlugin.xml53-106
_has_gizmo(for_node_3d) — Returns true if the given Node3D should receive a gizmo from this plugin. Called whenever a Node3D is added to the scene.
_create_gizmo(for_node_3d) — Returns a custom EditorNode3DGizmo instance, or null to use the default generic instance. Override when the simple plugin-only approach is insufficient.
| Method | Default | Purpose |
|---|---|---|
_get_priority() | 0 | Higher priority wins handle/subgizmo selection conflicts. Built-in gizmos return -1. |
_can_be_hidden() | true | Whether the gizmo can be toggled in the visibility menu. |
_is_selectable_when_hidden() | — | Whether the Node3D can still be selected when gizmo is hidden. |
_get_gizmo_name() | — | Name shown in the gizmo visibility menu. |
Sources: doc/classes/EditorNode3DGizmoPlugin.xml22-122
The plugin owns a named material registry. Materials are created once per plugin and reused across all gizmo instances. The system automatically generates selected/editable variants of each material.
| Method | Creates |
|---|---|
create_material(name, color, ...) | Unshaded line/mesh material |
create_handle_material(name, billboard, texture) | Handle sphere material (with optional custom texture) |
create_icon_material(name, texture, on_top, color) | Billboard icon material |
add_material(name, material) | Registers an externally created StandardMaterial3D |
Materials are retrieved via get_material(name, gizmo). When a gizmo argument is supplied, it returns the appropriate variant (normal, selected, or editable) for that gizmo's current state.
Sources: doc/classes/EditorNode3DGizmoPlugin.xml170-216
EditorNode3DGizmo extends Node3DGizmo and represents a single gizmo instance bound to one Node3D. It holds the visual elements and collision data for that specific node.
_redraw() is called by the editor whenever the gizmo needs to be rebuilt (e.g., when the node's properties change). The canonical pattern is:
clear() to remove all previous elements.Node3D's properties via get_node_3d().Diagram: Redraw and Visual Element Registration
Sources: doc/classes/EditorNode3DGizmo.xml75-79 doc/classes/EditorNode3DGizmo.xml116-171
| Method | What it adds |
|---|---|
add_lines(lines, material, billboard, modulate) | Pairs of points forming line segments |
add_mesh(mesh, material, transform, skeleton) | Arbitrary mesh with optional skinning |
add_unscaled_billboard(material, default_scale, modulate) | Screen-size-constant billboard (used for icons) |
add_collision_segments(segments) | Invisible segments for ray-cast picking |
add_collision_triangles(triangles) | Invisible triangle mesh for ray-cast picking |
Sources: doc/classes/EditorNode3DGizmo.xml116-171
Handles are interactive 3D points the user can drag to edit node properties. They are added with add_handles() and managed through a set of virtual callbacks.
Diagram: Handle Interaction Flow
Sources: doc/classes/EditorNode3DGizmo.xml13-90 doc/classes/EditorNode3DGizmoPlugin.xml13-141
add_handles(handles, material, ids, billboard, secondary):
handles — Array of Vector3 positions in local space.ids — Integer identifiers for each handle; passed back in callbacks.billboard — If true, handles always face the camera.secondary — Secondary handles normally have lower selection priority than primary handles, but swap to higher priority when the user holds Shift. Useful when multiple handles occupy the same point.| Callback | When called |
|---|---|
_get_handle_value(id, secondary) | At drag start; return current value for undo |
_begin_handle_action(id, secondary) | At drag start, after _get_handle_value |
_set_handle(id, secondary, camera, screen_pos) | Each frame during drag |
_commit_handle(id, secondary, restore, cancel) | On mouse release; cancel=true means revert |
_get_handle_name(id, secondary) | For display in the editor UI |
_is_handle_highlighted(id, secondary) | Return true to highlight the handle |
Sources: doc/classes/EditorNode3DGizmo.xml12-90
Subgizmos are independently selectable and transformable child elements within a gizmo. Unlike handles (which edit scalar properties), subgizmos carry full Transform3D data and behave like mini-selected objects within the parent node.
Typical use: individual skeleton bones, path points, or particle emitter shapes.
Diagram: Subgizmo Selection and Transform Flow
Sources: doc/classes/EditorNode3DGizmo.xml100-113 doc/classes/EditorNode3DGizmoPlugin.xml152-168
| Callback | Purpose |
|---|---|
_subgizmos_intersect_ray(camera, point) | Return ID of subgizmo hit by a ray, or -1 |
_subgizmos_intersect_frustum(camera, frustum_planes) | Return IDs of subgizmos inside a selection box |
_get_subgizmo_transform(id) | Return local-space transform at edit start (for undo) |
_set_subgizmo_transform(id, transform) | Apply transform during live edit |
_commit_subgizmos(ids, restores, cancel) | Finalize or revert a group of subgizmo edits |
All transforms are in the Node3D's local coordinate space.
get_subgizmo_selection() and is_subgizmo_selected(id) can be queried during _redraw() to visually distinguish selected subgizmos.
Sources: doc/classes/EditorNode3DGizmo.xml190-202
When using the plugin-only approach, all virtual methods on EditorNode3DGizmoPlugin receive the active EditorNode3DGizmo instance as their first argument. When using the custom gizmo approach, these methods are instead implemented directly on the EditorNode3DGizmo subclass (without the gizmo parameter).
Diagram: Method Dispatch Paths
Sources: doc/classes/EditorNode3DGizmoPlugin.xml53-58 doc/classes/EditorNode3DGizmo.xml75-90
A plugin must be registered with the editor before it takes effect:
EditorPlugin.add_node_3d_gizmo_plugin(plugin)
And removed on cleanup:
EditorPlugin.remove_node_3d_gizmo_plugin(plugin)
This is typically done in an EditorPlugin's _enter_tree and _exit_tree. See the EditorPlugin System page for lifecycle details.
Sources: doc/classes/EditorNode3DGizmoPlugin.xml7-8
EditorNode3DGizmoPlugin — Virtual Methods| Method | Override to... |
|---|---|
_has_gizmo(for_node_3d) | Declare which Node3D types get this gizmo |
_create_gizmo(for_node_3d) | Return a custom EditorNode3DGizmo subclass |
_get_gizmo_name() | Supply the name shown in the visibility menu |
_get_priority() | Control selection priority vs. other plugins |
_can_be_hidden() | Allow/disallow gizmo visibility toggling |
_redraw(gizmo) | Build gizmo visuals and handles |
_get_handle_name/value, _set/commit_handle | Handle drag editing |
_subgizmos_intersect_*, _get/set/commit_subgizmo_transform | Subgizmo selection and editing |
EditorNode3DGizmo — Building Methods| Method | What it registers |
|---|---|
add_lines | Line segments for display |
add_mesh | Mesh geometry for display |
add_unscaled_billboard | Screen-space constant icon |
add_handles | Interactive draggable points |
add_collision_segments | Invisible picking geometry (lines) |
add_collision_triangles | Invisible picking geometry (triangles) |
clear | Removes all registered elements |
Sources: doc/classes/EditorNode3DGizmo.xml116-177 doc/classes/EditorNode3DGizmoPlugin.xml13-169
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.