UI pass: medieval-warm Theme + real Build drawer thumbnails

Theme (scenes/ui/medieval_theme.gd):
- Procedural builder for an app-wide Theme: parchment buttons on
  dark-wood border, tan panels, ink text, gold focus ring.
- Applied on the root Window in Main._ready, with a tree-walk that
  re-seeds every CanvasLayer's topmost Control (CanvasLayer
  interrupts the root-Window theme cascade in Godot 4).
- Late-mounting popups + modals get themed via a child_entered_tree
  hook on each CanvasLayer.

Build drawer thumbnails (scenes/ui/build_drawer_thumb.gd):
- New BuildDrawerThumb Control that dispatches on tool_id and draws
  a recognisable silhouette of the entity each tool builds. 17 tools
  covered: chop/mine/dig_grave/no_roof (Designate), stone+wood walls,
  wood+stone floors, door, crate, bed, torch, 5 workbenches
  (Carpenter/Smelter/Millstone/Hearth/Cremation Pyre), stockpile,
  graveyard.
- Replaces the flat ColorRect placeholder. _add_tool_btn signature
  changed from (label, color, callback) to (label, tool_id, callback).
This commit is contained in:
megaproxy 2026-05-16 16:09:56 +01:00
parent 413054157a
commit 53cb92041c
4 changed files with 614 additions and 30 deletions

View file

