feat(client): compositor plumb for multi-region garments + per-character logos (T-1089)

_apply_clothing_shader routes coverage.json multi_region garments to
toon_garment (4 tints, cascading fallback) with the brand logo resolved from
the new descriptor field clothing_logos (item_id -> brand id -> logos/<id>.png
— a logo is a per-CHARACTER wardrobe choice, so it rides the descriptor, not
the garment). Legacy garments keep the single-tint path untouched. Server-side
descriptor mirror stays parked with T-1060/Q-114 (appearance is client-local).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 22:21:52 +02:00
co-authored by Claude Fable 5
parent e22ea0fa4a
commit 278e8b7c21
2 changed files with 57 additions and 12 deletions
@@ -104,6 +104,11 @@ var accessory_slots: Dictionary = {}
## Changed from single Color per Tyre architecture review (Task #6).
var accessory_tints: Dictionary = {}
## item_id → brand id, resolved to assets/characters/logos/<id>.png (T-1089).
## A logo is a per-CHARACTER wardrobe choice (which brand THIS shirt wears),
## so it rides the descriptor, not the garment's coverage.json.
var clothing_logos: Dictionary = {}
## Get the file key for the current body type (e.g. "average_m").
func body_type_key() -> String:
@@ -139,6 +144,7 @@ static func from_dict(data: Dictionary) -> CharacterVisualDescriptor:
desc.clothing_tints = _decode_tint_map(data.get("clothing_tints", {}))
desc.accessory_slots = data.get("accessory_slots", {})
desc.accessory_tints = _decode_tint_map(data.get("accessory_tints", {}))
desc.clothing_logos = data.get("clothing_logos", {})
return desc
@@ -160,6 +166,7 @@ func to_dict() -> Dictionary:
"clothing_tints": _encode_tint_map(clothing_tints),
"accessory_slots": accessory_slots,
"accessory_tints": _encode_tint_map(accessory_tints),
"clothing_logos": clothing_logos,
}