@ikijs/editor 0.16.1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -17
- package/dist/index.d.mts +101 -18
- package/dist/index.d.ts +101 -18
- package/dist/index.js +1127 -622
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1128 -622
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -40,26 +40,27 @@ leaves the document untouched.
|
|
|
40
40
|
|
|
41
41
|
## API
|
|
42
42
|
|
|
43
|
-
| Area | Exports
|
|
44
|
-
| ------------------ |
|
|
45
|
-
| Document | `EditorDocument`, `EditCommand`
|
|
46
|
-
| Part edits | `AddPart`, `DeletePart`, `SetPartColor`, `SetPartWidth`, `SetPartHeight`, `SetPartOrder`, `SetPartTransform`, `SetPartBindings`, `SetPartMesh`, `SetPartDeformer`
|
|
47
|
-
| Deformer edits | `AddDeformer`, `DeleteDeformer`, `SetDeformerParent`, `SetDeformerTransform`, `SetDeformerBindings`, `SetDeformerPivot` (+ `X`/`Y`), `CaptureGridKeyform`
|
|
48
|
-
| Physics edits | `AddPhysicsRig`, `SetPhysicsRig`, `DeletePhysicsRig`
|
|
49
|
-
| Referential guards | `validateDeformerReparent`, `validateDeformerDelete`, `validatePartAttach`
|
|
50
|
-
| Atlas | `packAtlas`, `uvRectFor`, `ATLAS_PADDING`, `UV_INSET_PX`
|
|
51
|
-
| Grid keyforms | `computeGridOffsets`, `interpolateGridOffsets`, `upsertGridKeyform`
|
|
52
|
-
| Factories | `createDefaultPart`, `createDefaultMatrixDeformer`, `createDefaultWarpDeformer`, `createGridMesh`
|
|
53
|
-
| Pixels | `detectAlphaBbox`, `ALPHA_BBOX_THRESHOLD`, `AlphaBbox`, `ALPHA_OPAQUE`, `HEAD_BAND`, `SPECK_CORE_FRACTION`, `denseCoreOf`, `isSpeckCore`, `foregroundSpan`, `headHalfOf`
|
|
54
|
-
| Auto-rig | `generateIkiFromLayerSet`, `parseLayerRoles`, `createLayerSetMeasurer`, `TurnTargets`, `DEFAULT_TURN_TARGETS`, `TurnSolveReport`, `RigStyle`
|
|
55
|
-
| Bindings | `captureBindingEndpoint`
|
|
43
|
+
| Area | Exports |
|
|
44
|
+
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
45
|
+
| Document | `EditorDocument`, `EditCommand` |
|
|
46
|
+
| Part edits | `AddPart`, `DeletePart`, `SetPartColor`, `SetPartWidth`, `SetPartHeight`, `SetPartOrder`, `SetPartTransform`, `SetPartBindings`, `SetPartMesh`, `SetPartDeformer` |
|
|
47
|
+
| Deformer edits | `AddDeformer`, `DeleteDeformer`, `SetDeformerParent`, `SetDeformerTransform`, `SetDeformerBindings`, `SetDeformerPivot` (+ `X`/`Y`), `CaptureGridKeyform` |
|
|
48
|
+
| Physics edits | `AddPhysicsRig`, `SetPhysicsRig`, `DeletePhysicsRig` |
|
|
49
|
+
| Referential guards | `validateDeformerReparent`, `validateDeformerDelete`, `validatePartAttach` |
|
|
50
|
+
| Atlas | `packAtlas`, `uvRectFor`, `ATLAS_PADDING`, `UV_INSET_PX` |
|
|
51
|
+
| Grid keyforms | `computeGridOffsets`, `interpolateGridOffsets`, `upsertGridKeyform` |
|
|
52
|
+
| Factories | `createDefaultPart`, `createDefaultMatrixDeformer`, `createDefaultWarpDeformer`, `createGridMesh` |
|
|
53
|
+
| Pixels | `detectAlphaBbox`, `ALPHA_BBOX_THRESHOLD`, `AlphaBbox`, `ALPHA_OPAQUE`, `HEAD_BAND`, `SPECK_CORE_FRACTION`, `denseCoreOf`, `isSpeckCore`, `foregroundSpan`, `headHalfOf` |
|
|
54
|
+
| Auto-rig | `generateIkiFromLayerSet`, `parseLayerRoles`, `partIdsOfRole`, `createLayerSetMeasurer`, `armGeometry`, `ArmGeometry`, `TurnTargets`, `DEFAULT_TURN_TARGETS`, `TurnSolveReport`, `RigStyle`, `LayerGeometryError` |
|
|
55
|
+
| Bindings | `captureBindingEndpoint` |
|
|
56
56
|
|
|
57
57
|
## Auto-rig
|
|
58
58
|
|
|
59
59
|
`generateIkiFromLayerSet` turns role-named layers (`face`, `eye_L`, `eye_R`,
|
|
60
60
|
`mouth`, plus optional `iris_*`, `brow_*`, `lash_*`, `lash_lower_*`, `hair_front`, `hair_back`,
|
|
61
|
-
…) into a rigged model that blinks, gazes, opens its mouth, turns its head over
|
|
62
|
-
a
|
|
61
|
+
`body`, `arm_*`, …) into a rigged model that blinks, gazes, opens its mouth, turns its head over
|
|
62
|
+
a body warp that breathes, follows the head a little and turns on
|
|
63
|
+
`ParamBodyAngleX/Y/Z`, and emotes with its brows — including a
|
|
63
64
|
hair-sway physics rig when a `hair_front` layer is present. With a `blush_*`
|
|
64
65
|
layer it declares `ParamCheek`, which fades the blush from faint at rest to
|
|
65
66
|
as drawn. Every rigged model also declares the head motions Nod, Shake and
|
|
@@ -77,8 +78,13 @@ edge further outside the back hair painted behind it than the nod alone does —
|
|
|
77
78
|
and the back hair stays behind; the neck and the
|
|
78
79
|
ears the face layer paints are cut off into islands of the plate's own mesh,
|
|
79
80
|
drawn behind the head — the neck stays (only the chin's shade slides across
|
|
80
|
-
it), the ears lag the face, the far one narrowing. AngleZ rolls the head 14° about the chin
|
|
81
|
-
breathes
|
|
81
|
+
it), the ears lag the face, the far one narrowing. AngleZ rolls the head 14° about the chin.
|
|
82
|
+
A `body` rides a body warp that breathes, follows the head's turn and tilt a
|
|
83
|
+
little and turns on `ParamBodyAngleX/Y/Z`, its legs planted, and the head
|
|
84
|
+
hangs from it. `arm_L` / `arm_R`, each a whole arm drawn hanging with its
|
|
85
|
+
shoulder at the top, hang from it too: each becomes an upper arm and a
|
|
86
|
+
forearm cut from the one crop, turning about the shoulder and the elbow on
|
|
87
|
+
`ParamArmL/R` and `ParamElbowL/R`. An arm needs a `body`.
|
|
82
88
|
|
|
83
89
|
On a layer set with a `nose`, `options.turnTargets` — the cues a 30° reference
|
|
84
90
|
measures (how far the eye pair slides, how much the far eye foreshortens,
|
package/dist/index.d.mts
CHANGED
|
@@ -696,7 +696,8 @@ interface RigStyle {
|
|
|
696
696
|
|
|
697
697
|
/** One role layer, as a host measured it off its decoded pixels. */
|
|
698
698
|
interface LayerInput {
|
|
699
|
-
/** Canonical role (see `parseLayerRoles`); becomes the part
|
|
699
|
+
/** Canonical role (see `parseLayerRoles`); becomes the part ids
|
|
700
|
+
* `partIdsOfRole` lists. */
|
|
700
701
|
role: string;
|
|
701
702
|
fileName: string;
|
|
702
703
|
canvasW: number;
|
|
@@ -712,12 +713,14 @@ interface LayerInput {
|
|
|
712
713
|
cropH: number;
|
|
713
714
|
/** Face only: half the opaque span of each crop row, canvas px (0 = none). */
|
|
714
715
|
rowHalfWidths?: number[];
|
|
715
|
-
/** `face` / `hair_front` / `hair_back`
|
|
716
|
-
* runs as a flat list of canvas
|
|
717
|
-
* each end exclusive (`[]` for a
|
|
718
|
-
* gap in the hair is a gap here:
|
|
719
|
-
*
|
|
720
|
-
* face's so it never bares skin.
|
|
716
|
+
/** `face` / `hair_front` / `hair_back` / `body` / `arm_L` / `arm_R` only:
|
|
717
|
+
* per crop row, its opaque (alpha ≥ 128) runs as a flat list of canvas
|
|
718
|
+
* columns `[start0, end0, start1, end1, …]`, each end exclusive (`[]` for a
|
|
719
|
+
* row with none). The actual pixels, so a gap in the hair is a gap here:
|
|
720
|
+
* the turn and the nod read off it where back hair is painted behind the
|
|
721
|
+
* front hair, and the crown's turn reads the face's so it never bares skin.
|
|
722
|
+
* The body's place the hips (where it splits into legs), and an arm's place
|
|
723
|
+
* its shoulder and elbow pivots. */
|
|
721
724
|
rowRuns?: number[][];
|
|
722
725
|
/** Nose only: the tight box of its alpha ≥ 128 pixels, canvas px. */
|
|
723
726
|
denseCore?: {
|
|
@@ -763,6 +766,14 @@ interface TurnTargets {
|
|
|
763
766
|
declare class TurnTargetError extends Error {
|
|
764
767
|
constructor(message: string);
|
|
765
768
|
}
|
|
769
|
+
/**
|
|
770
|
+
* Art geometry the rig cannot build on — today a body whose hips leave no row
|
|
771
|
+
* line under its pivots, or too little room for its motion (`body.ts`). A fact about the layers, not a bug, so a
|
|
772
|
+
* host reports it as an input error.
|
|
773
|
+
*/
|
|
774
|
+
declare class LayerGeometryError extends Error {
|
|
775
|
+
constructor(message: string);
|
|
776
|
+
}
|
|
766
777
|
/**
|
|
767
778
|
* The profile's own turn (`profile.ts`), in the cues' units — what a rig with
|
|
768
779
|
* no `turnTargets` renders on a head whose silhouette at the eye row is back
|
|
@@ -845,8 +856,75 @@ interface GenerateOptions {
|
|
|
845
856
|
}
|
|
846
857
|
|
|
847
858
|
/**
|
|
848
|
-
*
|
|
849
|
-
*
|
|
859
|
+
* The arms. Each `arm_L` / `arm_R` layer is one drawing of the whole arm,
|
|
860
|
+
* hanging, its shoulder at the top. It becomes two parts on two nested matrix
|
|
861
|
+
* deformers hung from the body warp:
|
|
862
|
+
* - the upper arm (the role's own id) on `armDeformer_X`, which turns about
|
|
863
|
+
* the shoulder, the deltoid cap's centre;
|
|
864
|
+
* - the forearm (`forearm_X`) on `forearmDeformer_X`, a child of the arm's,
|
|
865
|
+
* which turns about the elbow.
|
|
866
|
+
* The shoulder pivot rides an all-weight-1 cell of the body warp (`body.ts`),
|
|
867
|
+
* so the arm breathes and turns with the chest rigidly, never sheared.
|
|
868
|
+
*
|
|
869
|
+
* Both parts are cut from the one crop: they share its box, transform and
|
|
870
|
+
* texture rect, and their meshes meet on the seam, the elbow pivot's row. The
|
|
871
|
+
* upper arm is the band above the seam. The forearm is the band below it plus
|
|
872
|
+
* a half-disc fan above it, centred on the elbow pivot. Iki has no glue
|
|
873
|
+
* between meshes, and two bands hinged at a seam open a wedge as wide as the
|
|
874
|
+
* arm on a bend; the half-disc turns about its own centre, so it rotates into
|
|
875
|
+
* itself and keeps the joint covered at any bend.
|
|
876
|
+
*
|
|
877
|
+
* Draw order: hair_back < body < arm_L, forearm_L, arm_R, forearm_R < face …
|
|
878
|
+
* < hair_front. The forearm draws over the upper arm, so its cap hides the
|
|
879
|
+
* seam.
|
|
880
|
+
*
|
|
881
|
+
* Signs: ParamArmX + raises the arm outward on either side and ParamElbowX +
|
|
882
|
+
* turns the forearm the same way, both in degrees 1:1. A rotation is
|
|
883
|
+
* CCW-positive, so an arm whose shoulder lies right of the body's axis (+x,
|
|
884
|
+
* the character's left) turns CCW for +, and one at −x turns CW.
|
|
885
|
+
*/
|
|
886
|
+
|
|
887
|
+
type Point = {
|
|
888
|
+
x: number;
|
|
889
|
+
y: number;
|
|
890
|
+
};
|
|
891
|
+
interface ArmGeometry {
|
|
892
|
+
/** The shoulder pivot, model space: the deltoid cap's centre. */
|
|
893
|
+
shoulder: Point;
|
|
894
|
+
/** r_u: the upper arm's half-width under the cap, px. */
|
|
895
|
+
shoulderRadius: number;
|
|
896
|
+
/** The elbow pivot, model space. Its y is the seam the two meshes meet on. */
|
|
897
|
+
elbow: Point;
|
|
898
|
+
/** The forearm's half-disc radius, px. */
|
|
899
|
+
capRadius: number;
|
|
900
|
+
/** +1 for a shoulder right of the body's axis (+ turns CCW), −1 left of it
|
|
901
|
+
* (+ turns CW). */
|
|
902
|
+
side: 1 | -1;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* The arm's pivots, read off the widest opaque run of each crop row
|
|
906
|
+
* (`rowRuns`); a row without one, or a layer without runs, reads as the
|
|
907
|
+
* crop:
|
|
908
|
+
* - r_u is half the median width over the `CAP_ROWS` rows;
|
|
909
|
+
* - the shoulder pivot lies r_u under the first painted row's centre, at the
|
|
910
|
+
* run centre of the row it lands in;
|
|
911
|
+
* - the elbow is the centre of the row `ELBOW_AT` of the way from there to
|
|
912
|
+
* the last painted row, at its run centre;
|
|
913
|
+
* - the cap radius is half the elbow's run + 1 px, kept inside the crop.
|
|
914
|
+
* Pivots are on the 0.01 grid, as the written model is. `bodyAxisX` is the
|
|
915
|
+
* body's axis, model x: the shoulder's side of it sets the sign. An arm too
|
|
916
|
+
* short for its width to put the elbow under the shoulder would rig
|
|
917
|
+
* inverted, so it throws `LayerGeometryError`.
|
|
918
|
+
*/
|
|
919
|
+
declare function armGeometry(layer: LayerInput, bodyAxisX: number): ArmGeometry;
|
|
920
|
+
|
|
921
|
+
/** The part ids a `role`'s layer becomes, back to front: every one of them
|
|
922
|
+
* takes its texture from the layer's crop. Throws on an unknown role. */
|
|
923
|
+
declare function partIdsOfRole(role: string): readonly string[];
|
|
924
|
+
/**
|
|
925
|
+
* Map file names to roles. Throws on an unknown role, a role named twice, a
|
|
926
|
+
* required role (`face`, `eye_L`, `eye_R`, `mouth`) missing, or an arm
|
|
927
|
+
* without a body.
|
|
850
928
|
*/
|
|
851
929
|
declare function parseLayerRoles(fileNames: string[]): {
|
|
852
930
|
role: string;
|
|
@@ -856,13 +934,17 @@ declare function parseLayerRoles(fileNames: string[]): {
|
|
|
856
934
|
/**
|
|
857
935
|
* `generateIkiFromLayerSet`: role layers in, a rigged `.iki` out.
|
|
858
936
|
*
|
|
859
|
-
* The rig's shape is a 2D head rig's usual one (`profile.ts`): a
|
|
860
|
-
*
|
|
861
|
-
*
|
|
862
|
-
*
|
|
863
|
-
*
|
|
864
|
-
*
|
|
865
|
-
*
|
|
937
|
+
* The rig's shape is a 2D head rig's usual one (`profile.ts`): a body warp
|
|
938
|
+
* (`body.ts`) that breathes, follows the head's turn and tilt a little and
|
|
939
|
+
* turns on BodyAngleX/Y/Z, its legs planted; a head deformer hung from it
|
|
940
|
+
* that rolls about the chin and breathes; each arm hung from it too, as an
|
|
941
|
+
* upper arm and a forearm turning about the shoulder and the elbow
|
|
942
|
+
* (`arms.ts`); one small warp grid per feature
|
|
943
|
+
* (each eye, each brow, the nose, the mouth), translating and foreshortening
|
|
944
|
+
* it by its own lead over the plate; and the plate, the hair and the blush
|
|
945
|
+
* moved by per-vertex keyforms of their own — the plate as up to four
|
|
946
|
+
* islands of one drawing: a head that slides, a neck that stays on the torso
|
|
947
|
+
* and two ears that lag. Blink, gaze, brows, mouth, breath and
|
|
866
948
|
* hair sway are part warps and bindings under those. The model also declares
|
|
867
949
|
* the default expressions and the Nod, Shake and Tilt motions
|
|
868
950
|
* (`animations.ts`).
|
|
@@ -1004,7 +1086,8 @@ interface LayerSetMeasurer {
|
|
|
1004
1086
|
* it: only the set's opaque union, this layer's per-row opaque extent and
|
|
1005
1087
|
* the `LayerInput` it returns outlive the call, so the host may drop `rgba`
|
|
1006
1088
|
* as soon as it returns. Returns the layer's `LayerInput` — its crop
|
|
1007
|
-
* box, the face's `rowHalfWidths`, the face's
|
|
1089
|
+
* box, the face's `rowHalfWidths`, the face's, hair layers', body's and
|
|
1090
|
+
* arms' `rowRuns`, the nose's
|
|
1008
1091
|
* `denseCore` unless that is a speck of its crop (`isSpeckCore`) — or
|
|
1009
1092
|
* `null` for an empty layer, one with no pixel at or above
|
|
1010
1093
|
* `ALPHA_BBOX_THRESHOLD`, which it records nothing for: the host reports
|
|
@@ -1261,4 +1344,4 @@ declare function createGridMesh(cols: number, rows: number): IkiMesh;
|
|
|
1261
1344
|
*/
|
|
1262
1345
|
declare function createDefaultWarpDeformer(model: IkiModel): IkiWarpDeformer;
|
|
1263
1346
|
|
|
1264
|
-
export { ALPHA_BBOX_THRESHOLD, ALPHA_OPAQUE, ATLAS_PADDING, AddDeformer, AddPart, AddPhysicsRig, type AlphaBbox, type ApplyAtlasInput, type AtlasAssignment, type AtlasLayout, type AtlasPlacement, type AtlasSource, CaptureGridKeyform, DEFAULT_TURN_TARGETS, type DeformerTransformChannel, DeleteDeformer, DeletePart, DeletePhysicsRig, type EditCommand, type EditTransformChannel, EditorDocument, HEAD_BAND, type IrisStrand, type LayerInput, type LayerSetMeasurement, type LayerSetMeasurer, type RgbaLayer, type RigStyle, SPECK_CORE_FRACTION, SetDeformerBindings, SetDeformerParent, SetDeformerPivot, SetDeformerPivotX, SetDeformerPivotY, SetDeformerTransform, SetPartBindings, SetPartColor, SetPartDeformer, SetPartHeight, SetPartMesh, SetPartOrder, SetPartTransform, SetPartWidth, SetPhysicsRig, type StrandOverlap, type TurnDepths, type TurnSolveReport, TurnTargetError, type TurnTargets, UV_INSET_PX, captureBindingEndpoint, computeGridOffsets, createDefaultMatrixDeformer, createDefaultPart, createDefaultWarpDeformer, createGridMesh, createLayerSetMeasurer, denseCoreOf, detectAlphaBbox, foregroundSpan, generateIkiFromLayerSet, headHalfOf, interpolateGridOffsets, isSpeckCore, packAtlas, parseLayerRoles, upsertGridKeyform, uvRectFor, validateDeformerDelete, validateDeformerReparent, validatePartAttach };
|
|
1347
|
+
export { ALPHA_BBOX_THRESHOLD, ALPHA_OPAQUE, ATLAS_PADDING, AddDeformer, AddPart, AddPhysicsRig, type AlphaBbox, type ApplyAtlasInput, type ArmGeometry, type AtlasAssignment, type AtlasLayout, type AtlasPlacement, type AtlasSource, CaptureGridKeyform, DEFAULT_TURN_TARGETS, type DeformerTransformChannel, DeleteDeformer, DeletePart, DeletePhysicsRig, type EditCommand, type EditTransformChannel, EditorDocument, HEAD_BAND, type IrisStrand, LayerGeometryError, type LayerInput, type LayerSetMeasurement, type LayerSetMeasurer, type RgbaLayer, type RigStyle, SPECK_CORE_FRACTION, SetDeformerBindings, SetDeformerParent, SetDeformerPivot, SetDeformerPivotX, SetDeformerPivotY, SetDeformerTransform, SetPartBindings, SetPartColor, SetPartDeformer, SetPartHeight, SetPartMesh, SetPartOrder, SetPartTransform, SetPartWidth, SetPhysicsRig, type StrandOverlap, type TurnDepths, type TurnSolveReport, TurnTargetError, type TurnTargets, UV_INSET_PX, armGeometry, captureBindingEndpoint, computeGridOffsets, createDefaultMatrixDeformer, createDefaultPart, createDefaultWarpDeformer, createGridMesh, createLayerSetMeasurer, denseCoreOf, detectAlphaBbox, foregroundSpan, generateIkiFromLayerSet, headHalfOf, interpolateGridOffsets, isSpeckCore, packAtlas, parseLayerRoles, partIdsOfRole, upsertGridKeyform, uvRectFor, validateDeformerDelete, validateDeformerReparent, validatePartAttach };
|
package/dist/index.d.ts
CHANGED
|
@@ -696,7 +696,8 @@ interface RigStyle {
|
|
|
696
696
|
|
|
697
697
|
/** One role layer, as a host measured it off its decoded pixels. */
|
|
698
698
|
interface LayerInput {
|
|
699
|
-
/** Canonical role (see `parseLayerRoles`); becomes the part
|
|
699
|
+
/** Canonical role (see `parseLayerRoles`); becomes the part ids
|
|
700
|
+
* `partIdsOfRole` lists. */
|
|
700
701
|
role: string;
|
|
701
702
|
fileName: string;
|
|
702
703
|
canvasW: number;
|
|
@@ -712,12 +713,14 @@ interface LayerInput {
|
|
|
712
713
|
cropH: number;
|
|
713
714
|
/** Face only: half the opaque span of each crop row, canvas px (0 = none). */
|
|
714
715
|
rowHalfWidths?: number[];
|
|
715
|
-
/** `face` / `hair_front` / `hair_back`
|
|
716
|
-
* runs as a flat list of canvas
|
|
717
|
-
* each end exclusive (`[]` for a
|
|
718
|
-
* gap in the hair is a gap here:
|
|
719
|
-
*
|
|
720
|
-
* face's so it never bares skin.
|
|
716
|
+
/** `face` / `hair_front` / `hair_back` / `body` / `arm_L` / `arm_R` only:
|
|
717
|
+
* per crop row, its opaque (alpha ≥ 128) runs as a flat list of canvas
|
|
718
|
+
* columns `[start0, end0, start1, end1, …]`, each end exclusive (`[]` for a
|
|
719
|
+
* row with none). The actual pixels, so a gap in the hair is a gap here:
|
|
720
|
+
* the turn and the nod read off it where back hair is painted behind the
|
|
721
|
+
* front hair, and the crown's turn reads the face's so it never bares skin.
|
|
722
|
+
* The body's place the hips (where it splits into legs), and an arm's place
|
|
723
|
+
* its shoulder and elbow pivots. */
|
|
721
724
|
rowRuns?: number[][];
|
|
722
725
|
/** Nose only: the tight box of its alpha ≥ 128 pixels, canvas px. */
|
|
723
726
|
denseCore?: {
|
|
@@ -763,6 +766,14 @@ interface TurnTargets {
|
|
|
763
766
|
declare class TurnTargetError extends Error {
|
|
764
767
|
constructor(message: string);
|
|
765
768
|
}
|
|
769
|
+
/**
|
|
770
|
+
* Art geometry the rig cannot build on — today a body whose hips leave no row
|
|
771
|
+
* line under its pivots, or too little room for its motion (`body.ts`). A fact about the layers, not a bug, so a
|
|
772
|
+
* host reports it as an input error.
|
|
773
|
+
*/
|
|
774
|
+
declare class LayerGeometryError extends Error {
|
|
775
|
+
constructor(message: string);
|
|
776
|
+
}
|
|
766
777
|
/**
|
|
767
778
|
* The profile's own turn (`profile.ts`), in the cues' units — what a rig with
|
|
768
779
|
* no `turnTargets` renders on a head whose silhouette at the eye row is back
|
|
@@ -845,8 +856,75 @@ interface GenerateOptions {
|
|
|
845
856
|
}
|
|
846
857
|
|
|
847
858
|
/**
|
|
848
|
-
*
|
|
849
|
-
*
|
|
859
|
+
* The arms. Each `arm_L` / `arm_R` layer is one drawing of the whole arm,
|
|
860
|
+
* hanging, its shoulder at the top. It becomes two parts on two nested matrix
|
|
861
|
+
* deformers hung from the body warp:
|
|
862
|
+
* - the upper arm (the role's own id) on `armDeformer_X`, which turns about
|
|
863
|
+
* the shoulder, the deltoid cap's centre;
|
|
864
|
+
* - the forearm (`forearm_X`) on `forearmDeformer_X`, a child of the arm's,
|
|
865
|
+
* which turns about the elbow.
|
|
866
|
+
* The shoulder pivot rides an all-weight-1 cell of the body warp (`body.ts`),
|
|
867
|
+
* so the arm breathes and turns with the chest rigidly, never sheared.
|
|
868
|
+
*
|
|
869
|
+
* Both parts are cut from the one crop: they share its box, transform and
|
|
870
|
+
* texture rect, and their meshes meet on the seam, the elbow pivot's row. The
|
|
871
|
+
* upper arm is the band above the seam. The forearm is the band below it plus
|
|
872
|
+
* a half-disc fan above it, centred on the elbow pivot. Iki has no glue
|
|
873
|
+
* between meshes, and two bands hinged at a seam open a wedge as wide as the
|
|
874
|
+
* arm on a bend; the half-disc turns about its own centre, so it rotates into
|
|
875
|
+
* itself and keeps the joint covered at any bend.
|
|
876
|
+
*
|
|
877
|
+
* Draw order: hair_back < body < arm_L, forearm_L, arm_R, forearm_R < face …
|
|
878
|
+
* < hair_front. The forearm draws over the upper arm, so its cap hides the
|
|
879
|
+
* seam.
|
|
880
|
+
*
|
|
881
|
+
* Signs: ParamArmX + raises the arm outward on either side and ParamElbowX +
|
|
882
|
+
* turns the forearm the same way, both in degrees 1:1. A rotation is
|
|
883
|
+
* CCW-positive, so an arm whose shoulder lies right of the body's axis (+x,
|
|
884
|
+
* the character's left) turns CCW for +, and one at −x turns CW.
|
|
885
|
+
*/
|
|
886
|
+
|
|
887
|
+
type Point = {
|
|
888
|
+
x: number;
|
|
889
|
+
y: number;
|
|
890
|
+
};
|
|
891
|
+
interface ArmGeometry {
|
|
892
|
+
/** The shoulder pivot, model space: the deltoid cap's centre. */
|
|
893
|
+
shoulder: Point;
|
|
894
|
+
/** r_u: the upper arm's half-width under the cap, px. */
|
|
895
|
+
shoulderRadius: number;
|
|
896
|
+
/** The elbow pivot, model space. Its y is the seam the two meshes meet on. */
|
|
897
|
+
elbow: Point;
|
|
898
|
+
/** The forearm's half-disc radius, px. */
|
|
899
|
+
capRadius: number;
|
|
900
|
+
/** +1 for a shoulder right of the body's axis (+ turns CCW), −1 left of it
|
|
901
|
+
* (+ turns CW). */
|
|
902
|
+
side: 1 | -1;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* The arm's pivots, read off the widest opaque run of each crop row
|
|
906
|
+
* (`rowRuns`); a row without one, or a layer without runs, reads as the
|
|
907
|
+
* crop:
|
|
908
|
+
* - r_u is half the median width over the `CAP_ROWS` rows;
|
|
909
|
+
* - the shoulder pivot lies r_u under the first painted row's centre, at the
|
|
910
|
+
* run centre of the row it lands in;
|
|
911
|
+
* - the elbow is the centre of the row `ELBOW_AT` of the way from there to
|
|
912
|
+
* the last painted row, at its run centre;
|
|
913
|
+
* - the cap radius is half the elbow's run + 1 px, kept inside the crop.
|
|
914
|
+
* Pivots are on the 0.01 grid, as the written model is. `bodyAxisX` is the
|
|
915
|
+
* body's axis, model x: the shoulder's side of it sets the sign. An arm too
|
|
916
|
+
* short for its width to put the elbow under the shoulder would rig
|
|
917
|
+
* inverted, so it throws `LayerGeometryError`.
|
|
918
|
+
*/
|
|
919
|
+
declare function armGeometry(layer: LayerInput, bodyAxisX: number): ArmGeometry;
|
|
920
|
+
|
|
921
|
+
/** The part ids a `role`'s layer becomes, back to front: every one of them
|
|
922
|
+
* takes its texture from the layer's crop. Throws on an unknown role. */
|
|
923
|
+
declare function partIdsOfRole(role: string): readonly string[];
|
|
924
|
+
/**
|
|
925
|
+
* Map file names to roles. Throws on an unknown role, a role named twice, a
|
|
926
|
+
* required role (`face`, `eye_L`, `eye_R`, `mouth`) missing, or an arm
|
|
927
|
+
* without a body.
|
|
850
928
|
*/
|
|
851
929
|
declare function parseLayerRoles(fileNames: string[]): {
|
|
852
930
|
role: string;
|
|
@@ -856,13 +934,17 @@ declare function parseLayerRoles(fileNames: string[]): {
|
|
|
856
934
|
/**
|
|
857
935
|
* `generateIkiFromLayerSet`: role layers in, a rigged `.iki` out.
|
|
858
936
|
*
|
|
859
|
-
* The rig's shape is a 2D head rig's usual one (`profile.ts`): a
|
|
860
|
-
*
|
|
861
|
-
*
|
|
862
|
-
*
|
|
863
|
-
*
|
|
864
|
-
*
|
|
865
|
-
*
|
|
937
|
+
* The rig's shape is a 2D head rig's usual one (`profile.ts`): a body warp
|
|
938
|
+
* (`body.ts`) that breathes, follows the head's turn and tilt a little and
|
|
939
|
+
* turns on BodyAngleX/Y/Z, its legs planted; a head deformer hung from it
|
|
940
|
+
* that rolls about the chin and breathes; each arm hung from it too, as an
|
|
941
|
+
* upper arm and a forearm turning about the shoulder and the elbow
|
|
942
|
+
* (`arms.ts`); one small warp grid per feature
|
|
943
|
+
* (each eye, each brow, the nose, the mouth), translating and foreshortening
|
|
944
|
+
* it by its own lead over the plate; and the plate, the hair and the blush
|
|
945
|
+
* moved by per-vertex keyforms of their own — the plate as up to four
|
|
946
|
+
* islands of one drawing: a head that slides, a neck that stays on the torso
|
|
947
|
+
* and two ears that lag. Blink, gaze, brows, mouth, breath and
|
|
866
948
|
* hair sway are part warps and bindings under those. The model also declares
|
|
867
949
|
* the default expressions and the Nod, Shake and Tilt motions
|
|
868
950
|
* (`animations.ts`).
|
|
@@ -1004,7 +1086,8 @@ interface LayerSetMeasurer {
|
|
|
1004
1086
|
* it: only the set's opaque union, this layer's per-row opaque extent and
|
|
1005
1087
|
* the `LayerInput` it returns outlive the call, so the host may drop `rgba`
|
|
1006
1088
|
* as soon as it returns. Returns the layer's `LayerInput` — its crop
|
|
1007
|
-
* box, the face's `rowHalfWidths`, the face's
|
|
1089
|
+
* box, the face's `rowHalfWidths`, the face's, hair layers', body's and
|
|
1090
|
+
* arms' `rowRuns`, the nose's
|
|
1008
1091
|
* `denseCore` unless that is a speck of its crop (`isSpeckCore`) — or
|
|
1009
1092
|
* `null` for an empty layer, one with no pixel at or above
|
|
1010
1093
|
* `ALPHA_BBOX_THRESHOLD`, which it records nothing for: the host reports
|
|
@@ -1261,4 +1344,4 @@ declare function createGridMesh(cols: number, rows: number): IkiMesh;
|
|
|
1261
1344
|
*/
|
|
1262
1345
|
declare function createDefaultWarpDeformer(model: IkiModel): IkiWarpDeformer;
|
|
1263
1346
|
|
|
1264
|
-
export { ALPHA_BBOX_THRESHOLD, ALPHA_OPAQUE, ATLAS_PADDING, AddDeformer, AddPart, AddPhysicsRig, type AlphaBbox, type ApplyAtlasInput, type AtlasAssignment, type AtlasLayout, type AtlasPlacement, type AtlasSource, CaptureGridKeyform, DEFAULT_TURN_TARGETS, type DeformerTransformChannel, DeleteDeformer, DeletePart, DeletePhysicsRig, type EditCommand, type EditTransformChannel, EditorDocument, HEAD_BAND, type IrisStrand, type LayerInput, type LayerSetMeasurement, type LayerSetMeasurer, type RgbaLayer, type RigStyle, SPECK_CORE_FRACTION, SetDeformerBindings, SetDeformerParent, SetDeformerPivot, SetDeformerPivotX, SetDeformerPivotY, SetDeformerTransform, SetPartBindings, SetPartColor, SetPartDeformer, SetPartHeight, SetPartMesh, SetPartOrder, SetPartTransform, SetPartWidth, SetPhysicsRig, type StrandOverlap, type TurnDepths, type TurnSolveReport, TurnTargetError, type TurnTargets, UV_INSET_PX, captureBindingEndpoint, computeGridOffsets, createDefaultMatrixDeformer, createDefaultPart, createDefaultWarpDeformer, createGridMesh, createLayerSetMeasurer, denseCoreOf, detectAlphaBbox, foregroundSpan, generateIkiFromLayerSet, headHalfOf, interpolateGridOffsets, isSpeckCore, packAtlas, parseLayerRoles, upsertGridKeyform, uvRectFor, validateDeformerDelete, validateDeformerReparent, validatePartAttach };
|
|
1347
|
+
export { ALPHA_BBOX_THRESHOLD, ALPHA_OPAQUE, ATLAS_PADDING, AddDeformer, AddPart, AddPhysicsRig, type AlphaBbox, type ApplyAtlasInput, type ArmGeometry, type AtlasAssignment, type AtlasLayout, type AtlasPlacement, type AtlasSource, CaptureGridKeyform, DEFAULT_TURN_TARGETS, type DeformerTransformChannel, DeleteDeformer, DeletePart, DeletePhysicsRig, type EditCommand, type EditTransformChannel, EditorDocument, HEAD_BAND, type IrisStrand, LayerGeometryError, type LayerInput, type LayerSetMeasurement, type LayerSetMeasurer, type RgbaLayer, type RigStyle, SPECK_CORE_FRACTION, SetDeformerBindings, SetDeformerParent, SetDeformerPivot, SetDeformerPivotX, SetDeformerPivotY, SetDeformerTransform, SetPartBindings, SetPartColor, SetPartDeformer, SetPartHeight, SetPartMesh, SetPartOrder, SetPartTransform, SetPartWidth, SetPhysicsRig, type StrandOverlap, type TurnDepths, type TurnSolveReport, TurnTargetError, type TurnTargets, UV_INSET_PX, armGeometry, captureBindingEndpoint, computeGridOffsets, createDefaultMatrixDeformer, createDefaultPart, createDefaultWarpDeformer, createGridMesh, createLayerSetMeasurer, denseCoreOf, detectAlphaBbox, foregroundSpan, generateIkiFromLayerSet, headHalfOf, interpolateGridOffsets, isSpeckCore, packAtlas, parseLayerRoles, partIdsOfRole, upsertGridKeyform, uvRectFor, validateDeformerDelete, validateDeformerReparent, validatePartAttach };
|