UI Templates and Setup (v5.0)

v5.0 provides a comprehensive set of UI templates for building interfaces, selection systems, and user feedback. This guide covers template setup, customization, and integration using the drag-and-drop editor first approach.

For a complete setup overview, see Getting Started Setup.

Editor-First Approach

🎯 Primary Method: Drag and drop .tscn scenes directly into your game’s HUD/UI stack, then configure settings in the Inspector rather than through script.

Benefits of Editor-First Approach:

  • Visual Layout: See UI placement in real-time
  • Inspector Configuration: All settings available in the Inspector
  • No Script Dependencies: UI works without additional code
  • Easy Iteration: Adjust properties without recompiling
  • Scene Tree Integration: Natural Godot workflow

Template Overview

UI templates are located in /templates/ui/ and provide pre-built components for common building interface needs.

Core UI Templates

  • placeable_selection_ui.tscn - Building selection interface
  • action_bar.tscn - Main action buttons and controls
  • action_log.tscn - Message and feedback display
  • target_informer.tscn - Target information display
  • camera_zoom_slider.tscn - Camera zoom controls

Placeable Selection UI

Template Structure

PlaceableSelectionUI (Control)
├── CategoryTabs (TabContainer)
│   ├── Buildings (ScrollContainer)
│   ├── Decorations (ScrollContainer)
│   └── Units (ScrollContainer)
├── ItemGrid (GridContainer)
├── PreviewPanel (Panel)
└── SearchBox (LineEdit)

Setup Instructions (Editor-First)

  1. Drag and Drop Template

    • Open your UI/HUD scene in the editor
    • Drag placeable_selection_ui.tscn from the FileSystem dock into your scene tree
    • Position it within your UI hierarchy (typically under a CanvasLayer or Control node)
  2. Configure in Inspector

    • Select the instanced PlaceableSelectionUI node
    • In the Inspector, configure the folder properties:
      category_tags_folder: "res://your_game/categories/"
      placeables_folder: "res://your_game/placeables/"
      sequences_folder: "res://your_game/sequences/"
      
  3. Connect to Building System (Optional)

    • Most templates auto-connect to systems via the GBInjectorSystem
    • If manual connection needed, use the Inspector to assign system references:
      building_system: [Drag your BuildingSystem node here]
      targeting_system: [Drag your GridTargetingSystem node here]
      
  4. Adjust Visual Properties

    • Use the Inspector to modify colors, sizes, and layouts
    • Adjust anchors and margins for proper screen positioning
    • Configure theme overrides for custom styling

Script Alternative (Advanced Only):

1
2
3
4
# Only use if you need dynamic UI creation
var selection_ui = preload("res:///templates/ui/placement_selection/placeable_selection_ui.tscn").instantiate()
$UI/HUD.add_child(selection_ui)
# Configure properties as shown above

Other UI Templates

Action Bar

Editor Setup:

  1. Drag action_bar.tscn into your UI scene
  2. Configure button actions in the Inspector:
    build_confirm_action: "build_confirm"
    build_cancel_action: "build_cancel"
    rotate_left_action: "rotate_left"
    rotate_right_action: "rotate_right"
    

Action Log

Editor Setup:

  1. Drag action_log.tscn into your UI scene
  2. Configure display settings:
    max_messages: 50
    auto_clear_time: 5.0
    show_timestamps: true
    

Target Informer

Editor Setup:

  1. Drag target_informer.tscn into your UI scene
  2. Position near cursor or game area
  3. Configure display format in Inspector

Camera Zoom Slider

Editor Setup:

  1. Drag camera_zoom_slider.tscn into your UI scene
  2. Configure zoom limits:
    min_zoom: 0.5
    max_zoom: 3.0
    zoom_step: 0.1
    

Editor-First Best Practices

Visual Layout

  • Use the Scene Tree: Drag and drop to organize UI hierarchy
  • Live Preview: See changes immediately in the 2D editor
  • Anchor System: Use anchors for responsive design
  • Theme Integration: Apply custom themes via the Inspector

