@flighthq/skeleton2d 0.3.0-next.906.07cea63 → 0.3.1-next.209.43ef1bc
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 +1 -1
- package/dist/applyAnimationClipToSkeleton2D.d.ts.map +1 -1
- package/dist/applyAnimationClipToSkeleton2D.js +35 -36
- package/dist/applyAnimationClipToSkeleton2D.js.map +1 -1
- package/dist/boundingBoxAttachment2D.d.ts +3 -0
- package/dist/boundingBoxAttachment2D.d.ts.map +1 -0
- package/dist/boundingBoxAttachment2D.js +14 -0
- package/dist/boundingBoxAttachment2D.js.map +1 -0
- package/dist/clippingAttachment2D.d.ts +7 -0
- package/dist/clippingAttachment2D.d.ts.map +1 -0
- package/dist/clippingAttachment2D.js +26 -0
- package/dist/clippingAttachment2D.js.map +1 -0
- package/dist/contract.d.ts +17 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +17 -0
- package/dist/contract.js.map +1 -1
- package/dist/deformAnimationTarget2D.d.ts +2 -0
- package/dist/deformAnimationTarget2D.d.ts.map +1 -0
- package/dist/deformAnimationTarget2D.js +40 -0
- package/dist/deformAnimationTarget2D.js.map +1 -0
- package/dist/deformMeshAttachment2D.d.ts +1 -1
- package/dist/deformMeshAttachment2D.d.ts.map +1 -1
- package/dist/deformMeshAttachment2D.js +16 -46
- package/dist/deformMeshAttachment2D.js.map +1 -1
- package/dist/deformPathAttachment2D.d.ts +3 -0
- package/dist/deformPathAttachment2D.d.ts.map +1 -0
- package/dist/deformPathAttachment2D.js +36 -0
- package/dist/deformPathAttachment2D.js.map +1 -0
- package/dist/enableSkeleton2DGuards.d.ts +22 -0
- package/dist/enableSkeleton2DGuards.d.ts.map +1 -0
- package/dist/enableSkeleton2DGuards.js +42 -0
- package/dist/enableSkeleton2DGuards.js.map +1 -0
- package/dist/explainSkeleton2DChannel.d.ts +20 -0
- package/dist/explainSkeleton2DChannel.d.ts.map +1 -0
- package/dist/explainSkeleton2DChannel.js +33 -0
- package/dist/explainSkeleton2DChannel.js.map +1 -0
- package/dist/explainSkeleton2DDeformLength.d.ts +3 -0
- package/dist/explainSkeleton2DDeformLength.d.ts.map +1 -0
- package/dist/explainSkeleton2DDeformLength.js +23 -0
- package/dist/explainSkeleton2DDeformLength.js.map +1 -0
- package/dist/ikConstraint2D.d.ts +4 -0
- package/dist/ikConstraint2D.d.ts.map +1 -0
- package/dist/ikConstraint2D.js +162 -0
- package/dist/ikConstraint2D.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pathConstraint2D.d.ts +4 -0
- package/dist/pathConstraint2D.d.ts.map +1 -0
- package/dist/pathConstraint2D.js +171 -0
- package/dist/pathConstraint2D.js.map +1 -0
- package/dist/pointAttachment2D.d.ts +4 -0
- package/dist/pointAttachment2D.d.ts.map +1 -0
- package/dist/pointAttachment2D.js +34 -0
- package/dist/pointAttachment2D.js.map +1 -0
- package/dist/skeleton2d.d.ts +4 -1
- package/dist/skeleton2d.d.ts.map +1 -1
- package/dist/skeleton2d.js +113 -67
- package/dist/skeleton2d.js.map +1 -1
- package/dist/skeleton2dAnimationTarget.d.ts +15 -0
- package/dist/skeleton2dAnimationTarget.d.ts.map +1 -0
- package/dist/skeleton2dAnimationTarget.js +173 -0
- package/dist/skeleton2dAnimationTarget.js.map +1 -0
- package/dist/skeleton2dConstraint.d.ts +6 -0
- package/dist/skeleton2dConstraint.d.ts.map +1 -0
- package/dist/skeleton2dConstraint.js +37 -0
- package/dist/skeleton2dConstraint.js.map +1 -0
- package/dist/skeleton2dDrawOrderTarget.d.ts +38 -0
- package/dist/skeleton2dDrawOrderTarget.d.ts.map +1 -0
- package/dist/skeleton2dDrawOrderTarget.js +107 -0
- package/dist/skeleton2dDrawOrderTarget.js.map +1 -0
- package/dist/skeleton2dGuards.d.ts +16 -0
- package/dist/skeleton2dGuards.d.ts.map +1 -0
- package/dist/skeleton2dGuards.js +29 -0
- package/dist/skeleton2dGuards.js.map +1 -0
- package/dist/skinAttachment2DPoints.d.ts +3 -0
- package/dist/skinAttachment2DPoints.d.ts.map +1 -0
- package/dist/skinAttachment2DPoints.js +85 -0
- package/dist/skinAttachment2DPoints.js.map +1 -0
- package/dist/slotDeform2D.d.ts +4 -0
- package/dist/slotDeform2D.d.ts.map +1 -0
- package/dist/slotDeform2D.js +38 -0
- package/dist/slotDeform2D.js.map +1 -0
- package/dist/transformConstraint2D.d.ts +4 -0
- package/dist/transformConstraint2D.d.ts.map +1 -0
- package/dist/transformConstraint2D.js +113 -0
- package/dist/transformConstraint2D.js.map +1 -0
- package/package.json +11 -6
- package/src/applyAnimationClipToSkeleton2D.test.ts +230 -33
- package/src/boundingBoxAttachment2D.test.ts +84 -0
- package/src/clippingAttachment2D.test.ts +76 -0
- package/src/deformAnimationTarget2D.test.ts +143 -0
- package/src/deformMeshAttachment2D.test.ts +85 -1
- package/src/deformPathAttachment2D.test.ts +193 -0
- package/src/enableSkeleton2DGuards.test.ts +88 -0
- package/src/explainSkeleton2DChannel.test.ts +45 -0
- package/src/explainSkeleton2DDeformLength.test.ts +55 -0
- package/src/ikConstraint2D.test.ts +221 -0
- package/src/pathConstraint2D.test.ts +239 -0
- package/src/pointAttachment2D.test.ts +81 -0
- package/src/skeleton2d.test.ts +221 -2
- package/src/skeleton2dAnimationTarget.test.ts +160 -0
- package/src/skeleton2dConstraint.test.ts +119 -0
- package/src/skeleton2dDrawOrderTarget.test.ts +213 -0
- package/src/skeleton2dGuards.test.ts +80 -0
- package/src/skinAttachment2DPoints.test.ts +138 -0
- package/src/slotDeform2D.test.ts +132 -0
- package/src/transformConstraint2D.test.ts +178 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { AnimationClip, Skeleton2D } from '@flighthq/types/contract';
|
|
2
|
-
export declare function applyAnimationClipToSkeleton2D(clip: Readonly<AnimationClip>,
|
|
2
|
+
export declare function applyAnimationClipToSkeleton2D(clip: Readonly<AnimationClip>, setup: Readonly<Skeleton2D>, pose: Skeleton2D, time: number): void;
|
|
3
3
|
//# sourceMappingURL=applyAnimationClipToSkeleton2D.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applyAnimationClipToSkeleton2D.d.ts","sourceRoot":"","sources":["../src/applyAnimationClipToSkeleton2D.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"applyAnimationClipToSkeleton2D.d.ts","sourceRoot":"","sources":["../src/applyAnimationClipToSkeleton2D.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAA6B,MAAM,0BAA0B,CAAC;AA2BrG,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,CAkBN"}
|
|
@@ -1,45 +1,44 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// setup
|
|
6
|
-
//
|
|
7
|
-
// `
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
|
|
1
|
+
import { getSkeleton2DAnimationTargetBinder } from './skeleton2dAnimationTarget';
|
|
2
|
+
// Poses `pose` from an AnimationClip at `time` by COMPOSING each channel's sampled value onto the
|
|
3
|
+
// corresponding `setup` bone — the 2D-skeletal analogue of @flighthq/scene3d's `applyAnimationClipToScene3D`,
|
|
4
|
+
// but relative rather than absolute. This mirrors Spine's SkeletonData(setup)/Skeleton(instance) split:
|
|
5
|
+
// `setup` is the immutable rest pose, `pose` is the animated instance (typically a `cloneSkeleton2D(setup)`),
|
|
6
|
+
// and a clip carries RELATIVE deltas — translate/rotate/shear ADD to setup, scale MULTIPLIES it (Spine's
|
|
7
|
+
// timeline semantics; the `path` distinguishes which). Composing from `setup` every call (not from `pose`)
|
|
8
|
+
// is what makes clips blendable — a mixer accumulates deltas as `pose = setup + Σ wᵢ·deltaᵢ`, which averaging
|
|
9
|
+
// baked-absolute poses cannot express — and is why re-applying a clip does not accumulate across frames.
|
|
10
|
+
//
|
|
11
|
+
// One clip carries channels for several families at once — bone transforms, slot appearance, and whatever
|
|
12
|
+
// else has registered a binder — so this walks the channels ONCE and hands each to the binder its target
|
|
13
|
+
// kind names. Not every family follows the compose rule: a slot colour is an ABSOLUTE authored value that
|
|
14
|
+
// its binder writes without reading `setup` at all.
|
|
15
|
+
//
|
|
16
|
+
// It writes only what a channel targets; untouched pose bones keep their clone-of-setup values. The caller
|
|
17
|
+
// runs `computeSkeleton2DWorldTransforms(pose, …)` (then the deform) afterward, so a whole clip applies
|
|
18
|
+
// before one world propagation. A channel whose target is foreign, unregistered, or out of range is
|
|
19
|
+
// skipped (sentinel guard, no throw).
|
|
20
|
+
//
|
|
21
|
+
// This is the documented exception to the out-param aliasing rule: `setup` is read across the whole pass
|
|
22
|
+
// while `pose` is written, so they cannot be the same object. Passing one skeleton as both would clobber
|
|
23
|
+
// the rest pose the binder composes against and then accumulate against garbage every subsequent frame —
|
|
24
|
+
// a silent, delayed corruption — so it is a programmer error the guard below throws on, not a sentinel.
|
|
25
|
+
export function applyAnimationClipToSkeleton2D(clip, setup, pose, time) {
|
|
26
|
+
if (setup === pose) {
|
|
27
|
+
throw new Error('applyAnimationClipToSkeleton2D: setup and pose must be distinct skeletons — pass a cloneSkeleton2D(setup) as pose');
|
|
28
|
+
}
|
|
11
29
|
const channels = clip.channels;
|
|
12
|
-
const bones = skeleton.bones;
|
|
13
30
|
for (let i = 0; i < channels.length; i++) {
|
|
14
31
|
const channel = channels[i];
|
|
15
32
|
const target = channel.targetRef;
|
|
16
|
-
if (target === null || typeof target !== 'object'
|
|
33
|
+
if (target === null || typeof target !== 'object')
|
|
17
34
|
continue;
|
|
18
|
-
|
|
19
|
-
|
|
35
|
+
// `targetRef` is opaque, so the target's own kind says which family owns it. A registry rather than a
|
|
36
|
+
// shape probe: the two 2D-skeletal formats animate eight things that are not bone transforms, and at
|
|
37
|
+
// that width a probe on overlapping field names reroutes a channel silently.
|
|
38
|
+
const bind = getSkeleton2DAnimationTargetBinder(target.kind);
|
|
39
|
+
if (bind === null)
|
|
20
40
|
continue;
|
|
21
|
-
|
|
22
|
-
const bone = bones[boneIndex];
|
|
23
|
-
switch (target.path) {
|
|
24
|
-
case Skeleton2DAnimationPath.Translation:
|
|
25
|
-
bone.x = _scratch[0];
|
|
26
|
-
bone.y = _scratch[1];
|
|
27
|
-
break;
|
|
28
|
-
case Skeleton2DAnimationPath.Rotation:
|
|
29
|
-
bone.rotation = _scratch[0];
|
|
30
|
-
break;
|
|
31
|
-
case Skeleton2DAnimationPath.Scale:
|
|
32
|
-
bone.scaleX = _scratch[0];
|
|
33
|
-
bone.scaleY = _scratch[1];
|
|
34
|
-
break;
|
|
35
|
-
case Skeleton2DAnimationPath.Shear:
|
|
36
|
-
bone.shearX = _scratch[0];
|
|
37
|
-
bone.shearY = _scratch[1];
|
|
38
|
-
break;
|
|
39
|
-
default:
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
41
|
+
bind(channel, setup, pose, target, time);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
const _scratch = [0, 0, 0, 0];
|
|
45
44
|
//# sourceMappingURL=applyAnimationClipToSkeleton2D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applyAnimationClipToSkeleton2D.js","sourceRoot":"","sources":["../src/applyAnimationClipToSkeleton2D.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"applyAnimationClipToSkeleton2D.js","sourceRoot":"","sources":["../src/applyAnimationClipToSkeleton2D.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kCAAkC,EAAE,MAAM,6BAA6B,CAAC;AAEjF,kGAAkG;AAClG,8GAA8G;AAC9G,wGAAwG;AACxG,8GAA8G;AAC9G,yGAAyG;AACzG,2GAA2G;AAC3G,8GAA8G;AAC9G,yGAAyG;AACzG,EAAE;AACF,0GAA0G;AAC1G,yGAAyG;AACzG,0GAA0G;AAC1G,oDAAoD;AACpD,EAAE;AACF,2GAA2G;AAC3G,wGAAwG;AACxG,oGAAoG;AACpG,sCAAsC;AACtC,EAAE;AACF,yGAAyG;AACzG,yGAAyG;AACzG,yGAAyG;AACzG,wGAAwG;AACxG,MAAM,UAAU,8BAA8B,CAC5C,IAA6B,EAC7B,KAA2B,EAC3B,IAAgB,EAChB,IAAY;IAEZ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,mHAAmH,CACpH,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,SAA6C,CAAC;QACrE,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,SAAS;QAC5D,sGAAsG;QACtG,qGAAqG;QACrG,6EAA6E;QAC7E,MAAM,IAAI,GAAG,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,IAAI,KAAK,IAAI;YAAE,SAAS;QAC5B,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BoundingBoxAttachment2D, Skeleton2D } from '@flighthq/types/contract';
|
|
2
|
+
export declare function computeSkeleton2DBoundingBoxAttachmentVertices(out: Float32Array, attachment: Readonly<BoundingBoxAttachment2D>, skeleton: Readonly<Skeleton2D>, boneIndex: number, deform?: Readonly<Float32Array> | null): void;
|
|
3
|
+
//# sourceMappingURL=boundingBoxAttachment2D.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundingBoxAttachment2D.d.ts","sourceRoot":"","sources":["../src/boundingBoxAttachment2D.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAapF,wBAAgB,8CAA8C,CAC5D,GAAG,EAAE,YAAY,EACjB,UAAU,EAAE,QAAQ,CAAC,uBAAuB,CAAC,EAC7C,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,IAAW,GAC3C,IAAI,CAUN"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { skinSkeleton2DAttachmentPoints } from './skinAttachment2DPoints';
|
|
2
|
+
// Produces a bounding box's world polygon as flat interleaved `[x0, y0, x1, y1, …]` in `out` (length
|
|
3
|
+
// ≥ 2 × attachment.pointCount), for hit testing and region queries. Requires
|
|
4
|
+
// `computeSkeleton2DWorldTransforms` to have filled `skeleton.worldMatrices`. Out-parameter,
|
|
5
|
+
// allocation-free.
|
|
6
|
+
//
|
|
7
|
+
// It is `compute*` rather than `deform*` because nothing here is being drawn: the result is queried. The
|
|
8
|
+
// skinning underneath is identical to a mesh's, which is the point — a hit box bound to the same bones as
|
|
9
|
+
// the art it covers tracks that art exactly, rather than approximating it with a shape that drifts as the
|
|
10
|
+
// rig moves.
|
|
11
|
+
export function computeSkeleton2DBoundingBoxAttachmentVertices(out, attachment, skeleton, boneIndex, deform = null) {
|
|
12
|
+
skinSkeleton2DAttachmentPoints(out, attachment.skin, attachment.vertices, skeleton, boneIndex, deform, 'BoundingBoxAttachment2D');
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=boundingBoxAttachment2D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundingBoxAttachment2D.js","sourceRoot":"","sources":["../src/boundingBoxAttachment2D.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAE1E,qGAAqG;AACrG,6EAA6E;AAC7E,6FAA6F;AAC7F,mBAAmB;AACnB,EAAE;AACF,yGAAyG;AACzG,0GAA0G;AAC1G,0GAA0G;AAC1G,aAAa;AACb,MAAM,UAAU,8CAA8C,CAC5D,GAAiB,EACjB,UAA6C,EAC7C,QAA8B,EAC9B,SAAiB,EACjB,SAAwC,IAAI;IAE5C,8BAA8B,CAC5B,GAAG,EACH,UAAU,CAAC,IAAI,EACf,UAAU,CAAC,QAAQ,EACnB,QAAQ,EACR,SAAS,EACT,MAAM,EACN,yBAAyB,CAC1B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ClippingAttachment2D, Skeleton2D } from '@flighthq/types/contract';
|
|
2
|
+
export declare function computeSkeleton2DClippingAttachmentVertices(out: Float32Array, attachment: Readonly<ClippingAttachment2D>, skeleton: Readonly<Skeleton2D>, boneIndex: number, deform?: Readonly<Float32Array> | null): void;
|
|
3
|
+
export declare function getSkeleton2DClippingAttachmentSlotRange(attachment: Readonly<ClippingAttachment2D>, slotIndex: number, slotCount: number): {
|
|
4
|
+
end: number;
|
|
5
|
+
start: number;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=clippingAttachment2D.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clippingAttachment2D.d.ts","sourceRoot":"","sources":["../src/clippingAttachment2D.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAYjF,wBAAgB,2CAA2C,CACzD,GAAG,EAAE,YAAY,EACjB,UAAU,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EAC1C,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,IAAW,GAC3C,IAAI,CAUN;AASD,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EAC1C,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAKhC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { skinSkeleton2DAttachmentPoints } from './skinAttachment2DPoints';
|
|
2
|
+
// Produces a clipping polygon's world points as flat interleaved `[x0, y0, x1, y1, …]` in `out` (length
|
|
3
|
+
// ≥ 2 × attachment.pointCount). Requires `computeSkeleton2DWorldTransforms` to have filled
|
|
4
|
+
// `skeleton.worldMatrices`. Out-parameter, allocation-free.
|
|
5
|
+
//
|
|
6
|
+
// This computes the polygon and NOTHING ELSE. It does not clip, does not build a `ClipRegion`, and does
|
|
7
|
+
// not consult `endSlotIndex` — turning a polygon plus a slot range into an applied clip is the display
|
|
8
|
+
// layer's job, and doing it here would make a query function mutate a scene. See
|
|
9
|
+
// `getSkeleton2DClippingAttachmentSlotRange` for the range half.
|
|
10
|
+
export function computeSkeleton2DClippingAttachmentVertices(out, attachment, skeleton, boneIndex, deform = null) {
|
|
11
|
+
skinSkeleton2DAttachmentPoints(out, attachment.skin, attachment.vertices, skeleton, boneIndex, deform, 'ClippingAttachment2D');
|
|
12
|
+
}
|
|
13
|
+
// The half-open slot range a clipping attachment covers, given the slot it sits on: `[start, end)` into
|
|
14
|
+
// the skeleton's draw-order slot array. Clipping starts AFTER its own slot and runs through
|
|
15
|
+
// `endSlotIndex` INCLUSIVE, so the returned `end` is one past it; an `endSlotIndex` of -1, or one at or
|
|
16
|
+
// before the clipping slot, runs to the end of the draw order.
|
|
17
|
+
//
|
|
18
|
+
// It exists so a consumer does not re-derive the off-by-one from the field's prose. The two conventions
|
|
19
|
+
// in play — inclusive in the format, half-open in the result — are exactly where that mistake lives.
|
|
20
|
+
export function getSkeleton2DClippingAttachmentSlotRange(attachment, slotIndex, slotCount) {
|
|
21
|
+
const start = slotIndex + 1;
|
|
22
|
+
const declared = attachment.endSlotIndex;
|
|
23
|
+
const end = declared < start ? slotCount : Math.min(declared + 1, slotCount);
|
|
24
|
+
return { end: Math.max(start, end), start };
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=clippingAttachment2D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clippingAttachment2D.js","sourceRoot":"","sources":["../src/clippingAttachment2D.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAE1E,wGAAwG;AACxG,2FAA2F;AAC3F,4DAA4D;AAC5D,EAAE;AACF,wGAAwG;AACxG,uGAAuG;AACvG,iFAAiF;AACjF,iEAAiE;AACjE,MAAM,UAAU,2CAA2C,CACzD,GAAiB,EACjB,UAA0C,EAC1C,QAA8B,EAC9B,SAAiB,EACjB,SAAwC,IAAI;IAE5C,8BAA8B,CAC5B,GAAG,EACH,UAAU,CAAC,IAAI,EACf,UAAU,CAAC,QAAQ,EACnB,QAAQ,EACR,SAAS,EACT,MAAM,EACN,sBAAsB,CACvB,CAAC;AACJ,CAAC;AAED,wGAAwG;AACxG,4FAA4F;AAC5F,wGAAwG;AACxG,+DAA+D;AAC/D,EAAE;AACF,wGAAwG;AACxG,qGAAqG;AACrG,MAAM,UAAU,wCAAwC,CACtD,UAA0C,EAC1C,SAAiB,EACjB,SAAiB;IAEjB,MAAM,KAAK,GAAG,SAAS,GAAG,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,UAAU,CAAC,YAAY,CAAC;IACzC,MAAM,GAAG,GAAG,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;IAC7E,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AAC9C,CAAC"}
|
package/dist/contract.d.ts
CHANGED
|
@@ -2,4 +2,21 @@ export * from './skeleton2d';
|
|
|
2
2
|
export * from './deformMeshAttachment2D';
|
|
3
3
|
export * from './regionAttachment2D';
|
|
4
4
|
export * from './applyAnimationClipToSkeleton2D';
|
|
5
|
+
export * from './skeleton2dAnimationTarget';
|
|
6
|
+
export * from './deformPathAttachment2D';
|
|
7
|
+
export * from './skeleton2dConstraint';
|
|
8
|
+
export * from './ikConstraint2D';
|
|
9
|
+
export * from './transformConstraint2D';
|
|
10
|
+
export * from './pathConstraint2D';
|
|
11
|
+
export * from './skeleton2dGuards';
|
|
12
|
+
export * from './enableSkeleton2DGuards';
|
|
13
|
+
export * from './explainSkeleton2DChannel';
|
|
14
|
+
export * from './skinAttachment2DPoints';
|
|
15
|
+
export * from './boundingBoxAttachment2D';
|
|
16
|
+
export * from './clippingAttachment2D';
|
|
17
|
+
export * from './pointAttachment2D';
|
|
18
|
+
export * from './explainSkeleton2DDeformLength';
|
|
19
|
+
export * from './slotDeform2D';
|
|
20
|
+
export * from './deformAnimationTarget2D';
|
|
21
|
+
export * from './skeleton2dDrawOrderTarget';
|
|
5
22
|
//# sourceMappingURL=contract.d.ts.map
|
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kCAAkC,CAAC"}
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iCAAiC,CAAC;AAChD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC"}
|
package/dist/contract.js
CHANGED
|
@@ -2,4 +2,21 @@ export * from './skeleton2d';
|
|
|
2
2
|
export * from './deformMeshAttachment2D';
|
|
3
3
|
export * from './regionAttachment2D';
|
|
4
4
|
export * from './applyAnimationClipToSkeleton2D';
|
|
5
|
+
export * from './skeleton2dAnimationTarget';
|
|
6
|
+
export * from './deformPathAttachment2D';
|
|
7
|
+
export * from './skeleton2dConstraint';
|
|
8
|
+
export * from './ikConstraint2D';
|
|
9
|
+
export * from './transformConstraint2D';
|
|
10
|
+
export * from './pathConstraint2D';
|
|
11
|
+
export * from './skeleton2dGuards';
|
|
12
|
+
export * from './enableSkeleton2DGuards';
|
|
13
|
+
export * from './explainSkeleton2DChannel';
|
|
14
|
+
export * from './skinAttachment2DPoints';
|
|
15
|
+
export * from './boundingBoxAttachment2D';
|
|
16
|
+
export * from './clippingAttachment2D';
|
|
17
|
+
export * from './pointAttachment2D';
|
|
18
|
+
export * from './explainSkeleton2DDeformLength';
|
|
19
|
+
export * from './slotDeform2D';
|
|
20
|
+
export * from './deformAnimationTarget2D';
|
|
21
|
+
export * from './skeleton2dDrawOrderTarget';
|
|
5
22
|
//# sourceMappingURL=contract.js.map
|
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kCAAkC,CAAC"}
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iCAAiC,CAAC;AAChD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deformAnimationTarget2D.d.ts","sourceRoot":"","sources":["../src/deformAnimationTarget2D.ts"],"names":[],"mappings":"AAUA,wBAAgB,uCAAuC,IAAI,IAAI,CAE9D"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { sampleAnimationTrack } from '@flighthq/animation/contract';
|
|
2
|
+
import { Skeleton2DAnimationTargetKind } from '@flighthq/types/contract';
|
|
3
|
+
import { registerSkeleton2DAnimationTargetBinder } from './skeleton2dAnimationTarget';
|
|
4
|
+
import { setSkeleton2DSlotDeform } from './slotDeform2D';
|
|
5
|
+
// Opts a bundle into deform channels. Unlike the bone and slot binders — which are pre-entered because a
|
|
6
|
+
// bundle that shed them would leave the pose pass a silent no-op — a rig with no deform timeline should
|
|
7
|
+
// not carry this, so it registers explicitly like a constraint solver does.
|
|
8
|
+
export function registerSkeleton2DDeformAnimationTarget() {
|
|
9
|
+
registerSkeleton2DAnimationTargetBinder(Skeleton2DAnimationTargetKind.Deform, bindSkeleton2DDeformChannel);
|
|
10
|
+
}
|
|
11
|
+
// Samples a deform channel onto its slot, stamping the attachment the offsets were authored for so the
|
|
12
|
+
// pull seam can reject them once the slot shows something else.
|
|
13
|
+
//
|
|
14
|
+
// The track is ordinary and numeric: `components` is the whole offset stream length, so a keyframe is one
|
|
15
|
+
// complete set of offsets and `sampleAnimationTrack` interpolates between them normally. That is the right
|
|
16
|
+
// behaviour here and the opposite of an attachment-swap index — a morph that snapped between drawn keys
|
|
17
|
+
// instead of blending would be the bug.
|
|
18
|
+
//
|
|
19
|
+
// A channel whose slot is out of range writes nothing rather than throwing; a rig can carry a timeline for
|
|
20
|
+
// a slot a trimmed skeleton no longer has.
|
|
21
|
+
function bindSkeleton2DDeformChannel(channel, _setup, pose, target, time) {
|
|
22
|
+
const deformTarget = target;
|
|
23
|
+
const slots = pose.slots;
|
|
24
|
+
if (slots === undefined || slots === null)
|
|
25
|
+
return;
|
|
26
|
+
const slotIndex = deformTarget.slotIndex;
|
|
27
|
+
if (typeof slotIndex !== 'number' || slotIndex < 0 || slotIndex >= slots.length)
|
|
28
|
+
return;
|
|
29
|
+
const components = channel.track.components;
|
|
30
|
+
if (components <= 0)
|
|
31
|
+
return;
|
|
32
|
+
if (_scratch.length < components)
|
|
33
|
+
_scratch = new Float32Array(components);
|
|
34
|
+
sampleAnimationTrack(_scratch, channel.track, time);
|
|
35
|
+
// `_scratch` may be longer than the stream after a previous, wider channel, so only the components this
|
|
36
|
+
// track actually carries are written.
|
|
37
|
+
setSkeleton2DSlotDeform(slots[slotIndex], deformTarget.attachment ?? null, _scratch.subarray(0, components));
|
|
38
|
+
}
|
|
39
|
+
let _scratch = new Float32Array(0);
|
|
40
|
+
//# sourceMappingURL=deformAnimationTarget2D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deformAnimationTarget2D.js","sourceRoot":"","sources":["../src/deformAnimationTarget2D.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AAEzE,OAAO,EAAE,uCAAuC,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,yGAAyG;AACzG,wGAAwG;AACxG,4EAA4E;AAC5E,MAAM,UAAU,uCAAuC;IACrD,uCAAuC,CAAC,6BAA6B,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;AAC7G,CAAC;AAED,uGAAuG;AACvG,gEAAgE;AAChE,EAAE;AACF,0GAA0G;AAC1G,2GAA2G;AAC3G,wGAAwG;AACxG,wCAAwC;AACxC,EAAE;AACF,2GAA2G;AAC3G,2CAA2C;AAC3C,SAAS,2BAA2B,CAClC,OAAmC,EACnC,MAA4B,EAC5B,IAAgB,EAChB,MAAe,EACf,IAAY;IAEZ,MAAM,YAAY,GAAG,MAAmD,CAAC;IACzE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO;IAClD,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC;IACzC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO;IAExF,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC;IAC5C,IAAI,UAAU,IAAI,CAAC;QAAE,OAAO;IAC5B,IAAI,QAAQ,CAAC,MAAM,GAAG,UAAU;QAAE,QAAQ,GAAG,IAAI,YAAY,CAAC,UAAU,CAAC,CAAC;IAC1E,oBAAoB,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpD,wGAAwG;IACxG,sCAAsC;IACtC,uBAAuB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC,UAAU,IAAI,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAC/G,CAAC;AAED,IAAI,QAAQ,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { MeshAttachment2D, Skeleton2D } from '@flighthq/types/contract';
|
|
2
|
-
export declare function deformSkeleton2DMeshAttachment(out: Float32Array, attachment: Readonly<MeshAttachment2D>, skeleton: Readonly<Skeleton2D>, boneIndex: number): void;
|
|
2
|
+
export declare function deformSkeleton2DMeshAttachment(out: Float32Array, attachment: Readonly<MeshAttachment2D>, skeleton: Readonly<Skeleton2D>, boneIndex: number, deform?: Readonly<Float32Array> | null): void;
|
|
3
3
|
//# sourceMappingURL=deformMeshAttachment2D.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deformMeshAttachment2D.d.ts","sourceRoot":"","sources":["../src/deformMeshAttachment2D.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"deformMeshAttachment2D.d.ts","sourceRoot":"","sources":["../src/deformMeshAttachment2D.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AA4B7E,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,YAAY,EACjB,UAAU,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EACtC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,IAAW,GAC3C,IAAI,CAUN"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const MATRIX_STRIDE = 6;
|
|
1
|
+
import { skinSkeleton2DAttachmentPoints } from './skinAttachment2DPoints';
|
|
3
2
|
// Deforms a MeshAttachment2D's vertices into flat interleaved world positions `[x0, y0, x1, y1, …]` in
|
|
4
3
|
// `out` (length ≥ 2 × attachment.vertexCount), for the display layer to draw. Requires
|
|
5
4
|
// `computeSkeleton2DWorldTransforms` to have filled `skeleton.worldMatrices`. Out-parameter,
|
|
@@ -11,49 +10,20 @@ const MATRIX_STRIDE = 6;
|
|
|
11
10
|
// RIGID (attachment.skin null): the mesh's setup-pose local `vertices` are transformed by bone
|
|
12
11
|
// `boneIndex`'s (the slot's bone) world matrix. Alias-safe — each vertex is read into locals before its
|
|
13
12
|
// output is written, so `out` may be the same buffer as `attachment.vertices`.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const ly = inf[vi + 2];
|
|
30
|
-
const weight = inf[vi + 3];
|
|
31
|
-
wx += weight * (world[b] * lx + world[b + 2] * ly + world[b + 4]);
|
|
32
|
-
wy += weight * (world[b + 1] * lx + world[b + 3] * ly + world[b + 5]);
|
|
33
|
-
vi += 4;
|
|
34
|
-
}
|
|
35
|
-
out[oi] = wx;
|
|
36
|
-
out[oi + 1] = wy;
|
|
37
|
-
oi += 2;
|
|
38
|
-
}
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
// Rigid mesh: the whole attachment follows one bone's world transform.
|
|
42
|
-
const vertices = attachment.vertices;
|
|
43
|
-
if (vertices === null || vertices === undefined)
|
|
44
|
-
return;
|
|
45
|
-
const b = boneIndex * MATRIX_STRIDE;
|
|
46
|
-
const a = world[b];
|
|
47
|
-
const bb = world[b + 1];
|
|
48
|
-
const c = world[b + 2];
|
|
49
|
-
const d = world[b + 3];
|
|
50
|
-
const tx = world[b + 4];
|
|
51
|
-
const ty = world[b + 5];
|
|
52
|
-
for (let i = 0; i < vertices.length; i += 2) {
|
|
53
|
-
const vx = vertices[i];
|
|
54
|
-
const vy = vertices[i + 1];
|
|
55
|
-
out[i] = a * vx + c * vy + tx;
|
|
56
|
-
out[i + 1] = bb * vx + d * vy + ty;
|
|
57
|
-
}
|
|
13
|
+
//
|
|
14
|
+
// `deform` is the animated offset stream layered on top of the skinning, or null for the undeformed
|
|
15
|
+
// attachment. It is ADDRESSED BY WHATEVER THE ATTACHMENT STORES ITS POSITIONS AS, which is the one rule
|
|
16
|
+
// that makes deform work for meshes and paths alike: a weighted attachment's offsets parallel its
|
|
17
|
+
// INFLUENCE stream (two floats per influence, so a vertex with three bones consumes three pairs), and a
|
|
18
|
+
// rigid one's parallel its vertex stream. Offsets are in the same space as what they displace — bone-local
|
|
19
|
+
// for a weighted attachment, so they are added BEFORE the weighted sum. Adding them to the world position
|
|
20
|
+
// afterwards would put a bone-local displacement into world space, which looks correct at rest and wrong
|
|
21
|
+
// the moment the rig moves.
|
|
22
|
+
//
|
|
23
|
+
// A `deform` too short for the stream it parallels is ignored entirely rather than read past: an importer
|
|
24
|
+
// sizing that buffer from vertex count instead of influence count is an expected failure, not a
|
|
25
|
+
// programmer error, so it takes the sentinel.
|
|
26
|
+
export function deformSkeleton2DMeshAttachment(out, attachment, skeleton, boneIndex, deform = null) {
|
|
27
|
+
skinSkeleton2DAttachmentPoints(out, attachment.skin, attachment.vertices, skeleton, boneIndex, deform, 'MeshAttachment2D');
|
|
58
28
|
}
|
|
59
29
|
//# sourceMappingURL=deformMeshAttachment2D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deformMeshAttachment2D.js","sourceRoot":"","sources":["../src/deformMeshAttachment2D.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"deformMeshAttachment2D.js","sourceRoot":"","sources":["../src/deformMeshAttachment2D.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAE1E,uGAAuG;AACvG,uFAAuF;AACvF,6FAA6F;AAC7F,mBAAmB;AACnB,EAAE;AACF,2GAA2G;AAC3G,2GAA2G;AAC3G,mFAAmF;AACnF,iGAAiG;AACjG,4GAA4G;AAC5G,mFAAmF;AACnF,EAAE;AACF,oGAAoG;AACpG,wGAAwG;AACxG,kGAAkG;AAClG,wGAAwG;AACxG,2GAA2G;AAC3G,0GAA0G;AAC1G,yGAAyG;AACzG,4BAA4B;AAC5B,EAAE;AACF,0GAA0G;AAC1G,gGAAgG;AAChG,8CAA8C;AAC9C,MAAM,UAAU,8BAA8B,CAC5C,GAAiB,EACjB,UAAsC,EACtC,QAA8B,EAC9B,SAAiB,EACjB,SAAwC,IAAI;IAE5C,8BAA8B,CAC5B,GAAG,EACH,UAAU,CAAC,IAAI,EACf,UAAU,CAAC,QAAQ,EACnB,QAAQ,EACR,SAAS,EACT,MAAM,EACN,kBAAkB,CACnB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Path, PathAttachment2D, Skeleton2D } from '@flighthq/types/contract';
|
|
2
|
+
export declare function deformSkeleton2DPathAttachment(out: Path, attachment: Readonly<PathAttachment2D>, skeleton: Readonly<Skeleton2D>, boneIndex: number, deform?: Readonly<Float32Array> | null): void;
|
|
3
|
+
//# sourceMappingURL=deformPathAttachment2D.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deformPathAttachment2D.d.ts","sourceRoot":"","sources":["../src/deformPathAttachment2D.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AA2BnF,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,IAAI,EACT,UAAU,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EACtC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,IAAW,GAC3C,IAAI,CAkBN"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { skinSkeleton2DAttachmentPoints } from './skinAttachment2DPoints';
|
|
2
|
+
// Deforms a PathAttachment2D into `out`, filling its `data` with world coordinates under the attachment's
|
|
3
|
+
// own verb stream. Requires `computeSkeleton2DWorldTransforms` to have filled `skeleton.worldMatrices`.
|
|
4
|
+
// Out-parameter; allocates only when `out`'s arrays have to grow to fit.
|
|
5
|
+
//
|
|
6
|
+
// The math is the same as `deformSkeleton2DMeshAttachment` — deliberately so. A skinned point is a
|
|
7
|
+
// skinned point whether a triangle or a curve reads it, and Skin2D carries no triangles and no UVs, so it
|
|
8
|
+
// was already geometry-agnostic. Only the output target differs: a Path's `data` stream instead of an
|
|
9
|
+
// interleaved vertex buffer.
|
|
10
|
+
//
|
|
11
|
+
// CONTROL POINTS NEED NO SPECIAL CASE HERE, and that is by construction rather than by luck: a cubic
|
|
12
|
+
// handle is given its anchor's influence set at IMPORT (see PathAttachment2D), so it arrives as an
|
|
13
|
+
// ordinary entry in the influence stream. Nothing below distinguishes an anchor from a handle, which is
|
|
14
|
+
// exactly why a curve cannot end up with its anchors moved and its handles left behind, or with its
|
|
15
|
+
// tangents sheared by influences blended across a segment.
|
|
16
|
+
//
|
|
17
|
+
// `deform` is the animated offset stream layered on top of the skinning, addressed the same way the mesh
|
|
18
|
+
// deformer addresses it: parallel to the INFLUENCE stream when weighted (two floats per influence),
|
|
19
|
+
// parallel to the coordinate stream when rigid, and applied to the BONE-LOCAL offset before the weighted
|
|
20
|
+
// sum. A stream too short for what it parallels is ignored rather than read past.
|
|
21
|
+
//
|
|
22
|
+
// This writes coordinates and never queries geometry, so it needs the `Path` TYPE and no function from
|
|
23
|
+
// `@flighthq/path`. That is the whole reason path skinning can live here beside mesh skinning instead of
|
|
24
|
+
// in a package that depends on the path kernel.
|
|
25
|
+
export function deformSkeleton2DPathAttachment(out, attachment, skeleton, boneIndex, deform = null) {
|
|
26
|
+
const commands = attachment.commands;
|
|
27
|
+
const data = out.data;
|
|
28
|
+
const outCommands = out.commands;
|
|
29
|
+
outCommands.length = commands.length;
|
|
30
|
+
for (let i = 0; i < commands.length; i++)
|
|
31
|
+
outCommands[i] = commands[i];
|
|
32
|
+
out.winding = attachment.winding;
|
|
33
|
+
data.length = attachment.pointCount * 2;
|
|
34
|
+
skinSkeleton2DAttachmentPoints(data, attachment.skin, attachment.vertices, skeleton, boneIndex, deform, 'PathAttachment2D');
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=deformPathAttachment2D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deformPathAttachment2D.js","sourceRoot":"","sources":["../src/deformPathAttachment2D.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAE1E,0GAA0G;AAC1G,wGAAwG;AACxG,yEAAyE;AACzE,EAAE;AACF,mGAAmG;AACnG,0GAA0G;AAC1G,sGAAsG;AACtG,6BAA6B;AAC7B,EAAE;AACF,qGAAqG;AACrG,mGAAmG;AACnG,wGAAwG;AACxG,oGAAoG;AACpG,2DAA2D;AAC3D,EAAE;AACF,yGAAyG;AACzG,oGAAoG;AACpG,yGAAyG;AACzG,kFAAkF;AAClF,EAAE;AACF,uGAAuG;AACvG,yGAAyG;AACzG,gDAAgD;AAChD,MAAM,UAAU,8BAA8B,CAC5C,GAAS,EACT,UAAsC,EACtC,QAA8B,EAC9B,SAAiB,EACjB,SAAwC,IAAI;IAE5C,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;IACrC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC;IACjC,WAAW,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,WAAW,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvE,GAAG,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;IACjC,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,UAAU,GAAG,CAAC,CAAC;IAExC,8BAA8B,CAC5B,IAAI,EACJ,UAAU,CAAC,IAAI,EACf,UAAU,CAAC,QAAQ,EACnB,QAAQ,EACR,SAAS,EACT,MAAM,EACN,kBAAkB,CACnB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare function disableSkeleton2DGuards(): void;
|
|
2
|
+
/**
|
|
3
|
+
* Installs the caller-facing skeleton guards (opt-in, dev-only). Idempotent.
|
|
4
|
+
*
|
|
5
|
+
* This package does two things that are **correct and invisible**, which is the combination worth
|
|
6
|
+
* announcing. Neither is a bug to fix — coercing is right in both cases — but a coercion nobody can see
|
|
7
|
+
* is indistinguishable from the file having been authored that way, so an author who set an easing and
|
|
8
|
+
* never saw it take effect has no way to find out why.
|
|
9
|
+
*
|
|
10
|
+
* 1. **A non-blendable channel is walked as steps** whatever its track claims. An attachment index
|
|
11
|
+
* blended between two table entries names art that was never authored; a draw order blended between
|
|
12
|
+
* two orderings yields fractional sort keys and a sequence nobody wrote.
|
|
13
|
+
* 2. **A deform offset stream whose length does not match the vertex stream it addresses is ignored.**
|
|
14
|
+
* There is no correct prefix to consume, so applying what fits would deform some vertices and leave
|
|
15
|
+
* others behind, and reading past the buffer is never an option.
|
|
16
|
+
*
|
|
17
|
+
* The messages live here rather than beside the code that knows the fact, so a shipped build that never
|
|
18
|
+
* imports this module carries neither them nor `@flighthq/log`. Every case also has a `has*`/`explain*`
|
|
19
|
+
* query for a caller that wants the fact as data instead of a log line.
|
|
20
|
+
*/
|
|
21
|
+
export declare function enableSkeleton2DGuards(): void;
|
|
22
|
+
//# sourceMappingURL=enableSkeleton2DGuards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enableSkeleton2DGuards.d.ts","sourceRoot":"","sources":["../src/enableSkeleton2DGuards.ts"],"names":[],"mappings":"AAOA,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { logOnce } from '@flighthq/log/contract';
|
|
2
|
+
import { LogLevel } from '@flighthq/types/contract';
|
|
3
|
+
import { setSkeleton2DCoercedInterpolationGuard, setSkeleton2DDeformLengthGuard } from './skeleton2dGuards';
|
|
4
|
+
// Uninstalls the guards installed by enableSkeleton2DGuards.
|
|
5
|
+
export function disableSkeleton2DGuards() {
|
|
6
|
+
setSkeleton2DCoercedInterpolationGuard(null);
|
|
7
|
+
setSkeleton2DDeformLengthGuard(null);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Installs the caller-facing skeleton guards (opt-in, dev-only). Idempotent.
|
|
11
|
+
*
|
|
12
|
+
* This package does two things that are **correct and invisible**, which is the combination worth
|
|
13
|
+
* announcing. Neither is a bug to fix — coercing is right in both cases — but a coercion nobody can see
|
|
14
|
+
* is indistinguishable from the file having been authored that way, so an author who set an easing and
|
|
15
|
+
* never saw it take effect has no way to find out why.
|
|
16
|
+
*
|
|
17
|
+
* 1. **A non-blendable channel is walked as steps** whatever its track claims. An attachment index
|
|
18
|
+
* blended between two table entries names art that was never authored; a draw order blended between
|
|
19
|
+
* two orderings yields fractional sort keys and a sequence nobody wrote.
|
|
20
|
+
* 2. **A deform offset stream whose length does not match the vertex stream it addresses is ignored.**
|
|
21
|
+
* There is no correct prefix to consume, so applying what fits would deform some vertices and leave
|
|
22
|
+
* others behind, and reading past the buffer is never an option.
|
|
23
|
+
*
|
|
24
|
+
* The messages live here rather than beside the code that knows the fact, so a shipped build that never
|
|
25
|
+
* imports this module carries neither them nor `@flighthq/log`. Every case also has a `has*`/`explain*`
|
|
26
|
+
* query for a caller that wants the fact as data instead of a log line.
|
|
27
|
+
*/
|
|
28
|
+
export function enableSkeleton2DGuards() {
|
|
29
|
+
setSkeleton2DCoercedInterpolationGuard(warnOnCoercedInterpolation);
|
|
30
|
+
setSkeleton2DDeformLengthGuard(warnOnDeformLengthMismatch);
|
|
31
|
+
}
|
|
32
|
+
function warnOnCoercedInterpolation(report) {
|
|
33
|
+
logOnce(`skeleton2d:coerced-interpolation:${report.subject}`, LogLevel.Warn, {
|
|
34
|
+
message: `A ${report.subject} channel states '${report.stated}' interpolation but is walked as '${report.applied}'. The value it carries cannot be blended — an attachment index between two table entries names art nobody authored, and a draw order between two orderings gives fractional sort keys — so the step is forced and the stated easing has no effect. Author the track as '${report.applied}' to say what actually happens, or drive a blendable property instead.`,
|
|
35
|
+
}, 'skeleton2d');
|
|
36
|
+
}
|
|
37
|
+
function warnOnDeformLengthMismatch(report) {
|
|
38
|
+
logOnce(`skeleton2d:deform-length:${report.subject}`, LogLevel.Warn, {
|
|
39
|
+
message: `Deform offsets on '${report.subject}' carry ${report.offsets} values but the vertex stream they address needs ${report.addressed}. The offsets are ignored rather than partly applied: a stream of the wrong length has no correct prefix, so consuming what fits would deform some vertices and silently leave the rest in their setup pose. Re-export the attachment, or check that the deform timeline belongs to this attachment.`,
|
|
40
|
+
}, 'skeleton2d');
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=enableSkeleton2DGuards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enableSkeleton2DGuards.js","sourceRoot":"","sources":["../src/enableSkeleton2DGuards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,EAAE,sCAAsC,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAE5G,6DAA6D;AAC7D,MAAM,UAAU,uBAAuB;IACrC,sCAAsC,CAAC,IAAI,CAAC,CAAC;IAC7C,8BAA8B,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,sBAAsB;IACpC,sCAAsC,CAAC,0BAA0B,CAAC,CAAC;IACnE,8BAA8B,CAAC,0BAA0B,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,0BAA0B,CAAC,MAAgD;IAClF,OAAO,CACL,oCAAoC,MAAM,CAAC,OAAO,EAAE,EACpD,QAAQ,CAAC,IAAI,EACb;QACE,OAAO,EAAE,KAAK,MAAM,CAAC,OAAO,oBAAoB,MAAM,CAAC,MAAM,qCAAqC,MAAM,CAAC,OAAO,4QAA4Q,MAAM,CAAC,OAAO,wEAAwE;KACnd,EACD,YAAY,CACb,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CAAC,MAAgD;IAClF,OAAO,CACL,4BAA4B,MAAM,CAAC,OAAO,EAAE,EAC5C,QAAQ,CAAC,IAAI,EACb;QACE,OAAO,EAAE,sBAAsB,MAAM,CAAC,OAAO,WAAW,MAAM,CAAC,OAAO,oDAAoD,MAAM,CAAC,SAAS,sSAAsS;KACjb,EACD,YAAY,CACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AnimationChannel, Skeleton2DCoercedInterpolation } from '@flighthq/types/contract';
|
|
2
|
+
/**
|
|
3
|
+
* Whether this channel's stated interpolation will be overridden, as plain data — the shakeable query
|
|
4
|
+
* beside the guard's log line, for a caller that wants to check a whole clip before playing it rather
|
|
5
|
+
* than watch warnings arrive during playback.
|
|
6
|
+
*
|
|
7
|
+
* Returns `null` when nothing is coerced, which is the common answer. `subject` names the channel
|
|
8
|
+
* family the caller is about to bind the channel as, since the same track is only coerced by virtue of
|
|
9
|
+
* what it drives: an identical `Linear` track is honoured on a bone and stepped on an attachment.
|
|
10
|
+
*/
|
|
11
|
+
export declare function explainSkeleton2DChannelInterpolation(channel: Readonly<AnimationChannel>, subject: string): Skeleton2DCoercedInterpolation | null;
|
|
12
|
+
/**
|
|
13
|
+
* Whether a channel family carries a value that cannot be blended, and is therefore walked as steps
|
|
14
|
+
* whatever its track states.
|
|
15
|
+
*
|
|
16
|
+
* Kept a query rather than a field on the target: it is a property of what the channel *drives*, not
|
|
17
|
+
* of the channel, so a caller can ask before it has built a target at all.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isSkeleton2DSteppedChannelSubject(subject: string): boolean;
|
|
20
|
+
//# sourceMappingURL=explainSkeleton2DChannel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainSkeleton2DChannel.d.ts","sourceRoot":"","sources":["../src/explainSkeleton2DChannel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAEjG;;;;;;;;GAQG;AACH,wBAAgB,qCAAqC,CACnD,OAAO,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EACnC,OAAO,EAAE,MAAM,GACd,8BAA8B,GAAG,IAAI,CAKvC;AAED;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE1E"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether this channel's stated interpolation will be overridden, as plain data — the shakeable query
|
|
3
|
+
* beside the guard's log line, for a caller that wants to check a whole clip before playing it rather
|
|
4
|
+
* than watch warnings arrive during playback.
|
|
5
|
+
*
|
|
6
|
+
* Returns `null` when nothing is coerced, which is the common answer. `subject` names the channel
|
|
7
|
+
* family the caller is about to bind the channel as, since the same track is only coerced by virtue of
|
|
8
|
+
* what it drives: an identical `Linear` track is honoured on a bone and stepped on an attachment.
|
|
9
|
+
*/
|
|
10
|
+
export function explainSkeleton2DChannelInterpolation(channel, subject) {
|
|
11
|
+
if (!isSkeleton2DSteppedChannelSubject(subject))
|
|
12
|
+
return null;
|
|
13
|
+
const stated = channel.track.interpolation;
|
|
14
|
+
if (stated === STEP_INTERPOLATION)
|
|
15
|
+
return null;
|
|
16
|
+
return { applied: STEP_INTERPOLATION, stated, subject };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Whether a channel family carries a value that cannot be blended, and is therefore walked as steps
|
|
20
|
+
* whatever its track states.
|
|
21
|
+
*
|
|
22
|
+
* Kept a query rather than a field on the target: it is a property of what the channel *drives*, not
|
|
23
|
+
* of the channel, so a caller can ask before it has built a target at all.
|
|
24
|
+
*/
|
|
25
|
+
export function isSkeleton2DSteppedChannelSubject(subject) {
|
|
26
|
+
return subject === ATTACHMENT_SUBJECT || subject === DRAW_ORDER_SUBJECT;
|
|
27
|
+
}
|
|
28
|
+
// An attachment index blended between two table entries names art nobody authored; a draw order
|
|
29
|
+
// blended between two orderings gives fractional sort keys and a sequence nobody wrote.
|
|
30
|
+
const ATTACHMENT_SUBJECT = 'Attachment';
|
|
31
|
+
const DRAW_ORDER_SUBJECT = 'DrawOrder';
|
|
32
|
+
const STEP_INTERPOLATION = 'Step';
|
|
33
|
+
//# sourceMappingURL=explainSkeleton2DChannel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainSkeleton2DChannel.js","sourceRoot":"","sources":["../src/explainSkeleton2DChannel.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,qCAAqC,CACnD,OAAmC,EACnC,OAAe;IAEf,IAAI,CAAC,iCAAiC,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC;IAC3C,IAAI,MAAM,KAAK,kBAAkB;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC1D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iCAAiC,CAAC,OAAe;IAC/D,OAAO,OAAO,KAAK,kBAAkB,IAAI,OAAO,KAAK,kBAAkB,CAAC;AAC1E,CAAC;AAED,gGAAgG;AAChG,wFAAwF;AACxF,MAAM,kBAAkB,GAAG,YAAY,CAAC;AACxC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AACvC,MAAM,kBAAkB,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Skeleton2DDeformLengthExplanation, Skin2D } from '@flighthq/types/contract';
|
|
2
|
+
export declare function explainSkeleton2DDeformLength(skin: Readonly<Skin2D> | null | undefined, vertices: Readonly<Float32Array> | null | undefined, deform: Readonly<Float32Array> | null): Skeleton2DDeformLengthExplanation;
|
|
3
|
+
//# sourceMappingURL=explainSkeleton2DDeformLength.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainSkeleton2DDeformLength.d.ts","sourceRoot":"","sources":["../src/explainSkeleton2DDeformLength.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAa1F,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,SAAS,EACzC,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,IAAI,GAAG,SAAS,EACnD,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,IAAI,GACpC,iCAAiC,CAUnC"}
|