@haiyue/extensions 0.1.0 → 0.2.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.
Files changed (269) hide show
  1. package/README.md +25 -0
  2. package/dist/animation/Animation2DComponent.d.ts +18 -0
  3. package/dist/animation/Animation2DExtensionRegistry.d.ts +7 -0
  4. package/dist/animation/Animation2DRenderSystem.d.ts +6 -0
  5. package/dist/animation/Animation2DRuntime.d.ts +6 -2
  6. package/dist/animation/AnimationTextRasterizer.d.ts +4 -0
  7. package/dist/animation/AnimationVisual2D.d.ts +58 -2
  8. package/dist/animation/interaction/InteractionRuntime.d.ts +83 -0
  9. package/dist/animation/interaction/runtime-types.d.ts +257 -0
  10. package/dist/animation.d.ts +3 -1
  11. package/dist/animation.js +551 -59
  12. package/dist/animation3d.js +1 -1
  13. package/dist/canvas-text.js +1 -1
  14. package/dist/chunks/2d-ui-animation-2d.generated-FpziAeGJ.js +4 -0
  15. package/dist/chunks/2d-ui-indexed-sprite.generated-DmKR0CC3.js +4 -0
  16. package/dist/chunks/Animation2DStateMachine-BHcA6Cu3.js +18212 -0
  17. package/dist/chunks/{AnimationStateMachineController-BIcAh-sT.js → AnimationStateMachineController-4sKaqh9E.js} +2 -2
  18. package/dist/chunks/AnimationVisual2D-8y3qp0_U.js +230 -0
  19. package/dist/chunks/{RenderSystem2DBase-DDT61dAu.js → RenderSystem2DBase-CF2s00vg.js} +2 -2
  20. package/dist/controls/VirtualJoystickControls.d.ts +46 -0
  21. package/dist/controls/contracts.d.ts +91 -0
  22. package/dist/controls.d.ts +2 -0
  23. package/dist/controls.js +358 -0
  24. package/dist/deformable-animation/runtime/DeformableMesh2DRuntimeExtension.d.ts +11 -0
  25. package/dist/deformable-animation/runtime/DeformableMesh2DSampler.d.ts +11 -0
  26. package/dist/deformable-animation.d.ts +5 -0
  27. package/dist/deformable-animation.js +316 -0
  28. package/dist/experimental-indexed-sprite.d.ts +5 -0
  29. package/dist/experimental-indexed-sprite.js +482 -0
  30. package/dist/gltf-worker-runtime.js +9 -9
  31. package/dist/hya-state-machine.js +3 -2
  32. package/dist/index.js +1 -1
  33. package/dist/indexed-sprite/AtlasLayout.d.ts +2 -0
  34. package/dist/indexed-sprite/IndexedSpriteRenderer.d.ts +23 -0
  35. package/dist/indexed-sprite/contracts.d.ts +89 -0
  36. package/dist/internal/2d-ui-shader-artifact.js +232 -23
  37. package/dist/ray-tracing/acceleration/bvh.d.ts +37 -0
  38. package/dist/ray-tracing/acceleration/index.d.ts +6 -0
  39. package/dist/ray-tracing/acceleration/pack.d.ts +152 -0
  40. package/dist/ray-tracing/acceleration/query.d.ts +4 -0
  41. package/dist/ray-tracing/acceleration/runtime.d.ts +30 -0
  42. package/dist/ray-tracing/acceleration/tlas.d.ts +4 -0
  43. package/dist/ray-tracing/acceleration/types.d.ts +165 -0
  44. package/dist/ray-tracing/denoise/index.d.ts +3 -0
  45. package/dist/ray-tracing/denoise/layout.d.ts +9 -0
  46. package/dist/ray-tracing/denoise/runtime.d.ts +23 -0
  47. package/dist/ray-tracing/denoise/types.d.ts +28 -0
  48. package/dist/ray-tracing/hybrid/contract.d.ts +2 -0
  49. package/dist/ray-tracing/hybrid/index.d.ts +5 -0
  50. package/dist/ray-tracing/hybrid/layout.d.ts +17 -0
  51. package/dist/ray-tracing/hybrid/plan.d.ts +2 -0
  52. package/dist/ray-tracing/hybrid/runtime.d.ts +31 -0
  53. package/dist/ray-tracing/hybrid/shaders/hybrid-artifact.generated.d.ts +625 -0
  54. package/dist/ray-tracing/hybrid/types.d.ts +144 -0
  55. package/dist/ray-tracing/lifecycle/device-recovery.d.ts +31 -0
  56. package/dist/ray-tracing/lifecycle/index.d.ts +2 -0
  57. package/dist/ray-tracing/lifecycle/types.d.ts +37 -0
  58. package/dist/ray-tracing/material/index.d.ts +2 -0
  59. package/dist/ray-tracing/material/pack.d.ts +5 -0
  60. package/dist/ray-tracing/material/types.d.ts +63 -0
  61. package/dist/ray-tracing/reference/index.d.ts +122 -0
  62. package/dist/ray-tracing/renderer/index.d.ts +7 -0
  63. package/dist/ray-tracing/renderer/layout.d.ts +20 -0
  64. package/dist/ray-tracing/renderer/plan.d.ts +2 -0
  65. package/dist/ray-tracing/renderer/reference.d.ts +17 -0
  66. package/dist/ray-tracing/renderer/runtime.d.ts +39 -0
  67. package/dist/ray-tracing/renderer/scene.d.ts +4 -0
  68. package/dist/ray-tracing/renderer/types.d.ts +115 -0
  69. package/dist/ray-tracing/sampling/index.d.ts +8 -0
  70. package/dist/ray-tracing/sampling/layout.d.ts +12 -0
  71. package/dist/ray-tracing/sampling/plan.d.ts +5 -0
  72. package/dist/ray-tracing/sampling/revision.d.ts +15 -0
  73. package/dist/ray-tracing/sampling/runtime.d.ts +44 -0
  74. package/dist/ray-tracing/sampling/sequence.d.ts +2 -0
  75. package/dist/ray-tracing/sampling/types.d.ts +96 -0
  76. package/dist/ray-tracing/scene/index.d.ts +41 -0
  77. package/dist/ray-tracing/traversal/index.d.ts +4 -0
  78. package/dist/ray-tracing/traversal/layout.d.ts +16 -0
  79. package/dist/ray-tracing/traversal/plan.d.ts +2 -0
  80. package/dist/ray-tracing/traversal/runtime.d.ts +25 -0
  81. package/dist/ray-tracing/traversal/types.d.ts +79 -0
  82. package/dist/ray-tracing/worker/client.d.ts +25 -0
  83. package/dist/ray-tracing/worker/index.d.ts +5 -0
  84. package/dist/ray-tracing/worker/runtime.d.ts +11 -0
  85. package/dist/ray-tracing/worker/serialization.d.ts +16 -0
  86. package/dist/ray-tracing/worker/source.d.ts +1 -0
  87. package/dist/ray-tracing/worker/types.d.ts +91 -0
  88. package/dist/ray-tracing.d.ts +17 -0
  89. package/dist/ray-tracing.js +7666 -0
  90. package/dist/spine.js +1 -1
  91. package/dist/tilemap.js +1 -1
  92. package/package.json +26 -23
  93. package/dist/animation/Animation2DStateMachineVisualRuntime.d.ts +0 -27
  94. package/dist/animation/Particle2DDescriptorAdapter.d.ts +0 -5
  95. package/dist/animation3d/Animation3DResource.d.ts +0 -28
  96. package/dist/animation3d/hya/HyaAnimation3DStateMachineRuntime.d.ts +0 -65
  97. package/dist/animation3d/hya/index.d.ts +0 -4
  98. package/dist/animation3d/runtime/integration/Animation3DStateMachineMixerAdapter.d.ts +0 -81
  99. package/dist/animation3d/runtime/integration/Animation3DStateMachineMixerIntegration.d.ts +0 -39
  100. package/dist/animation3d/runtime/integration/index.d.ts +0 -2
  101. package/dist/animation3d/runtime/mixer/Action.d.ts +0 -150
  102. package/dist/animation3d/runtime/mixer/Animation3DMixerRuntimeStore.d.ts +0 -6
  103. package/dist/animation3d/runtime/mixer/Mixer.d.ts +0 -59
  104. package/dist/animation3d/runtime/mixer/PoseBuffer.d.ts +0 -1
  105. package/dist/animation3d/runtime/mixer/TrackSampler.d.ts +0 -24
  106. package/dist/animation3d/runtime/mixer/index.d.ts +0 -4
  107. package/dist/animation3d/runtime/state-machine/Animation3DBlendTreeWeights.d.ts +0 -1
  108. package/dist/animation3d/runtime/state-machine/Animation3DStateMachineCompiler.d.ts +0 -1
  109. package/dist/animation3d/runtime/state-machine/Animation3DStateMachineController.d.ts +0 -1
  110. package/dist/animation3d/runtime/state-machine/Animation3DStateMachineMixerPort.d.ts +0 -1
  111. package/dist/animation3d/runtime/state-machine/index.d.ts +0 -6
  112. package/dist/benchmark.d.ts +0 -30
  113. package/dist/chunks/2d-ui-animation-2d.generated-D4aHzFU2.js +0 -4
  114. package/dist/chunks/Animation2DStateMachine-9IonguNa.js +0 -3245
  115. package/dist/gltf/GltfAccessorReader.d.ts +0 -7
  116. package/dist/gltf/GltfDracoDecoder.d.ts +0 -4
  117. package/dist/gltf/GltfLoaderErrors.d.ts +0 -4
  118. package/dist/gltf/GltfMaterialDescriptor.d.ts +0 -23
  119. package/dist/gltf/GltfMaterialLoader.d.ts +0 -6
  120. package/dist/gltf-worker-runtime.d.ts +0 -7
  121. package/dist/plugins/pluginUtils.d.ts +0 -20
  122. package/dist/plugins.d.ts +0 -6
  123. package/dist/shaders/generated/2d-ui-artifact.generated.d.ts +0 -658
  124. package/dist/spine/Spine2DGpuRenderer.d.ts +0 -65
  125. package/dist/spine/Spine2DRuntime.d.ts +0 -103
  126. package/dist/spine/SpineAnimationBoneTimelines.d.ts +0 -8
  127. package/dist/spine/SpineFloatBuilder.d.ts +0 -15
  128. package/dist/spine/SpinePathConstraintSolver.d.ts +0 -32
  129. package/dist/spine/SpineSkeletonRuntime.d.ts +0 -185
  130. package/dist/spine/SpineSlotAnimation.d.ts +0 -17
  131. package/dist/spine/SpineTimelineRuntime.d.ts +0 -25
  132. package/dist/spine/SpineVertexBuilder.d.ts +0 -61
  133. package/dist/tilemap/Tilemap2DRenderer.d.ts +0 -24
  134. package/dist/utils/arrayAccess.d.ts +0 -4
  135. package/dist/utils/camera2d.d.ts +0 -12
  136. package/src/animation/Animation2DComponent.ts +0 -135
  137. package/src/animation/Animation2DExtensionRegistry.ts +0 -52
  138. package/src/animation/Animation2DRenderSystem.ts +0 -1026
  139. package/src/animation/Animation2DRuntime.ts +0 -1326
  140. package/src/animation/Animation2DStateMachine.ts +0 -39
  141. package/src/animation/Animation2DStateMachineComponent.ts +0 -228
  142. package/src/animation/Animation2DStateMachineRuntime.ts +0 -141
  143. package/src/animation/Animation2DStateMachineSystem.ts +0 -60
  144. package/src/animation/Animation2DStateMachineVisualRuntime.ts +0 -282
  145. package/src/animation/Animation2DSystem.ts +0 -72
  146. package/src/animation/AnimationAssetLoader.ts +0 -84
  147. package/src/animation/AnimationAudioClip.ts +0 -140
  148. package/src/animation/AnimationPathTessellator.ts +0 -691
  149. package/src/animation/AnimationTextRasterizer.ts +0 -340
  150. package/src/animation/AnimationVisual2D.ts +0 -153
  151. package/src/animation/HyaAnimation2DClipAdapter.ts +0 -845
  152. package/src/animation/Particle2DDescriptorAdapter.ts +0 -35
  153. package/src/animation/runtime/mixer/Action.ts +0 -876
  154. package/src/animation/runtime/mixer/Mixer.ts +0 -505
  155. package/src/animation/runtime/mixer/PoseBuffer.ts +0 -105
  156. package/src/animation/runtime/mixer/Sampler.ts +0 -252
  157. package/src/animation/runtime/mixer/Types.ts +0 -138
  158. package/src/animation/runtime/mixer/index.ts +0 -31
  159. package/src/animation-state-machine/AnimationStateMachine.ts +0 -146
  160. package/src/animation-state-machine/AnimationStateMachineChannels.ts +0 -116
  161. package/src/animation-state-machine/runtime/Animation2DStateMachineMixerAdapter.ts +0 -197
  162. package/src/animation-state-machine/runtime/AnimationStateMachineBlendTreeWeights.ts +0 -503
  163. package/src/animation-state-machine/runtime/AnimationStateMachineCompiler.ts +0 -763
  164. package/src/animation-state-machine/runtime/AnimationStateMachineController.ts +0 -987
  165. package/src/animation-state-machine/runtime/AnimationStateMachineMixerPort.ts +0 -54
  166. package/src/animation-state-machine/runtime/index.ts +0 -47
  167. package/src/animation.ts +0 -33
  168. package/src/animation3d/Animation3DAction.ts +0 -73
  169. package/src/animation3d/Animation3DBinding.ts +0 -116
  170. package/src/animation3d/Animation3DClip.ts +0 -22
  171. package/src/animation3d/Animation3DError.ts +0 -34
  172. package/src/animation3d/Animation3DMixer.ts +0 -82
  173. package/src/animation3d/Animation3DPose.ts +0 -100
  174. package/src/animation3d/Animation3DPoseBuffer.ts +0 -85
  175. package/src/animation3d/Animation3DResource.ts +0 -49
  176. package/src/animation3d/Animation3DStateMachine.ts +0 -126
  177. package/src/animation3d/Animation3DStateMachineRuntime.ts +0 -191
  178. package/src/animation3d/Animation3DTrack.ts +0 -29
  179. package/src/animation3d/hya/HyaAnimation3DRuntime.ts +0 -756
  180. package/src/animation3d/hya/HyaAnimation3DStateMachineRuntime.ts +0 -618
  181. package/src/animation3d/hya/HyaAnimation3DTypes.ts +0 -168
  182. package/src/animation3d/hya/index.ts +0 -10
  183. package/src/animation3d/index.ts +0 -76
  184. package/src/animation3d/runtime/integration/Animation3DStateMachineMixerAdapter.ts +0 -325
  185. package/src/animation3d/runtime/integration/Animation3DStateMachineMixerIntegration.ts +0 -158
  186. package/src/animation3d/runtime/integration/index.ts +0 -9
  187. package/src/animation3d/runtime/mixer/Action.ts +0 -833
  188. package/src/animation3d/runtime/mixer/Animation3DMixerRuntimeStore.ts +0 -26
  189. package/src/animation3d/runtime/mixer/Mixer.ts +0 -562
  190. package/src/animation3d/runtime/mixer/PoseBuffer.ts +0 -1
  191. package/src/animation3d/runtime/mixer/TrackSampler.ts +0 -399
  192. package/src/animation3d/runtime/mixer/index.ts +0 -8
  193. package/src/animation3d/runtime/state-machine/Animation3DBlendTreeWeights.ts +0 -4
  194. package/src/animation3d/runtime/state-machine/Animation3DStateMachineCompiler.ts +0 -1
  195. package/src/animation3d/runtime/state-machine/Animation3DStateMachineController.ts +0 -1
  196. package/src/animation3d/runtime/state-machine/Animation3DStateMachineMixerPort.ts +0 -1
  197. package/src/animation3d/runtime/state-machine/index.ts +0 -45
  198. package/src/animation3d.ts +0 -5
  199. package/src/benchmark.ts +0 -168
  200. package/src/canvas-text/CanvasText2DRenderSystem.ts +0 -292
  201. package/src/canvas-text/CanvasTextComponent.ts +0 -47
  202. package/src/canvas-text.ts +0 -4
  203. package/src/experimental-gltf-worker.ts +0 -18
  204. package/src/experimental-spine-worker.ts +0 -9
  205. package/src/gltf/GltfAccessorReader.ts +0 -271
  206. package/src/gltf/GltfAnimation3DAdapter.ts +0 -680
  207. package/src/gltf/GltfAnimationRuntime.ts +0 -392
  208. package/src/gltf/GltfAssetWorkerClient.ts +0 -136
  209. package/src/gltf/GltfCompatibilityReport.ts +0 -214
  210. package/src/gltf/GltfConservativeBounds.ts +0 -219
  211. package/src/gltf/GltfDracoDecoder.ts +0 -251
  212. package/src/gltf/GltfExtensionAdapter.ts +0 -340
  213. package/src/gltf/GltfLoaderContract.ts +0 -333
  214. package/src/gltf/GltfLoaderErrors.ts +0 -59
  215. package/src/gltf/GltfMaterialDescriptor.ts +0 -134
  216. package/src/gltf/GltfMaterialEncoder.ts +0 -173
  217. package/src/gltf/GltfMaterialLoader.ts +0 -293
  218. package/src/gltf/GltfModelComponent.ts +0 -115
  219. package/src/gltf/GltfModelSystem.ts +0 -208
  220. package/src/gltf/GltfPlugin.ts +0 -84
  221. package/src/gltf/GltfSchema.ts +0 -229
  222. package/src/gltf/GltfUvSemanticPlanner.ts +0 -166
  223. package/src/gltf/gltfLoader.ts +0 -910
  224. package/src/gltf-animation3d.ts +0 -10
  225. package/src/gltf-worker-runtime.ts +0 -10
  226. package/src/gltf.ts +0 -56
  227. package/src/grid/Grid2DComponent.ts +0 -69
  228. package/src/grid.ts +0 -2
  229. package/src/hya-state-machine.ts +0 -19
  230. package/src/index.ts +0 -2
  231. package/src/plugins/pluginUtils.ts +0 -50
  232. package/src/plugins.ts +0 -6
  233. package/src/shaders/generated/2d-ui-animation-2d.generated.wgsl +0 -242
  234. package/src/shaders/generated/2d-ui-artifact.generated.ts +0 -867
  235. package/src/shaders/generated/2d-ui-canvas-text-2d.generated.wgsl +0 -38
  236. package/src/shaders/generated/2d-ui-spine2d.generated.wgsl +0 -41
  237. package/src/shaders/generated/2d-ui-tilemap2d.generated.wgsl +0 -36
  238. package/src/spine/Spine2DComponent.ts +0 -168
  239. package/src/spine/Spine2DGpuRenderer.ts +0 -449
  240. package/src/spine/Spine2DRenderSystem.ts +0 -199
  241. package/src/spine/Spine2DRuntime.ts +0 -1529
  242. package/src/spine/SpineAnimationBoneTimelines.ts +0 -30
  243. package/src/spine/SpineAssetParser.ts +0 -20
  244. package/src/spine/SpineAssetWorkerClient.ts +0 -112
  245. package/src/spine/SpineAssetWorkerContract.ts +0 -4
  246. package/src/spine/SpineAtlasParser.ts +0 -127
  247. package/src/spine/SpineFloatBuilder.ts +0 -66
  248. package/src/spine/SpinePathConstraintSolver.ts +0 -582
  249. package/src/spine/SpinePlugin.ts +0 -76
  250. package/src/spine/SpineSkeletonRuntime.ts +0 -521
  251. package/src/spine/SpineSlotAnimation.ts +0 -195
  252. package/src/spine/SpineTimelineRuntime.ts +0 -453
  253. package/src/spine/SpineVertexBuilder.ts +0 -686
  254. package/src/spine.ts +0 -7
  255. package/src/tilemap/Tilemap2DComponent.ts +0 -232
  256. package/src/tilemap/Tilemap2DRenderSystem.ts +0 -58
  257. package/src/tilemap/Tilemap2DRenderer.ts +0 -289
  258. package/src/tilemap/TilemapPlugin.ts +0 -75
  259. package/src/tilemap.ts +0 -6
  260. package/src/tween/Tween2DComponent.ts +0 -83
  261. package/src/tween/Tween2DSystem.ts +0 -78
  262. package/src/tween.ts +0 -4
  263. package/src/types/earcut.d.ts +0 -7
  264. package/src/types/wgsl.d.ts +0 -4
  265. package/src/utils/RenderSystem2DBase.ts +0 -164
  266. package/src/utils/arrayAccess.ts +0 -17
  267. package/src/utils/camera2d.ts +0 -68
  268. package/src/utils/render2dGpu.ts +0 -132
  269. package/test/fixtures/gltf/animation-characterization.gltf +0 -344
