@flighthq/skeleton2d 0.3.0-next.1032.e2b99fc → 0.3.0-next.1162.e90e518
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/dist/applyAnimationClipToSkeleton2D.d.ts.map +1 -1
- package/dist/applyAnimationClipToSkeleton2D.js +43 -2
- package/dist/applyAnimationClipToSkeleton2D.js.map +1 -1
- package/dist/skeleton2d.d.ts +3 -1
- package/dist/skeleton2d.d.ts.map +1 -1
- package/dist/skeleton2d.js +92 -58
- package/dist/skeleton2d.js.map +1 -1
- package/package.json +6 -6
- package/src/applyAnimationClipToSkeleton2D.test.ts +90 -1
- package/src/skeleton2d.test.ts +94 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applyAnimationClipToSkeleton2D.d.ts","sourceRoot":"","sources":["../src/applyAnimationClipToSkeleton2D.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"applyAnimationClipToSkeleton2D.d.ts","sourceRoot":"","sources":["../src/applyAnimationClipToSkeleton2D.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,aAAa,EACb,UAAU,EAGX,MAAM,0BAA0B,CAAC;AA0BlC,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC3B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,GACX,IAAI,CA6CN"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sampleAnimationTrack } from '@flighthq/animation/contract';
|
|
2
|
-
import { Skeleton2DAnimationPath } from '@flighthq/types/contract';
|
|
2
|
+
import { Skeleton2DAnimationPath, Skeleton2DSlotAnimationPath } from '@flighthq/types/contract';
|
|
3
3
|
// Poses `pose` from an AnimationClip at `time` by COMPOSING each channel's sampled value onto the
|
|
4
4
|
// corresponding `setup` bone — the 2D-skeletal analogue of @flighthq/scene3d's `applyAnimationClipToScene3D`,
|
|
5
5
|
// but relative rather than absolute. This mirrors Spine's SkeletonData(setup)/Skeleton(instance) split:
|
|
@@ -9,6 +9,11 @@ import { Skeleton2DAnimationPath } from '@flighthq/types/contract';
|
|
|
9
9
|
// is what makes clips blendable — a mixer accumulates deltas as `pose = setup + Σ wᵢ·deltaᵢ`, which averaging
|
|
10
10
|
// baked-absolute poses cannot express — and is why re-applying a clip does not accumulate across frames.
|
|
11
11
|
//
|
|
12
|
+
// A clip may also carry SLOT channels (a `Skeleton2DSlotAnimationTarget` rather than a bone target). Those
|
|
13
|
+
// are dispatched by target SHAPE and follow different rules: a slot colour is an ABSOLUTE authored value, so
|
|
14
|
+
// it is written rather than composed, and `setup` is not consulted at all on that path. See
|
|
15
|
+
// applySkeleton2DSlotChannel.
|
|
16
|
+
//
|
|
12
17
|
// It writes only the bones a channel targets; untouched pose bones keep their clone-of-setup values. The
|
|
13
18
|
// caller runs `computeSkeleton2DWorldTransforms(pose, …)` (then the deform) afterward, so a whole clip
|
|
14
19
|
// applies before one world propagation. Module scratch, allocation-free. A channel whose target is foreign
|
|
@@ -28,8 +33,15 @@ export function applyAnimationClipToSkeleton2D(clip, setup, pose, time) {
|
|
|
28
33
|
for (let i = 0; i < channels.length; i++) {
|
|
29
34
|
const channel = channels[i];
|
|
30
35
|
const target = channel.targetRef;
|
|
31
|
-
if (target === null || typeof target !== 'object'
|
|
36
|
+
if (target === null || typeof target !== 'object')
|
|
37
|
+
continue;
|
|
38
|
+
// `targetRef` is opaque, so the shape itself says which array a channel addresses: a bone target names
|
|
39
|
+
// a bone index, a slot target names a slot index. Probing (rather than a discriminator field) is what
|
|
40
|
+
// lets slot channels be purely additive to a bone-only clip format.
|
|
41
|
+
if (typeof target.boneIndex !== 'number') {
|
|
42
|
+
applySkeleton2DSlotChannel(channel, pose, target, time);
|
|
32
43
|
continue;
|
|
44
|
+
}
|
|
33
45
|
const boneIndex = target.boneIndex;
|
|
34
46
|
if (boneIndex < 0 || boneIndex >= poseBones.length || boneIndex >= setupBones.length)
|
|
35
47
|
continue;
|
|
@@ -57,5 +69,34 @@ export function applyAnimationClipToSkeleton2D(clip, setup, pose, time) {
|
|
|
57
69
|
}
|
|
58
70
|
}
|
|
59
71
|
}
|
|
72
|
+
// Writes one slot channel's sampled value onto the pose slot. Unlike a bone channel this COMPOSES NOTHING:
|
|
73
|
+
// Spine and DragonBones both author slot colour as an ABSOLUTE value, so the sample replaces the slot's
|
|
74
|
+
// colour rather than tinting the setup colour again. There is therefore no `setup` read on this path.
|
|
75
|
+
//
|
|
76
|
+
// Channels are NORMALIZED 0..1 in R,G,B,A order and scaled to bytes here. The track holds 0..1 rather than
|
|
77
|
+
// 0..255 because that is the space Spine authors colour CURVE control points in — a byte-scaled track would
|
|
78
|
+
// rebase every colour easing against the wrong range. Samples are CLAMPED: a bezier segment may legitimately
|
|
79
|
+
// overshoot its endpoints (anticipation curves do), and an out-of-range channel would otherwise wrap when
|
|
80
|
+
// packed and flip the colour.
|
|
81
|
+
function applySkeleton2DSlotChannel(channel, pose, target, time) {
|
|
82
|
+
const slots = pose.slots;
|
|
83
|
+
if (slots === undefined || slots === null)
|
|
84
|
+
return;
|
|
85
|
+
const slotIndex = target.slotIndex;
|
|
86
|
+
if (typeof slotIndex !== 'number' || slotIndex < 0 || slotIndex >= slots.length)
|
|
87
|
+
return;
|
|
88
|
+
if (target.path !== Skeleton2DSlotAnimationPath.Color)
|
|
89
|
+
return;
|
|
90
|
+
sampleAnimationTrack(_scratch, channel.track, time);
|
|
91
|
+
slots[slotIndex].color =
|
|
92
|
+
((clampColorChannel(_scratch[0]) << 24) |
|
|
93
|
+
(clampColorChannel(_scratch[1]) << 16) |
|
|
94
|
+
(clampColorChannel(_scratch[2]) << 8) |
|
|
95
|
+
clampColorChannel(_scratch[3])) >>>
|
|
96
|
+
0;
|
|
97
|
+
}
|
|
98
|
+
function clampColorChannel(value) {
|
|
99
|
+
return value <= 0 ? 0 : value >= 1 ? 255 : Math.round(value * 255);
|
|
100
|
+
}
|
|
60
101
|
const _scratch = [0, 0, 0, 0];
|
|
61
102
|
//# sourceMappingURL=applyAnimationClipToSkeleton2D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applyAnimationClipToSkeleton2D.js","sourceRoot":"","sources":["../src/applyAnimationClipToSkeleton2D.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"applyAnimationClipToSkeleton2D.js","sourceRoot":"","sources":["../src/applyAnimationClipToSkeleton2D.ts"],"names":[],"mappings":"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"}
|
package/dist/skeleton2d.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Bone2D, MatrixLike, Skeleton2D } from '@flighthq/types/contract';
|
|
1
|
+
import type { AttachmentSkin2D, Bone2D, MatrixLike, Skeleton2D } from '@flighthq/types/contract';
|
|
2
2
|
export declare function cloneSkeleton2D(skeleton: Readonly<Skeleton2D>): Skeleton2D;
|
|
3
3
|
export declare function computeSkeleton2DBoneMatrices(skeleton: Readonly<Skeleton2D>): void;
|
|
4
4
|
export declare function computeSkeleton2DWorldTransforms(skeleton: Readonly<Skeleton2D>): void;
|
|
@@ -7,6 +7,8 @@ export declare function disposeSkeleton2D(skeleton: Skeleton2D): void;
|
|
|
7
7
|
export declare function equalsSkeleton2D(a: Readonly<Skeleton2D>, b: Readonly<Skeleton2D>): boolean;
|
|
8
8
|
export declare function getSkeleton2DBoneIndexByName(skeleton: Readonly<Skeleton2D>, name: string): number;
|
|
9
9
|
export declare function getSkeleton2DBoneWorldMatrix(out: MatrixLike, skeleton: Readonly<Skeleton2D>, boneIndex: number): boolean;
|
|
10
|
+
export declare function getSkeleton2DSkin(skeleton: Readonly<Skeleton2D>, name: string): AttachmentSkin2D | null;
|
|
10
11
|
export declare function setSkeleton2DBindPose(skeleton: Readonly<Skeleton2D>): void;
|
|
12
|
+
export declare function setSkeleton2DSkin(skeleton: Skeleton2D, skin: Readonly<AttachmentSkin2D>): void;
|
|
11
13
|
export declare function validateSkeleton2D(skeleton: Readonly<Skeleton2D>): string | null;
|
|
12
14
|
//# sourceMappingURL=skeleton2d.d.ts.map
|
package/dist/skeleton2d.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skeleton2d.d.ts","sourceRoot":"","sources":["../src/skeleton2d.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"skeleton2d.d.ts","sourceRoot":"","sources":["../src/skeleton2d.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAQjG,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,UAAU,CAS1E;AAMD,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAYlF;AAOD,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAmFrF;AAOD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,GAAE,UAAU,CAAC,OAAO,CAAQ,GAAG,UAAU,CAS/F;AAID,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI,CAG5D;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,OAAO,CAyB1F;AAGD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjG;AAID,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAIT;AAID,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAOvG;AAGD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAU1E;AAeD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAM9F;AAID,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,IAAI,CAiBhF"}
|
package/dist/skeleton2d.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createEntity } from '@flighthq/entity/contract';
|
|
2
2
|
import { inverseMatrix, multiplyMatrix } from '@flighthq/geometry/contract';
|
|
3
3
|
import { DEG_TO_RAD } from '@flighthq/math/contract';
|
|
4
|
-
import { TransformMode2D } from '@flighthq/types/contract';
|
|
5
4
|
// 6 floats per bone in the flat 2×3 affine buffers (a, b, c, d, tx, ty), matching the Matrix field order.
|
|
6
5
|
const MATRIX_STRIDE = 6;
|
|
7
6
|
// Deep-copies the bone array (each Bone2D cloned) and the transform buffers, producing an independently
|
|
@@ -67,62 +66,63 @@ export function computeSkeleton2DWorldTransforms(skeleton) {
|
|
|
67
66
|
const pb = world[p + 1];
|
|
68
67
|
const pc = world[p + 2];
|
|
69
68
|
const pd = world[p + 3];
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
69
|
+
const inherit = bone.transformMode;
|
|
70
|
+
// Position: the parent places the bone's local origin — unless translation inheritance is stripped, in
|
|
71
|
+
// which case the bone's local (x, y) is its world position directly.
|
|
72
|
+
if (inherit.translation) {
|
|
73
|
+
world[o + 4] = pa * bone.x + pc * bone.y + world[p + 4];
|
|
74
|
+
world[o + 5] = pb * bone.x + pd * bone.y + world[p + 5];
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
world[o + 4] = bone.x;
|
|
78
|
+
world[o + 5] = bone.y;
|
|
79
|
+
}
|
|
80
|
+
// Linear part: rotation, scale, and reflection are each inherited or stripped independently. When all
|
|
81
|
+
// three are inherited (Normal — the common case) it is the fast path: the raw parent columns × local,
|
|
82
|
+
// no decomposition. Otherwise the parent is decomposed into per-column scale (lengths) and a direction
|
|
83
|
+
// basis, each axis kept or replaced per its flag, recomposed, then × local. Reproduces the five presets
|
|
84
|
+
// exactly (NoScale keeps the parent's actual y-column, preserving shear; NoScaleOrReflection forces the
|
|
85
|
+
// y-axis to the +90° perpendicular of the x-axis, det +1, dropping shear and reflection).
|
|
86
|
+
let ea;
|
|
87
|
+
let eb;
|
|
88
|
+
let ec;
|
|
89
|
+
let ed;
|
|
90
|
+
if (inherit.rotation && inherit.scale && inherit.reflection) {
|
|
91
|
+
ea = pa;
|
|
92
|
+
eb = pb;
|
|
93
|
+
ec = pc;
|
|
94
|
+
ed = pd;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const psx = Math.hypot(pa, pb) || 1;
|
|
98
|
+
const psy = Math.hypot(pc, pd) || 1;
|
|
99
|
+
const d0x = inherit.rotation ? pa / psx : 1;
|
|
100
|
+
const d0y = inherit.rotation ? pb / psx : 0;
|
|
101
|
+
let d1x;
|
|
102
|
+
let d1y;
|
|
103
|
+
if (inherit.rotation && inherit.reflection) {
|
|
104
|
+
d1x = pc / psy;
|
|
105
|
+
d1y = pd / psy;
|
|
91
106
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// length, then compose with the local transform. NoScale keeps the parent's reflection (its
|
|
96
|
-
// normalized columns as-is); NoScaleOrReflection strips it, forcing the y-axis to the +90°
|
|
97
|
-
// rotation of the x-axis (det = +1) so the child never flips under a negatively-scaled parent.
|
|
98
|
-
const psx = Math.hypot(pa, pb) || 1;
|
|
99
|
-
const nax = pa / psx;
|
|
100
|
-
const nay = pb / psx;
|
|
101
|
-
let ncx;
|
|
102
|
-
let ncy;
|
|
103
|
-
if (bone.transformMode === TransformMode2D.NoScaleOrReflection) {
|
|
104
|
-
ncx = -nay;
|
|
105
|
-
ncy = nax;
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
const psy = Math.hypot(pc, pd) || 1;
|
|
109
|
-
ncx = pc / psy;
|
|
110
|
-
ncy = pd / psy;
|
|
111
|
-
}
|
|
112
|
-
world[o] = nax * la + ncx * lb;
|
|
113
|
-
world[o + 1] = nay * la + ncy * lb;
|
|
114
|
-
world[o + 2] = nax * lc + ncx * ld;
|
|
115
|
-
world[o + 3] = nay * lc + ncy * ld;
|
|
116
|
-
break;
|
|
107
|
+
else if (inherit.rotation) {
|
|
108
|
+
d1x = -d0y;
|
|
109
|
+
d1y = d0x;
|
|
117
110
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
111
|
+
else {
|
|
112
|
+
d1x = 0;
|
|
113
|
+
d1y = inherit.reflection && pa * pd - pb * pc < 0 ? -1 : 1;
|
|
114
|
+
}
|
|
115
|
+
const sx = inherit.scale ? psx : 1;
|
|
116
|
+
const sy = inherit.scale ? psy : 1;
|
|
117
|
+
ea = d0x * sx;
|
|
118
|
+
eb = d0y * sx;
|
|
119
|
+
ec = d1x * sy;
|
|
120
|
+
ed = d1y * sy;
|
|
125
121
|
}
|
|
122
|
+
world[o] = ea * la + ec * lb;
|
|
123
|
+
world[o + 1] = eb * la + ed * lb;
|
|
124
|
+
world[o + 2] = ea * lc + ec * ld;
|
|
125
|
+
world[o + 3] = eb * lc + ed * ld;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
// Allocates a Skeleton2D from a parent-before-child ordered bone array. Sizes the flat world/inverse-bind/
|
|
@@ -163,7 +163,10 @@ export function equalsSkeleton2D(a, b) {
|
|
|
163
163
|
x.shearX !== y.shearX ||
|
|
164
164
|
x.shearY !== y.shearY ||
|
|
165
165
|
x.length !== y.length ||
|
|
166
|
-
x.transformMode !== y.transformMode
|
|
166
|
+
x.transformMode.rotation !== y.transformMode.rotation ||
|
|
167
|
+
x.transformMode.scale !== y.transformMode.scale ||
|
|
168
|
+
x.transformMode.reflection !== y.transformMode.reflection ||
|
|
169
|
+
x.transformMode.translation !== y.transformMode.translation) {
|
|
167
170
|
return false;
|
|
168
171
|
}
|
|
169
172
|
}
|
|
@@ -186,9 +189,18 @@ export function getSkeleton2DBoneWorldMatrix(out, skeleton, boneIndex) {
|
|
|
186
189
|
readMatrix(out, skeleton.worldMatrices, boneIndex * MATRIX_STRIDE);
|
|
187
190
|
return true;
|
|
188
191
|
}
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
+
// The skeleton's named skin, or the `null` sentinel when it carries none by that name. Names are the rig's
|
|
193
|
+
// own (`"goblin"`, `"goblingirl"`); a rig with no wardrobe has no skins at all.
|
|
194
|
+
export function getSkeleton2DSkin(skeleton, name) {
|
|
195
|
+
const skins = skeleton.skins;
|
|
196
|
+
if (skins === undefined || skins === null)
|
|
197
|
+
return null;
|
|
198
|
+
for (const skin of skins) {
|
|
199
|
+
if (skin.name === name)
|
|
200
|
+
return skin;
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
192
204
|
// inverse-bind at identity (`inverseMatrix` returns false) rather than producing NaNs.
|
|
193
205
|
export function setSkeleton2DBindPose(skeleton) {
|
|
194
206
|
const world = skeleton.worldMatrices;
|
|
@@ -202,6 +214,28 @@ export function setSkeleton2DBindPose(skeleton) {
|
|
|
202
214
|
writeMatrix(out, o, _scratchB);
|
|
203
215
|
}
|
|
204
216
|
}
|
|
217
|
+
// Captures the current world transforms as the bind (setup) pose: `inverseBindMatrices[i] =
|
|
218
|
+
// inverse(worldMatrices[i])`. Call after posing the bones to setup and running
|
|
219
|
+
// `computeSkeleton2DWorldTransforms`. A non-invertible (degenerate, zero-scale) bone leaves its
|
|
220
|
+
// Dresses `skeleton` in `skin`: writes each of the skin's attachments onto the slot it names, leaving every
|
|
221
|
+
// other slot untouched. This is the whole runtime cost of the wardrobe — skins are inert until applied, and
|
|
222
|
+
// applying one is a slot-array write, no re-binding and no world propagation (a skin changes what is DRAWN,
|
|
223
|
+
// never where bones are).
|
|
224
|
+
//
|
|
225
|
+
// Slots the skin does not mention keep whatever they were showing. That is deliberate and matches how rigs
|
|
226
|
+
// are authored: a "default" skin carries the shared pieces while `goblin`/`goblingirl` override only the
|
|
227
|
+
// parts that differ, so applying one over the other must not blank the shared art. A caller wanting a clean
|
|
228
|
+
// swap applies the base skin first. An entry naming a slot outside the skeleton is skipped rather than
|
|
229
|
+
// throwing — third-party rigs are untrusted input, and a stale index is a dropped attachment, not a crash.
|
|
230
|
+
export function setSkeleton2DSkin(skeleton, skin) {
|
|
231
|
+
const slots = skeleton.slots;
|
|
232
|
+
if (slots === undefined || slots === null)
|
|
233
|
+
return;
|
|
234
|
+
for (const entry of skin.attachments) {
|
|
235
|
+
if (entry.slotIndex >= 0 && entry.slotIndex < slots.length)
|
|
236
|
+
slots[entry.slotIndex].attachment = entry.attachment;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
205
239
|
// Checks the parent-before-child ordering invariant (each bone's parentIndex is -1 or < its own index) and
|
|
206
240
|
// buffer sizing. Returns null when valid, or a message describing the first violation (sentinel over throw).
|
|
207
241
|
export function validateSkeleton2D(skeleton) {
|
package/dist/skeleton2d.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skeleton2d.js","sourceRoot":"","sources":["../src/skeleton2d.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,0GAA0G;AAC1G,MAAM,aAAa,GAAG,CAAC,CAAC;AAExB,wGAAwG;AACxG,yGAAyG;AACzG,6DAA6D;AAC7D,MAAM,UAAU,eAAe,CAAC,QAA8B;IAC5D,OAAO,YAAY,CAAC;QAClB,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE;QAC3C,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QAClD,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB,CAAC,KAAK,EAAE;QACzD,KAAK,EACH,QAAQ,CAAC,KAAK,KAAK,IAAI,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAClH,aAAa,EAAE,QAAQ,CAAC,aAAa,CAAC,KAAK,EAAE;KAC9C,CAAC,CAAC;AACL,CAAC;AAED,yGAAyG;AACzG,6GAA6G;AAC7G,yGAAyG;AACzG,oCAAoC;AACpC,MAAM,UAAU,6BAA6B,CAAC,QAA8B;IAC1E,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,mBAAmB,CAAC;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,CAAC;IAClC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC;QAC5B,UAAU,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAChC,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAClC,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAChD,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,2GAA2G;AAC3G,2GAA2G;AAC3G,yGAAyG;AACzG,0GAA0G;AAC1G,yGAAyG;AACzG,MAAM,UAAU,gCAAgC,CAAC,QAA8B;IAC7E,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,6FAA6F;QAC7F,qGAAqG;QACrG,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC;QACxD,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC;QAC7D,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACxC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACxC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACxC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC;QAC5B,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;YACd,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAClB,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAClB,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YAClB,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;YACtB,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;YACtB,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,GAAG,aAAa,CAAC;QAC3C,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxB,uEAAuE;QACvE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxD,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxD,QAAQ,IAAI,CAAC,aAAa,EAAE,CAAC;YAC3B,KAAK,eAAe,CAAC,eAAe;gBAClC,+FAA+F;gBAC/F,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;gBACd,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBAClB,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBAClB,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBAClB,MAAM;YACR,KAAK,eAAe,CAAC,sBAAsB,CAAC,CAAC,CAAC;gBAC5C,+FAA+F;gBAC/F,mEAAmE;gBACnE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC/B,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;gBACpB,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;gBACxB,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;gBACxB,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;gBACxB,MAAM;YACR,CAAC;YACD,KAAK,eAAe,CAAC,OAAO,CAAC;YAC7B,KAAK,eAAe,CAAC,mBAAmB,CAAC,CAAC,CAAC;gBACzC,6FAA6F;gBAC7F,4FAA4F;gBAC5F,2FAA2F;gBAC3F,+FAA+F;gBAC/F,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;gBACpC,MAAM,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC;gBACrB,MAAM,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC;gBACrB,IAAI,GAAW,CAAC;gBAChB,IAAI,GAAW,CAAC;gBAChB,IAAI,IAAI,CAAC,aAAa,KAAK,eAAe,CAAC,mBAAmB,EAAE,CAAC;oBAC/D,GAAG,GAAG,CAAC,GAAG,CAAC;oBACX,GAAG,GAAG,GAAG,CAAC;gBACZ,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;oBACpC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC;oBACf,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC;gBACjB,CAAC;gBACD,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;gBAC/B,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;gBACnC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;gBACnC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;gBACnC,MAAM;YACR,CAAC;YACD;gBACE,6DAA6D;gBAC7D,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;gBAC7B,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;gBACjC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;gBACjC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;gBACjC,MAAM;QACV,CAAC;IACH,CAAC;AACH,CAAC;AAED,2GAA2G;AAC3G,+FAA+F;AAC/F,6GAA6G;AAC7G,uGAAuG;AACvG,iFAAiF;AACjF,MAAM,UAAU,gBAAgB,CAAC,KAAe,EAAE,QAA6B,IAAI;IACjF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3B,OAAO,YAAY,CAAC;QAClB,YAAY,EAAE,IAAI,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC;QACrD,KAAK;QACL,mBAAmB,EAAE,IAAI,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC;QAC5D,KAAK;QACL,aAAa,EAAE,IAAI,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC;KACvD,CAAC,CAAC;AACL,CAAC;AAED,yGAAyG;AACzG,6FAA6F;AAC7F,MAAM,UAAU,iBAAiB,CAAC,QAAoB;IACpD,QAAQ,CAAC,KAAK,GAAG,EAAE,CAAC;IACpB,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,CAAuB,EAAE,CAAuB;IAC/E,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,IACE,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,WAAW;YAC/B,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACX,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACX,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;YACzB,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YACrB,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YACrB,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YACrB,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YACrB,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YACrB,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,aAAa,EACnC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,4BAA4B,CAAC,QAA8B,EAAE,IAAY;IACvF,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC;AAED,4GAA4G;AAC5G,8GAA8G;AAC9G,MAAM,UAAU,4BAA4B,CAC1C,GAAe,EACf,QAA8B,EAC9B,SAAiB;IAEjB,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACtE,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,aAAa,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,4FAA4F;AAC5F,+EAA+E;AAC/E,gGAAgG;AAChG,uFAAuF;AACvF,MAAM,UAAU,qBAAqB,CAAC,QAA8B;IAClE,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC;IACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,mBAAmB,CAAC;IACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC;QAC5B,UAAU,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,SAAS,CAAC;YAAE,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAC5E,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,2GAA2G;AAC3G,6GAA6G;AAC7G,MAAM,UAAU,kBAAkB,CAAC,QAA8B;IAC/D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IACpC,MAAM,QAAQ,GAAG,KAAK,GAAG,aAAa,CAAC;IACvC,IAAI,QAAQ,CAAC,aAAa,CAAC,MAAM,KAAK,QAAQ;QAC5C,OAAO,wBAAwB,QAAQ,CAAC,aAAa,CAAC,MAAM,OAAO,QAAQ,EAAE,CAAC;IAChF,IAAI,QAAQ,CAAC,mBAAmB,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACrD,OAAO,8BAA8B,QAAQ,CAAC,mBAAmB,CAAC,MAAM,OAAO,QAAQ,EAAE,CAAC;IAC5F,CAAC;IACD,IAAI,QAAQ,CAAC,YAAY,CAAC,MAAM,KAAK,QAAQ;QAC3C,OAAO,uBAAuB,QAAQ,CAAC,YAAY,CAAC,MAAM,OAAO,QAAQ,EAAE,CAAC;IAC9E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QAClD,IAAI,WAAW,IAAI,CAAC;YAClB,OAAO,QAAQ,CAAC,gBAAgB,WAAW,qEAAqE,CAAC;QACnH,IAAI,WAAW,GAAG,CAAC,CAAC;YAAE,OAAO,QAAQ,CAAC,gBAAgB,WAAW,OAAO,CAAC;IAC3E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,UAAU,CAAC,GAAe,EAAE,MAA8B,EAAE,MAAc;IACjF,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACvB,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3B,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3B,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3B,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,sBAAsB,CAAC,GAAe;IAC7C,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACV,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACV,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACV,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACV,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACX,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,MAAoB,EAAE,MAAc,EAAE,MAA4B;IACrF,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAC1B,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAC9B,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAC9B,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAC9B,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;IAC/B,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,SAAS,GAAe,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;AACvE,MAAM,SAAS,GAAe,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;AACvE,MAAM,SAAS,GAAe,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"skeleton2d.js","sourceRoot":"","sources":["../src/skeleton2d.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/skeleton2d",
|
|
3
|
-
"version": "0.3.0-next.
|
|
3
|
+
"version": "0.3.0-next.1162.e90e518",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/flighthq/flight.git",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@flighthq/animation": "0.3.0-next.
|
|
40
|
-
"@flighthq/entity": "0.3.0-next.
|
|
41
|
-
"@flighthq/geometry": "0.3.0-next.
|
|
42
|
-
"@flighthq/math": "0.3.0-next.
|
|
43
|
-
"@flighthq/types": "0.3.0-next.
|
|
39
|
+
"@flighthq/animation": "0.3.0-next.1162.e90e518",
|
|
40
|
+
"@flighthq/entity": "0.3.0-next.1162.e90e518",
|
|
41
|
+
"@flighthq/geometry": "0.3.0-next.1162.e90e518",
|
|
42
|
+
"@flighthq/math": "0.3.0-next.1162.e90e518",
|
|
43
|
+
"@flighthq/types": "0.3.0-next.1162.e90e518"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"typescript": "^5.3.0"
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { createAnimationChannel, createAnimationClip, createAnimationTrack } from '@flighthq/animation/contract';
|
|
2
2
|
import type { Bone2D } from '@flighthq/types/contract';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
AnimationInterpolationLinear,
|
|
5
|
+
Skeleton2DAnimationPath,
|
|
6
|
+
Skeleton2DSlotAnimationPath,
|
|
7
|
+
TransformMode2D,
|
|
8
|
+
} from '@flighthq/types/contract';
|
|
4
9
|
import { describe, expect, it } from 'vitest';
|
|
5
10
|
|
|
6
11
|
import { applyAnimationClipToSkeleton2D } from './applyAnimationClipToSkeleton2D';
|
|
@@ -95,3 +100,87 @@ describe('applyAnimationClipToSkeleton2D', () => {
|
|
|
95
100
|
expect(pose.bones[0].rotation).toBe(7); // untouched
|
|
96
101
|
});
|
|
97
102
|
});
|
|
103
|
+
|
|
104
|
+
describe('applyAnimationClipToSkeleton2D slot channels', () => {
|
|
105
|
+
it('WRITES an absolute slot colour rather than composing it onto the setup colour', () => {
|
|
106
|
+
// Composing would double-apply the tint; Spine and DragonBones both author colour absolutely.
|
|
107
|
+
const setup = createSkeleton2D([makeBone()], [{ attachment: null, boneIndex: 0, color: 0x112233ff, name: 's' }]);
|
|
108
|
+
const pose = cloneSkeleton2D(setup);
|
|
109
|
+
const clip = createAnimationClip([
|
|
110
|
+
createAnimationChannel(createAnimationTrack({ components: 4, times: [0, 1], values: [1, 0, 0, 1, 0, 0, 1, 1] }), {
|
|
111
|
+
path: Skeleton2DSlotAnimationPath.Color,
|
|
112
|
+
slotIndex: 0,
|
|
113
|
+
}),
|
|
114
|
+
]);
|
|
115
|
+
applyAnimationClipToSkeleton2D(clip, setup, pose, 0);
|
|
116
|
+
expect(pose.slots![0].color).toBe(0xff0000ff);
|
|
117
|
+
applyAnimationClipToSkeleton2D(clip, setup, pose, 1);
|
|
118
|
+
expect(pose.slots![0].color).toBe(0x0000ffff);
|
|
119
|
+
expect(setup.slots![0].color).toBe(0x112233ff); // setup untouched
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('interpolates colour channels between keyframes', () => {
|
|
123
|
+
const setup = createSkeleton2D([makeBone()], [{ attachment: null, boneIndex: 0, color: 0, name: 's' }]);
|
|
124
|
+
const pose = cloneSkeleton2D(setup);
|
|
125
|
+
const clip = createAnimationClip([
|
|
126
|
+
createAnimationChannel(createAnimationTrack({ components: 4, times: [0, 1], values: [0, 0, 0, 0, 1, 1, 1, 1] }), {
|
|
127
|
+
path: Skeleton2DSlotAnimationPath.Color,
|
|
128
|
+
slotIndex: 0,
|
|
129
|
+
}),
|
|
130
|
+
]);
|
|
131
|
+
applyAnimationClipToSkeleton2D(clip, setup, pose, 0.5);
|
|
132
|
+
expect(pose.slots![0].color).toBe(0x80808080); // 0.5 -> 127.5 rounds to 128 on every channel
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('CLAMPS an overshooting sample instead of letting it wrap the packed colour', () => {
|
|
136
|
+
// An easing curve can legitimately overshoot its endpoints; 1.4 must saturate, not wrap to a low byte.
|
|
137
|
+
const setup = createSkeleton2D([makeBone()], [{ attachment: null, boneIndex: 0, color: 0, name: 's' }]);
|
|
138
|
+
const pose = cloneSkeleton2D(setup);
|
|
139
|
+
const clip = createAnimationClip([
|
|
140
|
+
createAnimationChannel(createAnimationTrack({ components: 4, times: [0], values: [1.4, -0.2, 1, 1] }), {
|
|
141
|
+
path: Skeleton2DSlotAnimationPath.Color,
|
|
142
|
+
slotIndex: 0,
|
|
143
|
+
}),
|
|
144
|
+
]);
|
|
145
|
+
applyAnimationClipToSkeleton2D(clip, setup, pose, 0);
|
|
146
|
+
expect(pose.slots![0].color).toBe(0xff00ffff);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('ignores a slot channel whose index is out of range, or a skeleton with no slots', () => {
|
|
150
|
+
const setup = createSkeleton2D([makeBone()], [{ attachment: null, boneIndex: 0, color: 0x010203ff, name: 's' }]);
|
|
151
|
+
const pose = cloneSkeleton2D(setup);
|
|
152
|
+
const clip = createAnimationClip([
|
|
153
|
+
createAnimationChannel(createAnimationTrack({ components: 4, times: [0], values: [1, 1, 1, 1] }), {
|
|
154
|
+
path: Skeleton2DSlotAnimationPath.Color,
|
|
155
|
+
slotIndex: 9,
|
|
156
|
+
}),
|
|
157
|
+
]);
|
|
158
|
+
expect(() => applyAnimationClipToSkeleton2D(clip, setup, pose, 0)).not.toThrow();
|
|
159
|
+
expect(pose.slots![0].color).toBe(0x010203ff);
|
|
160
|
+
|
|
161
|
+
const boneOnly = createSkeleton2D([makeBone()]);
|
|
162
|
+
const bonePose = cloneSkeleton2D(boneOnly);
|
|
163
|
+
expect(() => applyAnimationClipToSkeleton2D(clip, boneOnly, bonePose, 0)).not.toThrow();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('drives bone and slot channels from ONE clip, dispatching on target shape', () => {
|
|
167
|
+
const setup = createSkeleton2D(
|
|
168
|
+
[makeBone({ rotation: 10 })],
|
|
169
|
+
[{ attachment: null, boneIndex: 0, color: 0, name: 's' }],
|
|
170
|
+
);
|
|
171
|
+
const pose = cloneSkeleton2D(setup);
|
|
172
|
+
const clip = createAnimationClip([
|
|
173
|
+
createAnimationChannel(createAnimationTrack({ components: 1, times: [0], values: [90] }), {
|
|
174
|
+
boneIndex: 0,
|
|
175
|
+
path: Skeleton2DAnimationPath.Rotation,
|
|
176
|
+
}),
|
|
177
|
+
createAnimationChannel(createAnimationTrack({ components: 4, times: [0], values: [1, 1, 1, 1] }), {
|
|
178
|
+
path: Skeleton2DSlotAnimationPath.Color,
|
|
179
|
+
slotIndex: 0,
|
|
180
|
+
}),
|
|
181
|
+
]);
|
|
182
|
+
applyAnimationClipToSkeleton2D(clip, setup, pose, 0);
|
|
183
|
+
expect(pose.bones[0].rotation).toBeCloseTo(100, 5); // bone still COMPOSES onto setup
|
|
184
|
+
expect(pose.slots![0].color).toBe(0xffffffff); // slot WRITES
|
|
185
|
+
});
|
|
186
|
+
});
|
package/src/skeleton2d.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createMatrix } from '@flighthq/geometry/contract';
|
|
2
|
-
import type { Bone2D } from '@flighthq/types/contract';
|
|
3
|
-
import { TransformMode2D } from '@flighthq/types/contract';
|
|
2
|
+
import type { Bone2D, RegionAttachment2D, Slot2D } from '@flighthq/types/contract';
|
|
3
|
+
import { RegionAttachment2DKind, TransformMode2D } from '@flighthq/types/contract';
|
|
4
4
|
import { describe, expect, it } from 'vitest';
|
|
5
5
|
|
|
6
6
|
import {
|
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
equalsSkeleton2D,
|
|
13
13
|
getSkeleton2DBoneIndexByName,
|
|
14
14
|
getSkeleton2DBoneWorldMatrix,
|
|
15
|
+
getSkeleton2DSkin,
|
|
15
16
|
setSkeleton2DBindPose,
|
|
17
|
+
setSkeleton2DSkin,
|
|
16
18
|
validateSkeleton2D,
|
|
17
19
|
} from './skeleton2d';
|
|
18
20
|
|
|
@@ -244,6 +246,27 @@ describe('computeSkeleton2DWorldTransforms', () => {
|
|
|
244
246
|
expect(s.worldMatrices[2]).toBeCloseTo(0, 5); // c
|
|
245
247
|
expect(s.worldMatrices[3]).toBeCloseTo(1, 5); // d
|
|
246
248
|
});
|
|
249
|
+
|
|
250
|
+
it('FORMULA parity: an inherit combo with NO named preset — keep rotation+scale, strip reflection', () => {
|
|
251
|
+
// {rotation, scale} true but reflection false has no TransformMode2D preset; the factored boolean model
|
|
252
|
+
// handles it. Under a reflected+scaled parent [2,0,0,-2] (det −4), it keeps the (2,2) scale but strips
|
|
253
|
+
// the reflection, so the child basis is [2,0,0,2] (det +4) rather than Normal's [2,0,0,-2].
|
|
254
|
+
const s = createSkeleton2D([
|
|
255
|
+
makeBone({ scaleX: 2, scaleY: -2 }), // reflected (negative Y scale)
|
|
256
|
+
makeBone({
|
|
257
|
+
parentIndex: 0,
|
|
258
|
+
transformMode: { reflection: false, rotation: true, scale: true, translation: true },
|
|
259
|
+
}),
|
|
260
|
+
]);
|
|
261
|
+
computeSkeleton2DWorldTransforms(s);
|
|
262
|
+
const out = createMatrix();
|
|
263
|
+
getSkeleton2DBoneWorldMatrix(out, s, 1);
|
|
264
|
+
expect(out.a).toBeCloseTo(2, 5);
|
|
265
|
+
expect(out.b).toBeCloseTo(0, 5);
|
|
266
|
+
expect(out.c).toBeCloseTo(0, 5);
|
|
267
|
+
expect(out.d).toBeCloseTo(2, 5); // reflection stripped: +2, not −2
|
|
268
|
+
expect(out.a * out.d - out.c * out.b).toBeCloseTo(4, 5); // det positive (scale kept, reflection dropped)
|
|
269
|
+
});
|
|
247
270
|
});
|
|
248
271
|
|
|
249
272
|
describe('createSkeleton2D', () => {
|
|
@@ -295,6 +318,23 @@ describe('getSkeleton2DBoneWorldMatrix', () => {
|
|
|
295
318
|
});
|
|
296
319
|
});
|
|
297
320
|
|
|
321
|
+
describe('getSkeleton2DSkin', () => {
|
|
322
|
+
it('finds a skin by name and returns the null sentinel otherwise', () => {
|
|
323
|
+
const skeleton = createSkeleton2D([makeBone({ name: 'root' })], [testSlot('head', 0)]);
|
|
324
|
+
skeleton.skins = [
|
|
325
|
+
{ attachments: [], name: 'goblin' },
|
|
326
|
+
{ attachments: [], name: 'goblingirl' },
|
|
327
|
+
];
|
|
328
|
+
expect(getSkeleton2DSkin(skeleton, 'goblingirl')!.name).toBe('goblingirl');
|
|
329
|
+
expect(getSkeleton2DSkin(skeleton, 'nope')).toBeNull();
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('returns null for a rig carrying no wardrobe at all', () => {
|
|
333
|
+
const skeleton = createSkeleton2D([makeBone({ name: 'root' })]);
|
|
334
|
+
expect(getSkeleton2DSkin(skeleton, 'goblin')).toBeNull();
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
|
|
298
338
|
describe('setSkeleton2DBindPose', () => {
|
|
299
339
|
it('captures the inverse of the current world so the palette is identity at bind', () => {
|
|
300
340
|
const s = createSkeleton2D([makeBone({ x: 4, rotation: 60, scaleX: 2 })]);
|
|
@@ -308,6 +348,49 @@ describe('setSkeleton2DBindPose', () => {
|
|
|
308
348
|
});
|
|
309
349
|
});
|
|
310
350
|
|
|
351
|
+
describe('setSkeleton2DSkin', () => {
|
|
352
|
+
it('writes the skin attachments onto the slots they name', () => {
|
|
353
|
+
const skeleton = createSkeleton2D([makeBone({ name: 'root' })], [testSlot('head', 0), testSlot('hand', 0)]);
|
|
354
|
+
const hat = testRegion('hat');
|
|
355
|
+
setSkeleton2DSkin(skeleton, { attachments: [{ attachment: hat, name: 'head', slotIndex: 0 }], name: 'goblin' });
|
|
356
|
+
expect(skeleton.slots![0].attachment).toBe(hat);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('LEAVES slots the skin does not mention alone, so a partial skin layers over a base', () => {
|
|
360
|
+
const base = testRegion('body');
|
|
361
|
+
const skeleton = createSkeleton2D([makeBone({ name: 'root' })], [testSlot('head', 0), testSlot('body', 0)]);
|
|
362
|
+
skeleton.slots![1].attachment = base;
|
|
363
|
+
const hat = testRegion('hat');
|
|
364
|
+
setSkeleton2DSkin(skeleton, { attachments: [{ attachment: hat, name: 'head', slotIndex: 0 }], name: 'goblin' });
|
|
365
|
+
expect(skeleton.slots![0].attachment).toBe(hat);
|
|
366
|
+
expect(skeleton.slots![1].attachment).toBe(base); // shared art survives the overlay
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('skips an entry naming a slot outside the skeleton rather than throwing', () => {
|
|
370
|
+
const skeleton = createSkeleton2D([makeBone({ name: 'root' })], [testSlot('head', 0)]);
|
|
371
|
+
expect(() =>
|
|
372
|
+
setSkeleton2DSkin(skeleton, {
|
|
373
|
+
attachments: [
|
|
374
|
+
{ attachment: testRegion('ghost'), name: 'ghost', slotIndex: 9 },
|
|
375
|
+
{ attachment: testRegion('ghost2'), name: 'ghost2', slotIndex: -1 },
|
|
376
|
+
],
|
|
377
|
+
name: 'broken',
|
|
378
|
+
}),
|
|
379
|
+
).not.toThrow();
|
|
380
|
+
expect(skeleton.slots![0].attachment).toBeNull();
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it('is a no-op on a skeleton with no slots', () => {
|
|
384
|
+
const skeleton = createSkeleton2D([makeBone({ name: 'root' })]);
|
|
385
|
+
expect(() =>
|
|
386
|
+
setSkeleton2DSkin(skeleton, {
|
|
387
|
+
attachments: [{ attachment: testRegion('x'), name: 'x', slotIndex: 0 }],
|
|
388
|
+
name: 's',
|
|
389
|
+
}),
|
|
390
|
+
).not.toThrow();
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
|
|
311
394
|
describe('validateSkeleton2D', () => {
|
|
312
395
|
it('returns null for a valid parent-before-child skeleton', () => {
|
|
313
396
|
const s = createSkeleton2D([makeBone(), makeBone({ parentIndex: 0 })]);
|
|
@@ -325,3 +408,12 @@ describe('validateSkeleton2D', () => {
|
|
|
325
408
|
expect(validateSkeleton2D(s)).toContain('worldMatrices');
|
|
326
409
|
});
|
|
327
410
|
});
|
|
411
|
+
|
|
412
|
+
// A minimal slot for wardrobe tests: no attachment until a skin supplies one.
|
|
413
|
+
function testSlot(name: string, boneIndex: number): Slot2D {
|
|
414
|
+
return { attachment: null, boneIndex, color: 0xffffffff, name };
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function testRegion(name: string): RegionAttachment2D {
|
|
418
|
+
return { height: 0, kind: RegionAttachment2DKind, name, rotation: 0, scaleX: 1, scaleY: 1, width: 0, x: 0, y: 0 };
|
|
419
|
+
}
|