fix(theme): drift-guard test, interactive stylebox states, ThemeKeys font consts, richer showcase (whole-branch review)
- build_game_theme.gd: extract build_theme() as a static func returning the fully-built Theme; _init() is now a thin save+quit wrapper. Enables a test to build a fresh Theme in memory without running the SceneTree main loop. - test_theme_resource.gd: add test_committed_tres_matches_builder() — builds a fresh Theme via the preloaded builder and compares bg_color against the committed game_theme.tres for PrimaryCTA/normal, ParchmentCard/panel, and DarkPanel/panel. Catches "palette/builder changed, .tres not regenerated." - build_game_theme.gd: give Tab, TabActive, and Chip explicit hover/pressed/ focus styleboxes (focus is StyleBoxEmpty to suppress the default ring) so they no longer fall back to Godot's default gray button on interaction. Add a disabled stylebox + font_disabled_color to PrimaryCTA for the unaffordable-CTA state the 2a shell will need. - theme_keys.gd: add HEADING/ACCENT/MONO font-role consts (kept out of ALL, which is stylebox-variation-only); build_game_theme.gd and theme_showcase.gd now reference them instead of raw StringName literals. - theme_showcase.gd: add an italic DM-voice RichTextLabel (EB Garamond italic face, spec §6) and two semantic-coloured chips (BLOOD for aggressive actions, GOLD for pay/faith) alongside the existing neutral chip, demonstrating the script-applied colouring from spec §5.3. - dark_bay.gdshader: comment noting the stripe uses FRAGCOORD (screen-space) while the vignette uses UV (node-local) — intended for full-bleed use. - surfaces/*.gd: ## comments documenting the accepted deviation from spec §5.4 (uniforms set at runtime from Palette rather than baked into the .tscn) — no behavior change. - Regenerated game_theme.tres via build_game_theme.gd. Full suite: 125/125 (was 124, +1 drift-guard test). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GFDm1ku9WDUacK2S78m2be
This commit is contained in:
@@ -5,6 +5,7 @@ extends Control
|
||||
const Palette = preload("res://scripts/theme/palette.gd")
|
||||
const ThemeKeys = preload("res://scripts/theme/theme_keys.gd")
|
||||
const GAME_THEME := "res://assets/theme/game_theme.tres"
|
||||
const SERIF_ITALIC := "res://assets/theme/fonts/EBGaramond-Italic-VariableFont_wght.ttf"
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -22,6 +23,7 @@ func _ready() -> void:
|
||||
col.add_child(_swatches())
|
||||
col.add_child(_variations())
|
||||
col.add_child(_fonts())
|
||||
col.add_child(_prose())
|
||||
col.add_child(_rarity())
|
||||
col.add_child(_bars())
|
||||
col.add_child(_surfaces())
|
||||
@@ -30,7 +32,7 @@ func _ready() -> void:
|
||||
func _heading(text: String) -> Label:
|
||||
var l := Label.new()
|
||||
l.text = text
|
||||
l.theme_type_variation = &"Heading"
|
||||
l.theme_type_variation = ThemeKeys.HEADING
|
||||
return l
|
||||
|
||||
|
||||
@@ -52,7 +54,7 @@ func _swatches() -> Control:
|
||||
col.add_child(r)
|
||||
var caption := Label.new()
|
||||
caption.text = entry[0]
|
||||
caption.theme_type_variation = &"Mono"
|
||||
caption.theme_type_variation = ThemeKeys.MONO
|
||||
col.add_child(caption)
|
||||
grid.add_child(col)
|
||||
return grid
|
||||
@@ -64,8 +66,12 @@ func _variations() -> Control:
|
||||
var cta := Button.new(); cta.text = "ENTER THE WORLD"; cta.theme_type_variation = ThemeKeys.PRIMARY_CTA
|
||||
var tab := Button.new(); tab.text = "INACTIVE"; tab.theme_type_variation = ThemeKeys.TAB
|
||||
var tab_a := Button.new(); tab_a.text = "ACTIVE"; tab_a.theme_type_variation = ThemeKeys.TAB_ACTIVE
|
||||
var chip := Button.new(); chip.text = "INTIMIDATE · STR"; chip.theme_type_variation = ThemeKeys.CHIP
|
||||
for b in [cta, tab, tab_a, chip]:
|
||||
# Neutral chip (grey) plus the semantic colours a script applies per-use
|
||||
# (spec §5.3): red for aggressive/combat actions, gold for pay/faith.
|
||||
var chip := Button.new(); chip.text = "STEALTH · DEX"; chip.theme_type_variation = ThemeKeys.CHIP
|
||||
var chip_red := _semantic_chip("INTIMIDATE · STR", Palette.BLOOD)
|
||||
var chip_gold := _semantic_chip("PAY ◈40", Palette.GOLD)
|
||||
for b in [cta, tab, tab_a, chip, chip_red, chip_gold]:
|
||||
row.add_child(b)
|
||||
var card := PanelContainer.new(); card.theme_type_variation = ThemeKeys.PARCHMENT_CARD
|
||||
card.custom_minimum_size = Vector2(160, 80)
|
||||
@@ -94,6 +100,40 @@ func _variations() -> Control:
|
||||
return row
|
||||
|
||||
|
||||
func _semantic_chip(text: String, color: Color) -> Button:
|
||||
# Chip base is neutral (ThemeKeys.CHIP); the semantic colour (§5.3) is set
|
||||
# by the consuming script, here via font-colour + border overrides.
|
||||
var chip := Button.new()
|
||||
chip.text = text
|
||||
chip.theme_type_variation = ThemeKeys.CHIP
|
||||
chip.add_theme_color_override("font_color", color)
|
||||
var tinted := StyleBoxFlat.new()
|
||||
tinted.bg_color = Color(color, 0.15)
|
||||
tinted.border_color = color
|
||||
tinted.set_border_width_all(1)
|
||||
tinted.set_corner_radius_all(3)
|
||||
tinted.content_margin_left = 12
|
||||
tinted.content_margin_right = 12
|
||||
tinted.content_margin_top = 6
|
||||
tinted.content_margin_bottom = 6
|
||||
chip.add_theme_stylebox_override("normal", tinted)
|
||||
return chip
|
||||
|
||||
|
||||
func _prose() -> Control:
|
||||
# Narrative italic (spec §6) — the bundled EB Garamond italic face, shown
|
||||
# nowhere else on this screen. RichTextLabel is required for bbcode italics;
|
||||
# a plain Label cannot render [i].
|
||||
var rtl := RichTextLabel.new()
|
||||
rtl.bbcode_enabled = true
|
||||
rtl.fit_content = true
|
||||
rtl.custom_minimum_size = Vector2(900, 0)
|
||||
rtl.add_theme_font_override("normal_font", load(GAME_THEME).default_font)
|
||||
rtl.add_theme_font_override("italics_font", load(SERIF_ITALIC))
|
||||
rtl.text = "[i]The chamber is cold. Something waits in the dark.[/i]"
|
||||
return rtl
|
||||
|
||||
|
||||
func _fonts() -> Control:
|
||||
# All three bundled font families, at their real Theme sizes, plus the
|
||||
# default serif body face (not otherwise shown elsewhere on this screen).
|
||||
@@ -106,12 +146,12 @@ func _fonts() -> Control:
|
||||
|
||||
var accent := Label.new()
|
||||
accent.text = "Vexcca of the Ashmarch"
|
||||
accent.theme_type_variation = &"Accent"
|
||||
accent.theme_type_variation = ThemeKeys.ACCENT
|
||||
col.add_child(accent)
|
||||
|
||||
var mono := Label.new()
|
||||
mono.text = "STR 14 · INITIATIVE +2 · AC 16"
|
||||
mono.theme_type_variation = &"Mono"
|
||||
mono.theme_type_variation = ThemeKeys.MONO
|
||||
col.add_child(mono)
|
||||
|
||||
return col
|
||||
|
||||
Reference in New Issue
Block a user