@@ -1,618 +0,0 @@
1
- import { ParticleEmitter3D } from '@haiyue/engine/components';
2
- import type { AnimationStateMachineDefinition } from '../../animation-state-machine/AnimationStateMachine.js';
3
- import {
4
- AnimationStateMachineController,
5
- compileAnimationStateMachine,
6
- runAnimationStateMachineControllerUpdateTransaction,
7
- type AnimationStateMachineActionOptions,
8
- type AnimationStateMachineMixerPort,
9
- } from '../../animation-state-machine/runtime/index.js';
10
- import type { Animation3DClip } from '../Animation3DClip.js';
11
- import type { Animation3DPose } from '../Animation3DPose.js';
12
- import { Animation3DPoseBuffer } from '../Animation3DPoseBuffer.js';
13
- import type { Animation3DStateMachineDefinition } from '../Animation3DStateMachine.js';
14
- import {
15
- Animation3DStateMachineMixerAdapter,
16
- type Animation3DStateMachineActionRuntimeHandle,
17
- } from '../runtime/integration/Animation3DStateMachineMixerAdapter.js';
18
- import { Animation3DMixerRuntime } from '../runtime/mixer/Mixer.js';
19
-
20
- const TIME_EPSILON = 1e-9;
21
-
22
- export interface HyaAnimation3DStateMachinePartition {
23
- readonly id: string;
24
- readonly mixer: Animation3DMixerRuntime;
25
- readonly clips: ReadonlyMap<string, Animation3DClip>;
26
- /** Maps authored HYA binding ids to a model runtime's source binding ids. */
27
- readonly bindingIds?: ReadonlyMap<string, string>;
28
- readonly pose?: Animation3DPoseBuffer;
29
- readonly apply: (pose: Animation3DPose) => void;
30
- }
31
-
32
- export interface HyaAnimation3DParticleCue {
33
- readonly key: string;
34
- readonly emitter: ParticleEmitter3D;
35
- readonly start: number;
36
- readonly end: number;
37
- }
38
-
39
- export interface HyaAnimation3DStateMachineRuntimeOptions {
40
- readonly definition: AnimationStateMachineDefinition | Animation3DStateMachineDefinition;
41
- readonly clips: readonly Animation3DClip[];
42
- readonly partitions: readonly HyaAnimation3DStateMachinePartition[];
43
- readonly particleCues?: ReadonlyMap<string, readonly HyaAnimation3DParticleCue[]>;
44
- }
45
-
46
- interface PartitionRuntime {
47
- readonly id: string;
48
- readonly mixer: Animation3DMixerRuntime;
49
- readonly adapter: Animation3DStateMachineMixerAdapter;
50
- readonly clips: ReadonlyMap<string, Animation3DClip>;
51
- readonly bindingIds: ReadonlyMap<string, string> | undefined;
52
- readonly pose: Animation3DPoseBuffer;
53
- readonly apply: (pose: Animation3DPose) => void;
54
- previousTime: number;
55
- frameCompleted: boolean;
56
- }
57
-
58
- interface ParticleCommand {
59
- readonly key: string;
60
- readonly kind: 'start' | 'stop';
61
- }
62
-
63
- interface GroupCheckpoint {
64
- readonly targetTime: number;
65
- readonly traversal: number;
66
- readonly playing: boolean;
67
- readonly activeCueKeys: ReadonlySet<string>;
68
- }
69
-
70
- export class HyaAnimation3DStateMachineActionHandle {
71
- readonly children: readonly Animation3DStateMachineActionRuntimeHandle[];
72
- readonly activeCueKeys = new Set<string>();
73
- targetTime = 0;
74
- traversal = 0;
75
- playing = false;
76
- destroyed = false;
77
- pendingDestroy = false;
78
-
79
- constructor(
80
- readonly id: string,
81
- readonly clipId: string,
82
- readonly duration: number,
83
- readonly loop: AnimationStateMachineActionOptions['loop'],
84
- children: readonly Animation3DStateMachineActionRuntimeHandle[],
85
- ) {
86
- this.children = Object.freeze([...children]);
87
- }
88
- }
89
-
90
- /**
91
- * One controller-facing port spanning the scene mixer and every loaded model
92
- * mixer. It is the only state-machine clock; child adapters only synchronize
93
- * existing mixer actions and participate in the same rollback boundary.
94
- */
95
- class HyaAnimation3DStateMachineMixerPort implements
96
- AnimationStateMachineMixerPort<HyaAnimation3DStateMachineActionHandle> {
97
- private readonly _clips = new Map<string, Animation3DClip>();
98
- private readonly _particles = new Map<string, ParticleEmitter3D>();
99
- private readonly _owners = new Map<string, string[]>();
100
- private readonly _handles = new Set<HyaAnimation3DStateMachineActionHandle>();
101
- private readonly _transactionCreated: HyaAnimation3DStateMachineActionHandle[] = [];
102
- private readonly _transactionPendingDestroy: HyaAnimation3DStateMachineActionHandle[] = [];
103
- private readonly _transactionCheckpoints = new Map<HyaAnimation3DStateMachineActionHandle, GroupCheckpoint>();
104
- private readonly _transactionCommands: ParticleCommand[] = [];
105
- private _transactionOwners = new Map<string, string[]>();
106
- private _nextHandleId = 1;
107
- private _transactionNextHandleId = 1;
108
- private _transactionActive = false;
109
- private _destroyed = false;
110
-
111
- constructor(
112
- readonly partitions: readonly PartitionRuntime[],
113
- clips: readonly Animation3DClip[],
114
- private readonly _particleCues: ReadonlyMap<string, readonly HyaAnimation3DParticleCue[]>,
115
- ) {
116
- for (const clip of clips) this._clips.set(clip.id, clip);
117
- for (const cues of _particleCues.values()) {
118
- for (const cue of cues) this._particles.set(cue.key, cue.emitter);
119
- }
120
- }
121
-
122
- get liveActionCount(): number { return this._handles.size; }
123
-
124
- get sideEffectOwnerCount(): number {
125
- let count = 0;
126
- for (const owners of this._owners.values()) count += owners.length;
127
- return count;
128
- }
129
-
130
- createAction(
131
- clipId: string,
132
- options: AnimationStateMachineActionOptions,
133
- ): HyaAnimation3DStateMachineActionHandle {
134
- this._requireActive();
135
- const clip = this._clips.get(clipId);
136
- if (!clip) throw new RangeError(`Unknown HYA Animation3D state-machine clip "${clipId}".`);
137
- const children: Animation3DStateMachineActionRuntimeHandle[] = [];
138
- try {
139
- for (const partition of this.partitions) {
140
- if (partition.clips.has(clipId)) {
141
- children.push(partition.adapter.createAction(
142
- clipId,
143
- translateActionOptions(options, partition.bindingIds),
144
- ));
145
- }
146
- }
147
- } catch (error) {
148
- let childIndex = 0;
149
- for (const partition of this.partitions) {
150
- if (!partition.clips.has(clipId) || childIndex >= children.length) continue;
151
- partition.adapter.destroyAction(children[childIndex++]!);
152
- }
153
- throw error;
154
- }
155
- const handle = new HyaAnimation3DStateMachineActionHandle(
156
- `hya-animation3d-state-machine:${this._nextHandleId++}`,
157
- clipId,
158
- clip.duration,
159
- options.loop,
160
- children,
161
- );
162
- this._handles.add(handle);
163
- if (this._transactionActive) this._transactionCreated.push(handle);
164
- return handle;
165
- }
166
-
167
- play(handle: HyaAnimation3DStateMachineActionHandle): void {
168
- this._requireHandle(handle);
169
- forEachChild(this.partitions, handle, (adapter, child) => adapter.play(child));
170
- if (handle.playing) return;
171
- handle.playing = true;
172
- this._syncParticleCues(handle, true);
173
- }
174
-
175
- stop(handle: HyaAnimation3DStateMachineActionHandle): void {
176
- this._requireHandle(handle);
177
- forEachChild(this.partitions, handle, (adapter, child) => adapter.stop(child));
178
- if (!handle.playing) return;
179
- handle.playing = false;
180
- this._releaseAllParticleCues(handle);
181
- }
182
-
183
- fade(
184
- handle: HyaAnimation3DStateMachineActionHandle,
185
- targetWeight: number,
186
- durationSeconds: number,
187
- ): void {
188
- this._requireHandle(handle);
189
- forEachChild(this.partitions, handle, (adapter, child) => adapter.fade(child, targetWeight, durationSeconds));
190
- }
191
-
192
- setWeight(handle: HyaAnimation3DStateMachineActionHandle, weight: number): void {
193
- this._requireHandle(handle);
194
- forEachChild(this.partitions, handle, (adapter, child) => adapter.setWeight(child, weight));
195
- }
196
-
197
- setTime(handle: HyaAnimation3DStateMachineActionHandle, timeSeconds: number): void {
198
- this._requireHandle(handle);
199
- forEachChild(this.partitions, handle, (adapter, child) => adapter.setTime(child, timeSeconds));
200
- const previousTraversal = handle.traversal;
201
- const position = playbackPosition(timeSeconds, handle.duration, handle.loop);
202
- handle.targetTime = timeSeconds;
203
- handle.traversal = position.traversal;
204
- if (!handle.playing) return;
205
- this._syncParticleCues(handle, false, position.localTime);
206
- if (position.traversal !== previousTraversal) this._restartDominantParticleCues(handle);
207
- }
208
-
209
- setTimeScale(handle: HyaAnimation3DStateMachineActionHandle, timeScale: number): void {
210
- this._requireHandle(handle);
211
- forEachChild(this.partitions, handle, (adapter, child) => adapter.setTimeScale(child, timeScale));
212
- }
213
-
214
- destroyAction(handle: HyaAnimation3DStateMachineActionHandle): void {
215
- if (handle.destroyed) return;
216
- this._requireHandle(handle);
217
- if (handle.playing) {
218
- handle.playing = false;
219
- this._releaseAllParticleCues(handle);
220
- }
221
- forEachChild(this.partitions, handle, (adapter, child) => adapter.destroyAction(child));
222
- if (this._transactionActive) {
223
- if (!handle.pendingDestroy) {
224
- handle.pendingDestroy = true;
225
- this._transactionPendingDestroy.push(handle);
226
- }
227
- return;
228
- }
229
- this._destroyGroupNow(handle);
230
- }
231
-
232
- beginControllerTransaction(): void {
233
- this._requireActive();
234
- if (this._transactionActive) throw new Error('HYA Animation3D state-machine transaction is already active.');
235
- this._transactionActive = true;
236
- this._transactionCreated.length = 0;
237
- this._transactionPendingDestroy.length = 0;
238
- this._transactionCheckpoints.clear();
239
- this._transactionCommands.length = 0;
240
- this._transactionOwners = cloneOwners(this._owners);
241
- this._transactionNextHandleId = this._nextHandleId;
242
- for (const handle of this._handles) {
243
- this._transactionCheckpoints.set(handle, {
244
- targetTime: handle.targetTime,
245
- traversal: handle.traversal,
246
- playing: handle.playing,
247
- activeCueKeys: new Set(handle.activeCueKeys),
248
- });
249
- }
250
- const begun: Animation3DStateMachineMixerAdapter[] = [];
251
- try {
252
- for (const partition of this.partitions) {
253
- partition.adapter.beginControllerTransaction();
254
- begun.push(partition.adapter);
255
- }
256
- } catch (error) {
257
- for (let index = begun.length - 1; index >= 0; index--) begun[index]!.rollbackControllerTransaction();
258
- this._transactionActive = false;
259
- this._clearTransaction();
260
- throw error;
261
- }
262
- }
263
-
264
- commitControllerTransaction(): void {
265
- if (!this._transactionActive) throw new Error('HYA Animation3D state-machine has no active transaction.');
266
- for (const partition of this.partitions) partition.adapter.commitControllerTransaction();
267
- this._transactionActive = false;
268
- for (const command of this._transactionCommands) this._applyParticleCommand(command);
269
- for (const handle of this._transactionPendingDestroy) this._destroyGroupNow(handle);
270
- this._clearTransaction();
271
- }
272
-
273
- rollbackControllerTransaction(): void {
274
- if (!this._transactionActive) return;
275
- this._transactionActive = false;
276
- for (let index = this.partitions.length - 1; index >= 0; index--) {
277
- this.partitions[index]!.adapter.rollbackControllerTransaction();
278
- }
279
- for (const handle of this._transactionCreated) {
280
- handle.destroyed = true;
281
- this._handles.delete(handle);
282
- }
283
- for (const [handle, checkpoint] of this._transactionCheckpoints) {
284
- if (handle.destroyed) continue;
285
- handle.targetTime = checkpoint.targetTime;
286
- handle.traversal = checkpoint.traversal;
287
- handle.playing = checkpoint.playing;
288
- handle.pendingDestroy = false;
289
- handle.activeCueKeys.clear();
290
- for (const key of checkpoint.activeCueKeys) handle.activeCueKeys.add(key);
291
- }
292
- this._owners.clear();
293
- for (const [key, owners] of this._transactionOwners) this._owners.set(key, [...owners]);
294
- this._nextHandleId = this._transactionNextHandleId;
295
- this._clearTransaction();
296
- }
297
-
298
- destroy(): void {
299
- if (this._destroyed) return;
300
- this.rollbackControllerTransaction();
301
- for (const handle of [...this._handles]) {
302
- if (handle.playing) this.stop(handle);
303
- forEachChild(this.partitions, handle, (adapter, child) => adapter.destroyAction(child));
304
- this._destroyGroupNow(handle);
305
- }
306
- for (const partition of this.partitions) partition.adapter.destroy();
307
- for (const emitter of this._particles.values()) stopParticle(emitter);
308
- this._owners.clear();
309
- this._destroyed = true;
310
- }
311
-
312
- private _syncParticleCues(
313
- handle: HyaAnimation3DStateMachineActionHandle,
314
- entering: boolean,
315
- localTime = playbackPosition(handle.targetTime, handle.duration, handle.loop).localTime,
316
- ): void {
317
- for (const cue of this._particleCues.get(handle.clipId) ?? []) {
318
- const active = particleCueActive(cue, localTime, handle.duration);
319
- const owned = handle.activeCueKeys.has(cue.key);
320
- if (active && !owned) this._acquireParticleCue(handle, cue);
321
- else if (!active && owned) this._releaseParticleCue(handle, cue.key);
322
- else if (entering && active && owned) this._recordParticleCommand({ key: cue.key, kind: 'start' });
323
- }
324
- }
325
-
326
- private _acquireParticleCue(
327
- handle: HyaAnimation3DStateMachineActionHandle,
328
- cue: HyaAnimation3DParticleCue,
329
- ): void {
330
- handle.activeCueKeys.add(cue.key);
331
- const owners = this._owners.get(cue.key) ?? [];
332
- if (!this._owners.has(cue.key)) this._owners.set(cue.key, owners);
333
- const existing = owners.indexOf(handle.id);
334
- if (existing >= 0) owners.splice(existing, 1);
335
- owners.push(handle.id);
336
- this._recordParticleCommand({ key: cue.key, kind: 'start' });
337
- }
338
-
339
- private _releaseParticleCue(handle: HyaAnimation3DStateMachineActionHandle, key: string): void {
340
- handle.activeCueKeys.delete(key);
341
- const owners = this._owners.get(key);
342
- if (!owners) return;
343
- const index = owners.indexOf(handle.id);
344
- const wasDominant = index === owners.length - 1;
345
- if (index >= 0) owners.splice(index, 1);
346
- if (owners.length === 0) {
347
- this._owners.delete(key);
348
- this._recordParticleCommand({ key, kind: 'stop' });
349
- } else if (wasDominant) this._recordParticleCommand({ key, kind: 'start' });
350
- }
351
-
352
- private _releaseAllParticleCues(handle: HyaAnimation3DStateMachineActionHandle): void {
353
- for (const key of [...handle.activeCueKeys]) this._releaseParticleCue(handle, key);
354
- }
355
-
356
- private _restartDominantParticleCues(handle: HyaAnimation3DStateMachineActionHandle): void {
357
- for (const key of handle.activeCueKeys) {
358
- const owners = this._owners.get(key);
359
- if (owners?.[owners.length - 1] === handle.id) this._recordParticleCommand({ key, kind: 'start' });
360
- }
361
- }
362
-
363
- private _recordParticleCommand(command: ParticleCommand): void {
364
- if (this._transactionActive) this._transactionCommands.push(command);
365
- else this._applyParticleCommand(command);
366
- }
367
-
368
- private _applyParticleCommand(command: ParticleCommand): void {
369
- const emitter = this._particles.get(command.key);
370
- if (!emitter) return;
371
- if (command.kind === 'stop') stopParticle(emitter);
372
- else {
373
- emitter.emitting = true;
374
- emitter.restart(true);
375
- emitter.playing = true;
376
- }
377
- }
378
-
379
- private _destroyGroupNow(handle: HyaAnimation3DStateMachineActionHandle): void {
380
- handle.playing = false;
381
- handle.pendingDestroy = false;
382
- handle.destroyed = true;
383
- handle.activeCueKeys.clear();
384
- this._handles.delete(handle);
385
- }
386
-
387
- private _clearTransaction(): void {
388
- this._transactionCreated.length = 0;
389
- this._transactionPendingDestroy.length = 0;
390
- this._transactionCheckpoints.clear();
391
- this._transactionCommands.length = 0;
392
- this._transactionOwners.clear();
393
- }
394
-
395
- private _requireHandle(handle: HyaAnimation3DStateMachineActionHandle): void {
396
- this._requireActive();
397
- if (handle.destroyed || !this._handles.has(handle)) {
398
- throw new Error('HYA Animation3D state-machine action is no longer valid.');
399
- }
400
- }
401
-
402
- private _requireActive(): void {
403
- if (this._destroyed) throw new Error('HYA Animation3D state-machine mixer port has been destroyed.');
404
- }
405
- }
406
-
407
- /** Coordinates native scene, glTF model and Particle3D channels with one controller transaction. */
408
- export class HyaAnimation3DStateMachineRuntime {
409
- readonly controller!: AnimationStateMachineController<HyaAnimation3DStateMachineActionHandle>;
410
- private readonly _partitions: readonly PartitionRuntime[];
411
- private readonly _port: HyaAnimation3DStateMachineMixerPort;
412
- private _time = 0;
413
- private _destroyed = false;
414
-
415
- constructor(options: HyaAnimation3DStateMachineRuntimeOptions) {
416
- this._partitions = Object.freeze(options.partitions.map(partition => {
417
- const resolver = { resolve: (clipId: string): Animation3DClip | null => partition.clips.get(clipId) ?? null };
418
- return {
419
- id: partition.id,
420
- mixer: partition.mixer,
421
- adapter: new Animation3DStateMachineMixerAdapter(partition.mixer, resolver),
422
- clips: partition.clips,
423
- bindingIds: partition.bindingIds,
424
- pose: partition.pose ?? new Animation3DPoseBuffer(),
425
- apply: partition.apply,
426
- previousTime: 0,
427
- frameCompleted: false,
428
- } satisfies PartitionRuntime;
429
- }));
430
- this._port = new HyaAnimation3DStateMachineMixerPort(
431
- this._partitions,
432
- options.clips,
433
- options.particleCues ?? new Map(),
434
- );
435
- try {
436
- this.controller = new AnimationStateMachineController(
437
- compileAnimationStateMachine(options.definition),
438
- this._port,
439
- );
440
- this.evaluate();
441
- } catch (error) {
442
- this.controller?.destroy();
443
- this._port.destroy();
444
- this._destroyed = true;
445
- throw error;
446
- }
447
- }
448
-
449
- get time(): number { return this._time; }
450
- get liveActionCount(): number { return this._port.liveActionCount; }
451
- get liveBindingCount(): number {
452
- let count = 0;
453
- for (const partition of this._partitions) count += partition.mixer.liveBindingCount;
454
- return count;
455
- }
456
- get sideEffectOwnerCount(): number { return this._port.sideEffectOwnerCount; }
457
-
458
- update(deltaSeconds: number): void {
459
- this._requireActive();
460
- if (!Number.isFinite(deltaSeconds) || deltaSeconds < 0) {
461
- throw new RangeError('HYA Animation3D state-machine deltaSeconds must be finite and non-negative.');
462
- }
463
- this._runFrame(deltaSeconds);
464
- }
465
-
466
- evaluate(): void {
467
- this._requireActive();
468
- this._runFrame(0);
469
- }
470
-
471
- reset(): void {
472
- this._requireActive();
473
- this.controller.reset();
474
- this._time = 0;
475
- this.evaluate();
476
- }
477
-
478
- destroy(): void {
479
- if (this._destroyed) return;
480
- this.controller.destroy();
481
- this._port.destroy();
482
- this._destroyed = true;
483
- }
484
-
485
- private _runFrame(deltaSeconds: number): void {
486
- const nextTime = this._time + deltaSeconds;
487
- this._openFrames(nextTime);
488
- let poses: readonly Animation3DPose[];
489
- try {
490
- poses = runAnimationStateMachineControllerUpdateTransaction(
491
- this.controller,
492
- deltaSeconds,
493
- () => {
494
- for (const partition of this._partitions) partition.adapter.beginFrame(partition.pose);
495
- },
496
- () => {
497
- for (const partition of this._partitions) partition.adapter.endFrame(partition.pose);
498
- const result: Animation3DPose[] = [];
499
- for (const partition of this._partitions) {
500
- result.push(partition.mixer.endSynchronizedFrame(partition.pose));
501
- partition.frameCompleted = true;
502
- }
503
- return result;
504
- },
505
- );
506
- } catch (error) {
507
- this._cancelFrames();
508
- throw error;
509
- }
510
- for (const partition of this._partitions) partition.frameCompleted = false;
511
- this._time = nextTime;
512
- for (let index = 0; index < this._partitions.length; index++) {
513
- this._partitions[index]!.apply(poses[index]!);
514
- }
515
- }
516
-
517
- private _openFrames(time: number): void {
518
- const opened: PartitionRuntime[] = [];
519
- try {
520
- for (const partition of this._partitions) {
521
- partition.previousTime = partition.mixer.time;
522
- partition.frameCompleted = false;
523
- partition.mixer.beginSynchronizedFrame(time, partition.pose);
524
- opened.push(partition);
525
- }
526
- } catch (error) {
527
- for (let index = opened.length - 1; index >= 0; index--) {
528
- opened[index]!.mixer.cancelSynchronizedFrame(opened[index]!.pose);
529
- }
530
- throw error;
531
- }
532
- }
533
-
534
- private _cancelFrames(): void {
535
- for (const partition of this._partitions) partition.adapter.cancelFrame(partition.pose);
536
- for (let index = this._partitions.length - 1; index >= 0; index--) {
537
- const partition = this._partitions[index]!;
538
- if (partition.frameCompleted) {
539
- partition.mixer.rollbackCompletedSynchronizedFrame(partition.previousTime);
540
- partition.frameCompleted = false;
541
- } else partition.mixer.cancelSynchronizedFrame(partition.pose);
542
- }
543
- }
544
-
545
- private _requireActive(): void {
546
- if (this._destroyed) throw new Error('HYA Animation3D state-machine runtime has been destroyed.');
547
- }
548
- }
549
-
550
- function forEachChild(
551
- partitions: readonly PartitionRuntime[],
552
- handle: HyaAnimation3DStateMachineActionHandle,
553
- visit: (adapter: Animation3DStateMachineMixerAdapter, child: Animation3DStateMachineActionRuntimeHandle) => void,
554
- ): void {
555
- let childIndex = 0;
556
- for (const partition of partitions) {
557
- if (!partition.clips.has(handle.clipId)) continue;
558
- visit(partition.adapter, handle.children[childIndex++]!);
559
- }
560
- }
561
-
562
- function cloneOwners(source: ReadonlyMap<string, readonly string[]>): Map<string, string[]> {
563
- const result = new Map<string, string[]>();
564
- for (const [key, owners] of source) result.set(key, [...owners]);
565
- return result;
566
- }
567
-
568
- function translateActionOptions(
569
- options: AnimationStateMachineActionOptions,
570
- bindingIds: ReadonlyMap<string, string> | undefined,
571
- ): AnimationStateMachineActionOptions {
572
- if (!options.mask || !bindingIds || bindingIds.size === 0) return options;
573
- const translate = (ids: readonly string[] | undefined): readonly string[] | undefined => {
574
- if (!ids) return undefined;
575
- return Object.freeze(ids.map(id => bindingIds.get(id) ?? id));
576
- };
577
- const include = translate(options.mask.include);
578
- const exclude = translate(options.mask.exclude);
579
- return {
580
- ...options,
581
- mask: Object.freeze({
582
- ...(include === undefined ? {} : { include }),
583
- ...(exclude === undefined ? {} : { exclude }),
584
- }),
585
- };
586
- }
587
-
588
- function playbackPosition(
589
- time: number,
590
- duration: number,
591
- loop: AnimationStateMachineActionOptions['loop'],
592
- ): { readonly localTime: number; readonly traversal: number } {
593
- if (duration <= TIME_EPSILON || loop === 'once') {
594
- return { localTime: Math.min(duration, Math.max(0, time)), traversal: 0 };
595
- }
596
- const traversal = Math.floor(time / duration);
597
- let localTime = time - traversal * duration;
598
- if (localTime < 0) localTime += duration;
599
- if (loop === 'ping-pong' && Math.abs(traversal % 2) === 1) localTime = duration - localTime;
600
- return { localTime, traversal };
601
- }
602
-
603
- function particleCueActive(
604
- cue: HyaAnimation3DParticleCue,
605
- time: number,
606
- duration: number,
607
- ): boolean {
608
- const atTerminalEnd = Math.abs(cue.end - duration) <= TIME_EPSILON
609
- && Math.abs(time - duration) <= TIME_EPSILON;
610
- return time >= cue.start - TIME_EPSILON
611
- && (time < cue.end - TIME_EPSILON || atTerminalEnd);
612
- }
613
-
614
- function stopParticle(emitter: ParticleEmitter3D): void {
615
- emitter.playing = false;
616
- emitter.emitting = false;
617
- emitter.clear();
618
- }