Files
idle/.opencode/plans/currency-panel.md
2026-04-24 00:55:00 +02:00

3.9 KiB

Plan: Create CurrencyPanel Widget

Goal

Regroup the 9 individual CurrencyTile nodes in tiny_sword.tscn into a single dynamic CurrencyPanel widget that automatically retrieves and displays all currencies from the LevelGameState catalogue.

Changes

1. Create CurrencyPanel script (core/currency/currency_panel.gd)

New file: res://core/currency/currency_panel.gd

Class: class_name CurrencyPanel, extends PanelContainer

Structure:

class_name CurrencyPanel
extends PanelContainer

const CURRENCY_TILE_SCENE: PackedScene = preload("res://currency_tile.tscn")

@onready var _tiles_container: VBoxContainer = $CurrencyTiles

var _game_state: LevelGameState

func _ready() -> void:
    _game_state = find_parent("LevelGameState")
    if _game_state == null:
        push_error("CurrencyPanel: No LevelGameState found in parent hierarchy")
        return
    _build_currency_tiles()
    _game_state.ready.connect(_on_game_state_ready)

func _build_currency_tiles() -> void:
    # Clear existing children
    for child in _tiles_container.get_children():
        child.queue_free()
    
    if _game_state.currency_catalogue == null:
        return
    
    for currency in _game_state.currency_catalogue.currencies:
        if currency == null:
            continue
        var tile: CurrencyTile = CURRENCY_TILE_SCENE.instantiate()
        # Set exports before add_child() so they're available in _ready()
        tile.currency = currency
        tile.game_state = _game_state
        _tiles_container.add_child(tile)

func _on_game_state_ready() -> void:
    pass

Why this works with existing CurrencyTile: CurrencyTile uses @export for currency and game_state. When instantiate() is called, _ready() is NOT invoked yet - it fires when the node is added to the scene tree. By setting properties before add_child(), _ready() sees them as non-null. The DebugIncomeButton is preserved since CurrencyTile is unchanged.

2. Update tiny_sword.tscn scene

Replace: 9 individual CurrencyTile nodes under LevelGameState/UI with a single CurrencyPanel hierarchy.

Remove from scene:

  • All 9 individual CurrencyTile nodes: GoldCurrencyTile, WorkerCurrencyTile, FoodCurrencyTile, WoodCurrencyTile, AscensionCurrencyTile, MagicGoldTile, ManaStoneTile, CogniteTile, PhilosoperStoneTile
  • ExtResource 7_0cs5o (currency_tile.tscn) - no longer referenced directly
  • All 9 individual currency resource ExtResources: 9_1363k (gold), 10_i1cck (worker), 11_hskcg (food), 12_l6a68 (wood), 15_ascension, 20_no27p (magic_gold), 22_rbyxa (mana_stone), 23_vrcrd (cognite), 24_eaq6h (philosoper_stone)

Add to scene:

  • ExtResource 8_cpnlres://core/currency/currency_panel.gd
  • New node hierarchy:
    LevelGameState/UI (Control, layout_mode=3)
      CurrencyPanel (PanelContainer, layout_mode=1, pos 5,5 size 250x340, script=8_cpnl)
        CurrencyTiles (VBoxContainer, separation=4)   ← script-less, populated at runtime
      GoalsDebugUI (repositioned: offset_left=265)
    

Keep: GoalsDebugUI (repositioned slightly from offset_left=1275 to offset_left=265 to account for panel width)

File Structure After Changes

core/
  level_game_state.gd              # unchanged (ready is built-in)
  currency/
    currency_panel.gd              # NEW: dynamic panel widget
docs/gyms/tiny_sword/
  tiny_sword.tscn                  # 9 tiles → 1 panel hierarchy (cleaner)

No Changes Needed

  • level_game_state.gd: The ready signal is built-in for Godot nodes - no addition needed.
  • currency_label.gd (CurrencyTile): Unchanged - DebugIncomeButton preserved.

Testing

  • Run Godot headless to verify scene loads without errors
  • Verify all 9 currencies appear in the CurrencyPanel
  • Verify currency values update on changes (currency_changed signal)
  • Verify DebugIncomeButton works on each tile
  • Verify the panel doesn't overlap with GoalsDebugUI