@ikijs/editor 0.19.0 → 0.20.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 CHANGED
@@ -40,19 +40,19 @@ 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`, `partIdsOfRole`, `createLayerSetMeasurer`, `armGeometry`, `ArmGeometry`, `TurnTargets`, `DEFAULT_TURN_TARGETS`, `TurnSolveReport`, `RigStyle`, `LayerGeometryError` |
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`, `forearmPoseGeometry`, `ForearmPoseGeometry`, `TurnTargets`, `DEFAULT_TURN_TARGETS`, `TurnSolveReport`, `RigStyle`, `LayerGeometryError` |
55
+ | Bindings | `captureBindingEndpoint` |
56
56
 
57
57
  ## Auto-rig
58
58
 
@@ -85,6 +85,10 @@ hangs from it. `arm_L` / `arm_R`, each a whole arm drawn hanging with its
85
85
  shoulder at the top, hang from it too: each becomes an elbow cap, an upper
86
86
  arm and a forearm cut from the one crop, turning about the shoulder and the
87
87
  elbow on `ParamArmL/R` and `ParamElbowL/R`. An arm needs a `body`.
88
+ `forearm_pose_L` / `forearm_pose_R`, a second forearm drawn raised, swap in for
89
+ the hanging one at the elbow on `ParamArmPoseL/R` and rock on
90
+ `ParamArmPoseAngleL/R`; a model with them also declares a `Wave` motion. A
91
+ pose forearm needs its arm.
88
92
 
89
93
  On a layer set with a `nose`, `options.turnTargets` — the cues a 30° reference
