feat(theme): palette tokens as the single colour source
This commit is contained in:
89
client/scripts/theme/palette.gd
Normal file
89
client/scripts/theme/palette.gd
Normal file
@@ -0,0 +1,89 @@
|
||||
class_name Palette
|
||||
extends RefCounted
|
||||
## The single source of truth for every colour token (mockups README, "Color
|
||||
## tokens"). §2: presentation — owns no state. No hex literal may live anywhere
|
||||
## else in the client; every script, shader, and the Theme builder reads here.
|
||||
|
||||
# --- Dark backgrounds ---
|
||||
const STAGE_1 := Color("0a0806")
|
||||
const STAGE_2 := Color("0f0d0b")
|
||||
const BAY_STRIPE_A := Color("26221c")
|
||||
const BAY_STRIPE_B := Color("221e18")
|
||||
const DARK_PANEL_70 := Color("120f0b", 0.7)
|
||||
const DARK_PANEL_85 := Color("0e0b09", 0.85)
|
||||
const DARK_PANEL_90 := Color("0a0806", 0.9)
|
||||
# border ladder, light -> dark
|
||||
const BORDER_1 := Color("6b6152")
|
||||
const BORDER_2 := Color("5a5348")
|
||||
const BORDER_3 := Color("4a4238")
|
||||
const BORDER_4 := Color("3a352e")
|
||||
const BORDER_5 := Color("1a1512")
|
||||
|
||||
# --- Parchment ---
|
||||
const SHEET_TOP := Color("ece2ca")
|
||||
const SHEET_BOTTOM := Color("e4d8bd")
|
||||
const LOG_TOP := Color("e7dcc4")
|
||||
const LOG_BOTTOM := Color("ddd0b2")
|
||||
const PARCHMENT_CARD := Color("f1e8d2")
|
||||
const PARCHMENT_INSET := Color("e6d9b8")
|
||||
const PARCHMENT_INSET_2 := Color("d9c9a2")
|
||||
const PARCHMENT_BORDER := Color("bfa878")
|
||||
const PARCHMENT_BORDER_2 := Color("cbb684")
|
||||
const PARCHMENT_BORDER_3 := Color("a99464")
|
||||
const TAB_INACTIVE_BG := Color("efe6cf")
|
||||
|
||||
# --- Ink (text on parchment) ---
|
||||
const INK_HEADING := Color("3a2f1c")
|
||||
const INK_HEADING_2 := Color("4a3520")
|
||||
const INK_BODY := Color("4a3f2c")
|
||||
const INK_MUTED := Color("6a5a3a")
|
||||
const INK_LABEL := Color("5a4326")
|
||||
const INK_GOLD := Color("8f6a2a")
|
||||
|
||||
# --- Text on dark ---
|
||||
const CREAM := Color("e8ddc8")
|
||||
const CREAM_BRIGHT := Color("f0e6d0")
|
||||
const CREAM_SECONDARY := Color("c9bda3")
|
||||
const MUTED_MONO := Color("9a8f78")
|
||||
const MUTED_MONO_DIM := Color("7a7060")
|
||||
|
||||
# --- Accents (muted for grit) ---
|
||||
const BLOOD := Color("8f3a34") # core CTA / danger / selection / enemies
|
||||
const BLOOD_BRIGHT := Color("b8524a") # hover
|
||||
const BLOOD_DARK := Color("7a2f29") # CTA gradient bottom
|
||||
const GOLD := Color("a9843f") # highlight / currency / current-turn
|
||||
const GOLD_BRIGHT := Color("c8963f")
|
||||
const STEEL := Color("5f8a9a") # allies / mana
|
||||
const STEEL_BLUE := Color("4f7ab8")
|
||||
const STEEL_DEEP := Color("243f6f")
|
||||
const GREEN := Color("5f8a4f") # stamina / success / cleared
|
||||
|
||||
# --- Stat bars ---
|
||||
const HP_A := Color("b8524a")
|
||||
const HP_B := Color("8f3a34")
|
||||
const MP_A := Color("4f7ab8")
|
||||
const MP_B := Color("243f6f")
|
||||
const STAMINA := Color("8f9a4f")
|
||||
const BAR_TRACK := Color("2a251f")
|
||||
const BAR_BORDER := Color("4a4238")
|
||||
|
||||
# --- Rarity (ordered common..legendary) ---
|
||||
const RARITY: Array[Color] = [
|
||||
Color("8a8378"), # 0 common
|
||||
Color("5f8a4f"), # 1 uncommon
|
||||
Color("4f7ab8"), # 2 rare
|
||||
Color("8a5fb8"), # 3 epic
|
||||
Color("c8963f"), # 4 legendary
|
||||
]
|
||||
|
||||
|
||||
static func rarity_color(rarity: int) -> Color:
|
||||
return RARITY[clampi(rarity, 0, RARITY.size() - 1)]
|
||||
|
||||
|
||||
static func stat_bar(kind: StringName) -> Array:
|
||||
match kind:
|
||||
&"hp": return [HP_A, HP_B]
|
||||
&"mp": return [MP_A, MP_B]
|
||||
&"stamina": return [STAMINA, STAMINA]
|
||||
_: return [MUTED_MONO, MUTED_MONO_DIM]
|
||||
45
client/tests/unit/test_palette.gd
Normal file
45
client/tests/unit/test_palette.gd
Normal file
@@ -0,0 +1,45 @@
|
||||
extends "res://addons/gut/test.gd"
|
||||
|
||||
const Palette = preload("res://scripts/theme/palette.gd")
|
||||
|
||||
|
||||
func test_core_tokens_are_colors():
|
||||
assert_true(Palette.BLOOD is Color)
|
||||
assert_true(Palette.GOLD is Color)
|
||||
assert_true(Palette.PARCHMENT_CARD is Color)
|
||||
assert_true(Palette.CREAM is Color)
|
||||
|
||||
|
||||
func test_blood_core_matches_readme_hex():
|
||||
# #8f3a34 — the primary CTA / danger / selection red.
|
||||
assert_eq(Palette.BLOOD, Color("8f3a34"))
|
||||
|
||||
|
||||
func test_dark_panel_is_translucent():
|
||||
assert_almost_eq(Palette.DARK_PANEL_70.a, 0.7, 0.01)
|
||||
|
||||
|
||||
func test_rarity_ladder_has_five_ordered_colors():
|
||||
assert_eq(Palette.RARITY.size(), 5)
|
||||
assert_eq(Palette.rarity_color(0), Color("8a8378")) # common
|
||||
assert_eq(Palette.rarity_color(4), Color("c8963f")) # legendary
|
||||
|
||||
|
||||
func test_rarity_color_clamps_out_of_range():
|
||||
# Out-of-range must NOT index-error (would emit an engine error -> fail).
|
||||
assert_eq(Palette.rarity_color(-3), Palette.RARITY[0])
|
||||
assert_eq(Palette.rarity_color(99), Palette.RARITY[4])
|
||||
|
||||
|
||||
func test_stat_bar_returns_from_to_pair():
|
||||
var hp = Palette.stat_bar(&"hp")
|
||||
assert_eq(hp.size(), 2)
|
||||
assert_eq(hp[0], Color("b8524a"))
|
||||
assert_eq(hp[1], Color("8f3a34"))
|
||||
|
||||
|
||||
func test_stat_bar_unknown_kind_is_safe():
|
||||
# Unknown kind returns a grey pair, never null / error.
|
||||
var pair = Palette.stat_bar(&"nonsense")
|
||||
assert_eq(pair.size(), 2)
|
||||
assert_true(pair[0] is Color)
|
||||
Reference in New Issue
Block a user