fix(client): address PR #95 review — 8 items

SLOT_TO_BONE expanded to 12 slots (earring_l/r, necklace, wrist_l/r).
_clear() outline teardown ordering fixed. toon_masked.gdshader: removed
cull_disabled, added ALPHA output. _attach_to_bone() returns node instead
of bool. skin_tone clamped in from_dict(). D-160 segment count 15→17.
Blender scripts: docstrings + __main__ guards. Reload test tightened.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-20 07:59:23 +01:00
co-authored by Claude Opus 4.6
parent f34e6362c4
commit bcd5887b82
7 changed files with 82 additions and 33 deletions
@@ -15,7 +15,7 @@
## 5. Facing rotation (set_facing / rotation change)
## 6. Edge cases: empty hair_id, no clothing, no accessories
##
## Spec: D-159 (body types), D-160 (15+2+2 segments), D-161 (head on Head bone),
## Spec: D-159 (body types), D-160 (17 bone-group regions), D-161 (head on Head bone),
## D-162 (clothing pre-baked per body type), D-164 (fork skeleton)
## Ticket: #704
class_name TestCharacterVisualSprint28
@@ -158,10 +158,11 @@ func test_reload_descriptor_clears_previous_nodes() -> void:
if count_after_first == 0:
push_warning("TestCharacterVisualSprint28: node count 0 — assets may not be present yet")
return
# Second load must not double the children (would indicate no cleanup)
assert_bool(count_after_second <= count_after_first * 2).override_failure_message(
"load_descriptor must clear previous node tree before building new one — children doubled, suggesting stale nodes were kept"
).is_true()
# Second load must produce exactly the same child count — no more, no less.
# _clear() frees and rebuilds; any deviation indicates stale nodes accumulating.
assert_int(count_after_second).override_failure_message(
"load_descriptor must produce identical child count on reload — stale nodes detected if higher, missing cleanup if lower"
).is_equal(count_after_first)
# =============================================================================