Skip to content

Palette Overlay UI

Relevant source files

This page documents the TajsModPaletteOverlay class, which implements the visual interface for the command palette system. It covers UI construction, display modes, search integration, and input handling. For the command registration and execution system that powers this UI, see Command Definitions and Registry. For the overall command palette architecture, see Command Palette System.

The TajsModPaletteOverlay extends CanvasLayer and provides a modal overlay with search capabilities, results display, and keyboard/mouse navigation. It operates in three distinct modes: normal command palette, node picker (for wire-drop feature), and group picker (for jump-to-group navigation).

ComponentTypePurpose
TajsModPaletteOverlayCanvasLayerRoot container at z-layer 100
backgroundColorRectSemi-transparent backdrop for modal behavior
panelPanelContainerCentered main UI panel (600×500px)
search_inputLineEditFuzzy search text field
results_containerVBoxContainerScrollable list of command/item results
breadcrumb_labelLabelNavigation path display in footer
_onboarding_hintControlFirst-time user guidance panel

Sources: extensions/scripts/palette/palette_overlay.gd L1-L72

flowchart TD

Overlay["TajsModPaletteOverlay<br>(CanvasLayer layer=100)"]
Background["background<br>(ColorRect)"]
Panel["panel<br>(PanelContainer)"]
VBox["VBoxContainer"]
Header["Header<br>(MarginContainer)"]
SearchHBox["HBoxContainer"]
SearchIcon["🔍 Label"]
SearchInput["search_input<br>(LineEdit)"]
ResultsScroll["results_scroll<br>(ScrollContainer)"]
ResultsContainer["results_container<br>(VBoxContainer)"]
OnboardingHint["_onboarding_hint<br>(PanelContainer)"]
NoResults["no_results_label<br>(Label)"]
ResultRow1["Result Row 1"]
ResultRow2["Result Row 2"]
ResultRowN["Result Row N"]
Footer["Footer<br>(PanelContainer)"]
FooterHBox["HBoxContainer"]
Breadcrumb["breadcrumb_label<br>(Label)"]
HintLabel["Hint Label"]

Overlay --> Background
Overlay --> Panel
Panel --> VBox
VBox --> Header
VBox --> ResultsScroll
VBox --> Footer
Header --> SearchHBox
SearchHBox --> SearchIcon
SearchHBox --> SearchInput
ResultsScroll --> ResultsContainer
ResultsContainer --> OnboardingHint
ResultsContainer --> NoResults
ResultsContainer --> ResultRow1
ResultsContainer --> ResultRow2
ResultsContainer --> ResultRowN
Footer --> FooterHBox
FooterHBox --> Breadcrumb
FooterHBox --> HintLabel

Sources: extensions/scripts/palette/palette_overlay.gd L96-L171

extensions/scripts/palette/palette_overlay.gd L174-L212

extensions/scripts/palette/palette_overlay.gd L215-L247

The overlay operates in three mutually exclusive modes, controlled by boolean flags:

ModeFlagTriggerPurpose
NormalDefault stateMMB or toggle_palette()Browse and execute commands from registry
Node Picker_picker_mode = trueWire dropped on empty canvasDisplay compatible nodes for connection
Group Picker_group_picker_mode = true”Jump to Group” commandList all node groups for navigation
stateDiagram-v2
    [*] --> Closed : "show_palette()"
    Closed --> Normal : "show_palette()"
    Closed --> NodePicker : "hide_palette()or node_selected"
    Closed --> GroupPicker : "show_group_picker()"
    Normal --> Closed : "show_palette()"
    Normal --> NodePicker : "hide_palette()or node_selected"
    Normal --> GroupPicker : "show_group_picker()"
    NodePicker --> Closed : "hide_palette()or node_selected"
    NodePicker --> Normal : "show_palette()"
    GroupPicker --> Closed : "show_group_picker()"
    GroupPicker --> Normal : "show_group_picker()"
    Closed --> [*] : "hide_palette()or node_selected"

