This page covers the 2D editor viewport plugin — the system that allows selecting, moving, rotating, and scaling CanvasItem nodes interactively in the editor's 2D view. It documents the plugin registration, tool architecture, input handling pipeline, transform commit flow, and snapping system.
For the 3D editor equivalent, see the Node3D Editor. For the gizmo system used in the 3D editor, see the Gizmo System. For details on what CanvasItem itself provides at runtime, see the CanvasItem System.
The CanvasItem Editor is a built-in EditorPlugin that occupies the 2D tab of the editor. It renders an interactive canvas overlay on top of the scene's 2D viewport, intercepts mouse and keyboard input forwarded from the editor, and applies transforms to selected CanvasItem nodes (including Node2D and Control subclasses).
The implementation lives in two files:
| File | Role |
|---|---|
editor/plugins/canvas_item_editor_plugin.h | Class declarations |
editor/plugins/canvas_item_editor_plugin.cpp | Full implementation |
Class Hierarchy Diagram
Sources: editor/plugins/canvas_item_editor_plugin.h
CanvasItemEditorPlugin is the thin EditorPlugin wrapper. It registers the editor tab, forwards GUI input to CanvasItemEditor, and calls edit() when the node selection changes.
CanvasItemEditor is the heavyweight panel (VBoxContainer) that contains the toolbar, the SubViewportContainer rendering the scene, and all interactive overlay drawing. It owns the selection map, current tool mode, and the in-progress drag state.
CanvasItemEditorSelectedItem is a plain struct (not a Node) that captures the transform snapshot of one selected item at the moment a drag begins. This snapshot is used both to compute delta transforms during the drag and to provide the "undo" state when committing via EditorUndoRedoManager.
The editor supports a linear set of exclusive tool modes, stored in the ToolMode enum inside CanvasItemEditor.
| Enum Value | Toolbar Key | Behaviour |
|---|---|---|
TOOL_MODE_SELECT | Q | Click-select and drag-move; also activates transform handles |
TOOL_MODE_LIST_SELECT | — | Shows a popup list when multiple items overlap at the click point |
TOOL_MODE_MOVE | W | Constrained move only; no accidental rotate/scale |
TOOL_MODE_ROTATE | E | Rotate around pivot |
TOOL_MODE_SCALE | R | Uniform or axis-constrained scale |
TOOL_MODE_PIVOT | — | Repositions the local pivot/origin of a Node2D |
TOOL_MODE_PAN | Space | Pan the 2D viewport without affecting selection |
TOOL_MODE_RULER | — | Drag a measurement ruler overlay |
Sources: editor/plugins/canvas_item_editor_plugin.h
During any mouse interaction the editor tracks what kind of in-progress drag is happening via the DragType enum. The value is DRAG_NONE when idle.
DragType State Diagram
Sources: editor/plugins/canvas_item_editor_plugin.h, editor/plugins/canvas_item_editor_plugin.cpp
Input flows from the editor's main window into the CanvasItem Editor through the standard EditorPlugin forwarding mechanism.
Input Flow Diagram
Sources: editor/plugins/canvas_item_editor_plugin.cpp
The key entry point is CanvasItemEditor::forward_canvas_gui_input(). It returns true if the event was consumed (preventing it from reaching the running game logic), or false to pass it on. This is the same contract as all EditorPlugin::forward_canvas_gui_input() implementations.
When a drag ends (mouse button release), CanvasItemEditor::_commit_canvas_item_state() is called. It:
selection.orig_transform stored in each CanvasItemEditorSelectedItem at drag start.EditorUndoRedoManager action:
orig_transform snapshots.This gives full Ctrl+Z / Ctrl+Y support for every interactive manipulation.
Commit Flow Diagram
Sources: editor/plugins/canvas_item_editor_plugin.cpp
The editor supports several overlapping snap mechanisms, each independently togglable via the toolbar or View menu. Snapping is evaluated in _snap_point() and _snap_transform().
| Snap Type | Storage | Governing Method |
|---|---|---|
| Grid snap | grid_step, grid_offset in editor settings | _snap_point() |
| Rotation snap | snap_rotation_step | angle quantization in rotate drag |
| Scale snap | snap_scale_step | scale quantization in scale drag |
| Pixel snap | global setting | rounds to integer pixels |
| Smart snap | snap_node_* flags | raycasts against other nodes' corners, centers, outlines |
| Guide snap | guides list in the scene | distance threshold to guide lines |
Smart snapping examines all CanvasItem nodes visible in the viewport and computes candidate snap points from their bounding boxes. The candidate closest to the cursor (below a pixel threshold) wins.
The editor draws all overlays (selection outlines, handles, grid, rulers, guides) directly onto the canvas by connecting to the draw signal of the viewport control, handled in CanvasItemEditor::_draw_canvas().
What _draw_canvas() renders:
grid_step intervals.CanvasItem, transformed into screen space via _get_canvas_transform().Node2D.Control nodes, icons representing the four anchors.Sources: editor/plugins/canvas_item_editor_plugin.cpp
When the selected node is a Control, the editor provides additional drag types for repositioning anchors:
| DragType | Anchor affected |
|---|---|
DRAG_ANCHOR_TOP_LEFT | anchor_left, anchor_top |
DRAG_ANCHOR_TOP_RIGHT | anchor_right, anchor_top |
DRAG_ANCHOR_BOTTOM_LEFT | anchor_left, anchor_bottom |
DRAG_ANCHOR_BOTTOM_RIGHT | anchor_right, anchor_bottom |
DRAG_ANCHOR_ALL | All four anchors simultaneously |
Anchor values are clamped to [0, 1] and committed through EditorUndoRedoManager the same way position/rotation/scale changes are. The preset anchor toolbar buttons (e.g., "Full Rect", "Top-Left", "Center") are handled by separate button callbacks that directly set all four anchor properties and record undo steps.
Sources: editor/plugins/canvas_item_editor_plugin.cpp
When Skeleton2D and Bone2D nodes are present in the selection, the editor draws bone outlines and exposes a dedicated IK drag mode. The _draw_bones() helper traverses the Skeleton2D node hierarchy, computing each bone's endpoint from its rest transform and length, and draws them as colored polygons. Dragging a bone tip applies inverse kinematics to the chain.
CanvasItemEditorPlugin registers itself via the standard EditorPlugins mechanism during editor startup. It calls add_control_to_container() to embed CanvasItemEditor into the editor's main 2D viewport area, and overrides:
| Method | Purpose |
|---|---|
get_name() | Returns "2D" — the tab label |
handles(Object*) | Returns true for any CanvasItem subclass |
edit(Object*) | Passes the node to CanvasItemEditor for focus |
make_visible(bool) | Shows/hides the 2D editor panel |
forward_canvas_gui_input() | Delegates to CanvasItemEditor::forward_canvas_gui_input() |
Sources: editor/plugins/canvas_item_editor_plugin.cpp
Sources: editor/plugins/canvas_item_editor_plugin.h, editor/plugins/canvas_item_editor_plugin.cpp
EditorNode (see EditorNode) instantiates CanvasItemEditorPlugin and manages tab visibility.EditorSelection provides the set of currently selected nodes; CanvasItemEditor reads it to populate its selection map.EditorUndoRedoManager records all transform commits.EditorSettings persists snap step values and grid settings across sessions (see ProjectSettings & EditorSettings).Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.