@ -180,10 +180,10 @@ func _build_designate_tab() -> Control:
var flow := _make_flow_grid()
box.add_child(flow)
_add_tool_btn(flow, Strings.t(&"tool.chop"), Color(0.3, 0.7, 0.2), func() -> void: _activate(&"chop", &"", Strings.t(&"tool.chop")))
_add_tool_btn(flow, Strings.t(&"tool.mine"), Color(0.6, 0.6, 0.6), func() -> void: _activate(&"mine", &"", Strings.t(&"tool.mine")))
_add_tool_btn(flow, Strings.t(&"tool.dig_grave"),Color(0.4, 0.3, 0.2), func() -> void: _activate(&"dig_grave",&"", Strings.t(&"tool.dig_grave")))
_add_tool_btn(flow, Strings.t(&"tool.no_roof"), Color(0.7, 0.7, 0.9), func() -> void: _activate(&"no_roof", &"", Strings.t(&"tool.no_roof")))
_add_tool_btn(flow, Strings.t(&"tool.chop"), &"chop", func() -> void: _activate(&"chop", &"", Strings.t(&"tool.chop")))
_add_tool_btn(flow, Strings.t(&"tool.mine"), &"mine", func() -> void: _activate(&"mine", &"", Strings.t(&"tool.mine")))
_add_tool_btn(flow, Strings.t(&"tool.dig_grave"),&"dig_grave", func() -> void: _activate(&"dig_grave", &"", Strings.t(&"tool.dig_grave")))
_add_tool_btn(flow, Strings.t(&"tool.no_roof"), &"no_roof", func() -> void: _activate(&"no_roof", &"", Strings.t(&"tool.no_roof")))
return box
@ -197,44 +197,44 @@ func _build_build_tab() -> Control:
box.add_child(flow)
# Wall — show material chooser on first tap.
_add_tool_btn(flow, Strings.t(&"tool.build_wall_stone"), Color(0.55, 0.55, 0.55),
_add_tool_btn(flow, Strings.t(&"tool.build_wall_stone"), &"build_wall_stone",
func() -> void: _activate_wall(&"stone"))
_add_tool_btn(flow, Strings.t(&"tool.build_wall_wood"), Color(0.65, 0.45, 0.25),
_add_tool_btn(flow, Strings.t(&"tool.build_wall_wood"), &"build_wall_wood",
func() -> void: _activate_wall(&"wood"))
# Floor.
_add_tool_btn(flow, Strings.t(&"tool.build_floor_wood"), Color(0.60, 0.40, 0.20),
_add_tool_btn(flow, Strings.t(&"tool.build_floor_wood"), &"build_floor_wood",
func() -> void: _activate_floor(&"wood"))
_add_tool_btn(flow, Strings.t(&"tool.build_floor_stone"), Color(0.60, 0.60, 0.55),
_add_tool_btn(flow, Strings.t(&"tool.build_floor_stone"), &"build_floor_stone",
func() -> void: _activate_floor(&"stone"))
# Door + Crate.
_add_tool_btn(flow, Strings.t(&"tool.build_door"), Color(0.55, 0.35, 0.15),
_add_tool_btn(flow, Strings.t(&"tool.build_door"), &"build_door",
func() -> void: _activate(&"build_door", &"", Strings.t(&"tool.build_door")))
_add_tool_btn(flow, Strings.t(&"tool.build_crate"), Color(0.65, 0.45, 0.10),
_add_tool_btn(flow, Strings.t(&"tool.build_crate"), &"build_crate",
func() -> void: _activate(&"build_crate", &"", Strings.t(&"tool.build_crate")))
# Bed + Torch.
_add_tool_btn(flow, Strings.t(&"tool.build_bed"), Color(0.40, 0.40, 0.80),
_add_tool_btn(flow, Strings.t(&"tool.build_bed"), &"build_bed",
func() -> void: _activate(&"build_bed", &"", Strings.t(&"tool.build_bed")))
_add_tool_btn(flow, Strings.t(&"tool.build_torch"), Color(0.90, 0.70, 0.20),
_add_tool_btn(flow, Strings.t(&"tool.build_torch"), &"build_torch",
func() -> void: _activate(&"build_torch", &"", Strings.t(&"tool.build_torch")))
# Workbenches.
_add_tool_btn(flow, Strings.t(&"tool.workbench_carpenter"),
Color(0.50, 0.35, 0.15),
&"build_workbench_carpenter",
func() -> void: _activate(&"build_workbench_carpenter", &"", Strings.t(&"tool.workbench_carpenter")))
_add_tool_btn(flow, Strings.t(&"tool.workbench_smelter"),
Color(0.60, 0.55, 0.45),
&"build_workbench_smelter",
func() -> void: _activate(&"build_workbench_smelter", &"", Strings.t(&"tool.workbench_smelter")))
_add_tool_btn(flow, Strings.t(&"tool.workbench_millstone"),
Color(0.55, 0.55, 0.55),
&"build_workbench_millstone",
func() -> void: _activate(&"build_workbench_millstone", &"", Strings.t(&"tool.workbench_millstone")))
_add_tool_btn(flow, Strings.t(&"tool.workbench_hearth"),
Color(0.80, 0.35, 0.15),
&"build_workbench_hearth",
func() -> void: _activate(&"build_workbench_hearth", &"", Strings.t(&"tool.workbench_hearth")))
_add_tool_btn(flow, Strings.t(&"tool.workbench_cremation_pyre"),
Color(0.30, 0.25, 0.20),
&"build_workbench_cremation_pyre",
func() -> void: _activate(&"build_workbench_cremation_pyre", &"", Strings.t(&"tool.workbench_cremation_pyre")))
return box
@ -248,9 +248,9 @@ func _build_stockpile_tab() -> Control:
var flow := _make_flow_grid()
box.add_child(flow)
_add_tool_btn(flow, Strings.t(&"tool.stockpile_general"), Color(0.30, 0.60, 0.30),
_add_tool_btn(flow, Strings.t(&"tool.stockpile_general"), &"paint_stockpile",
func() -> void: _activate(&"paint_stockpile", &"", Strings.t(&"tool.stockpile_general")))
_add_tool_btn(flow, Strings.t(&"tool.graveyard"), Color(0.25, 0.20, 0.15),
_add_tool_btn(flow, Strings.t(&"tool.graveyard"), &"graveyard",
func() -> void: _activate(&"graveyard", &"", Strings.t(&"tool.graveyard")))
return box
@ -291,10 +291,13 @@ func _make_flow_grid() -> GridContainer:
return g
## Add a single tool button to `container`. Each button is a VBoxContainer of
## [ColorRect icon area + Label] wrapped in a Button so the whole cell is one
## touch target.
func _add_tool_btn(container: Control, label_text: String, icon_color: Color, callback: Callable) -> void:
const _THUMB_SCRIPT: Script = preload("res://scenes/ui/build_drawer_thumb.gd")
## Add a single tool button to `container`. The button is a VBoxContainer of
## [thumb preview + Label] wrapped in a Button so the whole cell is one touch
## target. `tool_id` drives the procedural preview shape (BuildDrawerThumb).
func _add_tool_btn(container: Control, label_text: String, tool_id: StringName, callback: Callable) -> void:
var btn := Button.new()
btn.custom_minimum_size = Vector2(BTN_SIZE, BTN_SIZE + LABEL_HEIGHT)
btn.focus_mode = Control.FOCUS_NONE
@ -303,13 +306,16 @@ func _add_tool_btn(container: Control, label_text: String, icon_color: Color, ca
vb.mouse_filter = Control.MOUSE_FILTER_IGNORE
vb.add_theme_constant_override("separation", 2)
# Icon area — procedural colored rect (real sprites land with Phase 17 art pass).
var icon := ColorRect.new()
icon.color = icon_color
icon.custom_minimum_size = Vector2(BTN_SIZE - 8, BTN_SIZE - LABEL_HEIGHT - 8)
icon.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
vb.add_child(icon)
# Procedural preview of the entity this tool builds.
var thumb := Control.new()
thumb.set_script(_THUMB_SCRIPT)
# Use .set() — the static type is Control (set_script doesn't refine it),
# but the runtime instance has the tool_id property from the script.
thumb.set("tool_id", tool_id)
thumb.custom_minimum_size = Vector2(BTN_SIZE - 8, BTN_SIZE - LABEL_HEIGHT - 8)
thumb.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
thumb.mouse_filter = Control.MOUSE_FILTER_IGNORE
vb.add_child(thumb)
# Label.
var lbl := Label.new()