Sources: extensions/scripts/palette/palette_overlay.gd L38-L46

extensions/scripts/palette/palette_overlay.gd L335-L398

In normal mode, the overlay displays commands from the registry, organized by categories with breadcrumb navigation.

flowchart TD

ShowPalette["show_palette()"]
Refresh["context.refresh()"]
ShowHome["_show_home_screen()"]
DisplayItems["_display_items()"]
CreateRows["_create_result_row()"]
UpdateSelection["_update_selection()"]

ShowPalette --> Refresh
Refresh --> ShowHome
ShowHome --> DisplayItems
DisplayItems --> CreateRows
CreateRows --> UpdateSelection

The home screen displays:

  1. Favorites (if configured via palette_config.get_favorites())
  2. Recent commands (up to 5, via palette_config.get_recents())
  3. Root categories (from registry.get_root_items())

Sources: extensions/scripts/palette/palette_overlay.gd L335-L368

extensions/scripts/palette/palette_overlay.gd L627-L673

Node picker mode is activated when a wire is dropped on empty canvas space. It filters and displays nodes compatible with the wire’s origin pin.

flowchart TD

WireDrop["Wire dropped<br>on empty canvas"]
Controller["PaletteController<br>identifies compatible nodes"]
ShowPicker["show_node_picker(<br>compatible_nodes,<br>origin_info,<br>spawn_position)"]
SetState["Set _picker_mode = true<br>Store origin_info<br>Store spawn_position"]
DisplayPicker["_display_picker_nodes()"]
CreateItems["Convert node data<br>to display format"]
UserSelect["User selects node"]
EmitSignal["emit node_selected<br>(node_id, position, origin_info)"]
SpawnAndConnect["Controller spawns<br>and connects node"]

WireDrop --> Controller
Controller --> ShowPicker
ShowPicker --> SetState
SetState --> DisplayPicker
DisplayPicker --> CreateItems
CreateItems --> UserSelect
UserSelect --> EmitSignal
EmitSignal --> SpawnAndConnect

Key state stored during node picker mode:

  • _picker_origin_info: Dictionary containing wire connection details (is_output, pin type)
  • _picker_spawn_position: Vector2 for where to create the new node
  • _picker_nodes: Array of compatible node definitions

Sources: extensions/scripts/palette/palette_overlay.gd L401-L428

extensions/scripts/palette/palette_overlay.gd L432-L463

extensions/scripts/palette/palette_overlay.gd L1018-L1031

Group picker mode displays all node groups on the desktop for quick camera navigation.

flowchart TD

JumpCmd["Jump to Group command"]
GetGroups["goto_group_manager<br>.get_all_groups()"]
ShowGroupPicker["show_group_picker(<br>groups,<br>goto_group_manager)"]
SetState["Set _group_picker_mode = true<br>Store groups array<br>Store manager reference"]
DisplayGroups["_display_group_picker()"]
FormatItems["Format groups<br>with names and icons"]
UserSelect["User selects group"]
EmitSignal["emit group_selected(group)"]
Navigate["goto_group_manager<br>.navigate_to_group()"]

JumpCmd --> GetGroups
GetGroups --> ShowGroupPicker
ShowGroupPicker --> SetState
SetState --> DisplayGroups
DisplayGroups --> FormatItems
FormatItems --> UserSelect
UserSelect --> EmitSignal
EmitSignal --> Navigate

Sources: extensions/scripts/palette/palette_overlay.gd L500-L533

extensions/scripts/palette/palette_overlay.gd L537-L587

extensions/scripts/palette/default_commands.gd L162-L193

The overlay uses a debounced search system with mode-specific filtering logic.

flowchart TD

Input["User types in<br>search_input"]
OnChange["_on_search_changed()"]
StartTimer["Start _debounce_timer<br>(30ms)"]
Timeout["Timer timeout"]
PerformSearch["_perform_search()"]
ModeCheck["Check mode"]
NormalSearch["FuzzySearch.search()<br>on all commands"]
PickerFilter["_filter_picker_nodes()"]
GroupFilter["_filter_group_picker()"]
Display["Display filtered results"]

