fix: address shape mounting issues in StkRigAdapter

- Implement anisotropic scaling for shape mounting to prevent distortion.
- Replace bounding-box midpoint anchors with joint-based anchors for correct rotation.
- Reset node transforms to ensure clean scaling and rotation before mounting shapes.
- Introduce new helper functions for computing bounding boxes, anchors, part lengths, and scales.
- Neutralize driver rotations to maintain a consistent frame of reference during shape mounting.
- Update documentation to reflect changes and provide detailed bugfix specifications.
This commit is contained in:
2026-08-19 10:01:25 -04:00
parent 1252728c06
commit 6b273c049c
5 changed files with 491 additions and 30 deletions
+17 -3
View File
@@ -110,15 +110,29 @@ assembled in a "Whole Stickman" preview that supports translation, rotation, and
- `scripts/stk_rig_adapter.gd``class_name StkRigAdapter`, `extends RefCounted`; a **standalone
runtime adapter** (Phase 8, **not referenced by the editor**, extended by Phase 9).
`static func apply(stk_data, rig)` fits an instantiated `master_rig.tscn` to a loaded `.stk`
dictionary, calling three private helpers in order: `_fit_bones` (re-fits the 8 limb `Bone2D`
dictionary, calling four private helpers in order: `_fit_bones` (re-fits the 8 limb `Bone2D`
lengths + lower-bone origins), `_recalibrate_ik` (repositions the `IK_Targets/Left|Right_Hand`
and `Left|Right_Leg` targets), and `_mount_shapes` (mounts `.stk` shapes onto the `Body/*`
visual nodes — open → `Line2D`, closed → `Polygon2D` fill + `Line2D` outline, width 16).
and `Left|Right_Leg` targets), `_neutralize_driver_rotations` (sets `update_rotation = false`
on the 10 `Body/*` `RemoteTransform2D` drivers so the `Body/*` nodes stay in the clean
unrotated frame the mount math assumes; position/scale pushes are retained), and
`_mount_shapes` (mounts `.stk` shapes onto the `Body/*` visual nodes — open → `Line2D`,
closed → `Polygon2D` fill + `Line2D` outline, width 16).
- **Phase 9 extension:** also fits the head bone (`Skeleton2D/Torso/Head.position.y =
-proportions.torso_length`, x preserved) and mounts the head as **full geometry** like every
other part — it clears the `Body/Head` node's inline `@tool` circle script via
`set_script(null)` and mounts `.stk` head shapes as `Line2D`/`Polygon2D`. Dead helpers
`_mount_head_circle`, `_compute_shapes_bbox`, and `_first_shape_color` were removed.
- **Phase 9 Round 1 bugfix (mount math):** `_mount_shapes()` no longer reads the file's
`pivot`/`length` fields — it recomputes a per-part bounding box at mount time via
`_compute_part_bbox()` (empty bbox → the part is skipped). `_compute_anchor()` derives a
**joint-based anchor** per part family: head → bottom-center `(cx, max_y)`; torso + legs →
top-center `(cx, min_y)`; left arms → `(max_x, cy)`; right arms → `(min_x, cy)`. Scaling is
**anisotropic** via `_compute_scale()`, applied as a `Vector2`: arms scale X only
`(bone_length/part_length, 1.0)`, legs/torso scale Y only `(1.0, bone_length/part_length)`,
head unscaled `(1.0, 1.0)`, with a `part_length <= 0` guard → `1.0`. `_bone_length_for()`
maps each part to its bone length (upper/lower arm/leg, torso); `X_AXIS_PARTS` const
identifies the four arm keys. `_reset_node_transform()` resets each `Body/*` container's
scale to `(1, 1)` and rotation to `0` (position untouched, owned by the driver).
Targets `master_rig.tscn` node paths; every node lookup is null-guarded (missing node →
`push_warning` + skip, never crash). Consumed by a future runtime pipeline.
- `scripts/stickman_factory.gd` — `class_name StickmanFactory`, `extends RefCounted`; a **static