File size: 2,510 Bytes
7faaef2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | """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",
]
|