Input --> OnChange
OnChange --> StartTimer
StartTimer --> Timeout
Timeout --> PerformSearch
PerformSearch --> ModeCheck
ModeCheck --> NormalSearch
ModeCheck --> PickerFilter
ModeCheck --> GroupFilter
NormalSearch --> Display
PickerFilter --> Display
GroupFilter --> Display

Sources: extensions/scripts/palette/palette_overlay.gd L323-L328

extensions/scripts/palette/palette_overlay.gd L856-L889

In normal mode, search delegates to FuzzySearch.search() for intelligent matching:

Search FeatureImplementation
AlgorithmUses FuzzySearch preload from fuzzy_search.gd
InputQuery string, all executable commands, context, max results
ScoringKeywords, title matching, category relevance
FilteringRespects can_run() and tools visibility from context
Max Results10 items (MAX_VISIBLE_ITEMS)

Sources: extensions/scripts/palette/palette_overlay.gd L11

extensions/scripts/palette/palette_overlay.gd L881-L889

Node Picker Filtering (_filter_picker_nodes):

  • Searches node name, description, and category fields
  • Case-insensitive substring matching
  • No fuzzy scoring (exact substring required)

Group Picker Filtering (_filter_group_picker):

  • Retrieves group names via goto_group_manager.get_group_name()
  • Fallback to get_window_name() or custom_name property
  • Case-insensitive substring matching

Sources: extensions/scripts/palette/palette_overlay.gd L477-L493

extensions/scripts/palette/palette_overlay.gd L596-L620

Each result item is rendered as a styled PanelContainer with dynamic content based on the item’s properties.

flowchart TD

Row["PanelContainer<br>(50px height)"]
Margin["MarginContainer<br>(12px margins)"]
HBox["HBoxContainer"]
Indicator["Favorite ★<br>or Recent ⏱"]
Icon["TextureRect<br>(24×24px)"]
Title["Label<br>(18pt font)"]
Path["Category path<br>(12pt gray)"]
Arrow["→ indicator"]
Badge["[SAFE/OPT-IN]<br>(12pt colored)"]

Row --> Margin
Margin --> HBox
HBox --> Indicator
HBox --> Icon
HBox --> Title
HBox --> Path
HBox --> Arrow
HBox --> Badge

The _create_result_row() method builds each row with conditional elements:

ElementConditionAppearance
Favorite staritem._is_favorite == true★ (yellow, 16pt)
Recent clockitem._is_recent == true⏱ (gray, 14pt)
Iconitem.icon_path exists and loadable24×24px texture
TitleAlways shownDynamic via get_title() callable or title field
Category pathNot empty and at home screen”Cat1 > Cat2” format
Arrow indicatoritem.is_category == true→ symbol
BadgeAlways shown[SAFE], [OPT-IN], or [GAMEPLAY]

Dynamic Title Support: Commands can provide a get_title callable that returns the current title, enabling dynamic labels like “Wire Drop Menu [ON]” that reflect real-time state.

Sources: extensions/scripts/palette/palette_overlay.gd L725-L819

The _update_selection() method applies visual feedback to the selected row:

flowchart TD

UpdateSel["_update_selection()"]
Loop["For each row in _result_items"]
Check["i == _selected_index?"]
Selected["bg_color = COLOR_SELECTED<br>border = 1px blue<br>border_color = rgba(0.4,0.6,0.8,0.6)"]
Unselected["bg_color = rgba(0.1,0.12,0.16,0.3)<br>border = 0px"]
Scroll["results_scroll.ensure_control_visible()"]

UpdateSel --> Loop
Loop --> Check
Check --> Selected
Check --> Unselected
Selected --> Scroll
Unselected --> Loop

Sources: extensions/scripts/palette/palette_overlay.gd L822-L842

The overlay implements comprehensive keyboard navigation in _on_search_input():

