@haiyue/extensions 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/animation/Animation2DComponent.d.ts +46 -0
- package/dist/animation/Animation2DExtensionRegistry.d.ts +27 -0
- package/dist/animation/Animation2DRenderSystem.d.ts +89 -0
- package/dist/animation/Animation2DRuntime.d.ts +99 -0
- package/dist/animation/Animation2DStateMachine.d.ts +13 -0
- package/dist/animation/Animation2DStateMachineComponent.d.ts +54 -0
- package/dist/animation/Animation2DStateMachineRuntime.d.ts +30 -0
- package/dist/animation/Animation2DStateMachineSystem.d.ts +14 -0
- package/dist/animation/Animation2DStateMachineVisualRuntime.d.ts +27 -0
- package/dist/animation/Animation2DSystem.d.ts +14 -0
- package/dist/animation/AnimationAssetLoader.d.ts +9 -0
- package/dist/animation/AnimationAudioClip.d.ts +26 -0
- package/dist/animation/AnimationPathTessellator.d.ts +52 -0
- package/dist/animation/AnimationTextRasterizer.d.ts +21 -0
- package/dist/animation/AnimationVisual2D.d.ts +68 -0
- package/dist/animation/HyaAnimation2DClipAdapter.d.ts +16 -0
- package/dist/animation/Particle2DDescriptorAdapter.d.ts +5 -0
- package/dist/animation/runtime/mixer/Action.d.ts +150 -0
- package/dist/animation/runtime/mixer/Mixer.d.ts +54 -0
- package/dist/animation/runtime/mixer/PoseBuffer.d.ts +23 -0
- package/dist/animation/runtime/mixer/Sampler.d.ts +17 -0
- package/dist/animation/runtime/mixer/Types.d.ts +101 -0
- package/dist/animation/runtime/mixer/index.d.ts +6 -0
- package/dist/animation-state-machine/AnimationStateMachine.d.ts +111 -0
- package/dist/animation-state-machine/AnimationStateMachineChannels.d.ts +23 -0
- package/dist/animation-state-machine/runtime/Animation2DStateMachineMixerAdapter.d.ts +51 -0
- package/dist/animation-state-machine/runtime/AnimationStateMachineBlendTreeWeights.d.ts +14 -0
- package/dist/animation-state-machine/runtime/AnimationStateMachineCompiler.d.ts +109 -0
- package/dist/animation-state-machine/runtime/AnimationStateMachineController.d.ts +103 -0
- package/dist/animation-state-machine/runtime/AnimationStateMachineMixerPort.d.ts +35 -0
- package/dist/animation-state-machine/runtime/index.d.ts +7 -0
- package/dist/animation.d.ts +15 -0
- package/dist/animation.js +1171 -0
- package/dist/animation3d/Animation3DAction.d.ts +46 -0
- package/dist/animation3d/Animation3DBinding.d.ts +85 -0
- package/dist/animation3d/Animation3DClip.d.ts +20 -0
- package/dist/animation3d/Animation3DError.d.ts +13 -0
- package/dist/animation3d/Animation3DMixer.d.ts +27 -0
- package/dist/animation3d/Animation3DPose.d.ts +40 -0
- package/dist/animation3d/Animation3DPoseBuffer.d.ts +24 -0
- package/dist/animation3d/Animation3DResource.d.ts +28 -0
- package/dist/animation3d/Animation3DStateMachine.d.ts +95 -0
- package/dist/animation3d/Animation3DStateMachineRuntime.d.ts +70 -0
- package/dist/animation3d/Animation3DTrack.d.ts +19 -0
- package/dist/animation3d/hya/HyaAnimation3DRuntime.d.ts +73 -0
- package/dist/animation3d/hya/HyaAnimation3DStateMachineRuntime.d.ts +65 -0
- package/dist/animation3d/hya/HyaAnimation3DTypes.d.ts +170 -0
- package/dist/animation3d/hya/index.d.ts +4 -0
- package/dist/animation3d/index.d.ts +14 -0
- package/dist/animation3d/runtime/integration/Animation3DStateMachineMixerAdapter.d.ts +81 -0
- package/dist/animation3d/runtime/integration/Animation3DStateMachineMixerIntegration.d.ts +39 -0
- package/dist/animation3d/runtime/integration/index.d.ts +2 -0
- package/dist/animation3d/runtime/mixer/Action.d.ts +150 -0
- package/dist/animation3d/runtime/mixer/Animation3DMixerRuntimeStore.d.ts +6 -0
- package/dist/animation3d/runtime/mixer/Mixer.d.ts +59 -0
- package/dist/animation3d/runtime/mixer/PoseBuffer.d.ts +1 -0
- package/dist/animation3d/runtime/mixer/TrackSampler.d.ts +24 -0
- package/dist/animation3d/runtime/mixer/index.d.ts +4 -0
- package/dist/animation3d/runtime/state-machine/Animation3DBlendTreeWeights.d.ts +1 -0
- package/dist/animation3d/runtime/state-machine/Animation3DStateMachineCompiler.d.ts +1 -0
- package/dist/animation3d/runtime/state-machine/Animation3DStateMachineController.d.ts +1 -0
- package/dist/animation3d/runtime/state-machine/Animation3DStateMachineMixerPort.d.ts +1 -0
- package/dist/animation3d/runtime/state-machine/index.d.ts +6 -0
- package/dist/animation3d.d.ts +5 -0
- package/dist/animation3d.js +1708 -0
- package/dist/benchmark.d.ts +30 -0
- package/dist/benchmark.js +119 -0
- package/dist/canvas-text/CanvasText2DRenderSystem.d.ts +24 -0
- package/dist/canvas-text/CanvasTextComponent.d.ts +18 -0
- package/dist/canvas-text.d.ts +4 -0
- package/dist/canvas-text.js +276 -0
- package/dist/chunks/2d-ui-animation-2d.generated-D4aHzFU2.js +4 -0
- package/dist/chunks/2d-ui-canvas-text-2d.generated-C0Eaej2m.js +4 -0
- package/dist/chunks/2d-ui-spine2d.generated-CUUi8xjl.js +4 -0
- package/dist/chunks/2d-ui-tilemap2d.generated-gebw4mX7.js +4 -0
- package/dist/chunks/Animation2DStateMachine-9IonguNa.js +3245 -0
- package/dist/chunks/AnimationStateMachineController-BIcAh-sT.js +1438 -0
- package/dist/chunks/GltfAnimation3DAdapter-Cu3rQQsW.js +2240 -0
- package/dist/chunks/GltfAnimationRuntime-CRHsLycN.js +631 -0
- package/dist/chunks/RenderSystem2DBase-DDT61dAu.js +227 -0
- package/dist/chunks/Spine2DRuntime-D9M9LAQR.js +3056 -0
- package/dist/chunks/SpineAssetParser-BSDmPge1.js +378 -0
- package/dist/chunks/gltfLoader-Dm22jLYB.js +2085 -0
- package/dist/chunks/pluginUtils-CvwroRMd.js +33 -0
- package/dist/experimental-gltf-worker.d.ts +4 -0
- package/dist/experimental-gltf-worker.js +138 -0
- package/dist/experimental-spine-worker.d.ts +4 -0
- package/dist/experimental-spine-worker.js +110 -0
- package/dist/gltf/GltfAccessorReader.d.ts +7 -0
- package/dist/gltf/GltfAnimation3DAdapter.d.ts +47 -0
- package/dist/gltf/GltfAnimationRuntime.d.ts +10 -0
- package/dist/gltf/GltfAssetWorkerClient.d.ts +20 -0
- package/dist/gltf/GltfCompatibilityReport.d.ts +70 -0
- package/dist/gltf/GltfConservativeBounds.d.ts +18 -0
- package/dist/gltf/GltfDracoDecoder.d.ts +4 -0
- package/dist/gltf/GltfExtensionAdapter.d.ts +54 -0
- package/dist/gltf/GltfLoaderContract.d.ts +249 -0
- package/dist/gltf/GltfLoaderErrors.d.ts +4 -0
- package/dist/gltf/GltfMaterialDescriptor.d.ts +23 -0
- package/dist/gltf/GltfMaterialEncoder.d.ts +20 -0
- package/dist/gltf/GltfMaterialLoader.d.ts +6 -0
- package/dist/gltf/GltfModelComponent.d.ts +72 -0
- package/dist/gltf/GltfModelSystem.d.ts +37 -0
- package/dist/gltf/GltfPlugin.d.ts +6 -0
- package/dist/gltf/GltfSchema.d.ts +225 -0
- package/dist/gltf/GltfUvSemanticPlanner.d.ts +33 -0
- package/dist/gltf/gltfLoader.d.ts +9 -0
- package/dist/gltf-animation3d.d.ts +3 -0
- package/dist/gltf-animation3d.js +8 -0
- package/dist/gltf-worker-runtime.d.ts +7 -0
- package/dist/gltf-worker-runtime.js +6981 -0
- package/dist/gltf.d.ts +12 -0
- package/dist/gltf.js +517 -0
- package/dist/grid/Grid2DComponent.d.ts +25 -0
- package/dist/grid.d.ts +2 -0
- package/dist/grid.js +56 -0
- package/dist/hya-state-machine.d.ts +7 -0
- package/dist/hya-state-machine.js +2934 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/internal/2d-ui-shader-artifact.js +870 -0
- package/dist/plugins/pluginUtils.d.ts +20 -0
- package/dist/plugins.d.ts +6 -0
- package/dist/shaders/generated/2d-ui-artifact.generated.d.ts +658 -0
- package/dist/spine/Spine2DComponent.d.ts +116 -0
- package/dist/spine/Spine2DGpuRenderer.d.ts +65 -0
- package/dist/spine/Spine2DRenderSystem.d.ts +27 -0
- package/dist/spine/Spine2DRuntime.d.ts +103 -0
- package/dist/spine/SpineAnimationBoneTimelines.d.ts +8 -0
- package/dist/spine/SpineAssetParser.d.ts +18 -0
- package/dist/spine/SpineAssetWorkerClient.d.ts +19 -0
- package/dist/spine/SpineAssetWorkerContract.d.ts +6 -0
- package/dist/spine/SpineAtlasParser.d.ts +21 -0
- package/dist/spine/SpineFloatBuilder.d.ts +15 -0
- package/dist/spine/SpinePathConstraintSolver.d.ts +32 -0
- package/dist/spine/SpinePlugin.d.ts +8 -0
- package/dist/spine/SpineSkeletonRuntime.d.ts +185 -0
- package/dist/spine/SpineSlotAnimation.d.ts +17 -0
- package/dist/spine/SpineTimelineRuntime.d.ts +25 -0
- package/dist/spine/SpineVertexBuilder.d.ts +61 -0
- package/dist/spine.d.ts +7 -0
- package/dist/spine.js +578 -0
- package/dist/tilemap/Tilemap2DComponent.d.ts +110 -0
- package/dist/tilemap/Tilemap2DRenderSystem.d.ts +11 -0
- package/dist/tilemap/Tilemap2DRenderer.d.ts +24 -0
- package/dist/tilemap/TilemapPlugin.d.ts +8 -0
- package/dist/tilemap.d.ts +6 -0
- package/dist/tilemap.js +535 -0
- package/dist/tween/Tween2DComponent.d.ts +70 -0
- package/dist/tween/Tween2DSystem.d.ts +12 -0
- package/dist/tween.d.ts +4 -0
- package/dist/tween.js +138 -0
- package/dist/utils/RenderSystem2DBase.d.ts +42 -0
- package/dist/utils/arrayAccess.d.ts +4 -0
- package/dist/utils/camera2d.d.ts +12 -0
- package/dist/utils/render2dGpu.d.ts +32 -0
- package/package.json +124 -0
- package/src/animation/Animation2DComponent.ts +135 -0
- package/src/animation/Animation2DExtensionRegistry.ts +52 -0
- package/src/animation/Animation2DRenderSystem.ts +1026 -0
- package/src/animation/Animation2DRuntime.ts +1326 -0
- package/src/animation/Animation2DStateMachine.ts +39 -0
- package/src/animation/Animation2DStateMachineComponent.ts +228 -0
- package/src/animation/Animation2DStateMachineRuntime.ts +141 -0
- package/src/animation/Animation2DStateMachineSystem.ts +60 -0
- package/src/animation/Animation2DStateMachineVisualRuntime.ts +282 -0
- package/src/animation/Animation2DSystem.ts +72 -0
- package/src/animation/AnimationAssetLoader.ts +84 -0
- package/src/animation/AnimationAudioClip.ts +140 -0
- package/src/animation/AnimationPathTessellator.ts +691 -0
- package/src/animation/AnimationTextRasterizer.ts +340 -0
- package/src/animation/AnimationVisual2D.ts +153 -0
- package/src/animation/HyaAnimation2DClipAdapter.ts +845 -0
- package/src/animation/Particle2DDescriptorAdapter.ts +35 -0
- package/src/animation/runtime/mixer/Action.ts +876 -0
- package/src/animation/runtime/mixer/Mixer.ts +505 -0
- package/src/animation/runtime/mixer/PoseBuffer.ts +105 -0
- package/src/animation/runtime/mixer/Sampler.ts +252 -0
- package/src/animation/runtime/mixer/Types.ts +138 -0
- package/src/animation/runtime/mixer/index.ts +31 -0
- package/src/animation-state-machine/AnimationStateMachine.ts +146 -0
- package/src/animation-state-machine/AnimationStateMachineChannels.ts +116 -0
- package/src/animation-state-machine/runtime/Animation2DStateMachineMixerAdapter.ts +197 -0
- package/src/animation-state-machine/runtime/AnimationStateMachineBlendTreeWeights.ts +503 -0
- package/src/animation-state-machine/runtime/AnimationStateMachineCompiler.ts +763 -0
- package/src/animation-state-machine/runtime/AnimationStateMachineController.ts +987 -0
- package/src/animation-state-machine/runtime/AnimationStateMachineMixerPort.ts +54 -0
- package/src/animation-state-machine/runtime/index.ts +47 -0
- package/src/animation.ts +33 -0
- package/src/animation3d/Animation3DAction.ts +73 -0
- package/src/animation3d/Animation3DBinding.ts +116 -0
- package/src/animation3d/Animation3DClip.ts +22 -0
- package/src/animation3d/Animation3DError.ts +34 -0
- package/src/animation3d/Animation3DMixer.ts +82 -0
- package/src/animation3d/Animation3DPose.ts +100 -0
- package/src/animation3d/Animation3DPoseBuffer.ts +85 -0
- package/src/animation3d/Animation3DResource.ts +49 -0
- package/src/animation3d/Animation3DStateMachine.ts +126 -0
- package/src/animation3d/Animation3DStateMachineRuntime.ts +191 -0
- package/src/animation3d/Animation3DTrack.ts +29 -0
- package/src/animation3d/hya/HyaAnimation3DRuntime.ts +756 -0
- package/src/animation3d/hya/HyaAnimation3DStateMachineRuntime.ts +618 -0
- package/src/animation3d/hya/HyaAnimation3DTypes.ts +168 -0
- package/src/animation3d/hya/index.ts +10 -0
- package/src/animation3d/index.ts +76 -0
- package/src/animation3d/runtime/integration/Animation3DStateMachineMixerAdapter.ts +325 -0
- package/src/animation3d/runtime/integration/Animation3DStateMachineMixerIntegration.ts +158 -0
- package/src/animation3d/runtime/integration/index.ts +9 -0
- package/src/animation3d/runtime/mixer/Action.ts +833 -0
- package/src/animation3d/runtime/mixer/Animation3DMixerRuntimeStore.ts +26 -0
- package/src/animation3d/runtime/mixer/Mixer.ts +562 -0
- package/src/animation3d/runtime/mixer/PoseBuffer.ts +1 -0
- package/src/animation3d/runtime/mixer/TrackSampler.ts +399 -0
- package/src/animation3d/runtime/mixer/index.ts +8 -0
- package/src/animation3d/runtime/state-machine/Animation3DBlendTreeWeights.ts +4 -0
- package/src/animation3d/runtime/state-machine/Animation3DStateMachineCompiler.ts +1 -0
- package/src/animation3d/runtime/state-machine/Animation3DStateMachineController.ts +1 -0
- package/src/animation3d/runtime/state-machine/Animation3DStateMachineMixerPort.ts +1 -0
- package/src/animation3d/runtime/state-machine/index.ts +45 -0
- package/src/animation3d.ts +5 -0
- package/src/benchmark.ts +168 -0
- package/src/canvas-text/CanvasText2DRenderSystem.ts +292 -0
- package/src/canvas-text/CanvasTextComponent.ts +47 -0
- package/src/canvas-text.ts +4 -0
- package/src/experimental-gltf-worker.ts +18 -0
- package/src/experimental-spine-worker.ts +9 -0
- package/src/gltf/GltfAccessorReader.ts +271 -0
- package/src/gltf/GltfAnimation3DAdapter.ts +680 -0
- package/src/gltf/GltfAnimationRuntime.ts +392 -0
- package/src/gltf/GltfAssetWorkerClient.ts +136 -0
- package/src/gltf/GltfCompatibilityReport.ts +214 -0
- package/src/gltf/GltfConservativeBounds.ts +219 -0
- package/src/gltf/GltfDracoDecoder.ts +251 -0
- package/src/gltf/GltfExtensionAdapter.ts +340 -0
- package/src/gltf/GltfLoaderContract.ts +333 -0
- package/src/gltf/GltfLoaderErrors.ts +59 -0
- package/src/gltf/GltfMaterialDescriptor.ts +134 -0
- package/src/gltf/GltfMaterialEncoder.ts +173 -0
- package/src/gltf/GltfMaterialLoader.ts +293 -0
- package/src/gltf/GltfModelComponent.ts +115 -0
- package/src/gltf/GltfModelSystem.ts +208 -0
- package/src/gltf/GltfPlugin.ts +84 -0
- package/src/gltf/GltfSchema.ts +229 -0
- package/src/gltf/GltfUvSemanticPlanner.ts +166 -0
- package/src/gltf/gltfLoader.ts +910 -0
- package/src/gltf-animation3d.ts +10 -0
- package/src/gltf-worker-runtime.ts +10 -0
- package/src/gltf.ts +56 -0
- package/src/grid/Grid2DComponent.ts +69 -0
- package/src/grid.ts +2 -0
- package/src/hya-state-machine.ts +19 -0
- package/src/index.ts +2 -0
- package/src/plugins/pluginUtils.ts +50 -0
- package/src/plugins.ts +6 -0
- package/src/shaders/generated/2d-ui-animation-2d.generated.wgsl +242 -0
- package/src/shaders/generated/2d-ui-artifact.generated.ts +867 -0
- package/src/shaders/generated/2d-ui-canvas-text-2d.generated.wgsl +38 -0
- package/src/shaders/generated/2d-ui-spine2d.generated.wgsl +41 -0
- package/src/shaders/generated/2d-ui-tilemap2d.generated.wgsl +36 -0
- package/src/spine/Spine2DComponent.ts +168 -0
- package/src/spine/Spine2DGpuRenderer.ts +449 -0
- package/src/spine/Spine2DRenderSystem.ts +199 -0
- package/src/spine/Spine2DRuntime.ts +1529 -0
- package/src/spine/SpineAnimationBoneTimelines.ts +30 -0
- package/src/spine/SpineAssetParser.ts +20 -0
- package/src/spine/SpineAssetWorkerClient.ts +112 -0
- package/src/spine/SpineAssetWorkerContract.ts +4 -0
- package/src/spine/SpineAtlasParser.ts +127 -0
- package/src/spine/SpineFloatBuilder.ts +66 -0
- package/src/spine/SpinePathConstraintSolver.ts +582 -0
- package/src/spine/SpinePlugin.ts +76 -0
- package/src/spine/SpineSkeletonRuntime.ts +521 -0
- package/src/spine/SpineSlotAnimation.ts +195 -0
- package/src/spine/SpineTimelineRuntime.ts +453 -0
- package/src/spine/SpineVertexBuilder.ts +686 -0
- package/src/spine.ts +7 -0
- package/src/tilemap/Tilemap2DComponent.ts +232 -0
- package/src/tilemap/Tilemap2DRenderSystem.ts +58 -0
- package/src/tilemap/Tilemap2DRenderer.ts +289 -0
- package/src/tilemap/TilemapPlugin.ts +75 -0
- package/src/tilemap.ts +6 -0
- package/src/tween/Tween2DComponent.ts +83 -0
- package/src/tween/Tween2DSystem.ts +78 -0
- package/src/tween.ts +4 -0
- package/src/types/earcut.d.ts +7 -0
- package/src/types/wgsl.d.ts +4 -0
- package/src/utils/RenderSystem2DBase.ts +164 -0
- package/src/utils/arrayAccess.ts +17 -0
- package/src/utils/camera2d.ts +68 -0
- package/src/utils/render2dGpu.ts +132 -0
- package/test/fixtures/gltf/animation-characterization.gltf +344 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
const CURVE_LINEAR = 0;
|
|
2
|
+
const CURVE_STEPPED = 1;
|
|
3
|
+
const CURVE_BEZIER = 2;
|
|
4
|
+
|
|
5
|
+
interface CompiledNumericChannel {
|
|
6
|
+
readonly values: Float32Array;
|
|
7
|
+
readonly curveKinds: Uint8Array;
|
|
8
|
+
readonly curves: Float32Array;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface CompiledColorChannel {
|
|
12
|
+
readonly values: Float32Array;
|
|
13
|
+
readonly curveKinds: Uint8Array;
|
|
14
|
+
readonly curves: Float32Array;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface CompiledFrameTimeline {
|
|
18
|
+
readonly times: Float64Array;
|
|
19
|
+
readonly numericChannels: Map<string, CompiledNumericChannel>;
|
|
20
|
+
readonly color: CompiledColorChannel | null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface SpineTimelineCursor {
|
|
24
|
+
intervalCursor: number;
|
|
25
|
+
intervalTime: number;
|
|
26
|
+
discreteCursor: number;
|
|
27
|
+
discreteTime: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Runtime-local playback cursors; compiled timeline TypedArrays remain immutable and shareable. */
|
|
31
|
+
export interface SpineTimelineSamplerState {
|
|
32
|
+
readonly cursors: WeakMap<object, SpineTimelineCursor>;
|
|
33
|
+
cursorMisses: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface SpineTimelineCompileStats {
|
|
37
|
+
readonly timelineCount: number;
|
|
38
|
+
readonly frameCount: number;
|
|
39
|
+
readonly numericChannelCount: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const compiledFrames = new WeakMap<object, CompiledFrameTimeline>();
|
|
43
|
+
const animationDurations = new WeakMap<object, number>();
|
|
44
|
+
|
|
45
|
+
export function createSpineTimelineSamplerState(): SpineTimelineSamplerState {
|
|
46
|
+
return { cursors: new WeakMap(), cursorMisses: 0 };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Eagerly compiles every frame array reachable from the animation tree. */
|
|
50
|
+
export function compileSpineTimelines(
|
|
51
|
+
animations: Record<string, unknown>,
|
|
52
|
+
samplerState?: SpineTimelineSamplerState,
|
|
53
|
+
): SpineTimelineCompileStats {
|
|
54
|
+
let timelineCount = 0;
|
|
55
|
+
let frameCount = 0;
|
|
56
|
+
let numericChannelCount = 0;
|
|
57
|
+
for (const animation of Object.values(animations)) {
|
|
58
|
+
let duration = 0;
|
|
59
|
+
const visit = (value: unknown): void => {
|
|
60
|
+
if (Array.isArray(value)) {
|
|
61
|
+
const compiled = compileFrameArray(value);
|
|
62
|
+
if (compiled) {
|
|
63
|
+
getTimelineCursor(value, samplerState);
|
|
64
|
+
timelineCount++;
|
|
65
|
+
frameCount += compiled.times.length;
|
|
66
|
+
numericChannelCount += compiled.numericChannels.size;
|
|
67
|
+
const lastTime = compiled.times[compiled.times.length - 1];
|
|
68
|
+
if (lastTime !== undefined && lastTime > duration) duration = lastTime;
|
|
69
|
+
} else {
|
|
70
|
+
for (const child of value) visit(child);
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (!value || typeof value !== 'object') return;
|
|
75
|
+
for (const child of Object.values(value)) visit(child);
|
|
76
|
+
};
|
|
77
|
+
visit(animation);
|
|
78
|
+
if (animation && typeof animation === 'object') animationDurations.set(animation, duration);
|
|
79
|
+
}
|
|
80
|
+
return { timelineCount, frameCount, numericChannelCount };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function getCompiledAnimationDuration(animation: unknown): number {
|
|
84
|
+
if (!animation || typeof animation !== 'object') return 0;
|
|
85
|
+
const cached = animationDurations.get(animation);
|
|
86
|
+
if (cached !== undefined) return cached;
|
|
87
|
+
let duration = 0;
|
|
88
|
+
const visit = (value: unknown): void => {
|
|
89
|
+
if (Array.isArray(value)) {
|
|
90
|
+
const compiled = getOrCompileFrames(value);
|
|
91
|
+
if (compiled) {
|
|
92
|
+
const lastTime = compiled.times[compiled.times.length - 1];
|
|
93
|
+
if (lastTime !== undefined && lastTime > duration) duration = lastTime;
|
|
94
|
+
} else {
|
|
95
|
+
for (const child of value) visit(child);
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (!value || typeof value !== 'object') return;
|
|
100
|
+
for (const child of Object.values(value)) visit(child);
|
|
101
|
+
};
|
|
102
|
+
visit(animation);
|
|
103
|
+
animationDurations.set(animation, duration);
|
|
104
|
+
return duration;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function sampleCompiledTimeline(
|
|
108
|
+
frames: unknown[],
|
|
109
|
+
time: number,
|
|
110
|
+
key: string,
|
|
111
|
+
fallback: number,
|
|
112
|
+
_duration = 0,
|
|
113
|
+
_loop = false,
|
|
114
|
+
samplerState?: SpineTimelineSamplerState,
|
|
115
|
+
): number {
|
|
116
|
+
const timeline = getOrCompileFrames(frames);
|
|
117
|
+
if (!timeline || timeline.times.length === 0) return fallback;
|
|
118
|
+
const channel = timeline.numericChannels.get(key) ?? timeline.numericChannels.get('value');
|
|
119
|
+
if (!channel) return fallback;
|
|
120
|
+
const lastIndex = timeline.times.length - 1;
|
|
121
|
+
const firstTime = timeline.times[0] ?? 0;
|
|
122
|
+
if (time < firstTime) return fallback;
|
|
123
|
+
const lastTime = timeline.times[lastIndex] ?? 0;
|
|
124
|
+
if (time >= lastTime) return finiteOrFallback(channel.values[lastIndex], fallback);
|
|
125
|
+
const previousIndex = findIntervalIndex(timeline, time, getTimelineCursor(frames, samplerState));
|
|
126
|
+
const nextIndex = Math.min(lastIndex, previousIndex + 1);
|
|
127
|
+
const start = finiteOrFallback(channel.values[previousIndex], fallback);
|
|
128
|
+
const end = finiteOrFallback(channel.values[nextIndex], fallback);
|
|
129
|
+
const previousTime = timeline.times[previousIndex] ?? 0;
|
|
130
|
+
const nextTime = timeline.times[nextIndex] ?? previousTime;
|
|
131
|
+
if (nextIndex === previousIndex || nextTime === previousTime) return start;
|
|
132
|
+
const curveKind = channel.curveKinds[previousIndex] ?? CURVE_LINEAR;
|
|
133
|
+
if (curveKind === CURVE_STEPPED) return start;
|
|
134
|
+
if (curveKind === CURVE_BEZIER) {
|
|
135
|
+
return sampleBezierChannel(time, previousTime, start, channel.curves, previousIndex * 4, nextTime, end);
|
|
136
|
+
}
|
|
137
|
+
const alpha = clampUnit((time - previousTime) / (nextTime - previousTime));
|
|
138
|
+
return start + (end - start) * alpha;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Returns the last frame whose time is <= sample time, or -1 before the first frame. */
|
|
142
|
+
export function findCompiledFrameIndex(
|
|
143
|
+
frames: unknown[] | undefined,
|
|
144
|
+
time: number,
|
|
145
|
+
samplerState?: SpineTimelineSamplerState,
|
|
146
|
+
): number {
|
|
147
|
+
const timeline = getOrCompileFrames(frames);
|
|
148
|
+
if (!timeline || timeline.times.length === 0 || time < (timeline.times[0] ?? 0)) return -1;
|
|
149
|
+
const lastIndex = timeline.times.length - 1;
|
|
150
|
+
if (time >= (timeline.times[lastIndex] ?? 0)) {
|
|
151
|
+
const state = getTimelineCursor(frames, samplerState);
|
|
152
|
+
if (state) {
|
|
153
|
+
state.discreteCursor = lastIndex;
|
|
154
|
+
state.discreteTime = time;
|
|
155
|
+
}
|
|
156
|
+
return lastIndex;
|
|
157
|
+
}
|
|
158
|
+
const state = getTimelineCursor(frames, samplerState);
|
|
159
|
+
let cursor = state?.discreteCursor ?? 0;
|
|
160
|
+
if (
|
|
161
|
+
state
|
|
162
|
+
&& time >= state.discreteTime
|
|
163
|
+
&& cursor >= 0
|
|
164
|
+
&& cursor < lastIndex
|
|
165
|
+
&& time >= (timeline.times[cursor] ?? 0)
|
|
166
|
+
) {
|
|
167
|
+
while (cursor < lastIndex && (timeline.times[cursor + 1] ?? Infinity) <= time) cursor++;
|
|
168
|
+
} else {
|
|
169
|
+
cursor = upperBound(timeline.times, time) - 1;
|
|
170
|
+
}
|
|
171
|
+
if (state) {
|
|
172
|
+
state.discreteCursor = Math.max(0, cursor);
|
|
173
|
+
state.discreteTime = time;
|
|
174
|
+
}
|
|
175
|
+
return cursor;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function sampleCompiledColor(
|
|
179
|
+
frames: unknown[],
|
|
180
|
+
time: number,
|
|
181
|
+
fallback: ArrayLike<number>,
|
|
182
|
+
out: [number, number, number, number],
|
|
183
|
+
samplerState?: SpineTimelineSamplerState,
|
|
184
|
+
): [number, number, number, number] {
|
|
185
|
+
const timeline = getOrCompileFrames(frames);
|
|
186
|
+
if (!timeline?.color || timeline.times.length === 0) return copyColor(fallback, out);
|
|
187
|
+
const channel = timeline.color;
|
|
188
|
+
const lastIndex = timeline.times.length - 1;
|
|
189
|
+
const firstTime = timeline.times[0] ?? 0;
|
|
190
|
+
if (time < firstTime) return copyColor(fallback, out);
|
|
191
|
+
const lastTime = timeline.times[lastIndex] ?? 0;
|
|
192
|
+
if (time >= lastTime) return copyCompiledColor(channel, lastIndex, fallback, out);
|
|
193
|
+
const previousIndex = findIntervalIndex(timeline, time, getTimelineCursor(frames, samplerState));
|
|
194
|
+
const nextIndex = Math.min(lastIndex, previousIndex + 1);
|
|
195
|
+
const previousTime = timeline.times[previousIndex] ?? 0;
|
|
196
|
+
const nextTime = timeline.times[nextIndex] ?? previousTime;
|
|
197
|
+
for (let colorChannel = 0; colorChannel < 4; colorChannel++) {
|
|
198
|
+
const start = finiteOrFallback(channel.values[previousIndex * 4 + colorChannel], fallback[colorChannel] ?? 1);
|
|
199
|
+
const end = finiteOrFallback(channel.values[nextIndex * 4 + colorChannel], fallback[colorChannel] ?? 1);
|
|
200
|
+
if (nextIndex === previousIndex || nextTime === previousTime) {
|
|
201
|
+
out[colorChannel] = start;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const curveIndex = previousIndex * 4 + colorChannel;
|
|
205
|
+
const curveKind = channel.curveKinds[curveIndex] ?? CURVE_LINEAR;
|
|
206
|
+
if (curveKind === CURVE_STEPPED) out[colorChannel] = start;
|
|
207
|
+
else if (curveKind === CURVE_BEZIER) {
|
|
208
|
+
out[colorChannel] = sampleBezierChannel(
|
|
209
|
+
time,
|
|
210
|
+
previousTime,
|
|
211
|
+
start,
|
|
212
|
+
channel.curves,
|
|
213
|
+
curveIndex * 4,
|
|
214
|
+
nextTime,
|
|
215
|
+
end,
|
|
216
|
+
);
|
|
217
|
+
} else {
|
|
218
|
+
const alpha = clampUnit((time - previousTime) / (nextTime - previousTime));
|
|
219
|
+
out[colorChannel] = start + (end - start) * alpha;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return out;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function compileFrameArray(frames: unknown[]): CompiledFrameTimeline | null {
|
|
226
|
+
if (frames.length === 0 || compiledFrames.has(frames)) return compiledFrames.get(frames) ?? null;
|
|
227
|
+
for (const frame of frames) {
|
|
228
|
+
if (!frame || typeof frame !== 'object' || Array.isArray(frame)) return null;
|
|
229
|
+
}
|
|
230
|
+
const records = frames as Array<Record<string, unknown>>;
|
|
231
|
+
const times = new Float64Array(records.length);
|
|
232
|
+
const numericKeys = new Set<string>();
|
|
233
|
+
let hasColor = false;
|
|
234
|
+
for (let frameIndex = 0; frameIndex < records.length; frameIndex++) {
|
|
235
|
+
const frame = records[frameIndex];
|
|
236
|
+
if (!frame) continue;
|
|
237
|
+
times[frameIndex] = finiteNumber(frame.time, 0);
|
|
238
|
+
for (const [key, value] of Object.entries(frame)) {
|
|
239
|
+
if (key === 'time' || key === 'curve') continue;
|
|
240
|
+
if (key === 'color' && typeof value === 'string') hasColor = true;
|
|
241
|
+
else if (typeof value === 'number') numericKeys.add(key);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const numericChannels = new Map<string, CompiledNumericChannel>();
|
|
245
|
+
for (const key of numericKeys) numericChannels.set(key, compileNumericChannel(records, key));
|
|
246
|
+
const timeline: CompiledFrameTimeline = {
|
|
247
|
+
times,
|
|
248
|
+
numericChannels,
|
|
249
|
+
color: hasColor ? compileColorChannel(records) : null,
|
|
250
|
+
};
|
|
251
|
+
compiledFrames.set(frames, timeline);
|
|
252
|
+
return timeline;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function compileNumericChannel(frames: Array<Record<string, unknown>>, key: string): CompiledNumericChannel {
|
|
256
|
+
const values = new Float32Array(frames.length);
|
|
257
|
+
const curveKinds = new Uint8Array(frames.length);
|
|
258
|
+
const curves = new Float32Array(frames.length * 4);
|
|
259
|
+
const curveOffset = getCurveOffset(key);
|
|
260
|
+
for (let frameIndex = 0; frameIndex < frames.length; frameIndex++) {
|
|
261
|
+
const frame = frames[frameIndex];
|
|
262
|
+
const value = frame?.[key] ?? frame?.value;
|
|
263
|
+
values[frameIndex] = typeof value === 'number' && Number.isFinite(value) ? value : Number.NaN;
|
|
264
|
+
compileCurve(frame?.curve, curveOffset, curveKinds, frameIndex, curves, frameIndex * 4);
|
|
265
|
+
}
|
|
266
|
+
return { values, curveKinds, curves };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function compileColorChannel(frames: Array<Record<string, unknown>>): CompiledColorChannel {
|
|
270
|
+
const values = new Float32Array(frames.length * 4);
|
|
271
|
+
values.fill(Number.NaN);
|
|
272
|
+
const curveKinds = new Uint8Array(frames.length * 4);
|
|
273
|
+
const curves = new Float32Array(frames.length * 16);
|
|
274
|
+
for (let frameIndex = 0; frameIndex < frames.length; frameIndex++) {
|
|
275
|
+
const frame = frames[frameIndex];
|
|
276
|
+
writeHexColor(frame?.color, values, frameIndex * 4);
|
|
277
|
+
for (let channel = 0; channel < 4; channel++) {
|
|
278
|
+
const curveIndex = frameIndex * 4 + channel;
|
|
279
|
+
compileCurve(frame?.curve, channel * 4, curveKinds, curveIndex, curves, curveIndex * 4);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return { values, curveKinds, curves };
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function compileCurve(
|
|
286
|
+
curve: unknown,
|
|
287
|
+
sourceOffset: number,
|
|
288
|
+
kinds: Uint8Array,
|
|
289
|
+
kindIndex: number,
|
|
290
|
+
curves: Float32Array,
|
|
291
|
+
targetOffset: number,
|
|
292
|
+
): void {
|
|
293
|
+
if (curve === 'stepped') {
|
|
294
|
+
kinds[kindIndex] = CURVE_STEPPED;
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (!Array.isArray(curve) || curve.length < sourceOffset + 4) return;
|
|
298
|
+
kinds[kindIndex] = CURVE_BEZIER;
|
|
299
|
+
curves[targetOffset] = finiteNumber(curve[sourceOffset], 0);
|
|
300
|
+
curves[targetOffset + 1] = finiteNumber(curve[sourceOffset + 1], 0);
|
|
301
|
+
curves[targetOffset + 2] = finiteNumber(curve[sourceOffset + 2], 0);
|
|
302
|
+
curves[targetOffset + 3] = finiteNumber(curve[sourceOffset + 3], 0);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function getOrCompileFrames(frames: unknown[] | undefined): CompiledFrameTimeline | null {
|
|
306
|
+
if (!Array.isArray(frames) || frames.length === 0) return null;
|
|
307
|
+
return compiledFrames.get(frames) ?? compileFrameArray(frames);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function findIntervalIndex(
|
|
311
|
+
timeline: CompiledFrameTimeline,
|
|
312
|
+
time: number,
|
|
313
|
+
state: SpineTimelineCursor | null,
|
|
314
|
+
): number {
|
|
315
|
+
const times = timeline.times;
|
|
316
|
+
const lastInterval = Math.max(0, times.length - 2);
|
|
317
|
+
let cursor = Math.min(lastInterval, state?.intervalCursor ?? 0);
|
|
318
|
+
if (
|
|
319
|
+
state
|
|
320
|
+
&& time >= state.intervalTime
|
|
321
|
+
&& time >= (times[cursor] ?? 0)
|
|
322
|
+
&& time <= (times[cursor + 1] ?? Infinity)
|
|
323
|
+
) {
|
|
324
|
+
state.intervalTime = time;
|
|
325
|
+
return cursor;
|
|
326
|
+
}
|
|
327
|
+
if (state && time >= state.intervalTime && time >= (times[cursor] ?? 0)) {
|
|
328
|
+
while (cursor < lastInterval && (times[cursor + 1] ?? Infinity) < time) cursor++;
|
|
329
|
+
} else {
|
|
330
|
+
cursor = Math.max(0, lowerBound(times, time) - 1);
|
|
331
|
+
}
|
|
332
|
+
if (state) {
|
|
333
|
+
state.intervalCursor = cursor;
|
|
334
|
+
state.intervalTime = time;
|
|
335
|
+
}
|
|
336
|
+
return cursor;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function getTimelineCursor(
|
|
340
|
+
frames: object | undefined,
|
|
341
|
+
samplerState: SpineTimelineSamplerState | undefined,
|
|
342
|
+
): SpineTimelineCursor | null {
|
|
343
|
+
if (!frames || !samplerState) return null;
|
|
344
|
+
let cursor = samplerState.cursors.get(frames);
|
|
345
|
+
if (!cursor) {
|
|
346
|
+
cursor = { intervalCursor: 0, intervalTime: -Infinity, discreteCursor: 0, discreteTime: -Infinity };
|
|
347
|
+
samplerState.cursors.set(frames, cursor);
|
|
348
|
+
samplerState.cursorMisses++;
|
|
349
|
+
}
|
|
350
|
+
return cursor;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function lowerBound(values: Float64Array, target: number): number {
|
|
354
|
+
let low = 0;
|
|
355
|
+
let high = values.length;
|
|
356
|
+
while (low < high) {
|
|
357
|
+
const middle = (low + high) >>> 1;
|
|
358
|
+
if ((values[middle] ?? Infinity) < target) low = middle + 1;
|
|
359
|
+
else high = middle;
|
|
360
|
+
}
|
|
361
|
+
return low;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function upperBound(values: Float64Array, target: number): number {
|
|
365
|
+
let low = 0;
|
|
366
|
+
let high = values.length;
|
|
367
|
+
while (low < high) {
|
|
368
|
+
const middle = (low + high) >>> 1;
|
|
369
|
+
if ((values[middle] ?? Infinity) <= target) low = middle + 1;
|
|
370
|
+
else high = middle;
|
|
371
|
+
}
|
|
372
|
+
return low;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function sampleBezierChannel(
|
|
376
|
+
time: number,
|
|
377
|
+
time1: number,
|
|
378
|
+
value1: number,
|
|
379
|
+
curves: Float32Array,
|
|
380
|
+
curveOffset: number,
|
|
381
|
+
time2: number,
|
|
382
|
+
value2: number,
|
|
383
|
+
): number {
|
|
384
|
+
const cx1 = curves[curveOffset] ?? time1;
|
|
385
|
+
const cy1 = curves[curveOffset + 1] ?? value1;
|
|
386
|
+
const cx2 = curves[curveOffset + 2] ?? time2;
|
|
387
|
+
const cy2 = curves[curveOffset + 3] ?? value2;
|
|
388
|
+
let low = 0;
|
|
389
|
+
let high = 1;
|
|
390
|
+
let parameter = 0;
|
|
391
|
+
for (let iteration = 0; iteration < 12; iteration++) {
|
|
392
|
+
parameter = (low + high) * 0.5;
|
|
393
|
+
if (cubicBezier(time1, cx1, cx2, time2, parameter) < time) low = parameter;
|
|
394
|
+
else high = parameter;
|
|
395
|
+
}
|
|
396
|
+
parameter = (low + high) * 0.5;
|
|
397
|
+
return cubicBezier(value1, cy1, cy2, value2, parameter);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function cubicBezier(p0: number, p1: number, p2: number, p3: number, time: number): number {
|
|
401
|
+
const inverse = 1 - time;
|
|
402
|
+
return inverse * inverse * inverse * p0
|
|
403
|
+
+ 3 * inverse * inverse * time * p1
|
|
404
|
+
+ 3 * inverse * time * time * p2
|
|
405
|
+
+ time * time * time * p3;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function copyCompiledColor(
|
|
409
|
+
channel: CompiledColorChannel,
|
|
410
|
+
frameIndex: number,
|
|
411
|
+
fallback: ArrayLike<number>,
|
|
412
|
+
out: [number, number, number, number],
|
|
413
|
+
): [number, number, number, number] {
|
|
414
|
+
for (let colorChannel = 0; colorChannel < 4; colorChannel++) {
|
|
415
|
+
out[colorChannel] = finiteOrFallback(
|
|
416
|
+
channel.values[frameIndex * 4 + colorChannel],
|
|
417
|
+
fallback[colorChannel] ?? 1,
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
return out;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function copyColor(source: ArrayLike<number>, out: [number, number, number, number]): [number, number, number, number] {
|
|
424
|
+
out[0] = source[0] ?? 1;
|
|
425
|
+
out[1] = source[1] ?? 1;
|
|
426
|
+
out[2] = source[2] ?? 1;
|
|
427
|
+
out[3] = source[3] ?? 1;
|
|
428
|
+
return out;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function writeHexColor(value: unknown, out: Float32Array, offset: number): void {
|
|
432
|
+
if (typeof value !== 'string' || value.length < 8) return;
|
|
433
|
+
out[offset] = parseInt(value.slice(0, 2), 16) / 255;
|
|
434
|
+
out[offset + 1] = parseInt(value.slice(2, 4), 16) / 255;
|
|
435
|
+
out[offset + 2] = parseInt(value.slice(4, 6), 16) / 255;
|
|
436
|
+
out[offset + 3] = parseInt(value.slice(6, 8), 16) / 255;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function getCurveOffset(key: string): number {
|
|
440
|
+
return key === 'y' || key === 'scaleY' || key === 'softness' ? 4 : 0;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function finiteNumber(value: unknown, fallback: number): number {
|
|
444
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function finiteOrFallback(value: number | undefined, fallback: number): number {
|
|
448
|
+
return value !== undefined && Number.isFinite(value) ? value : fallback;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function clampUnit(value: number): number {
|
|
452
|
+
return Math.max(0, Math.min(1, value));
|
|
453
|
+
}
|