# 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**: ```gdscript 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_cpnl` → `res://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