KeyActionImplementation
EscapeClose palettehide_palette()
EnterExecute selected item_execute_selected()
Previous item_select_previous()
Next item_select_next()
→ or TabEnter category_enter_category()
← or BackspaceGo back_go_back() if search is empty
Ctrl+FToggle favorite_toggle_favorite_selected()
Ctrl+ASelect all textsearch_input.select_all()

Sources: extensions/scripts/palette/palette_overlay.gd L896-L940

Background clicks: Clicking the dimmed background closes the palette via _on_background_input().

Row interaction:

  • Hover: Sets _selected_index via _on_item_hover()
  • Click: Executes item via _on_item_click()

Mouse button navigation:

  • X1 (back button): _go_back()
  • X2 (forward button): _enter_category()

Sources: extensions/scripts/palette/palette_overlay.gd L943-L964

The overlay maintains forward/backward history stacks for breadcrumb-style navigation:

flowchart TD

EnterCat["_enter_category()"]
PushBack["Push _current_path<br>to _history_back"]
ClearFwd["Clear _history_forward"]
Navigate["Append category to path<br>Show new category"]
GoBack["_go_back()"]
CheckBack["_history_back<br>empty?"]
PopLevel["Pop from _current_path"]
PopHistory["Pop from _history_back"]
PushFwd["Push to _history_forward"]
ShowCat["Show category or home"]

EnterCat --> PushBack
PushBack --> ClearFwd
ClearFwd --> Navigate
GoBack --> CheckBack
CheckBack --> PopLevel
CheckBack --> PopHistory
PopHistory --> PushFwd
PopLevel --> PushFwd
PushFwd --> ShowCat

Sources: extensions/scripts/palette/palette_overlay.gd L1050-L1088