90
94
  measures (how far the eye pair slides, how much the far eye foreshortens,
package/dist/index.d.mts CHANGED
@@ -713,14 +713,15 @@ interface LayerInput {
713
713
  cropH: number;
714
714
  /** Face only: half the opaque span of each crop row, canvas px (0 = none). */
715
715
  rowHalfWidths?: number[];
716
- /** `face` / `hair_front` / `hair_back` / `body` / `arm_L` / `arm_R` only:
716
+ /** `face` / `hair_front` / `hair_back` / `body` / `arm_L` / `arm_R` /
717
+ * `forearm_pose_L` / `forearm_pose_R` only:
717
718
  * per crop row, its opaque (alpha ≥ 128) runs as a flat list of canvas
718
719
  * columns `[start0, end0, start1, end1, …]`, each end exclusive (`[]` for a
719
720
  * row with none). The actual pixels, so a gap in the hair is a gap here:
720
721
  * the turn and the nod read off it where back hair is painted behind the
721
722
  * front hair, and the crown's turn reads the face's so it never bares skin.
722
723
  * The body's place the hips (where it splits into legs), and an arm's place
723
- * its shoulder and elbow pivots. */
724
+ * its shoulder and elbow pivots, a pose forearm's its elbow-end pivot. */
724
725
  rowRuns?: number[][];
725
726
  /** Nose only: the tight box of its alpha ≥ 128 pixels, canvas px. */
726
727
  denseCore?: {
@@ -923,9 +924,9 @@ interface ArmGeometry {
923
924
  * The arm's pivots, read off the widest opaque run of each crop row
924
925
  * (`rowRuns`); a row without one, or a layer without runs, reads as the
925
926
  * crop:
926
- * - r_u is half the median width over the `CAP_ROWS` rows;
927
- * - the shoulder pivot lies r_u under the first painted row's centre, at the
928
- * run centre of the row it lands in;
927
+ * - the shoulder pivot and r_u are `endPivot(layer, "top")`: r_u is half the
928
+ * median width over the `CAP_ROWS` rows, the pivot lies r_u under the first
929
+ * painted row's centre, at the run centre of the row it lands in;
929
930
  * - the elbow is the centre of the row `ELBOW_AT` of the way from there to
930
931
  * the last painted row, at its run centre;
931
932
  * - the cap radius is half the elbow's run + 1 px, kept inside the crop;
@@ -941,13 +942,59 @@ interface ArmGeometry {
941
942
  */
942
943
  declare function armGeometry(layer: LayerInput, bodyAxisX: number): ArmGeometry;
943
944
 
945
+ /**
946
+ * The pose forearm. A second drawn forearm per side (`forearm_pose_L` /
947
+ * `forearm_pose_R`), drawn raised: it hangs from the arm's elbow and is
948
+ * swapped in for the hanging forearm by a switch.
949
+ * - One part, the role's own id, over its crop's box on `armPoseDeformer_X`,
950
+ * a child of `armDeformer_X` pivoting at the arm's elbow. It is not a child
951
+ * of `forearmDeformer_X`, so `ParamElbowX` never moves it, and the shoulder
952
+ * still carries it.
953
+ * - `ParamArmPoseX` (0..1) swaps: the hanging forearm and the elbow cap fade
954
+ * out on it, 1 to 0 (`armParts`), the pose forearm fades in, 0 to 1. The
955
+ * pair is exclusive by construction, and between the ends both show at
956
+ * partial opacity. The part has no mesh: the engine draws a meshless part
957
+ * as its full-box quad with its texture rect, and a rigid part needs no
958
+ * more.
959
+ * - `ParamArmPoseAngleX` rocks it about the elbow, in degrees over
960
+ * `POSE_ANGLE_RANGE`. + tips the raised hand outward, away from the body,
961
+ * mirrored per side. The part points up from its pivot where the hanging
962
+ * forearm points down, so its rotate binding takes −side × the value; the
963
+ * elbow's multiplier is the same −side, which gives the shoulder's reading.
964
+ * The composer puts the drawing's elbow end on the pivot (`measure` warns
965
+ * when it is off), so the rig does not use the crop's own pivot
966
+ * (`forearmPoseGeometry`).
967
+ *
968
+ * It draws after the hair, above the face and the front hair: a raised hand
969
+ * passes them (`ROLE_TABLE`).
970
+ */
971
+
972
+ interface ForearmPoseGeometry {
973
+ /** The elbow end's pivot, model space: where the drawing's elbow end is
974
+ * centred. */
975
+ pivot: {
976
+ x: number;
977
+ y: number;
978
+ };
979
+ /** r_e: half the elbow end's width, px. */
980
+ radius: number;
981
+ /** The first painted row's model y: the raised hand's top. */
982
+ top: number;
983
+ }
984
+ /**
985
+ * The pose forearm's own geometry: the shoulder rule run from the bottom
986
+ * (`endPivot`), since it is drawn standing up from its elbow, plus the top of
987
+ * the paint.
988
+ */
989
+ declare function forearmPoseGeometry(layer: LayerInput): ForearmPoseGeometry;
990
+
944
991
  /** The part ids a `role`'s layer becomes, back to front: every one of them
945
992
  * takes its texture from the layer's crop. Throws on an unknown role. */
946
993
  declare function partIdsOfRole(role: string): readonly string[];
947
994
  /**
948
995
  * Map file names to roles. Throws on an unknown role, a role named twice, a
949
- * required role (`face`, `eye_L`, `eye_R`, `mouth`) missing, or an arm
950
- * without a body.
996
+ * required role (`face`, `eye_L`, `eye_R`, `mouth`) missing, an arm without a
997
+ * body, or a pose forearm without its arm.
951
998
  */
952
999
  declare function parseLayerRoles(fileNames: string[]): {
953
1000
  role: string;
@@ -962,15 +1009,16 @@ declare function parseLayerRoles(fileNames: string[]): {
962
1009
  * turns on BodyAngleX/Y/Z, its legs planted; a head deformer hung from it
963
1010
  * that rolls about the chin and breathes; each arm hung from it too, as an
964
1011
  * upper arm, a forearm and an elbow cap turning about the shoulder and the
965
- * elbow (`arms.ts`); one small warp grid per feature
1012
+ * elbow (`arms.ts`), and with a drawn pose forearm a switch that swaps it in
1013
+ * for the hanging one (`forearm-pose.ts`); one small warp grid per feature
966
1014
  * (each eye, each brow, the nose, the mouth), translating and foreshortening
967
1015
  * it by its own lead over the plate; and the plate, the hair and the blush
968
1016
  * moved by per-vertex keyforms of their own — the plate as up to four
969
1017
  * islands of one drawing: a head that slides, a neck that stays on the torso
970
1018
  * and two ears that lag. Blink, gaze, brows, mouth, breath and
971
1019
  * hair sway are part warps and bindings under those. The model also declares
972
- * the default expressions and the Nod, Shake and Tilt motions
973
- * (`animations.ts`).
1020
+ * the default expressions and the Nod, Shake and Tilt motions, and
1021
+ * with a pose forearm the Wave (`animations.ts`).
974
1022
  */
975
1023
 
976
1024
  declare function generateIkiFromLayerSet(layers: LayerInput[], canvas: {
@@ -1106,11 +1154,12 @@ interface RgbaLayer {
1106
1154
  interface LayerSetMeasurer {
1107
1155
  /**
1108
1156
  * Measure one layer while its `rgba` is in memory, keeping no reference to
1109
- * it: only the set's opaque union, this layer's per-row opaque extent and
1157
+ * it: only the set's opaque union (a pose forearm, hidden at rest, stays out
1158
+ * of it and of the per-role edges), this layer's per-row opaque extent and
1110
1159
  * the `LayerInput` it returns outlive the call, so the host may drop `rgba`
1111
1160
  * as soon as it returns. Returns the layer's `LayerInput` — its crop
1112
- * box, the face's `rowHalfWidths`, the face's, hair layers', body's and
1113
- * arms' `rowRuns`, the nose's
1161
+ * box, the face's `rowHalfWidths`, the face's, hair layers', body's, arms'
1162
+ * and pose forearms' `rowRuns`, the nose's
1114
1163
  * `denseCore` unless that is a speck of its crop (`isSpeckCore`) — or
1115
1164
  * `null` for an empty layer, one with no pixel at or above
1116
1165
  * `ALPHA_BBOX_THRESHOLD`, which it records nothing for: the host reports
@@ -1367,4 +1416,4 @@ declare function createGridMesh(cols: number, rows: number): IkiMesh;
1367
1416
  */
1368
1417
  declare function createDefaultWarpDeformer(model: IkiModel): IkiWarpDeformer;
1369
1418
 
1370
- 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 };
1419
+ 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, type ForearmPoseGeometry, 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, forearmPoseGeometry, foregroundSpan, generateIkiFromLayerSet, headHalfOf, interpolateGridOffsets, isSpeckCore, packAtlas, parseLayerRoles, partIdsOfRole, upsertGridKeyform, uvRectFor, validateDeformerDelete, validateDeformerReparent, validatePartAttach };
package/dist/index.d.ts CHANGED
@@ -713,14 +713,15 @@ interface LayerInput {
713
713
  cropH: number;
714
714
  /** Face only: half the opaque span of each crop row, canvas px (0 = none). */
715
715
  rowHalfWidths?: number[];
716
- /** `face` / `hair_front` / `hair_back` / `body` / `arm_L` / `arm_R` only:
716
+ /** `face` / `hair_front` / `hair_back` / `body` / `arm_L` / `arm_R` /
717
+ * `forearm_pose_L` / `forearm_pose_R` only:
717
718
  * per crop row, its opaque (alpha ≥ 128) runs as a flat list of canvas
718
719
  * columns `[start0, end0, start1, end1, …]`, each end exclusive (`[]` for a
719
720
  * row with none). The actual pixels, so a gap in the hair is a gap here:
720
721
  * the turn and the nod read off it where back hair is painted behind the
721
722
  * front hair, and the crown's turn reads the face's so it never bares skin.
722
723
  * The body's place the hips (where it splits into legs), and an arm's place
723
- * its shoulder and elbow pivots. */
724
+ * its shoulder and elbow pivots, a pose forearm's its elbow-end pivot. */
724
725
  rowRuns?: number[][];
725
726
  /** Nose only: the tight box of its alpha ≥ 128 pixels, canvas px. */
726
727
  denseCore?: {
@@ -923,9 +924,9 @@ interface ArmGeometry {
923
924
  * The arm's pivots, read off the widest opaque run of each crop row
924
925
  * (`rowRuns`); a row without one, or a layer without runs, reads as the
925
926
  * crop:
926
- * - r_u is half the median width over the `CAP_ROWS` rows;
927
- * - the shoulder pivot lies r_u under the first painted row's centre, at the
928
- * run centre of the row it lands in;
927
+ * - the shoulder pivot and r_u are `endPivot(layer, "top")`: r_u is half the
928
+ * median width over the `CAP_ROWS` rows, the pivot lies r_u under the first
929
+ * painted row's centre, at the run centre of the row it lands in;
929
930
  * - the elbow is the centre of the row `ELBOW_AT` of the way from there to
930
931
  * the last painted row, at its run centre;
931
932
  * - the cap radius is half the elbow's run + 1 px, kept inside the crop;
@@ -941,13 +942,59 @@ interface ArmGeometry {
941
942
  */
942
943
  declare function armGeometry(layer: LayerInput, bodyAxisX: number): ArmGeometry;
943
944
 
945
+ /**
946
+ * The pose forearm. A second drawn forearm per side (`forearm_pose_L` /
947
+ * `forearm_pose_R`), drawn raised: it hangs from the arm's elbow and is
948
+ * swapped in for the hanging forearm by a switch.
949
+ * - One part, the role's own id, over its crop's box on `armPoseDeformer_X`,
950
+ * a child of `armDeformer_X` pivoting at the arm's elbow. It is not a child
951
+ * of `forearmDeformer_X`, so `ParamElbowX` never moves it, and the shoulder
952
+ * still carries it.
953
+ * - `ParamArmPoseX` (0..1) swaps: the hanging forearm and the elbow cap fade
954
+ * out on it, 1 to 0 (`armParts`), the pose forearm fades in, 0 to 1. The
955
+ * pair is exclusive by construction, and between the ends both show at
956
+ * partial opacity. The part has no mesh: the engine draws a meshless part
957
+ * as its full-box quad with its texture rect, and a rigid part needs no
958
+ * more.
959
+ * - `ParamArmPoseAngleX` rocks it about the elbow, in degrees over
960
+ * `POSE_ANGLE_RANGE`. + tips the raised hand outward, away from the body,
961
+ * mirrored per side. The part points up from its pivot where the hanging
962
+ * forearm points down, so its rotate binding takes −side × the value; the
963
+ * elbow's multiplier is the same −side, which gives the shoulder's reading.
964
+ * The composer puts the drawing's elbow end on the pivot (`measure` warns
965
+ * when it is off), so the rig does not use the crop's own pivot
966
+ * (`forearmPoseGeometry`).
967
+ *
968
+ * It draws after the hair, above the face and the front hair: a raised hand
969
+ * passes them (`ROLE_TABLE`).
970
+ */
971
+
972
+ interface ForearmPoseGeometry {
973
+ /** The elbow end's pivot, model space: where the drawing's elbow end is
974
+ * centred. */
975
+ pivot: {
976
+ x: number;
977
+ y: number;
978
+ };
979
+ /** r_e: half the elbow end's width, px. */
980
+ radius: number;
981
+ /** The first painted row's model y: the raised hand's top. */
982
+ top: number;
983
+ }
984
+ /**
985
+ * The pose forearm's own geometry: the shoulder rule run from the bottom
986
+ * (`endPivot`), since it is drawn standing up from its elbow, plus the top of
987
+ * the paint.
988
+ */
989
+ declare function forearmPoseGeometry(layer: LayerInput): ForearmPoseGeometry;
990
+
944
991
  /** The part ids a `role`'s layer becomes, back to front: every one of them
945
992
  * takes its texture from the layer's crop. Throws on an unknown role. */
946
993
  declare function partIdsOfRole(role: string): readonly string[];
947
994
  /**
948
995
  * Map file names to roles. Throws on an unknown role, a role named twice, a
949
- * required role (`face`, `eye_L`, `eye_R`, `mouth`) missing, or an arm
950
- * without a body.
996
+ * required role (`face`, `eye_L`, `eye_R`, `mouth`) missing, an arm without a
997
+ * body, or a pose forearm without its arm.
951
998
  */
952
999
  declare function parseLayerRoles(fileNames: string[]): {
953
1000
  role: string;
@@ -962,15 +1009,16 @@ declare function parseLayerRoles(fileNames: string[]): {
962
1009
  * turns on BodyAngleX/Y/Z, its legs planted; a head deformer hung from it
963
1010
  * that rolls about the chin and breathes; each arm hung from it too, as an
964
1011
  * upper arm, a forearm and an elbow cap turning about the shoulder and the
965
- * elbow (`arms.ts`); one small warp grid per feature
1012
+ * elbow (`arms.ts`), and with a drawn pose forearm a switch that swaps it in
1013
+ * for the hanging one (`forearm-pose.ts`); one small warp grid per feature
966
1014
  * (each eye, each brow, the nose, the mouth), translating and foreshortening
967
1015
  * it by its own lead over the plate; and the plate, the hair and the blush
968
1016
  * moved by per-vertex keyforms of their own — the plate as up to four
969
1017
  * islands of one drawing: a head that slides, a neck that stays on the torso
970
1018
  * and two ears that lag. Blink, gaze, brows, mouth, breath and
971
1019
  * hair sway are part warps and bindings under those. The model also declares
972
- * the default expressions and the Nod, Shake and Tilt motions
973
- * (`animations.ts`).
1020
+ * the default expressions and the Nod, Shake and Tilt motions, and
1021
+ * with a pose forearm the Wave (`animations.ts`).
974
1022
  */
975
1023
 
976
1024
  declare function generateIkiFromLayerSet(layers: LayerInput[], canvas: {
@@ -1106,11 +1154,12 @@ interface RgbaLayer {
1106
1154
  interface LayerSetMeasurer {
1107
1155
  /**
1108
1156
  * Measure one layer while its `rgba` is in memory, keeping no reference to
1109
- * it: only the set's opaque union, this layer's per-row opaque extent and
1157
+ * it: only the set's opaque union (a pose forearm, hidden at rest, stays out
1158
+ * of it and of the per-role edges), this layer's per-row opaque extent and
1110
1159
  * the `LayerInput` it returns outlive the call, so the host may drop `rgba`
1111
1160
  * as soon as it returns. Returns the layer's `LayerInput` — its crop
1112
- * box, the face's `rowHalfWidths`, the face's, hair layers', body's and
1113
- * arms' `rowRuns`, the nose's
1161
+ * box, the face's `rowHalfWidths`, the face's, hair layers', body's, arms'
1162
+ * and pose forearms' `rowRuns`, the nose's
1114
1163
  * `denseCore` unless that is a speck of its crop (`isSpeckCore`) — or
1115
1164
  * `null` for an empty layer, one with no pixel at or above
1116
1165
  * `ALPHA_BBOX_THRESHOLD`, which it records nothing for: the host reports
@@ -1367,4 +1416,4 @@ declare function createGridMesh(cols: number, rows: number): IkiMesh;
1367
1416
  */
1368
1417
  declare function createDefaultWarpDeformer(model: IkiModel): IkiWarpDeformer;
1369
1418
 
1370
- 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 };
1419
+ 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, type ForearmPoseGeometry, 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, forearmPoseGeometry, foregroundSpan, generateIkiFromLayerSet, headHalfOf, interpolateGridOffsets, isSpeckCore, packAtlas, parseLayerRoles, partIdsOfRole, upsertGridKeyform, uvRectFor, validateDeformerDelete, validateDeformerReparent, validatePartAttach };