| """studio.rigging β auto-rigging foundation (Phase 3). |
| |
| Picked stack (see ../../PHASE_3_RESEARCH.md): |
| segment.flood_fill_segment β flood-fill from corners + alpha fast path |
| joints.detect_joints β distance-transform + mask-topology hybrid |
| overlay.render_overlay β numpy + PIL debug visualisation |
| sidecar.load_sidecar/save_sidecar β operator-annotation JSON I/O |
| |
| Top-level entry point: |
| rig_sprite(image_path) β tries sidecar first, falls back to auto-detect |
| |
| Mesh skinning and pose deformation belong to Session 3 and are not implemented here. |
| """ |
| from __future__ import annotations |
|
|
| from pathlib import Path |
| from typing import Tuple |
|
|
| import numpy as np |
| from PIL import Image |
|
|
| from pixel_cursor.rigging import Skeleton |
|
|
| from .deform import deform_sprite, forward_kinematics |
| from .joints import detect_joints |
| from .overlay import render_overlay |
| from .parts import ( |
| CANONICAL_HUMANOID_PIECES, |
| PartsMask, |
| Piece, |
| canonical_humanoid_pieces, |
| load_parts, |
| parts_json_path_for, |
| parts_png_path_for, |
| parts_preview_path_for, |
| save_parts, |
| save_preview, |
| ) |
| from .rigid_piece import deform_sprite_rigid |
| from .segment import flood_fill_segment |
| from .sidecar import ( |
| SCHEMA_VERSION, |
| load_sidecar, |
| save_sidecar, |
| sidecar_path_for, |
| sidecar_template, |
| ) |
| from .skin import compute_skin_weights |
|
|
|
|
| def rig_sprite(image_path: Path | str) -> Tuple[Skeleton, np.ndarray, str]: |
| """Produce a 14-joint skeleton for a sprite on disk. |
| |
| Strategy: sidecar JSON first (operator-authoritative), auto-detect fallback. |
| |
| Returns (skeleton, mask, source) where source β {"sidecar", "auto"}. |
| """ |
| path = Path(image_path) |
| image = np.asarray(Image.open(path)) |
| mask = flood_fill_segment(image) |
| sidecar = load_sidecar(path, image_shape=mask.shape) |
| if sidecar is not None: |
| return sidecar, mask, "sidecar" |
| return detect_joints(mask), mask, "auto" |
|
|
|
|
| __all__ = [ |
| "flood_fill_segment", |
| "detect_joints", |
| "render_overlay", |
| "rig_sprite", |
| "load_sidecar", |
| "save_sidecar", |
| "sidecar_path_for", |
| "sidecar_template", |
| "SCHEMA_VERSION", |
| "compute_skin_weights", |
| "forward_kinematics", |
| "deform_sprite", |
| "CANONICAL_HUMANOID_PIECES", |
| "PartsMask", |
| "Piece", |
| "canonical_humanoid_pieces", |
| "load_parts", |
| "parts_json_path_for", |
| "parts_png_path_for", |
| "parts_preview_path_for", |
| "save_parts", |
| "save_preview", |
| "deform_sprite_rigid", |
| ] |
|
|