test_committed_tres_matches_builder has now been "fixed" three times (traps.md #12). v1 hardcoded 3 checks; v2 iterated ThemeKeys.ALL but missed the six font roles; v3 added a meta-guard specifically to catch "the builder styles a thing guarded by nothing" — but that meta-guard contained `if fresh.get_type_variation_base(variation) == &"": continue`, which whitelisted exactly the case it was built to catch. The builder styles RichTextLabel directly (build_game_theme.gd's _rich_text()), with no set_type_variation, so it reports base "" and was skipped unconditionally — and RichTextLabel is what renders every line of DM prose the creation screen shows (_origin_text, _detail_blurb). Nothing compared its fonts, font size, or colour, nor the theme-level default_font/default_font_size, against the committed .tres. Adds ThemeKeys.BASE_TYPES for base Control types the builder styles directly, folds it into the drift guard's coverage, replaces the meta-guard's continue with an assertion that names the offending type, and adds the missing theme-level default font/size comparison. Proved with three reverted breaks: a RichTextLabel font-size edit, a theme-level default_font_size edit, and an unregistered "GhostRole" variation — all three now go red and name the drifted property. Also: strengthens test_creation_copy's error-copy sweep to assert a mapped error actually reaches its authored line rather than silently falling through to the generic UNSPOKEN fallback (CreationCopy.UNSPOKEN satisfied all four prior checks, so a renamed validator string could regress silently); and removes two assertions that were true by construction / already true before their test's action ran. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
83 lines
3.3 KiB
GDScript
83 lines
3.3 KiB
GDScript
# client/scripts/theme/theme_keys.gd
|
|
class_name ThemeKeys
|
|
extends RefCounted
|
|
## Type-variation names for game_theme.tres. Scripts set `theme_type_variation`
|
|
## to one of these so a typo is a compile-time symbol error, not a silent miss.
|
|
## §2: presentation.
|
|
|
|
const PRIMARY_CTA := &"PrimaryCTA"
|
|
const TAB := &"Tab"
|
|
const TAB_ACTIVE := &"TabActive"
|
|
const CHIP := &"Chip"
|
|
const DOCK_BUTTON := &"DockButton"
|
|
const PARCHMENT_BUTTON := &"ParchmentButton"
|
|
const ITEM_TILE := &"ItemTile"
|
|
const ITEM_TILE_EMPTY := &"ItemTileEmpty"
|
|
const PARCHMENT_CARD := &"ParchmentCard"
|
|
const PARCHMENT_INSET := &"ParchmentInset"
|
|
const DARK_PANEL := &"DarkPanel"
|
|
const SELECT_CARD := &"SelectCard" # race/calling card: a Button whose `pressed` is CHOSEN
|
|
const SKILL_CHIP := &"SkillChip" # toggle: unpicked / picked / granted-so-inert
|
|
const CHOSEN_TAG := &"ChosenTag" # the little crimson "CHOSEN" flag
|
|
const PRIMARY_TAG := &"PrimaryTag" # the little gold "PRIMARY" flag
|
|
const PRIMARY_CARD := &"PrimaryCard" # the ability card ringed as the calling's primary
|
|
|
|
## Font roles (Label type-variations carrying a font, not a stylebox). Kept
|
|
## separate from ALL below, which is stylebox variations + their base type only.
|
|
const HEADING := &"Heading"
|
|
const ACCENT := &"Accent"
|
|
const MONO := &"Mono"
|
|
const TITLE_LOGO := &"TitleLogo"
|
|
const TITLE_KICKER := &"TitleKicker"
|
|
const SECTION_LABEL := &"SectionLabel"
|
|
|
|
## Every FONT role + the base Control type it decorates. Deliberately NOT folded
|
|
## into ALL — ALL's "stylebox variations only" contract is relied on elsewhere
|
|
## (test_every_variation_resolves, and the styleboxes the screens set). Kept as a
|
|
## second enumerable set so a guard that means "every variation the builder
|
|
## touches" can iterate BOTH and never silently cover only half of them: the
|
|
## drift guard used to iterate ALL alone, so a font, a font size or a font colour
|
|
## could change in the builder and the committed .tres stay stale, suite green.
|
|
const FONT_ROLES := {
|
|
HEADING: "Label",
|
|
ACCENT: "Label",
|
|
MONO: "Label",
|
|
TITLE_LOGO: "Label",
|
|
TITLE_KICKER: "Label",
|
|
SECTION_LABEL: "Label",
|
|
}
|
|
|
|
## Base Control types the builder styles DIRECTLY — no set_type_variation is
|
|
## ever called for these, so a fresh Theme reports get_type_variation_base("")
|
|
## for them. Kept as its own set (not folded into ALL or FONT_ROLES) because a
|
|
## base type is not a variation: nothing sets `theme_type_variation` to
|
|
## "RichTextLabel" anywhere, the node's own class name is the lookup key.
|
|
## Today: RichTextLabel, the builder's prose voice (mock README Typography:
|
|
## serif body/italic emphasis) — the creation screen's origin panel and
|
|
## calling detail panel are RichTextLabels rendering this styling directly,
|
|
## i.e. every line of DM prose the screen shows.
|
|
const BASE_TYPES := {
|
|
&"RichTextLabel": true,
|
|
}
|
|
|
|
## Every variation name + the base Control type it decorates. The builder and the
|
|
## test both iterate this so they can never drift apart.
|
|
const ALL := {
|
|
PRIMARY_CTA: "Button",
|
|
TAB: "Button",
|
|
TAB_ACTIVE: "Button",
|
|
CHIP: "Button",
|
|
DOCK_BUTTON: "Button",
|
|
PARCHMENT_BUTTON: "Button",
|
|
ITEM_TILE: "PanelContainer",
|
|
ITEM_TILE_EMPTY: "PanelContainer",
|
|
PARCHMENT_CARD: "PanelContainer",
|
|
PARCHMENT_INSET: "PanelContainer",
|
|
DARK_PANEL: "PanelContainer",
|
|
SELECT_CARD: "Button",
|
|
SKILL_CHIP: "Button",
|
|
CHOSEN_TAG: "Label",
|
|
PRIMARY_TAG: "Label",
|
|
PRIMARY_CARD: "PanelContainer",
|
|
}
|