Configuration Workflow

  1. Instance Template: Drag .tscn file into scene
  2. Select Node: Click the instanced UI node
  3. Configure Properties: Use the Inspector for all settings
  4. Test Layout: Run scene to verify positioning
  5. Iterate: Adjust properties without code changes

Property Assignment

  • Drag References: Assign system nodes by dragging from Scene Tree
  • Resource Assignment: Load resources via the Inspector
  • Path Configuration: Use NodePath properties for scene references
  • Export Variables: All important properties are exported for Inspector access

Customization Options

Category Configuration

Editor Method:

  1. Create category files in your categories folder
  2. Configure folder paths in the Inspector
  3. Templates auto-load categories based on folder structure

File Structure:

res://your_game/categories/
├── buildings.json
├── decorations.json
└── units.json

{ “name”: “Buildings”, “icon”: “res://icons/buildings.png”, “description”: “Structures and buildings”, “tags”: [“structure”, “building”] }


#### Placeable Resources
```gdscript
# Create placeable resources
extends PlaceableResource
@export var scene: PackedScene
@export var cost: Dictionary = {"wood": 10, "stone": 5}
@export var description: String = "A basic building"
@export var icon: Texture2D

Action Bar

Template Structure

ActionBar (HBoxContainer)
├── BuildModeButton (Button)
├── ManipulateModeButton (Button)
├── DeleteModeButton (Button)
├── Separator (VSeparator)
├── UndoButton (Button)
├── RedoButton (Button)
└── SettingsButton (Button)

Setup and Configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Instance and configure action bar
var action_bar = preload("res:///templates/ui/action_bar.tscn").instantiate()
$UI/HUD.add_child(action_bar)

# Connect to systems
action_bar.building_system = $Systems/BuildingSystem
action_bar.manipulation_system = $Systems/ManipulationSystem

# Customize button actions
action_bar.build_mode_button.pressed.connect(_on_build_mode_pressed)
action_bar.delete_mode_button.pressed.connect(_on_delete_mode_pressed)

Custom Button Actions

1
2
3
4
5
6
7
func _on_build_mode_pressed():
    var building_system = $Systems/BuildingSystem
    building_system.set_mode(BuildingSystem.Mode.BUILD)
    
func _on_delete_mode_pressed():
    var manipulation_system = $Systems/ManipulationSystem
    manipulation_system.set_mode(ManipulationSystem.Mode.DELETE)

Action Log

Template Structure

GBActionLog (PanelContainer)
├── ScrollContainer (ScrollContainer)
│   └── MessageList (VBoxContainer)
└── Header (HBoxContainer)
    ├── TitleLabel (Label)
    └── ClearButton (Button)

Configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Setup action log
var action_log = preload("res:///templates/ui/action_log/action_log.tscn").instantiate()
$UI/HUD.add_child(action_log)

# Configure log settings
action_log.max_messages = 50
action_log.message_duration = 5.0
action_log.show_timestamps = true

# Connect to event bus
var event_bus = composition_container.get_event_bus()
event_bus.message_logged.connect(action_log.add_message)

Custom Message Types

1
2
3
4
# Add custom message styling
action_log.add_message("Building placed", Color.GREEN, "building")
action_log.add_message("Error: Invalid placement", Color.RED, "error")
action_log.add_message("Info: Grid mode activated", Color.BLUE, "info")

Target Informer

Template Structure

TargetInformer (Panel)
├── Icon (TextureRect)
├── TitleLabel (Label)
├── DescriptionLabel (Label)
└── CostLabel (Label)

Setup

1
2
3
4
5
6
7
# Setup target informer
var target_informer = preload("res:///templates/ui/target_informer.tscn").instantiate()
$UI/HUD.add_child(target_informer)

# Connect to targeting system
var targeting_system = $Systems/GridTargetingSystem
targeting_system.target_changed.connect(target_informer.update_target_info)

Custom Information Display

1
2
3
4
5
6
# Update target information
func update_target_info(target_data: TargetData):
    $Icon.texture = target_data.icon
    $TitleLabel.text = target_data.name
    $DescriptionLabel.text = target_data.description
    $CostLabel.text = format_cost(target_data.cost)

Camera Controls

Zoom Slider Setup

1
2
3
4
5
6
7
8
9
# Setup camera zoom controls
var zoom_slider = preload("res:///templates/ui/camera_zoom_slider.tscn").instantiate()
$UI/HUD.add_child(zoom_slider)

# Connect to camera
var camera = $World/Camera2D
zoom_slider.min_zoom = 0.5
zoom_slider.max_zoom = 3.0
zoom_slider.value_changed.connect(camera.set_zoom)

Custom Camera Controls

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Add custom camera controls
func setup_camera_controls():
    var camera = $World/Camera2D
    
    # Pan controls
    InputEventPan.connect(_on_camera_pan)
    
    # Zoom controls
    InputEventZoom.connect(_on_camera_zoom)
    
func _on_camera_pan(direction: Vector2):
    camera.position += direction * pan_speed

func _on_camera_zoom(delta: float):
    var new_zoom = camera.zoom.x + delta
    camera.zoom = Vector2(new_zoom, new_zoom)

Custom UI Components

Creating Custom Templates

  1. Copy Existing Template
1
2
# Duplicate an existing template
# Modify as needed for your game
  1. Extend Base Classes
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Custom selection UI
extends PlaceableSelectionUI

func _ready():
    super._ready()
    # Add custom initialization
    setup_custom_features()

func setup_custom_features():
    # Add custom tabs, filters, etc.
    pass

Custom Placeable Cards

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Custom placeable card UI
extends Control

@export var placeable_resource: PlaceableResource
@onready var icon: TextureRect = $Icon
@onready var name_label: Label = $NameLabel
@onready var cost_label: Label = $CostLabel

func setup(placeable: PlaceableResource):
    placeable_resource = placeable
    icon.texture = placeable.icon
    name_label.text = placeable.name
    cost_label.text = format_cost(placeable.cost)

func _on_pressed():
    # Handle selection
    BuildingSystem.select_placeable(placeable_resource)

Integration Patterns

Complete UI Setup

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Complete UI setup for a building game
func setup_building_ui():
    var hud = $UI/HUD
    
    # Add core components
    var selection_ui = create_selection_ui()
    var action_bar = create_action_bar()
    var action_log = create_action_log()
    var target_informer = create_target_informer()
    
    # Position components
    selection_ui.anchors_preset = PRESET_TOP_RIGHT
    action_bar.anchors_preset = PRESET_BOTTOM_WIDE
    action_log.anchors_preset = PRESET_BOTTOM_RIGHT
    target_informer.anchors_preset = PRESET_TOP_CENTER
    
    # Connect systems
    connect_ui_to_systems()

Responsive UI Layout

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Responsive UI that adapts to screen size
func setup_responsive_ui():
    var screen_size = get_viewport().get_visible_rect().size
    
    if screen_size.x < 1024:  # Mobile
        setup_mobile_layout()
    elif screen_size.x < 1920:  # Tablet
        setup_tablet_layout()
    else:  # Desktop
        setup_desktop_layout()

func setup_mobile_layout():
    # Compact layout for mobile
    $SelectionUI.scale = Vector2(0.8, 0.8)
    $ActionBar.position = Vector2(0, screen_size.y - 100)

Theming and Styling

Custom Theme Setup

1
2
3
4
5
6
7
# Apply custom theme to UI components
func apply_custom_theme():
    var custom_theme = preload("res://themes/building_theme.tres")
    
    $SelectionUI.theme = custom_theme
    $ActionBar.theme = custom_theme
    $ActionLog.theme = custom_theme

Theme Customization

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Create custom theme variations
func create_theme_variants():
    # Day theme
    var day_theme = Theme.new()
    day_theme.set_color("font_color", "Label", Color.BLACK)
    day_theme.set_color("panel", "Panel", Color.WHITE)
    
    # Night theme
    var night_theme = Theme.new()
    night_theme.set_color("font_color", "Label", Color.WHITE)
    night_theme.set_color("panel", "Panel", Color.BLACK)

Performance Optimization

UI Pooling

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Pool UI elements for better performance
class UIElementPool:
    var available_elements: Array[Control] = []
    var active_elements: Array[Control] = []
    
    func get_element() -> Control:
        if available_elements.is_empty():
            return create_new_element()
        return available_elements.pop_back()
    
    func return_element(element: Control):
        element.visible = false
        active_elements.erase(element)
        available_elements.append(element)

Lazy Loading

1
2
3
4
5
6
7
# Lazy load UI components
func lazy_load_ui():
    # Only load UI when needed
    if not ui_loaded:
        load_selection_ui()
        load_action_bar()
        ui_loaded = true

Accessibility

Keyboard Navigation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Setup keyboard navigation
func setup_keyboard_navigation():
    # Tab order
    $SelectionUI.focus_next = $ActionBar
    $ActionBar.focus_next = $ActionLog
    
    # Keyboard shortcuts
    set_process_input(true)

func _input(event):
    if event.is_action_pressed("ui_accept"):
        handle_confirm_action()
    elif event.is_action_pressed("ui_cancel"):
        handle_cancel_action()

Screen Reader Support

1
2
3
4
5
6
7
8
# Add accessibility labels
func setup_accessibility():
    $BuildModeButton.tooltip_text = "Enter build mode for placing structures"
    $DeleteModeButton.tooltip_text = "Enter delete mode for removing objects"
    
    # Add accessibility hints
    $SelectionUI.set_accessibility_name("Building selection panel")
    $SelectionUI.set_accessibility_hint("Choose from available buildings to place")

Testing and Debugging

UI Testing Framework

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Test UI interactions
func test_selection_ui():
    var selection_ui = $SelectionUI
    
    # Test category switching
    selection_ui.switch_to_category("Buildings")
    assert(selection_ui.current_category == "Buildings")
    
    # Test item selection
    var first_item = selection_ui.get_first_placeable()
    selection_ui.select_placeable(first_item)
    assert(selection_ui.selected_placeable == first_item)

Debug Visualization

1
2
3
4
5
6
7
8
# Debug UI layout
func _draw():
    if debug_mode:
        # Draw UI bounds
        draw_ui_bounds()
        
        # Draw interaction areas
        draw_interaction_areas()

Best Practices

1. Consistent Design

  • Use consistent spacing and sizing
  • Follow established UI patterns
  • Maintain visual hierarchy

2. Performance Awareness

  • Pool expensive UI elements
  • Use lazy loading for complex components
  • Optimize for target frame rate

3. Accessibility First

  • Include keyboard navigation
  • Add proper tooltips and labels
  • Support screen readers

4. Responsive Design

  • Adapt to different screen sizes
  • Support both mobile and desktop
  • Test on various devices

Common Patterns

1
2
3
4
5
6
# Custom confirmation dialogs
func show_confirmation_dialog(title: String, message: String, callback: Callable):
    var dialog = create_confirmation_dialog()
    dialog.setup(title, message, callback)
    add_child(dialog)
    dialog.popup_centered()

Tooltips and Help

1
2
3
4
5
# Context-sensitive help
func setup_help_system():
    var help_system = HelpSystem.new()
    help_system.register_tooltip($BuildModeButton, "build_mode_help")
    help_system.register_tooltip($DeleteModeButton, "delete_mode_help")

The UI template system provides a solid foundation for building interfaces while allowing extensive customization to match your game’s specific needs and visual style.