sequenceDiagram
  participant User
  participant TajsModPaletteOverlay
  participant TajsModCommandRegistry
  participant TajsModPaletteConfig
  participant TajsModContextProvider

  User->>TajsModPaletteOverlay: Press Enter on selected item
  TajsModPaletteOverlay->>TajsModPaletteOverlay: _execute_selected()
  loop [keep_open ==
    TajsModPaletteOverlay->>TajsModPaletteOverlay: _enter_category()
    TajsModPaletteOverlay->>TajsModCommandRegistry: run(command_id, context)
    TajsModCommandRegistry->>TajsModContextProvider: Validate can_run()
    TajsModContextProvider-->>TajsModCommandRegistry: true
    TajsModCommandRegistry->>TajsModCommandRegistry: Execute command.run(ctx)
    TajsModCommandRegistry-->>TajsModPaletteOverlay: true
    TajsModPaletteOverlay->>TajsModPaletteConfig: add_recent(command_id)
    TajsModPaletteOverlay->>TajsModPaletteOverlay: emit command_executed
    TajsModPaletteOverlay->>TajsModPaletteOverlay: hide_palette()
    TajsModPaletteOverlay->>TajsModPaletteOverlay: emit node_selected(node_id, position, origin_info)
    TajsModPaletteOverlay->>TajsModPaletteOverlay: hide_palette()
    TajsModPaletteOverlay->>TajsModPaletteOverlay: emit group_selected(group)
    TajsModPaletteOverlay->>TajsModPaletteOverlay: hide_palette()
  end

Sources: extensions/scripts/palette/palette_overlay.gd L981-L1048

VariableTypePurpose
_is_openboolWhether palette is currently visible
_current_pathArray[String]Current category breadcrumb path
_displayed_itemsArray[Dictionary]Items currently shown in results
_selected_indexintIndex of highlighted result row
_result_itemsArray[Control]UI node references for result rows
_history_backArrayNavigation history for back button
_history_forwardArrayNavigation history for forward button

Node Picker State:

  • _picker_mode: bool flag
  • _picker_origin_info: Dictionary with is_output, pin type
  • _picker_spawn_position: Vector2 for node creation
  • _picker_nodes: Array[Dictionary] of compatible node definitions

Group Picker State:

  • _group_picker_mode: bool flag
  • _group_picker_groups: Array of group node references
  • "goto_group_manager" metadata: Reference to GotoGroupManager instance

Sources: extensions/scripts/palette/palette_overlay.gd L27-L46

The overlay defines semantic colors as class constants:

ConstantValueUsage
COLOR_BG_DIMrgba(0,0,0,0.6)Modal background overlay
COLOR_SELECTEDrgba(0.2,0.4,0.6,0.8)Selected result row highlight
COLOR_HOVERrgba(0.15,0.25,0.35,0.5)Row hover state
COLOR_BADGE_SAFErgb(0.3,0.7,0.4)[SAFE] badge (green)
COLOR_BADGE_OPTINrgb(0.85,0.65,0.2)[OPT-IN] badge (orange)
COLOR_BADGE_GAMEPLAYrgb(0.8,0.3,0.3)[GAMEPLAY] badge (red)
COLOR_TEXT_SHADOWrgba(0,0,0,0.8)Text shadow/outline
COLOR_TEXT_GLOWrgba(0.4,0.65,1.0,0.5)Text outline glow effect

Sources: extensions/scripts/palette/palette_overlay.gd L54-L62

The main panel uses StyleBoxFlat with rounded corners and shadow:

Background: rgba(0.08, 0.1, 0.14, 0.95)
Border: 2px rgba(0.3, 0.5, 0.7, 0.6)
Corner Radius: 12px (all corners)
Shadow: 10px rgba(0, 0, 0, 0.5)

Theme Integration: If res://themes/main.tres exists, it is applied to the panel for consistent font rendering with the base game.

Sources: extensions/scripts/palette/palette_overlay.gd L96-L134

The _apply_text_style() helper applies outline-based glow effects:

# Glow effect via outline
outline_size: 5
font_outline_color: COLOR_TEXT_GLOW (for glowing labels)

Applied to:

  • Command titles (with glow)
  • Category paths (shadow only, no glow)
  • Breadcrumbs (shadow only)

Sources: extensions/scripts/palette/palette_overlay.gd L89-L94

The overlay includes a first-time user hint panel that displays keyboard shortcuts and features.

flowchart TD

ShowPalette["show_palette()"]
CheckOnboard["palette_config<br>.is_onboarded()?"]
ShowHint["Display _onboarding_hint"]
HideHint["Hide _onboarding_hint"]
UserDismiss["User clicks 'Got it!'"]
SetFlag["palette_config<br>.set_onboarded(true)"]

ShowPalette --> CheckOnboard
CheckOnboard --> ShowHint
CheckOnboard --> HideHint
ShowHint --> UserDismiss
UserDismiss --> SetFlag

Manual Trigger: The “Palette Help” command can re-display the hint via show_onboarding_hint().

Hint Content:

  • MMB (Middle Mouse) to open/close
  • ↑↓ navigate, Enter select, Esc close
  • Ctrl+F toggle favorite
  • Wire drop → Node Picker feature

Sources: extensions/scripts/palette/palette_overlay.gd L250-L321

extensions/scripts/palette/palette_overlay.gd L355-L361

extensions/scripts/palette/default_commands.gd L878-L890

The overlay emits three signals for communication with the controller layer:

SignalParametersPurpose
command_executedcommand_id: StringNotify that a command was run
node_selectedwindow_id: String, spawn_pos: Vector2, origin_info: DictionaryRequest node spawn in picker mode
group_selectedgroupRequest navigation to group in group picker mode
closedNoneNotify that palette was hidden

Sources: extensions/scripts/palette/palette_overlay.gd L64-L67

MethodCalled ByPurpose
_init()GodotSet layer = 100, name node
_ready()GodotBuild UI, setup debounce timer
setup()PaletteControllerInject dependencies (registry, context, config)
show_palette()PaletteControllerDisplay in normal mode
hide_palette()User input or command executionClose and reset state
toggle_palette()Input handlerOpen/close based on current state

Sources: extensions/scripts/palette/palette_overlay.gd L70-L87