This page documents the common GUI control widgets in Godot's scene/gui/ directory: hierarchical trees, flat item lists, color pickers, numeric spinboxes, range-based controls, and popup menus. It covers their class structure, internal data models, input handling, and key APIs.
For the foundational Control class (anchors, layout, theming, focus), see 4.4. For text editing controls (TextEdit, CodeEdit, RichTextLabel, Label, LineEdit), see 11.
The controls documented here all inherit from Control, which itself extends CanvasItem → Node → Object.
Class hierarchy diagram
Sources: scene/gui/base_button.h scene/gui/button.h scene/gui/tree.h scene/gui/item_list.h scene/gui/color_picker.h scene/gui/popup_menu.h scene/gui/spin_box.h scene/gui/range.cpp scene/gui/popup.cpp
Range (scene/gui/range.cpp) is the abstract base class for any control whose value is constrained within a numeric interval. All concrete range widgets (SpinBox, HSlider, VSlider, HScrollBar, VScrollBar, ProgressBar) inherit from it.
| Property | Description |
|---|---|
min_value | Minimum allowed value |
max_value | Maximum allowed value |
step | Increment unit (0 = continuous) |
value | Current value, clamped to [min, max] |
ratio | Normalized position (value - min) / (max - min) |
exp_edit | Whether editing uses exponential scaling |
allow_greater / allow_lesser | Permit values outside the declared range |
Multiple Range controls can be linked via Range::share(). Linked controls maintain the same internal Shared data structure, so changing one updates all peers. This is used by SpinBox to sync its embedded LineEdit display with the slider value.
Sources: scene/gui/range.cpp scene/gui/spin_box.cpp83-115
SpinBox (scene/gui/spin_box.cpp) is a Range subclass that presents a LineEdit for direct text entry plus up/down increment buttons drawn on the right side.
Internal structure diagram
SpinBoxLineEdit, a private subclass of LineEdit defined in scene/gui/spin_box.h It exposes accessibility increment/decrement actions._update_text() scene/gui/spin_box.cpp89-115 formats the current value with prefix, suffix, and optional numeral-system localization via TranslationServer._text_submitted() scene/gui/spin_box.cpp117 parses the text using Godot's Expression evaluator, allowing the user to type arithmetic expressions like 2+3.update_on_text_changed mode commits the value on each keystroke rather than on Enter.get_minimum_size() scene/gui/spin_box.cpp83-87 returns the sum of the LineEdit's minimum size and the cached sizing_cache.buttons_block_width.
Sources: scene/gui/spin_box.cpp scene/gui/spin_box.h doc/classes/SpinBox.xml
BaseButton (scene/gui/base_button.cpp) is the abstract parent for all clickable controls. It does not render itself; subclasses implement drawing.
When toggle_mode is enabled, press events flip status.pressed instead of momentarily activating. ButtonGroup enforces mutual exclusion: pressing one button in the group calls _unpress_group(), which iterates button_group->buttons and calls set_pressed(false) on all others scene/gui/base_button.cpp39-56
BaseButton::shortcut_input() scene/gui/base_button.cpp436 intercepts keyboard events matching the assigned Shortcut. When triggered, it briefly sets in_shortcut_feedback = true and starts shortcut_feedback_timer to visually highlight the button.
get_draw_mode() scene/gui/base_button.cpp326-359 returns one of:
| Value | Condition |
|---|---|
DRAW_NORMAL | Default idle state |
DRAW_HOVER | Mouse over, not pressed |
DRAW_PRESSED | Currently pressed |
DRAW_HOVER_PRESSED | Hovered while pressed (toggle) |
DRAW_DISABLED | Disabled |
Button (scene/gui/button.cpp) uses this to select the correct StyleBox from the theme cache (normal, hover, pressed, disabled, and their RTL-mirrored variants).
Sources: scene/gui/base_button.cpp scene/gui/base_button.h scene/gui/button.cpp scene/gui/button.h doc/classes/BaseButton.xml doc/classes/Button.xml
OptionButton (scene/gui/option_button.cpp) extends Button to show a dropdown list. It internally owns a PopupMenu (popup) that it populates with radio-check items.
Items are delegated directly to the internal PopupMenu. OptionButton::add_item() calls popup->add_radio_check_item(), and set_item_text() forwards to popup->set_item_text(). When an item is selected via the popup's id_pressed signal, _selected() calls _select(index, true) which updates the button's text and icon to match scene/gui/option_button.cpp191-220
fit_to_longest_item causes OptionButton to maintain _cached_size, which is the widest item's size. This is recalculated via _refresh_size_cache() on NOTIFICATION_THEME_CHANGED and NOTIFICATION_TRANSLATION_CHANGED.
Sources: scene/gui/option_button.cpp scene/gui/option_button.h doc/classes/OptionButton.xml
MenuButton (scene/gui/menu_button.cpp) is a Button that, when pressed, pops up its owned PopupMenu directly below itself. It does not toggle; it always emits about_to_popup and displays the menu.
MenuBar (scene/gui/menu_bar.cpp) is a horizontal row of MenuButton-like entries that render child PopupMenu nodes. On platforms with native menu support (NativeMenu::FEATURE_GLOBAL_MENU), MenuBar can delegate the entire menu to the OS menu bar.
Sources: scene/gui/menu_button.cpp scene/gui/menu_bar.cpp
PopupMenu (scene/gui/popup_menu.h scene/gui/popup_menu.cpp) inherits from Popup (which itself inherits from Window). It renders a vertical list of Item entries in a ScrollContainer.
Each entry is a PopupMenu::Item struct scene/gui/popup_menu.h48-102:
| Field | Purpose |
|---|---|
text / xl_text | Display text (raw and translated) |
icon | Optional icon texture |
checked | Check state |
checkable_type | None, checkbox, or radio button |
separator | If true, renders as a horizontal divider |
disabled | Grays out and ignores input |
shortcut | Keyboard shortcut |
accel | Direct key accelerator |
submenu | Nested PopupMenu* |
id | Integer identifier (32-bit) |
metadata | Arbitrary Variant attached to the item |
| Method | Adds |
|---|---|
add_item(text, id, accel) | Plain text item |
add_icon_item(icon, text, id) | Item with icon |
add_check_item(text, id) | Checkable item (checkbox) |
add_radio_check_item(text, id) | Radio-style checkable item |
add_separator(text) | Separator (with optional label) |
add_submenu_node_item(text, submenu) | Item that opens a child PopupMenu |
_input_from_window_internal() scene/gui/popup_menu.cpp488-797 processes:
mouse_over index, scrolling to keep the focused item visible.ui_right: Open submenu via _activate_submenu().ui_left: Close and return focus to parent popup or MenuBar.ui_accept: Call activate_item(mouse_over).activate_item().search_string and jump to the first matching item name scene/gui/popup_menu.cpp758-796_activate_submenu() scene/gui/popup_menu.cpp353-447 calculates the submenu's screen position, accounting for RTL layout and screen bounds. It sets up "autohide areas" — rectangular regions on the parent menu above and below the triggering item. If the mouse enters an autohide area (not moving toward the submenu), the submenu closes.
When the platform supports it (NativeMenu::FEATURE_POPUP_MENU), bind_global_menu() scene/gui/popup_menu.cpp82-154 registers the entire item list with the OS via NativeMenu. system_menu_id maps to one of the platform's reserved menu slots (e.g., the macOS application menu).
PopupMenu data flow diagram
Sources: scene/gui/popup_menu.cpp scene/gui/popup_menu.h doc/classes/PopupMenu.xml
Tree (scene/gui/tree.h scene/gui/tree.cpp) displays hierarchically organized data in rows and columns. TreeItem represents a single row and is not a Node — it is an Object managed entirely by the Tree.
Each TreeItem holds a Vector<Cell> where the number of cells equals the number of columns in the owning Tree. The linked-list structure is:
Navigation pointers:
parent, first_child, last_childprev, next (siblings)children_cache — a LocalVector<TreeItem*> built on demand for O(1) indexed accessEach cell has a TreeCellMode that controls how it is rendered and edited:
| Mode | Description |
|---|---|
CELL_MODE_STRING | Plain text, optionally editable via LineEdit |
CELL_MODE_CHECK | Checkbox with checked / indeterminate states |
CELL_MODE_RANGE | Numeric slider or dropdown (using min, max, step, val) |
CELL_MODE_ICON | Displays only a Texture2D icon |
CELL_MODE_CUSTOM | Custom draw via Callable custom_draw_callback |
Set with TreeItem::set_cell_mode(column, mode) scene/gui/tree.cpp187-208
Key fields inside TreeItem::Cell scene/gui/tree.h62-137:
| Field | Purpose |
|---|---|
text / xl_text | Raw and translated text |
icon / icon_overlay | Main icon and overlay texture |
icon_region | Sub-region of a texture atlas |
checked / indeterminate | Check state (for CELL_MODE_CHECK) |
min, max, step, val | Range parameters (for CELL_MODE_RANGE) |
editable | Whether the user can edit this cell inline |
selectable / selected | Selection state |
custom_color, color | Per-cell font color override |
custom_bg_color, bg_color | Per-cell background color |
buttons | Vector<Cell::Button> — icon buttons at end of cell |
custom_draw_callback | Callable for CELL_MODE_CUSTOM |
custom_stylebox | Per-cell StyleBox override |
meta | Arbitrary Variant metadata |
Tree::SelectMode controls how selection works:
| Mode | Behavior |
|---|---|
SELECT_SINGLE | One cell selected at a time |
SELECT_ROW | Entire row selected when any cell is clicked |
SELECT_MULTI | Multiple rows/cells with Shift/Ctrl |
TreeItem::propagate_check(column) scene/gui/tree.cpp284-292 propagates a check state change both downward (all descendants) and upward (parents become indeterminate if children are mixed). This implements a tri-state checkbox tree pattern.
Tree::DropModeFlags controls drag-and-drop behavior:
| Flag | Behavior |
|---|---|
DROP_MODE_DISABLED | No drop |
DROP_MODE_ON_ITEM | Drop onto items |
DROP_MODE_INBETWEEN | Drop between items |
When a cell is double-clicked, the Tree spawns an inline editor widget (a LineEdit, TextEdit, or a PopupMenu for range/combo cells). The popup_edited_item pointer tracks which TreeItem is being edited. The editor is a child of the Tree, positioned over the cell's rect.
TreeItem and Tree relationship diagram
Sources: scene/gui/tree.h scene/gui/tree.cpp doc/classes/Tree.xml doc/classes/TreeItem.xml
ItemList (scene/gui/item_list.h scene/gui/item_list.cpp) is a flat (non-hierarchical) scrollable list that displays items as text, icons, or both. It supports single and multi-column grid layout.
Each entry is an ItemList::Item struct scene/gui/item_list.h containing:
| Field | Purpose |
|---|---|
text / xl_text | Display text (raw and translated) |
icon | Optional Texture2D |
icon_region | Sub-region for atlas textures |
icon_transposed | Rotate icon 90° |
icon_modulate | Color multiplier for icon |
tag_icon | Small overlay tag texture |
selectable / selected | Selection state |
disabled | Prevents selection |
custom_bg / custom_fg | Per-item background/foreground color |
tooltip | Hover tooltip string |
metadata | Arbitrary Variant |
text_buf | Shaped TextLine for rendering |
ItemList::IconMode controls item presentation:
| Mode | Description |
|---|---|
ICON_MODE_TOP | Icon above text; enables word wrap with max_text_lines |
ICON_MODE_LEFT | Icon to the left of text |
Column layout is controlled by max_columns (0 = auto-fit). fixed_column_width forces uniform column widths. same_column_width makes all columns the width of the widest item.
ItemList::SelectMode:
| Mode | Behavior |
|---|---|
SELECT_SINGLE | One item at a time; deselects others |
SELECT_MULTI | Multiple items via Shift/Ctrl click |
select(idx, single) scene/gui/item_list.cpp427-452 clears all others if single == true or select_mode == SELECT_SINGLE.
Like Tree and PopupMenu, ItemList supports incremental search: typing characters jumps to the first item whose text starts with the typed prefix. The timeout interval is controlled by ProjectSettings.gui/timers/incremental_search_max_interval_msec.
Sources: scene/gui/item_list.cpp scene/gui/item_list.h doc/classes/ItemList.xml
ColorPicker (scene/gui/color_picker.h scene/gui/color_picker.cpp) is a VBoxContainer providing a full color editing UI. It is used inside ColorPickerButton (a Button that opens a Popup containing a ColorPicker).
Internally, ColorPicker maintains three color values:
| Variable | Purpose |
|---|---|
color | The actual selected color (possibly HDR / overbright) |
color_normalized | Color clamped to [0,1] range per channel |
intensity | Log₂ HDR multiplier (when edit_intensity is enabled) |
h, s, v | HSV representation (cached) |
ok_hsl_h/s/l | OKHSl representation (cached) |
The relationship is: color = color_normalized * 2^intensity (applied in linear space).
ColorModeType selects the slider axis interpretation:
| Mode | Sliders |
|---|---|
MODE_RGB | R, G, B |
MODE_HSV | H, S, V |
MODE_LINEAR | Linear R, G, B |
MODE_OKHSL | OKHsl H, S, L |
Modes are stored in modes (LocalVector<ColorMode*>) scene/gui/color_picker.h188 and the active one is selected by current_mode.
PickerShapeType controls the 2D color selector widget:
| Shape | Description |
|---|---|
SHAPE_HSV_RECTANGLE | Hue bar + SV rectangle |
SHAPE_HSV_WHEEL | Hue ring + SV triangle |
SHAPE_VHS_CIRCLE | Value bar + HS circle |
SHAPE_OKHSL_CIRCLE | OKHsl wheel |
SHAPE_OK_HS_RECTANGLE | OKHsl HS rectangle |
SHAPE_OK_HL_RECTANGLE | OKHsl HL rectangle |
SHAPE_NONE | No 2D selector; sliders only |
Shapes are lazy-initialized: shape->initialize_controls() is only called when a shape becomes active scene/gui/color_picker.cpp312-322
create_slider() scene/gui/color_picker.cpp449-496 adds a Label, HSlider, and SpinBox as a row inside a GridContainer. The slider and spinbox are linked via slider->share(val) (Range sharing). Each slider's draw signal is connected to _slider_draw(idx) to paint the color gradient background.
ColorPicker maintains two lists:
presets — user-saved named color swatchesrecent_presets — automatically populated as colors are pickedBoth are optionally persisted through editor_settings (used in the Godot editor context).
ColorPicker internal structure
Sources: scene/gui/color_picker.cpp scene/gui/color_picker.h doc/classes/ColorPicker.xml
Popup (scene/gui/popup.cpp) is a Window subclass that auto-hides when focus is lost or a click occurs outside its bounds (FLAG_POPUP). Both PopupMenu and ColorPickerButton's color window inherit from it.
Key behaviors:
_parent_focused() — triggers hide unless the click was inside a declared safe area.add_autohide_area() / clear_autohide_areas() — rectangles that suppress auto-hide (used by PopupMenu for submenu safe zones).Sources: scene/gui/popup.cpp
All controls in scene/gui/ pull visual style from the Theme resource. Each control defines a local ThemeCache struct and populates it in _update_theme_item_cache(). The default runtime theme is populated by scene/theme/default_theme.cpp. The editor overrides these with editor/themes/editor_theme_manager.cpp.
Typical theme items per control:
| Control | Key theme items |
|---|---|
Button | normal, hover, pressed, disabled StyleBoxes; font, font_color, icon_max_width |
Tree | selected, cursor, relationship_line, column separation constants |
ItemList | panel_style, selected, selected_focus StyleBoxes |
PopupMenu | panel_style, checked/radio_checked icons, h_separation, v_separation |
SpinBox | updown icon, internal button region sizes |
ColorPicker | sv_width, sv_height, h_width, bar_arrow, screen_picker icon |
Sources: scene/theme/default_theme.cpp editor/themes/editor_theme_manager.cpp
Tree, ItemList, and PopupMenu all implement the same incremental search pattern:
search_string.gui/timers/incremental_search_max_interval_msec, reset search_string.search_string.All three controls use a text_buf (either TextParagraph or TextLine) per item. A dirty flag marks when the shaped text must be rebuilt via _shape_text() or _shape_item(). This avoids redundant text layout work when items are unchanged.
Controls call queue_accessibility_update() on state changes (selection, value, checked state) and implement NOTIFICATION_ACCESSIBILITY_UPDATE to push updated attributes to DisplayServer::get_singleton(). TreeItem and ItemList::Item each maintain a RID accessibility_*_element for their corresponding accessibility tree node.
Sources: scene/gui/tree.cpp85-108 scene/gui/item_list.cpp70-89 scene/gui/popup_menu.cpp488-540 scene/gui/base_button.cpp109-138 scene/gui/spin_box.cpp55-81
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.