feat(assets): wardrobe wave 1 — per-body shells, 8 garments, try-on UI (T-1089)

Infra: offset-shell gains --per-body mode (each body's own segments, cut/mask
thresholds derived from that body's bone landmarks — reproduces the
hand-calibrated reference constants exactly on average_m); compositor prefers
<body>_mask.png with reference_mask.png fallback; tshirt re-authored per-body
on all 11 (the Q-060 torso poke-through class is GONE — residual flags are a
sleeve-hem epsilon artifact on thick arms, offset-insensitive, documented).

Garments (all per-body x 11, chromakey-gated <=150px worst, previewed):
hoodie (hood-down roll, kangaroo pocket, logo), button-down (collar/placket),
shorts, jeans (analytic denim field driving albedo+mask together; boundary
weld + open-rim flattening — real segment-splitter findings), formal pants,
jacket (over-shirt standoff, zip), suit_jacket_black (lapel region, tintable
shirt triangle — the hand-author proof), uniform_utility (11-segment
coverall, gap-free waist join by construction, 4-zone showcase, logo patch).

Try-on UI: creation screen shows per-region tint pickers (multi_region
garments) + logo picker (logo_capable + logos/*.png scan), data-driven off
manifest+coverage. Manifest merged by the lead: 12 clothing entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 00:35:20 +02:00
co-authored by Claude Fable 5
parent dd0d220846
commit c765efd54e
345 changed files with 5369 additions and 54 deletions
+6 -2
View File
@@ -586,8 +586,12 @@ func _load_clothing(desc: CharacterVisualDescriptor) -> void:
if coverage.get("torso_variant") == "upper":
_active_torso_variant = "upper"
# Load recolor mask: shared across all body-type variants (same UV layout after Surface Deform).
var mask_path := item_dir + "reference_mask.png"
# Load recolor mask: per-body-authored garments (offset-shell route) ship
# one mask per body type; SD-fit garments share reference_mask.png
# (same UV layout across variants after Surface Deform).
var mask_path := item_dir + "%s_mask.png" % desc.body_type_key()
if not ResourceLoader.exists(mask_path):
mask_path = item_dir + "reference_mask.png"
var mask_tex: Texture2D = null
if ResourceLoader.exists(mask_path):
mask_tex = load(mask_path) as Texture2D