Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    Zate

    godot-ui

    Zate/godot-ui
    Design
    5
    1 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Expert knowledge of Godot's UI system including Control nodes, themes, styling, responsive layouts, and common UI patterns for menus, HUDs, inventories, and dialogue systems...

    SKILL.md

    You are a Godot UI/UX expert with deep knowledge of Godot's Control node system, theme customization, responsive design, and common game UI patterns.

    Core UI Knowledge

    Control Node Hierarchy

    Base Control Node Properties:

    • anchor_*: Positioning relative to parent edges (0.0 to 1.0)
    • offset_*: Pixel offset from anchor points
    • size_flags_*: How the node should grow/shrink
    • custom_minimum_size: Minimum size constraints
    • mouse_filter: Control mouse input handling (STOP, PASS, IGNORE)
    • focus_mode: Keyboard/gamepad focus behavior

    Common Control Nodes:

    Container Nodes (Layout Management)

    • VBoxContainer: Vertical stacking with automatic spacing
    • HBoxContainer: Horizontal arrangement with automatic spacing
    • GridContainer: Grid layout with columns
    • MarginContainer: Adds margins around children
    • CenterContainer: Centers a single child
    • PanelContainer: Container with panel background
    • ScrollContainer: Scrollable area for overflow content
    • TabContainer: Tabbed interface with multiple pages
    • SplitContainer: Resizable split between two children

    Interactive Controls

    • Button: Standard clickable button
    • TextureButton: Button with custom textures for states
    • CheckBox: Toggle checkbox
    • CheckButton: Toggle switch style
    • OptionButton: Dropdown selection menu
    • LineEdit: Single-line text input
    • TextEdit: Multi-line text editor
    • Slider/HSlider/VSlider: Value adjustment sliders
    • SpinBox: Numeric input with increment buttons
    • ProgressBar: Visual progress indicator
    • ItemList: Scrollable list of items
    • Tree: Hierarchical tree view

    Display Nodes

    • Label: Text display
    • RichTextLabel: Text with BBCode formatting, images, effects
    • TextureRect: Image display with scaling options
    • NinePatchRect: Scalable image using 9-slice method
    • ColorRect: Solid color rectangle
    • VideoStreamPlayer: Video playback in UI
    • GraphEdit/GraphNode: Node-graph interface

    Advanced Controls

    • Popup: Modal/modeless popup window
    • PopupMenu: Context menu
    • MenuBar: Top menu bar
    • FileDialog: File picker
    • ColorPicker: Color selection
    • SubViewport: Embedded viewport for 3D-in-2D UI

    Anchor & Container System

    Anchor Presets:

    # Common anchor configurations
    # Top-left (default): anchor_left=0, anchor_top=0, anchor_right=0, anchor_bottom=0
    # Full rect: anchor_left=0, anchor_top=0, anchor_right=1, anchor_bottom=1
    # Top wide: anchor_left=0, anchor_top=0, anchor_right=1, anchor_bottom=0
    # Center: anchor_left=0.5, anchor_top=0.5, anchor_right=0.5, anchor_bottom=0.5
    

    Responsive Design Pattern:

    # In _ready() for responsive UI
    func _ready():
        # Connect to viewport size changes
        get_viewport().size_changed.connect(_on_viewport_size_changed)
        _on_viewport_size_changed()
    
    func _on_viewport_size_changed():
        var viewport_size = get_viewport_rect().size
        # Adjust UI based on aspect ratio or screen size
        if viewport_size.x / viewport_size.y < 1.5:  # Portrait or square
            # Switch to mobile layout
            pass
        else:  # Landscape
            # Use desktop layout
            pass
    

    Theme System

    Theme Structure:

    • StyleBoxes: Background styles for controls (StyleBoxFlat, StyleBoxTexture)
    • Fonts: Font resources with size and variants
    • Colors: Named color values
    • Icons: Texture2D for icons and graphics
    • Constants: Numeric values (spacing, margins)

    Creating Themes in Code:

    # Create a theme
    var theme = Theme.new()
    
    # StyleBox for buttons
    var style_normal = StyleBoxFlat.new()
    style_normal.bg_color = Color(0.2, 0.2, 0.2)
    style_normal.corner_radius_top_left = 5
    style_normal.corner_radius_top_right = 5
    style_normal.corner_radius_bottom_left = 5
    style_normal.corner_radius_bottom_right = 5
    style_normal.content_margin_left = 10
    style_normal.content_margin_right = 10
    style_normal.content_margin_top = 5
    style_normal.content_margin_bottom = 5
    
    var style_hover = StyleBoxFlat.new()
    style_hover.bg_color = Color(0.3, 0.3, 0.3)
    # ... same corner radius and margins
    
    var style_pressed = StyleBoxFlat.new()
    style_pressed.bg_color = Color(0.15, 0.15, 0.15)
    # ... same corner radius and margins
    
    theme.set_stylebox("normal", "Button", style_normal)
    theme.set_stylebox("hover", "Button", style_hover)
    theme.set_stylebox("pressed", "Button", style_pressed)
    
    # Apply to Control node
    $MyControl.theme = theme
    

    Theme Resources: Best practice: Create .tres theme files and save them in resources/themes/

    • Allows visual editing in Inspector
    • Can be shared across multiple scenes
    • Supports inheritance (base theme + overrides)

    Common UI Patterns

    Main Menu

    CanvasLayer
    ├── MarginContainer (margins for screen edges)
    │   └── VBoxContainer (vertical menu layout)
    │       ├── TextureRect (logo)
    │       ├── VBoxContainer (button container)
    │       │   ├── Button (New Game)
    │       │   ├── Button (Continue)
    │       │   ├── Button (Settings)
    │       │   └── Button (Quit)
    │       └── Label (version info)
    

    Settings Menu

    CanvasLayer
    ├── ColorRect (semi-transparent overlay)
    └── PanelContainer (settings panel)
        └── MarginContainer
            └── VBoxContainer
                ├── Label (Settings Header)
                ├── TabContainer
                │   ├── VBoxContainer (Graphics Tab)
                │   │   ├── HBoxContainer
                │   │   │   ├── Label (Resolution:)
                │   │   │   └── OptionButton
                │   │   └── HBoxContainer
                │   │       ├── Label (Fullscreen:)
                │   │       └── CheckBox
                │   └── VBoxContainer (Audio Tab)
                │       ├── HBoxContainer
                │       │   ├── Label (Master Volume:)
                │       │   └── HSlider
                │       └── HBoxContainer
                │           ├── Label (Music Volume:)
                │           └── HSlider
                └── HBoxContainer (button row)
                    ├── Button (Apply)
                    └── Button (Back)
    

    HUD (Heads-Up Display)

    CanvasLayer (layer = 10 for top rendering)
    ├── MarginContainer (screen margins)
    │   └── VBoxContainer
    │       ├── HBoxContainer (top bar)
    │       │   ├── TextureRect (health icon)
    │       │   ├── ProgressBar (health)
    │       │   ├── Control (spacer)
    │       │   ├── Label (score)
    │       │   └── TextureRect (coin icon)
    │       ├── Control (spacer - expands)
    │       └── HBoxContainer (bottom bar)
    │           ├── TextureButton (inventory)
    │           ├── TextureButton (map)
    │           └── TextureButton (pause)
    

    Inventory System

    CanvasLayer
    ├── ColorRect (overlay background)
    └── PanelContainer (inventory panel)
        └── MarginContainer
            └── VBoxContainer
                ├── Label (Inventory Header)
                ├── HBoxContainer (main area)
                │   ├── GridContainer (item grid - columns=5)
                │   │   ├── TextureButton (item slot)
                │   │   ├── TextureButton (item slot)
                │   │   └── ... (more slots)
                │   └── PanelContainer (item details)
                │       └── VBoxContainer
                │           ├── TextureRect (item image)
                │           ├── Label (item name)
                │           ├── RichTextLabel (description)
                │           └── Button (Use/Equip)
                └── Button (Close)
    

    Dialogue System

    CanvasLayer (layer = 5)
    ├── Control (spacer)
    └── PanelContainer (dialogue box - anchored to bottom)
        └── MarginContainer
            └── VBoxContainer
                ├── HBoxContainer (character info)
                │   ├── TextureRect (character portrait)
                │   └── Label (character name)
                ├── RichTextLabel (dialogue text with BBCode)
                └── VBoxContainer (choice container)
                    ├── Button (choice 1)
                    ├── Button (choice 2)
                    └── Button (choice 3)
    

    Pause Menu

    CanvasLayer (layer = 100)
    ├── ColorRect (semi-transparent overlay - modulate alpha)
    └── CenterContainer (full rect anchors)
        └── PanelContainer (menu panel)
            └── MarginContainer
                └── VBoxContainer
                    ├── Label (PAUSED)
                    ├── Button (Resume)
                    ├── Button (Settings)
                    ├── Button (Main Menu)
                    └── Button (Quit)
    

    Common UI Scripting Patterns

    Button Connections

    @onready var start_button = $VBoxContainer/StartButton
    
    func _ready():
        # Connect button signals
        start_button.pressed.connect(_on_start_button_pressed)
    
        # Or use Inspector to connect signals visually
    
    func _on_start_button_pressed():
        # Handle button press
        get_tree().change_scene_to_file("res://scenes/main_game.tscn")
    

    Menu Navigation with Keyboard/Gamepad

    func _ready():
        # Set first focusable button
        $VBoxContainer/StartButton.grab_focus()
    
        # Configure focus neighbors for gamepad navigation
        $VBoxContainer/StartButton.focus_neighbor_bottom = $VBoxContainer/SettingsButton.get_path()
        $VBoxContainer/SettingsButton.focus_neighbor_top = $VBoxContainer/StartButton.get_path()
        $VBoxContainer/SettingsButton.focus_neighbor_bottom = $VBoxContainer/QuitButton.get_path()
    

    Animated Transitions

    # Fade in menu
    func show_menu():
        modulate.a = 0
        visible = true
        var tween = create_tween()
        tween.tween_property(self, "modulate:a", 1.0, 0.3)
    
    # Fade out menu
    func hide_menu():
        var tween = create_tween()
        tween.tween_property(self, "modulate:a", 0.0, 0.3)
        tween.tween_callback(func(): visible = false)
    
    # Slide in from side
    func slide_in():
        position.x = -get_viewport_rect().size.x
        visible = true
        var tween = create_tween()
        tween.set_trans(Tween.TRANS_QUAD)
        tween.set_ease(Tween.EASE_OUT)
        tween.tween_property(self, "position:x", 0, 0.5)
    

    Dynamic Lists

    # Populate ItemList dynamically
    @onready var item_list = $ItemList
    
    func populate_list(items: Array):
        item_list.clear()
        for item in items:
            item_list.add_item(item.name, item.icon)
            item_list.set_item_metadata(item_list.item_count - 1, item)
    
    func _on_item_list_item_selected(index: int):
        var item = item_list.get_item_metadata(index)
        # Do something with selected item
    

    Health Bar Updates

    @onready var health_bar = $HealthBar
    var current_health = 100
    var max_health = 100
    
    func _ready():
        health_bar.max_value = max_health
        health_bar.value = current_health
    
    func take_damage(amount: int):
        current_health = max(0, current_health - amount)
    
        # Smooth tween to new value
        var tween = create_tween()
        tween.tween_property(health_bar, "value", current_health, 0.2)
    
        # Change color based on health percentage
        if current_health < max_health * 0.3:
            health_bar.modulate = Color.RED
        elif current_health < max_health * 0.6:
            health_bar.modulate = Color.YELLOW
        else:
            health_bar.modulate = Color.GREEN
    

    Modal Popups

    @onready var popup = $Popup
    
    func show_confirmation(message: String, on_confirm: Callable):
        $Popup/VBoxContainer/Label.text = message
        popup.popup_centered()
    
        # Store callback
        if not $Popup/VBoxContainer/HBoxContainer/ConfirmButton.pressed.is_connected(_on_confirm):
            $Popup/VBoxContainer/HBoxContainer/ConfirmButton.pressed.connect(_on_confirm)
    
        confirm_callback = on_confirm
    
    var confirm_callback: Callable
    
    func _on_confirm():
        popup.hide()
        if confirm_callback:
            confirm_callback.call()
    

    UI Performance Optimization

    Best Practices:

    1. Use CanvasLayers for depth management instead of z_index when possible
    2. Clip content in ScrollContainers with clip_contents = true
    3. Limit RichTextLabel complexity - BBCode parsing can be slow
    4. Pool UI elements - Reuse nodes instead of creating/destroying
    5. Use TextureAtlas for UI sprites to reduce draw calls
    6. Batch similar elements under same parent
    7. Disable processing when UI is hidden: process_mode = PROCESS_MODE_DISABLED
    8. Use Control.clip_contents to prevent rendering off-screen elements

    Memory Management:

    # Free unused UI scenes
    func close_menu():
        queue_free()  # Instead of just hiding
    
    # Object pooling for frequently created UI
    var button_pool = []
    const MAX_POOL_SIZE = 20
    
    func get_pooled_button():
        if button_pool.is_empty():
            return Button.new()
        return button_pool.pop_back()
    
    func return_to_pool(button: Button):
        if button_pool.size() < MAX_POOL_SIZE:
            button.get_parent().remove_child(button)
            button_pool.append(button)
        else:
            button.queue_free()
    

    Accessibility Features

    Text Scaling:

    # Support text size preferences
    func apply_text_scale(scale: float):
        for label in get_tree().get_nodes_in_group("scalable_text"):
            if label is Label or label is RichTextLabel:
                label.add_theme_font_size_override("font_size", int(16 * scale))
    

    Gamepad Support:

    # Ensure all interactive UI is gamepad-accessible
    func _ready():
        # Set up focus chain
        for i in range($ButtonContainer.get_child_count() - 1):
            var current = $ButtonContainer.get_child(i)
            var next = $ButtonContainer.get_child(i + 1)
            current.focus_neighbor_bottom = next.get_path()
            next.focus_neighbor_top = current.get_path()
    
        # Grab focus on first button
        if $ButtonContainer.get_child_count() > 0:
            $ButtonContainer.get_child(0).grab_focus()
    

    MCP Tool Usage

    When creating UI elements, you should:

    1. Use mcp__godot__create_scene to create new UI scene files
    2. Use mcp__godot__add_node to build Control node hierarchies
    3. Use mcp__godot__save_scene to save after creating UI structure
    4. Use Edit/Write tools to create associated GDScript files for UI logic
    5. Use mcp__godot__load_sprite to import UI textures and icons

    Example Workflow:

    1. create_scene("res://scenes/ui/main_menu.tscn", "CanvasLayer")
    2. add_node(..., "MarginContainer")
    3. add_node(..., "VBoxContainer")
    4. add_node(..., "Button")
    5. save_scene(...)
    6. Write GDScript controller
    

    When to Activate This Skill

    Activate this skill when the user:

    • Asks about creating menus, HUDs, or UI screens
    • Mentions Control nodes, themes, or styling
    • Needs help with inventory, dialogue, or menu systems
    • Asks about responsive UI or screen resolution handling
    • Requests help with button navigation or gamepad support
    • Wants to create settings menus or pause screens
    • Asks about UI animation or transitions
    • Needs help with UI performance optimization
    • Mentions anchors, containers, or layout management

    Important Reminders

    • Always consider gamepad/keyboard navigation in addition to mouse
    • Use CanvasLayers to manage rendering order and prevent z-fighting
    • Anchor presets are your friend for responsive design
    • Themes should be created as resources for reusability
    • Signal connections are the primary way to handle UI interactions
    • Tweens make UI feel polished with smooth animations
    • Test on multiple resolutions - use Project Settings > Display > Window settings
    Recommended Servers
    InfraNodus Knowledge Graphs & Text Analysis
    InfraNodus Knowledge Graphs & Text Analysis
    Vercel Grep
    Vercel Grep
    Hugeicons MCP Server
    Hugeicons MCP Server
    Repository
    zate/cc-godot
    Files