diff --git a/.opencode/plans/currency-panel.md b/.opencode/plans/currency-panel.md new file mode 100644 index 0000000..495ab7e --- /dev/null +++ b/.opencode/plans/currency-panel.md @@ -0,0 +1,97 @@ +# 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 diff --git a/core/currency/currency_panel.gd b/core/currency/currency_panel.gd new file mode 100644 index 0000000..c7cb9b0 --- /dev/null +++ b/core/currency/currency_panel.gd @@ -0,0 +1,35 @@ +## Dynamically displays all currencies from the LevelGameState catalogue as CurrencyTile widgets. +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: + 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() + tile.currency = currency + tile.game_state = _game_state + _tiles_container.add_child(tile) + +func _on_game_state_ready() -> void: + pass diff --git a/core/currency/currency_panel.gd.uid b/core/currency/currency_panel.gd.uid new file mode 100644 index 0000000..f5e762d --- /dev/null +++ b/core/currency/currency_panel.gd.uid @@ -0,0 +1 @@ +uid://blfou5xiynxqf diff --git a/docs/gyms/tiny_sword/currency_panel.tscn b/docs/gyms/tiny_sword/currency_panel.tscn new file mode 100644 index 0000000..7635dd7 --- /dev/null +++ b/docs/gyms/tiny_sword/currency_panel.tscn @@ -0,0 +1,15 @@ +[gd_scene format=3 uid="uid://cur_panel_scene_uid"] + +[ext_resource type="Script" uid="uid://9_vbox" path="res://core/currency/currency_panel.gd" id="1_cpnl"] + +[node name="CurrencyPanel" type="PanelContainer" unique_id=3000000001] +custom_minimum_size = Vector2(250, 340) +offset_left = 5.0 +offset_top = 5.0 +offset_right = 255.0 +offset_bottom = 345.0 +script = ExtResource("1_cpnl") + +[node name="CurrencyTiles" type="VBoxContainer" parent="." unique_id=3000000002] +layout_mode = 2 +theme_override_constants/separation = 4 diff --git a/docs/gyms/tiny_sword/tiny_sword.tscn b/docs/gyms/tiny_sword/tiny_sword.tscn index 5a17843..fac7e99 100644 --- a/docs/gyms/tiny_sword/tiny_sword.tscn +++ b/docs/gyms/tiny_sword/tiny_sword.tscn @@ -9,22 +9,13 @@ [ext_resource type="Resource" uid="uid://umi37hotcq8m" path="res://docs/gyms/tiny_sword/research/ts_research_catalogue.tres" id="5_v0pty"] [ext_resource type="Script" uid="uid://srkiu4qe8s2m" path="res://core/prestige/prestige_manager.gd" id="5_x77df"] [ext_resource type="Resource" uid="uid://dwmfvmusfskk6" path="res://docs/gyms/tiny_sword/prestige/primary_prestige.tres" id="6_xnhlc"] -[ext_resource type="PackedScene" uid="uid://btkxru2gdjsgc" path="res://currency_tile.tscn" id="7_0cs5o"] -[ext_resource type="Resource" uid="uid://w4u1hddplb4e" path="res://docs/gyms/tiny_sword/currencies/gold.tres" id="9_1363k"] -[ext_resource type="PackedScene" uid="uid://djedqovgngrx5" path="res://docs/gyms/tiny_sword/buildings/farm/farm.tscn" id="10_1lv5i"] -[ext_resource type="Resource" uid="uid://dfxk30o34qe2s" path="res://docs/gyms/tiny_sword/currencies/worker.tres" id="10_i1cck"] -[ext_resource type="PackedScene" uid="uid://dirvi76rkoowf" path="res://goals_debug_ui.tscn" id="10_qifrv"] -[ext_resource type="Resource" uid="uid://bxg2au0ijp242" path="res://docs/gyms/tiny_sword/currencies/food.tres" id="11_hskcg"] -[ext_resource type="PackedScene" uid="uid://cf01wvy3f17i" path="res://docs/gyms/tiny_sword/buildings/forestry/forestry.tscn" id="11_pyqyw"] -[ext_resource type="Resource" uid="uid://bgsk8h4w80h45" path="res://docs/gyms/tiny_sword/currencies/wood.tres" id="12_l6a68"] -[ext_resource type="PackedScene" uid="uid://bf8lqbexvnx6e" path="res://docs/gyms/tiny_sword/buildings/monastery/monastery.tscn" id="13_no27p"] [ext_resource type="PackedScene" uid="uid://rejxvjwybkll" path="res://sandbox/tiny_swords/Terrain/Resources/Wood/Trees/tree_1.tscn" id="14_0cs5o"] [ext_resource type="PackedScene" uid="uid://bp5ng4vu4ot4a" path="res://docs/gyms/tiny_sword/buildings/alchemy_tower/alchemy_tower.tscn" id="14_hum8s"] -[ext_resource type="Resource" uid="uid://bfrb0ayrljac2" path="res://docs/gyms/tiny_sword/currencies/ascension.tres" id="15_ascension"] -[ext_resource type="Resource" uid="uid://dpbndqxvsffa0" path="res://docs/gyms/tiny_sword/currencies/magic_gold.tres" id="20_no27p"] -[ext_resource type="Resource" uid="uid://brctmnpmhjas6" path="res://docs/gyms/tiny_sword/currencies/mana_stone.tres" id="22_rbyxa"] -[ext_resource type="Resource" uid="uid://t6du7gm2ywbi" path="res://docs/gyms/tiny_sword/currencies/cognite.tres" id="23_vrcrd"] -[ext_resource type="Resource" uid="uid://co4fiqgluwit0" path="res://docs/gyms/tiny_sword/currencies/philosoper_stone.tres" id="24_eaq6h"] +[ext_resource type="PackedScene" uid="uid://djedqovgngrx5" path="res://docs/gyms/tiny_sword/buildings/farm/farm.tscn" id="10_1lv5i"] +[ext_resource type="PackedScene" uid="uid://cf01wvy3f17i" path="res://docs/gyms/tiny_sword/buildings/forestry/forestry.tscn" id="11_pyqyw"] +[ext_resource type="PackedScene" uid="uid://bf8lqbexvnx6e" path="res://docs/gyms/tiny_sword/buildings/monastery/monastery.tscn" id="13_no27p"] +[ext_resource type="PackedScene" uid="uid://dirvi76rkoowf" path="res://goals_debug_ui.tscn" id="10_qifrv"] +[ext_resource type="PackedScene" uid="uid://cur_panel_scene_uid" path="res://docs/gyms/tiny_sword/currency_panel.tscn" id="9_cpnl"] [node name="TinySwords" type="Node" unique_id=498237642] @@ -87,83 +78,16 @@ anchors_preset = 0 offset_right = 40.0 offset_bottom = 40.0 -[node name="GoldCurrencyTile" parent="LevelGameState/UI" unique_id=1440583137 node_paths=PackedStringArray("game_state") instance=ExtResource("7_0cs5o")] -layout_mode = 0 -offset_right = 160.0 -offset_bottom = 31.0 -currency = ExtResource("9_1363k") -game_state = NodePath("../..") - -[node name="WorkerCurrencyTile" parent="LevelGameState/UI" unique_id=1164876942 node_paths=PackedStringArray("game_state") instance=ExtResource("7_0cs5o")] -layout_mode = 0 -offset_top = 32.0 -offset_right = 160.0 -offset_bottom = 63.0 -currency = ExtResource("10_i1cck") -game_state = NodePath("../..") - -[node name="FoodCurrencyTile" parent="LevelGameState/UI" unique_id=1814936562 node_paths=PackedStringArray("game_state") instance=ExtResource("7_0cs5o")] -layout_mode = 0 -offset_top = 63.0 -offset_right = 160.0 -offset_bottom = 94.0 -currency = ExtResource("11_hskcg") -game_state = NodePath("../..") - -[node name="WoodCurrencyTile" parent="LevelGameState/UI" unique_id=338003163 node_paths=PackedStringArray("game_state") instance=ExtResource("7_0cs5o")] -layout_mode = 0 -offset_top = 94.0 -offset_right = 160.0 -offset_bottom = 125.0 -currency = ExtResource("12_l6a68") -game_state = NodePath("../..") - -[node name="AscensionCurrencyTile" parent="LevelGameState/UI" unique_id=705032705 node_paths=PackedStringArray("game_state") instance=ExtResource("7_0cs5o")] -layout_mode = 0 -offset_top = 125.0 -offset_right = 160.0 -offset_bottom = 156.0 -currency = ExtResource("15_ascension") -game_state = NodePath("../..") - -[node name="MagicGoldTile" parent="LevelGameState/UI" unique_id=707573446 node_paths=PackedStringArray("game_state") instance=ExtResource("7_0cs5o")] -layout_mode = 0 -offset_top = 152.0 -offset_right = 203.0 -offset_bottom = 183.0 -currency = ExtResource("20_no27p") -game_state = NodePath("../..") - -[node name="ManaStoneTile" parent="LevelGameState/UI" unique_id=1333819600 node_paths=PackedStringArray("game_state") instance=ExtResource("7_0cs5o")] -layout_mode = 0 -offset_left = 1.0 -offset_top = 178.0 -offset_right = 204.0 -offset_bottom = 209.0 -currency = ExtResource("22_rbyxa") -game_state = NodePath("../..") - -[node name="CogniteTile" parent="LevelGameState/UI" unique_id=150108085 node_paths=PackedStringArray("game_state") instance=ExtResource("7_0cs5o")] -layout_mode = 0 -offset_left = 1.0 -offset_top = 210.0 -offset_right = 204.0 -offset_bottom = 241.0 -currency = ExtResource("23_vrcrd") -game_state = NodePath("../..") - -[node name="PhilosoperStoneTile" parent="LevelGameState/UI" unique_id=1360957288 node_paths=PackedStringArray("game_state") instance=ExtResource("7_0cs5o")] -layout_mode = 0 -offset_left = 1.0 -offset_top = 240.0 -offset_right = 204.0 -offset_bottom = 271.0 -currency = ExtResource("24_eaq6h") -game_state = NodePath("../..") +[node name="CurrencyPanel" parent="LevelGameState/UI" unique_id=2000000001 instance=ExtResource("9_cpnl")] +layout_mode = 1 +offset_left = 5.0 +offset_top = 5.0 +offset_right = 255.0 +offset_bottom = 345.0 [node name="GoalsDebugUI" parent="LevelGameState/UI" unique_id=1494700185 instance=ExtResource("10_qifrv")] layout_mode = 1 -offset_left = 1275.0 -offset_top = 4.0 +offset_left = 265.0 +offset_top = 5.0 offset_right = 1913.0 offset_bottom = 263.0