Merge campaign-cc-batch-g: Batch G — real color wheel mechanism (inert until closeout wiring)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

# Conflicts:
#	docs/research/2026-08-16-campaign-cc-gate-round1-findings.md
This commit is contained in:
Erik 2026-08-16 14:19:30 +02:00
commit 1f6365d3e5
10 changed files with 1558 additions and 30 deletions

View file

@ -38,8 +38,42 @@ acdream GradCircle vs retail's color wheel).
disc) where retail shows the gradient wheel + gold swatch dots that
CHANGE per selected part — the user's gate PROMOTES AP-216/AP-217's
remaining halves (real palette-color swatch rendering + gradient tint)
from partial-closed to must-port. — OUT OF SCOPE for Batch E; still
open.
from partial-closed to must-port. **CODE-COMPLETE at Batch G (2026-08-16),
register AP-216/AP-217 rewritten (not retired — see their own rows):**
the retail mechanism (`gmCGAppearancePage::DoColorSpots @0x0047d850` /
`SetSelection @0x0047e260` / `DoGradDisk @0x0047da90`) is fully re-derived
and ported — a new pure Core resolver
(`AcDream.Core.CharGen.ChargenSwatchColorResolver`) computes each of the
nine swatches' representative RGB (PalSet-averaged for Hair/Nose+Mouth+
Skin/Headgear/Shirt/Trousers/Footwear at retail's own fixed sample
indices `0xd0`/`0xb0`/`0x520`, direct-Palette for Eyes at `0x103`) backed
by a new `ChargenAppearanceCatalog.TryGetColor` reading real Palette dat
objects, pinned against the installed EoR dat
(`ChargenAppearanceCatalogColorTests` — e.g. Aluvian male's shared skin
PalSet measures a plausible flesh-tone RGB(182,148,118)).
`CharacterCreationAppearancePage` recomputes all nine swatches + the
gradient disc's tint on every refresh (part change / color change /
heritage change, `CharacterCreationAppearancePageSwatchColorTests`), and
paints them through a new `ChargenSwatchColorTile` overlay element.
**Two STOPPED items block this from being visually live**, both outside
Batch G's file contract: (1) the new `PalSetSource`/`ClothingTableSource`/
`PaletteColorSource` late-bound seams (mirroring the existing
`PreviewControl` pattern) are never assigned by the composition root
(`CharacterCreationUiController.cs`) — until wired, the mechanism stays
fully inert, matching PRE-Batch-G behavior exactly; (2) the rendering
primitive is a flat-color-fill approximation of retail's actual
recolored-sprite blit — neither `UiButton` (sealed) nor `UiDatElement`
exposes a per-instance sprite `Tint`, though the retained-UI sprite
pipeline's `DrawSprite` already carries the `Vector4 tint` multiply
retail's own `Blit_Multiply` needs; adding that property is a small,
precisely-specified addition to those two shared widget files for the
lead to sequence. Nose/Mouth/Skin (retail's own non-interactive single
representative swatch, `SetSelection`'s hard-coded `var_1e0 = 1`) is ALSO
ported, beyond AP-216/AP-217's original six-part scope. Tests: 11 new
Core (`ChargenSwatchColorResolverTests`), 6 new Content live-DAT
(`ChargenAppearanceCatalogColorTests`), 8 new App-layer fixture
(`CharacterCreationAppearancePageSwatchColorTests`) — App suite
5321/3 -> 5329/3, Runtime 1735/0 unchanged, zero regressions.
- **R2-6: Town description text misaligned** — R2-1 family. — **FIXED
(Batch E)**, same shared mechanism as R2-1.
- **R2-7: Summary — (a) text misaligned (R2-1); (b) the summary OVERVIEW