fix(design): address PR #97 review — all items

Review fixes:
- Eyebrows moved from Head tab to Hair tab (with brow tint + beard tint)
- Head tab now has skin tone dock only
- Eyebrow names match asset keys (regular, female, teen, thick)
- Added earring L/R and necklace slots to Accessories tab
- Added wrist L/R slot labels already present, shifted grid for 3rd row
- Removed "Other" row label for Child (no gendered framing)
- D-155 cross-reference anchor fixed (was stale "full-360-rotation")
- D-160 segment count corrected 17→18 (added torso_upper)
- D-164 rationale corrected: Superhero mesh retained as muscular type
- Added compositor segment visibility note to implementation section
- D-165 cross-ref clarified (clothing colors only, not skin tones)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-22 16:42:50 +01:00
co-authored by Claude Opus 4.6
parent 93260ed696
commit 143185741e
9 changed files with 180 additions and 99 deletions
@@ -59,21 +59,21 @@ Each tab follows the same layout pattern:
## Tab Contents
### Body
- **Skin tone dock** (bottom): 9 preset swatches (D-165 does not apply — skin tones are separate from clothing colors)
- **Skin tone dock** (bottom): 9 preset swatches (separate from the D-165 clothing palette)
- **Body type grid**: 11 options (D-159) organized as:
- Female row: Thin, Average, Muscular, Heavy, Teen
- Male row: Thin, Average, Muscular, Heavy, Teen
- Other row: Child
- Child (unlabeled row — no gendered framing)
### Head
- **Head template grid**: Trellis-generated unique heads (D-163), scrollable. Starts with 4 Quaternius starters.
- **Eyebrow selector**: Thick, Thin, Arched, None
- **Skin tone dock** (bottom): same 9 swatches as Body tab (shared state)
### Hair
- **Hair style grid**: Short A, Short B, Medium A, Medium B, Long A, Bald (and more via scroll)
- **Facial hair selector**: None, Stubble, Beard, Moustache
- **Hair color dock** (bottom): Primary swatch + Highlight swatch (auto-derives from primary if unset)
- **Eyebrow selector**: Regular, Female, Teen, Thick (matches Source tier asset keys)
- **Hair color dock** (bottom): Hair primary + Hair highlight (auto) + Eyebrow tint (auto from hair, independent override) + Facial hair tint (auto from hair, independent override — single tint for both beard and moustache)
### Clothing
- **Slot selector** (fixed): Torso, Legs, Feet, Hands — click to filter the grid below
@@ -81,7 +81,7 @@ Each tab follows the same layout pattern:
- **Item color dock** (bottom): Primary / Secondary / Accent swatches. Secondary and Accent auto-derive if unset.
### Accessories
- **Slot selector** (fixed): Hat, Goggles, Mask, Backpack, Belt, Wrist L, Wrist R
- **Slot selector** (fixed): Hat, Goggles, Mask, Backpack, Belt, Wrist L, Wrist R, Earring L, Earring R, Necklace
- **Item grid**: Shows items for the selected slot
- **Item color dock** (bottom): Primary / Secondary swatches
@@ -129,7 +129,8 @@ Full keyboard/controller support required (existing `character_select.gd` is key
| D-158 | Frontal camera default for editor |
| D-159 | 11 body types (5 types × 2 genders + 1 child) |
| D-163 | Trellis-generated unique heads |
| D-165 | Color picker palette (5×9 muted hues + 1×9 neutral gray) |
| D-160 | 18 body segments (clothing hides covered segments) |
| D-165 | Color picker palette (5×9 muted hues + 1×9 neutral gray — clothing colors only, not skin tones) |
---
@@ -139,3 +140,6 @@ Full keyboard/controller support required (existing `character_select.gd` is key
- The color picker modal should preview changes live on the 3D model before OK is pressed.
- Search filters items by name within the active tab only.
- The skin tone dock appears on both Body and Head tabs and shares state — changing it on one updates the other.
- **Compositor coverage:** Changing body type or clothing in the editor must update segment visibility on the `CharacterCompositor`. Clothing items hide the body segments they cover (e.g. torso clothing hides `seg_torso`). The preview must reflect this in real time — switching from a tank top to a jacket should hide the arm segments underneath.
- **Eyebrow tint** and **facial hair tint** are independent from hair color. Default: auto-derive from hair primary. Player can override to any color via the color picker.
- Earring L/R and Necklace are jewelry accessory slots — they use `accessory_primary` / `accessory_secondary` color regions like other accessories.
@@ -275,81 +275,123 @@
"text": "Wrist R",
"fontColor": "#c8d0e0", "fontSize": 11
},
"slot-earring-l": {
"type": "Rectangle",
"parent": "tab-content",
"left": 756, "top": 232, "width": 76, "height": 28,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"slot-earring-l-label": {
"type": "Text",
"parent": "slot-earring-l",
"left": 762, "top": 238,
"text": "Earring L",
"fontColor": "#c8d0e0", "fontSize": 11
},
"slot-earring-r": {
"type": "Rectangle",
"parent": "tab-content",
"left": 838, "top": 232, "width": 76, "height": 28,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"slot-earring-r-label": {
"type": "Text",
"parent": "slot-earring-r",
"left": 844, "top": 238,
"text": "Earring R",
"fontColor": "#c8d0e0", "fontSize": 11
},
"slot-necklace": {
"type": "Rectangle",
"parent": "tab-content",
"left": 920, "top": 232, "width": 80, "height": 28,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"slot-necklace-label": {
"type": "Text",
"parent": "slot-necklace",
"left": 926, "top": 238,
"text": "Necklace",
"fontColor": "#c8d0e0", "fontSize": 11
},
"items-label": {
"type": "Text",
"parent": "tab-content",
"left": 756, "top": 240,
"left": 756, "top": 274,
"text": "HATS",
"fontColor": "#c8d0e0", "fontSize": 12
},
"item-1": {
"type": "Rectangle",
"parent": "tab-content",
"left": 756, "top": 258, "width": 104, "height": 90,
"left": 756, "top": 292, "width": 104, "height": 90,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"item-1-label": {
"type": "Text",
"parent": "item-1",
"left": 784, "top": 328,
"left": 784, "top": 362,
"text": "None",
"fontColor": "#c8d0e0", "fontSize": 10
},
"item-2": {
"type": "Rectangle",
"parent": "tab-content",
"left": 868, "top": 258, "width": 104, "height": 90,
"left": 868, "top": 292, "width": 104, "height": 90,
"fillColor": "#3a4050", "strokeColor": "#c8d8f0",
"corners": [4, 4, 4, 4]
},
"item-2-label": {
"type": "Text",
"parent": "item-2",
"left": 900, "top": 328,
"left": 900, "top": 362,
"text": "Cap",
"fontColor": "#c8d8f0", "fontSize": 10
},
"item-3": {
"type": "Rectangle",
"parent": "tab-content",
"left": 980, "top": 258, "width": 104, "height": 90,
"left": 980, "top": 292, "width": 104, "height": 90,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"item-3-label": {
"type": "Text",
"parent": "item-3",
"left": 1006, "top": 328,
"left": 1006, "top": 362,
"text": "Beanie",
"fontColor": "#c8d0e0", "fontSize": 10
},
"item-4": {
"type": "Rectangle",
"parent": "tab-content",
"left": 756, "top": 356, "width": 104, "height": 90,
"left": 756, "top": 390, "width": 104, "height": 90,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"item-4-label": {
"type": "Text",
"parent": "item-4",
"left": 784, "top": 426,
"left": 784, "top": 460,
"text": "Helmet",
"fontColor": "#c8d0e0", "fontSize": 10
},
"item-5": {
"type": "Rectangle",
"parent": "tab-content",
"left": 868, "top": 356, "width": 104, "height": 90,
"left": 868, "top": 390, "width": 104, "height": 90,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"item-5-label": {
"type": "Text",
"parent": "item-5",
"left": 896, "top": 426,
"left": 896, "top": 460,
"text": "Hood",
"fontColor": "#c8d0e0", "fontSize": 10
},
Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 94 KiB

@@ -326,55 +326,154 @@
"fontColor": "#c8d0e0", "fontSize": 10
},
"eyebrows-label": {
"type": "Text",
"parent": "tab-content",
"left": 756, "top": 462,
"text": "EYEBROWS",
"fontColor": "#c8d0e0", "fontSize": 12
},
"brow-1": {
"type": "Rectangle",
"parent": "tab-content",
"left": 756, "top": 480, "width": 80, "height": 48,
"fillColor": "#3a4050", "strokeColor": "#c8d8f0",
"corners": [4, 4, 4, 4]
},
"brow-1-label": {
"type": "Text",
"parent": "brow-1",
"left": 766, "top": 508,
"text": "Regular",
"fontColor": "#c8d8f0", "fontSize": 10
},
"brow-2": {
"type": "Rectangle",
"parent": "tab-content",
"left": 844, "top": 480, "width": 80, "height": 48,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"brow-2-label": {
"type": "Text",
"parent": "brow-2",
"left": 854, "top": 508,
"text": "Female",
"fontColor": "#c8d0e0", "fontSize": 10
},
"brow-3": {
"type": "Rectangle",
"parent": "tab-content",
"left": 932, "top": 480, "width": 80, "height": 48,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"brow-3-label": {
"type": "Text",
"parent": "brow-3",
"left": 952, "top": 508,
"text": "Teen",
"fontColor": "#c8d0e0", "fontSize": 10
},
"brow-4": {
"type": "Rectangle",
"parent": "tab-content",
"left": 1020, "top": 480, "width": 80, "height": 48,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"brow-4-label": {
"type": "Text",
"parent": "brow-4",
"left": 1038, "top": 508,
"text": "Thick",
"fontColor": "#c8d0e0", "fontSize": 10
},
"color-dock": {
"type": "Rectangle",
"parent": "tab-content",
"left": 740, "top": 568, "width": 380, "height": 88,
"left": 740, "top": 548, "width": 380, "height": 108,
"fillColor": "#1a1e24", "strokeColor": "#333340",
"corners": [0, 0, 8, 8]
},
"color-dock-label": {
"type": "Text",
"parent": "color-dock",
"left": 756, "top": 576,
"left": 756, "top": 554,
"text": "HAIR COLOR",
"fontColor": "#c8d0e0", "fontSize": 11
},
"color-primary-label": {
"type": "Text",
"parent": "color-dock",
"left": 756, "top": 596,
"left": 756, "top": 572,
"text": "Primary",
"fontColor": "#555568", "fontSize": 10
},
"color-primary-swatch": {
"type": "Rectangle",
"parent": "color-dock",
"left": 756, "top": 610, "width": 140, "height": 32,
"left": 756, "top": 586, "width": 100, "height": 28,
"fillColor": "#3a2a1a", "strokeColor": "#c8d8f0",
"corners": [4, 4, 4, 4]
},
"color-highlight-label": {
"type": "Text",
"parent": "color-dock",
"left": 916, "top": 596,
"left": 868, "top": 572,
"text": "Highlight",
"fontColor": "#555568", "fontSize": 10
},
"color-highlight-swatch": {
"type": "Rectangle",
"parent": "color-dock",
"left": 916, "top": 610, "width": 140, "height": 32,
"left": 868, "top": 586, "width": 100, "height": 28,
"fillColor": "#5a4a3a", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"color-auto-hint": {
"color-highlight-auto": {
"type": "Text",
"parent": "color-dock",
"left": 1066, "top": 622,
"left": 974, "top": 592,
"text": "auto",
"fontColor": "#555568", "fontSize": 9
},
"color-brow-label": {
"type": "Text",
"parent": "color-dock",
"left": 756, "top": 622,
"text": "Brow tint",
"fontColor": "#555568", "fontSize": 10
},
"color-brow-swatch": {
"type": "Rectangle",
"parent": "color-dock",
"left": 820, "top": 620, "width": 64, "height": 28,
"fillColor": "#3a2a1a", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"color-facial-label": {
"type": "Text",
"parent": "color-dock",
"left": 900, "top": 622,
"text": "Beard tint",
"fontColor": "#555568", "fontSize": 10
},
"color-facial-swatch": {
"type": "Rectangle",
"parent": "color-dock",
"left": 968, "top": 620, "width": 64, "height": 28,
"fillColor": "#3a2a1a", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"color-tints-auto": {
"type": "Text",
"parent": "color-dock",
"left": 1040, "top": 626,
"text": "auto",
"fontColor": "#555568", "fontSize": 9
},
"footer": {
"type": "Rectangle",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 102 KiB

@@ -269,70 +269,6 @@
"fontColor": "#c8d0e0", "fontSize": 10
},
"eyebrows-label": {
"type": "Text",
"parent": "tab-content",
"left": 756, "top": 414,
"text": "EYEBROWS",
"fontColor": "#c8d0e0", "fontSize": 12
},
"brow-1": {
"type": "Rectangle",
"parent": "tab-content",
"left": 756, "top": 432, "width": 80, "height": 52,
"fillColor": "#3a4050", "strokeColor": "#c8d8f0",
"corners": [4, 4, 4, 4]
},
"brow-1-label": {
"type": "Text",
"parent": "brow-1",
"left": 770, "top": 464,
"text": "Thick",
"fontColor": "#c8d8f0", "fontSize": 10
},
"brow-2": {
"type": "Rectangle",
"parent": "tab-content",
"left": 844, "top": 432, "width": 80, "height": 52,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"brow-2-label": {
"type": "Text",
"parent": "brow-2",
"left": 862, "top": 464,
"text": "Thin",
"fontColor": "#c8d0e0", "fontSize": 10
},
"brow-3": {
"type": "Rectangle",
"parent": "tab-content",
"left": 932, "top": 432, "width": 80, "height": 52,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"brow-3-label": {
"type": "Text",
"parent": "brow-3",
"left": 946, "top": 464,
"text": "Arched",
"fontColor": "#c8d0e0", "fontSize": 10
},
"brow-4": {
"type": "Rectangle",
"parent": "tab-content",
"left": 1020, "top": 432, "width": 80, "height": 52,
"fillColor": "#3a4050", "strokeColor": "#333340",
"corners": [4, 4, 4, 4]
},
"brow-4-label": {
"type": "Text",
"parent": "brow-4",
"left": 1038, "top": 464,
"text": "None",
"fontColor": "#c8d0e0", "fontSize": 10
},
"scroll-hint": {
"type": "Text",
"parent": "tab-content",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 87 KiB