@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.
- package/README.md +25 -0
- package/dist/animation/Animation2DComponent.d.ts +18 -0
- package/dist/animation/Animation2DExtensionRegistry.d.ts +7 -0
- package/dist/animation/Animation2DRenderSystem.d.ts +6 -0
- package/dist/animation/Animation2DRuntime.d.ts +6 -2
- package/dist/animation/AnimationTextRasterizer.d.ts +4 -0
- package/dist/animation/AnimationVisual2D.d.ts +58 -2
- package/dist/animation/interaction/InteractionRuntime.d.ts +83 -0
- package/dist/animation/interaction/runtime-types.d.ts +257 -0
- package/dist/animation.d.ts +3 -1
- package/dist/animation.js +551 -59
- package/dist/animation3d.js +1 -1
- package/dist/canvas-text.js +1 -1
- package/dist/chunks/2d-ui-animation-2d.generated-FpziAeGJ.js +4 -0
- package/dist/chunks/2d-ui-indexed-sprite.generated-DmKR0CC3.js +4 -0
- package/dist/chunks/Animation2DStateMachine-BHcA6Cu3.js +18212 -0
- package/dist/chunks/{AnimationStateMachineController-BIcAh-sT.js → AnimationStateMachineController-4sKaqh9E.js} +2 -2
- package/dist/chunks/AnimationVisual2D-8y3qp0_U.js +230 -0
- package/dist/chunks/{RenderSystem2DBase-DDT61dAu.js → RenderSystem2DBase-CF2s00vg.js} +2 -2
- package/dist/controls/VirtualJoystickControls.d.ts +46 -0
- package/dist/controls/contracts.d.ts +91 -0
- package/dist/controls.d.ts +2 -0
- package/dist/controls.js +358 -0
- package/dist/deformable-animation/runtime/DeformableMesh2DRuntimeExtension.d.ts +11 -0
- package/dist/deformable-animation/runtime/DeformableMesh2DSampler.d.ts +11 -0
- package/dist/deformable-animation.d.ts +5 -0
- package/dist/deformable-animation.js +316 -0
- package/dist/experimental-indexed-sprite.d.ts +5 -0
- package/dist/experimental-indexed-sprite.js +482 -0
- package/dist/gltf-worker-runtime.js +9 -9
- package/dist/hya-state-machine.js +3 -2
- package/dist/index.js +1 -1
- package/dist/indexed-sprite/AtlasLayout.d.ts +2 -0
- package/dist/indexed-sprite/IndexedSpriteRenderer.d.ts +23 -0
- package/dist/indexed-sprite/contracts.d.ts +89 -0
- package/dist/internal/2d-ui-shader-artifact.js +232 -23
- package/dist/ray-tracing/acceleration/bvh.d.ts +37 -0
- package/dist/ray-tracing/acceleration/index.d.ts +6 -0
- package/dist/ray-tracing/acceleration/pack.d.ts +152 -0
- package/dist/ray-tracing/acceleration/query.d.ts +4 -0
- package/dist/ray-tracing/acceleration/runtime.d.ts +30 -0
- package/dist/ray-tracing/acceleration/tlas.d.ts +4 -0
- package/dist/ray-tracing/acceleration/types.d.ts +165 -0
- package/dist/ray-tracing/denoise/index.d.ts +3 -0
- package/dist/ray-tracing/denoise/layout.d.ts +9 -0
- package/dist/ray-tracing/denoise/runtime.d.ts +23 -0
- package/dist/ray-tracing/denoise/types.d.ts +28 -0
- package/dist/ray-tracing/hybrid/contract.d.ts +2 -0
- package/dist/ray-tracing/hybrid/index.d.ts +5 -0
- package/dist/ray-tracing/hybrid/layout.d.ts +17 -0
- package/dist/ray-tracing/hybrid/plan.d.ts +2 -0
- package/dist/ray-tracing/hybrid/runtime.d.ts +31 -0
- package/dist/ray-tracing/hybrid/shaders/hybrid-artifact.generated.d.ts +625 -0
- package/dist/ray-tracing/hybrid/types.d.ts +144 -0
- package/dist/ray-tracing/lifecycle/device-recovery.d.ts +31 -0
- package/dist/ray-tracing/lifecycle/index.d.ts +2 -0
- package/dist/ray-tracing/lifecycle/types.d.ts +37 -0
- package/dist/ray-tracing/material/index.d.ts +2 -0
- package/dist/ray-tracing/material/pack.d.ts +5 -0
- package/dist/ray-tracing/material/types.d.ts +63 -0
- package/dist/ray-tracing/reference/index.d.ts +122 -0
- package/dist/ray-tracing/renderer/index.d.ts +7 -0
- package/dist/ray-tracing/renderer/layout.d.ts +20 -0
- package/dist/ray-tracing/renderer/plan.d.ts +2 -0
- package/dist/ray-tracing/renderer/reference.d.ts +17 -0
- package/dist/ray-tracing/renderer/runtime.d.ts +39 -0
- package/dist/ray-tracing/renderer/scene.d.ts +4 -0
- package/dist/ray-tracing/renderer/types.d.ts +115 -0
- package/dist/ray-tracing/sampling/index.d.ts +8 -0
- package/dist/ray-tracing/sampling/layout.d.ts +12 -0
- package/dist/ray-tracing/sampling/plan.d.ts +5 -0
- package/dist/ray-tracing/sampling/revision.d.ts +15 -0
- package/dist/ray-tracing/sampling/runtime.d.ts +44 -0
- package/dist/ray-tracing/sampling/sequence.d.ts +2 -0
- package/dist/ray-tracing/sampling/types.d.ts +96 -0
- package/dist/ray-tracing/scene/index.d.ts +41 -0
- package/dist/ray-tracing/traversal/index.d.ts +4 -0
- package/dist/ray-tracing/traversal/layout.d.ts +16 -0
- package/dist/ray-tracing/traversal/plan.d.ts +2 -0
- package/dist/ray-tracing/traversal/runtime.d.ts +25 -0
- package/dist/ray-tracing/traversal/types.d.ts +79 -0
- package/dist/ray-tracing/worker/client.d.ts +25 -0
- package/dist/ray-tracing/worker/index.d.ts +5 -0
- package/dist/ray-tracing/worker/runtime.d.ts +11 -0
- package/dist/ray-tracing/worker/serialization.d.ts +16 -0
- package/dist/ray-tracing/worker/source.d.ts +1 -0
- package/dist/ray-tracing/worker/types.d.ts +91 -0
- package/dist/ray-tracing.d.ts +17 -0
- package/dist/ray-tracing.js +7666 -0
- package/dist/spine.js +1 -1
- package/dist/tilemap.js +1 -1
- package/package.json +26 -23
- package/dist/animation/Animation2DStateMachineVisualRuntime.d.ts +0 -27
- package/dist/animation/Particle2DDescriptorAdapter.d.ts +0 -5
- package/dist/animation3d/Animation3DResource.d.ts +0 -28
- package/dist/animation3d/hya/HyaAnimation3DStateMachineRuntime.d.ts +0 -65
- package/dist/animation3d/hya/index.d.ts +0 -4
- package/dist/animation3d/runtime/integration/Animation3DStateMachineMixerAdapter.d.ts +0 -81
- package/dist/animation3d/runtime/integration/Animation3DStateMachineMixerIntegration.d.ts +0 -39
- package/dist/animation3d/runtime/integration/index.d.ts +0 -2
- package/dist/animation3d/runtime/mixer/Action.d.ts +0 -150
- package/dist/animation3d/runtime/mixer/Animation3DMixerRuntimeStore.d.ts +0 -6
- package/dist/animation3d/runtime/mixer/Mixer.d.ts +0 -59
- package/dist/animation3d/runtime/mixer/PoseBuffer.d.ts +0 -1
- package/dist/animation3d/runtime/mixer/TrackSampler.d.ts +0 -24
- package/dist/animation3d/runtime/mixer/index.d.ts +0 -4
- package/dist/animation3d/runtime/state-machine/Animation3DBlendTreeWeights.d.ts +0 -1
- package/dist/animation3d/runtime/state-machine/Animation3DStateMachineCompiler.d.ts +0 -1
- package/dist/animation3d/runtime/state-machine/Animation3DStateMachineController.d.ts +0 -1
- package/dist/animation3d/runtime/state-machine/Animation3DStateMachineMixerPort.d.ts +0 -1
- package/dist/animation3d/runtime/state-machine/index.d.ts +0 -6
- package/dist/benchmark.d.ts +0 -30
- package/dist/chunks/2d-ui-animation-2d.generated-D4aHzFU2.js +0 -4
- package/dist/chunks/Animation2DStateMachine-9IonguNa.js +0 -3245
- package/dist/gltf/GltfAccessorReader.d.ts +0 -7
- package/dist/gltf/GltfDracoDecoder.d.ts +0 -4
- package/dist/gltf/GltfLoaderErrors.d.ts +0 -4
- package/dist/gltf/GltfMaterialDescriptor.d.ts +0 -23
- package/dist/gltf/GltfMaterialLoader.d.ts +0 -6
- package/dist/gltf-worker-runtime.d.ts +0 -7
- package/dist/plugins/pluginUtils.d.ts +0 -20
- package/dist/plugins.d.ts +0 -6
- package/dist/shaders/generated/2d-ui-artifact.generated.d.ts +0 -658
- package/dist/spine/Spine2DGpuRenderer.d.ts +0 -65
- package/dist/spine/Spine2DRuntime.d.ts +0 -103
- package/dist/spine/SpineAnimationBoneTimelines.d.ts +0 -8
- package/dist/spine/SpineFloatBuilder.d.ts +0 -15
- package/dist/spine/SpinePathConstraintSolver.d.ts +0 -32
- package/dist/spine/SpineSkeletonRuntime.d.ts +0 -185
- package/dist/spine/SpineSlotAnimation.d.ts +0 -17
- package/dist/spine/SpineTimelineRuntime.d.ts +0 -25
- package/dist/spine/SpineVertexBuilder.d.ts +0 -61
- package/dist/tilemap/Tilemap2DRenderer.d.ts +0 -24
- package/dist/utils/arrayAccess.d.ts +0 -4
- package/dist/utils/camera2d.d.ts +0 -12
- package/src/animation/Animation2DComponent.ts +0 -135
- package/src/animation/Animation2DExtensionRegistry.ts +0 -52
- package/src/animation/Animation2DRenderSystem.ts +0 -1026
- package/src/animation/Animation2DRuntime.ts +0 -1326
- package/src/animation/Animation2DStateMachine.ts +0 -39
- package/src/animation/Animation2DStateMachineComponent.ts +0 -228
- package/src/animation/Animation2DStateMachineRuntime.ts +0 -141
- package/src/animation/Animation2DStateMachineSystem.ts +0 -60
- package/src/animation/Animation2DStateMachineVisualRuntime.ts +0 -282
- package/src/animation/Animation2DSystem.ts +0 -72
- package/src/animation/AnimationAssetLoader.ts +0 -84
- package/src/animation/AnimationAudioClip.ts +0 -140
- package/src/animation/AnimationPathTessellator.ts +0 -691
- package/src/animation/AnimationTextRasterizer.ts +0 -340
- package/src/animation/AnimationVisual2D.ts +0 -153
- package/src/animation/HyaAnimation2DClipAdapter.ts +0 -845
- package/src/animation/Particle2DDescriptorAdapter.ts +0 -35
- package/src/animation/runtime/mixer/Action.ts +0 -876
- package/src/animation/runtime/mixer/Mixer.ts +0 -505
- package/src/animation/runtime/mixer/PoseBuffer.ts +0 -105
- package/src/animation/runtime/mixer/Sampler.ts +0 -252
- package/src/animation/runtime/mixer/Types.ts +0 -138
- package/src/animation/runtime/mixer/index.ts +0 -31
- package/src/animation-state-machine/AnimationStateMachine.ts +0 -146
- package/src/animation-state-machine/AnimationStateMachineChannels.ts +0 -116
- package/src/animation-state-machine/runtime/Animation2DStateMachineMixerAdapter.ts +0 -197
- package/src/animation-state-machine/runtime/AnimationStateMachineBlendTreeWeights.ts +0 -503
- package/src/animation-state-machine/runtime/AnimationStateMachineCompiler.ts +0 -763
- package/src/animation-state-machine/runtime/AnimationStateMachineController.ts +0 -987
- package/src/animation-state-machine/runtime/AnimationStateMachineMixerPort.ts +0 -54
- package/src/animation-state-machine/runtime/index.ts +0 -47
- package/src/animation.ts +0 -33
- package/src/animation3d/Animation3DAction.ts +0 -73
- package/src/animation3d/Animation3DBinding.ts +0 -116
- package/src/animation3d/Animation3DClip.ts +0 -22
- package/src/animation3d/Animation3DError.ts +0 -34
- package/src/animation3d/Animation3DMixer.ts +0 -82
- package/src/animation3d/Animation3DPose.ts +0 -100
- package/src/animation3d/Animation3DPoseBuffer.ts +0 -85
- package/src/animation3d/Animation3DResource.ts +0 -49
- package/src/animation3d/Animation3DStateMachine.ts +0 -126
- package/src/animation3d/Animation3DStateMachineRuntime.ts +0 -191
- package/src/animation3d/Animation3DTrack.ts +0 -29
- package/src/animation3d/hya/HyaAnimation3DRuntime.ts +0 -756
- package/src/animation3d/hya/HyaAnimation3DStateMachineRuntime.ts +0 -618
- package/src/animation3d/hya/HyaAnimation3DTypes.ts +0 -168
- package/src/animation3d/hya/index.ts +0 -10
- package/src/animation3d/index.ts +0 -76
- package/src/animation3d/runtime/integration/Animation3DStateMachineMixerAdapter.ts +0 -325
- package/src/animation3d/runtime/integration/Animation3DStateMachineMixerIntegration.ts +0 -158
- package/src/animation3d/runtime/integration/index.ts +0 -9
- package/src/animation3d/runtime/mixer/Action.ts +0 -833
- package/src/animation3d/runtime/mixer/Animation3DMixerRuntimeStore.ts +0 -26
- package/src/animation3d/runtime/mixer/Mixer.ts +0 -562
- package/src/animation3d/runtime/mixer/PoseBuffer.ts +0 -1
- package/src/animation3d/runtime/mixer/TrackSampler.ts +0 -399
- package/src/animation3d/runtime/mixer/index.ts +0 -8
- package/src/animation3d/runtime/state-machine/Animation3DBlendTreeWeights.ts +0 -4
- package/src/animation3d/runtime/state-machine/Animation3DStateMachineCompiler.ts +0 -1
- package/src/animation3d/runtime/state-machine/Animation3DStateMachineController.ts +0 -1
- package/src/animation3d/runtime/state-machine/Animation3DStateMachineMixerPort.ts +0 -1
- package/src/animation3d/runtime/state-machine/index.ts +0 -45
- package/src/animation3d.ts +0 -5
- package/src/benchmark.ts +0 -168
- package/src/canvas-text/CanvasText2DRenderSystem.ts +0 -292
- package/src/canvas-text/CanvasTextComponent.ts +0 -47
- package/src/canvas-text.ts +0 -4
- package/src/experimental-gltf-worker.ts +0 -18
- package/src/experimental-spine-worker.ts +0 -9
- package/src/gltf/GltfAccessorReader.ts +0 -271
- package/src/gltf/GltfAnimation3DAdapter.ts +0 -680
- package/src/gltf/GltfAnimationRuntime.ts +0 -392
- package/src/gltf/GltfAssetWorkerClient.ts +0 -136
- package/src/gltf/GltfCompatibilityReport.ts +0 -214
- package/src/gltf/GltfConservativeBounds.ts +0 -219
- package/src/gltf/GltfDracoDecoder.ts +0 -251
- package/src/gltf/GltfExtensionAdapter.ts +0 -340
- package/src/gltf/GltfLoaderContract.ts +0 -333
- package/src/gltf/GltfLoaderErrors.ts +0 -59
- package/src/gltf/GltfMaterialDescriptor.ts +0 -134
- package/src/gltf/GltfMaterialEncoder.ts +0 -173
- package/src/gltf/GltfMaterialLoader.ts +0 -293
- package/src/gltf/GltfModelComponent.ts +0 -115
- package/src/gltf/GltfModelSystem.ts +0 -208
- package/src/gltf/GltfPlugin.ts +0 -84
- package/src/gltf/GltfSchema.ts +0 -229
- package/src/gltf/GltfUvSemanticPlanner.ts +0 -166
- package/src/gltf/gltfLoader.ts +0 -910
- package/src/gltf-animation3d.ts +0 -10
- package/src/gltf-worker-runtime.ts +0 -10
- package/src/gltf.ts +0 -56
- package/src/grid/Grid2DComponent.ts +0 -69
- package/src/grid.ts +0 -2
- package/src/hya-state-machine.ts +0 -19
- package/src/index.ts +0 -2
- package/src/plugins/pluginUtils.ts +0 -50
- package/src/plugins.ts +0 -6
- package/src/shaders/generated/2d-ui-animation-2d.generated.wgsl +0 -242
- package/src/shaders/generated/2d-ui-artifact.generated.ts +0 -867
- package/src/shaders/generated/2d-ui-canvas-text-2d.generated.wgsl +0 -38
- package/src/shaders/generated/2d-ui-spine2d.generated.wgsl +0 -41
- package/src/shaders/generated/2d-ui-tilemap2d.generated.wgsl +0 -36
- package/src/spine/Spine2DComponent.ts +0 -168
- package/src/spine/Spine2DGpuRenderer.ts +0 -449
- package/src/spine/Spine2DRenderSystem.ts +0 -199
- package/src/spine/Spine2DRuntime.ts +0 -1529
- package/src/spine/SpineAnimationBoneTimelines.ts +0 -30
- package/src/spine/SpineAssetParser.ts +0 -20
- package/src/spine/SpineAssetWorkerClient.ts +0 -112
- package/src/spine/SpineAssetWorkerContract.ts +0 -4
- package/src/spine/SpineAtlasParser.ts +0 -127
- package/src/spine/SpineFloatBuilder.ts +0 -66
- package/src/spine/SpinePathConstraintSolver.ts +0 -582
- package/src/spine/SpinePlugin.ts +0 -76
- package/src/spine/SpineSkeletonRuntime.ts +0 -521
- package/src/spine/SpineSlotAnimation.ts +0 -195
- package/src/spine/SpineTimelineRuntime.ts +0 -453
- package/src/spine/SpineVertexBuilder.ts +0 -686
- package/src/spine.ts +0 -7
- package/src/tilemap/Tilemap2DComponent.ts +0 -232
- package/src/tilemap/Tilemap2DRenderSystem.ts +0 -58
- package/src/tilemap/Tilemap2DRenderer.ts +0 -289
- package/src/tilemap/TilemapPlugin.ts +0 -75
- package/src/tilemap.ts +0 -6
- package/src/tween/Tween2DComponent.ts +0 -83
- package/src/tween/Tween2DSystem.ts +0 -78
- package/src/tween.ts +0 -4
- package/src/types/earcut.d.ts +0 -7
- package/src/types/wgsl.d.ts +0 -4
- package/src/utils/RenderSystem2DBase.ts +0 -164
- package/src/utils/arrayAccess.ts +0 -17
- package/src/utils/camera2d.ts +0 -68
- package/src/utils/render2dGpu.ts +0 -132
- package/test/fixtures/gltf/animation-characterization.gltf +0 -344
|
@@ -1,763 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AnimationStateMachineBindingMask as Animation3DBindingMask,
|
|
3
|
-
AnimationStateMachineBlendMode as Animation3DBlendMode,
|
|
4
|
-
AnimationStateMachineDefinition,
|
|
5
|
-
AnimationStateMachineLoopMode as Animation3DLoopMode,
|
|
6
|
-
AnimationStateMachineMotionDefinition as Animation3DMotionDefinition,
|
|
7
|
-
AnimationStateMachineParameterDefinition as Animation3DParameterDefinition,
|
|
8
|
-
AnimationStateMachineTransitionCondition as Animation3DTransitionCondition,
|
|
9
|
-
AnimationStateMachineTransitionInterruption as Animation3DTransitionInterruption,
|
|
10
|
-
} from '../AnimationStateMachine.js';
|
|
11
|
-
|
|
12
|
-
type LegacyAnimation3DStateMachineDefinition =
|
|
13
|
-
Omit<AnimationStateMachineDefinition, 'format'> & Readonly<{
|
|
14
|
-
format: 'haiyue-animation3d-state-machine@1';
|
|
15
|
-
}>;
|
|
16
|
-
|
|
17
|
-
type SupportedAnimationStateMachineDefinition =
|
|
18
|
-
| AnimationStateMachineDefinition
|
|
19
|
-
| LegacyAnimation3DStateMachineDefinition;
|
|
20
|
-
|
|
21
|
-
export type Animation3DStateMachineValidationCode =
|
|
22
|
-
| 'invalid-value'
|
|
23
|
-
| 'duplicate-id'
|
|
24
|
-
| 'missing-reference'
|
|
25
|
-
| 'parameter-type-mismatch'
|
|
26
|
-
| 'invalid-operator'
|
|
27
|
-
| 'empty-blend-tree'
|
|
28
|
-
| 'invalid-thresholds'
|
|
29
|
-
| 'recursive-motion';
|
|
30
|
-
|
|
31
|
-
export interface Animation3DStateMachineValidationIssue {
|
|
32
|
-
readonly code: Animation3DStateMachineValidationCode;
|
|
33
|
-
readonly path: string;
|
|
34
|
-
readonly message: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export class AnimationStateMachineValidationError extends Error {
|
|
38
|
-
readonly issues: readonly Animation3DStateMachineValidationIssue[];
|
|
39
|
-
|
|
40
|
-
constructor(issues: readonly Animation3DStateMachineValidationIssue[]) {
|
|
41
|
-
super(
|
|
42
|
-
`Invalid animation state-machine definition (${issues.length} ${
|
|
43
|
-
issues.length === 1 ? 'issue' : 'issues'
|
|
44
|
-
}).`,
|
|
45
|
-
);
|
|
46
|
-
this.name = 'AnimationStateMachineValidationError';
|
|
47
|
-
this.issues = Object.freeze([...issues]);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export type CompiledAnimation3DParameterType =
|
|
52
|
-
| 'float'
|
|
53
|
-
| 'integer'
|
|
54
|
-
| 'boolean'
|
|
55
|
-
| 'trigger';
|
|
56
|
-
|
|
57
|
-
export interface CompiledAnimation3DParameter {
|
|
58
|
-
readonly index: number;
|
|
59
|
-
readonly name: string;
|
|
60
|
-
readonly type: CompiledAnimation3DParameterType;
|
|
61
|
-
/** Triggers and false booleans use 0; true booleans use 1. */
|
|
62
|
-
readonly defaultValue: number;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export type CompiledAnimation3DConditionOperator =
|
|
66
|
-
| 'greater'
|
|
67
|
-
| 'greater-or-equal'
|
|
68
|
-
| 'less'
|
|
69
|
-
| 'less-or-equal'
|
|
70
|
-
| 'equal'
|
|
71
|
-
| 'not-equal'
|
|
72
|
-
| 'is-true'
|
|
73
|
-
| 'is-false'
|
|
74
|
-
| 'triggered';
|
|
75
|
-
|
|
76
|
-
export interface CompiledAnimation3DCondition {
|
|
77
|
-
readonly parameterIndex: number;
|
|
78
|
-
readonly operator: CompiledAnimation3DConditionOperator;
|
|
79
|
-
readonly value: number;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface CompiledAnimation3DClipMotion {
|
|
83
|
-
readonly kind: 'clip';
|
|
84
|
-
readonly clipId: string;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface CompiledAnimation3DBlend1DChild {
|
|
88
|
-
readonly threshold: number;
|
|
89
|
-
readonly motion: CompiledAnimation3DMotion;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export interface CompiledAnimation3DBlend1DMotion {
|
|
93
|
-
readonly kind: 'blend-1d';
|
|
94
|
-
readonly parameterIndex: number;
|
|
95
|
-
readonly children: readonly CompiledAnimation3DBlend1DChild[];
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export interface CompiledAnimation3DBlend2DChild {
|
|
99
|
-
readonly position: readonly [number, number];
|
|
100
|
-
readonly motion: CompiledAnimation3DMotion;
|
|
101
|
-
readonly declarationIndex: number;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export interface CompiledAnimation3DBlend2DMotion {
|
|
105
|
-
readonly kind: 'blend-2d';
|
|
106
|
-
readonly algorithm: 'cartesian' | 'directional';
|
|
107
|
-
readonly parameterXIndex: number;
|
|
108
|
-
readonly parameterYIndex: number;
|
|
109
|
-
readonly children: readonly CompiledAnimation3DBlend2DChild[];
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export type CompiledAnimation3DMotion =
|
|
113
|
-
| CompiledAnimation3DClipMotion
|
|
114
|
-
| CompiledAnimation3DBlend1DMotion
|
|
115
|
-
| CompiledAnimation3DBlend2DMotion;
|
|
116
|
-
|
|
117
|
-
export interface CompiledAnimation3DState {
|
|
118
|
-
readonly index: number;
|
|
119
|
-
readonly id: string;
|
|
120
|
-
readonly name: string;
|
|
121
|
-
readonly motion: CompiledAnimation3DMotion;
|
|
122
|
-
readonly speed: number;
|
|
123
|
-
readonly speedParameterIndex: number;
|
|
124
|
-
readonly loop: Animation3DLoopMode;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export interface CompiledAnimation3DTransition {
|
|
128
|
-
readonly index: number;
|
|
129
|
-
readonly id: string;
|
|
130
|
-
/** -1 denotes any-state. */
|
|
131
|
-
readonly fromStateIndex: number;
|
|
132
|
-
readonly toStateIndex: number;
|
|
133
|
-
readonly conditions: readonly CompiledAnimation3DCondition[];
|
|
134
|
-
readonly triggerParameterIndices: readonly number[];
|
|
135
|
-
readonly duration: number;
|
|
136
|
-
readonly hasExitTime: boolean;
|
|
137
|
-
readonly exitTime: number;
|
|
138
|
-
readonly destinationOffset: number;
|
|
139
|
-
readonly interruption: Animation3DTransitionInterruption;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface CompiledAnimation3DLayer {
|
|
143
|
-
readonly index: number;
|
|
144
|
-
readonly id: string;
|
|
145
|
-
readonly name: string;
|
|
146
|
-
readonly initialStateIndex: number;
|
|
147
|
-
readonly states: readonly CompiledAnimation3DState[];
|
|
148
|
-
/** Preserves declaration order, which is transition priority. */
|
|
149
|
-
readonly transitions: readonly CompiledAnimation3DTransition[];
|
|
150
|
-
readonly blendMode: Animation3DBlendMode;
|
|
151
|
-
readonly weight: number;
|
|
152
|
-
readonly mask: Animation3DBindingMask | null;
|
|
153
|
-
/** Compiler-created lookup; the update path uses numeric indices instead. */
|
|
154
|
-
readonly stateIndexById: ReadonlyMap<string, number>;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export interface CompiledAnimation3DStateMachine {
|
|
158
|
-
readonly format: 'haiyue-animation-state-machine-compiled@1';
|
|
159
|
-
readonly id: string;
|
|
160
|
-
readonly name: string;
|
|
161
|
-
readonly parameters: readonly CompiledAnimation3DParameter[];
|
|
162
|
-
readonly layers: readonly CompiledAnimation3DLayer[];
|
|
163
|
-
/** Setter/query boundary lookup; the update path uses numeric indices. */
|
|
164
|
-
readonly parameterIndexByName: ReadonlyMap<string, number>;
|
|
165
|
-
readonly layerIndexById: ReadonlyMap<string, number>;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
interface ValidationContext {
|
|
169
|
-
readonly issues: Animation3DStateMachineValidationIssue[];
|
|
170
|
-
readonly parameterByName: Map<string, Animation3DParameterDefinition>;
|
|
171
|
-
readonly motionStack: Set<object>;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const INTERRUPTION_VALUES: readonly Animation3DTransitionInterruption[] = [
|
|
175
|
-
'none',
|
|
176
|
-
'source',
|
|
177
|
-
'destination',
|
|
178
|
-
'source-then-destination',
|
|
179
|
-
'destination-then-source',
|
|
180
|
-
];
|
|
181
|
-
|
|
182
|
-
export function validateAnimationStateMachineDefinition(
|
|
183
|
-
definition: SupportedAnimationStateMachineDefinition,
|
|
184
|
-
): readonly Animation3DStateMachineValidationIssue[] {
|
|
185
|
-
const issues: Animation3DStateMachineValidationIssue[] = [];
|
|
186
|
-
const parameterByName = new Map<string, Animation3DParameterDefinition>();
|
|
187
|
-
const context: ValidationContext = {
|
|
188
|
-
issues,
|
|
189
|
-
parameterByName,
|
|
190
|
-
motionStack: new Set<object>(),
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
if (
|
|
194
|
-
definition.format !== 'haiyue-animation-state-machine@1'
|
|
195
|
-
&& definition.format !== 'haiyue-animation3d-state-machine@1'
|
|
196
|
-
) {
|
|
197
|
-
issue(context, 'invalid-value', 'format', 'Unsupported state-machine format.');
|
|
198
|
-
}
|
|
199
|
-
validateNonEmptyString(context, definition.id, 'id');
|
|
200
|
-
validateNonEmptyString(context, definition.name, 'name');
|
|
201
|
-
|
|
202
|
-
definition.parameters.forEach((parameter, parameterIndex) => {
|
|
203
|
-
const path = `parameters[${parameterIndex}]`;
|
|
204
|
-
validateNonEmptyString(context, parameter.name, `${path}.name`);
|
|
205
|
-
if (parameterByName.has(parameter.name)) {
|
|
206
|
-
issue(
|
|
207
|
-
context,
|
|
208
|
-
'duplicate-id',
|
|
209
|
-
`${path}.name`,
|
|
210
|
-
`Duplicate parameter name "${parameter.name}".`,
|
|
211
|
-
);
|
|
212
|
-
} else {
|
|
213
|
-
parameterByName.set(parameter.name, parameter);
|
|
214
|
-
}
|
|
215
|
-
if (parameter.type === 'float') {
|
|
216
|
-
validateFinite(context, parameter.defaultValue, `${path}.defaultValue`);
|
|
217
|
-
} else if (parameter.type === 'integer') {
|
|
218
|
-
if (!Number.isSafeInteger(parameter.defaultValue)) {
|
|
219
|
-
issue(
|
|
220
|
-
context,
|
|
221
|
-
'invalid-value',
|
|
222
|
-
`${path}.defaultValue`,
|
|
223
|
-
'Integer parameter defaults must be safe integers.',
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
} else if (parameter.type === 'boolean') {
|
|
227
|
-
if (typeof parameter.defaultValue !== 'boolean') {
|
|
228
|
-
issue(
|
|
229
|
-
context,
|
|
230
|
-
'invalid-value',
|
|
231
|
-
`${path}.defaultValue`,
|
|
232
|
-
'Boolean parameter defaults must be boolean.',
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
} else if (parameter.type === 'trigger') {
|
|
236
|
-
// Triggers always compile with a cleared default.
|
|
237
|
-
} else {
|
|
238
|
-
issue(context, 'invalid-value', `${path}.type`, 'Unknown parameter type.');
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
const layerIds = new Set<string>();
|
|
243
|
-
definition.layers.forEach((layer, layerIndex) => {
|
|
244
|
-
const layerPath = `layers[${layerIndex}]`;
|
|
245
|
-
validateNonEmptyString(context, layer.id, `${layerPath}.id`);
|
|
246
|
-
validateNonEmptyString(context, layer.name, `${layerPath}.name`);
|
|
247
|
-
if (layerIds.has(layer.id)) {
|
|
248
|
-
issue(context, 'duplicate-id', `${layerPath}.id`, `Duplicate layer id "${layer.id}".`);
|
|
249
|
-
}
|
|
250
|
-
layerIds.add(layer.id);
|
|
251
|
-
validateUnitWeight(context, layer.weight ?? 1, `${layerPath}.weight`);
|
|
252
|
-
if (
|
|
253
|
-
layer.blendMode !== undefined
|
|
254
|
-
&& layer.blendMode !== 'override'
|
|
255
|
-
&& layer.blendMode !== 'additive'
|
|
256
|
-
) {
|
|
257
|
-
issue(context, 'invalid-value', `${layerPath}.blendMode`, 'Unknown layer blend mode.');
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const stateIds = new Set<string>();
|
|
261
|
-
layer.states.forEach((state, stateIndex) => {
|
|
262
|
-
const statePath = `${layerPath}.states[${stateIndex}]`;
|
|
263
|
-
validateNonEmptyString(context, state.id, `${statePath}.id`);
|
|
264
|
-
validateNonEmptyString(context, state.name, `${statePath}.name`);
|
|
265
|
-
if (stateIds.has(state.id)) {
|
|
266
|
-
issue(context, 'duplicate-id', `${statePath}.id`, `Duplicate state id "${state.id}".`);
|
|
267
|
-
}
|
|
268
|
-
stateIds.add(state.id);
|
|
269
|
-
validateFinite(context, state.speed ?? 1, `${statePath}.speed`);
|
|
270
|
-
if (
|
|
271
|
-
state.loop !== undefined
|
|
272
|
-
&& state.loop !== 'once'
|
|
273
|
-
&& state.loop !== 'repeat'
|
|
274
|
-
&& state.loop !== 'ping-pong'
|
|
275
|
-
) {
|
|
276
|
-
issue(context, 'invalid-value', `${statePath}.loop`, 'Unknown state loop mode.');
|
|
277
|
-
}
|
|
278
|
-
if (state.speedParameter !== undefined) {
|
|
279
|
-
validateNumericParameter(context, state.speedParameter, `${statePath}.speedParameter`);
|
|
280
|
-
}
|
|
281
|
-
validateMotion(context, state.motion, `${statePath}.motion`);
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
if (!stateIds.has(layer.initialStateId)) {
|
|
285
|
-
issue(
|
|
286
|
-
context,
|
|
287
|
-
'missing-reference',
|
|
288
|
-
`${layerPath}.initialStateId`,
|
|
289
|
-
`Initial state "${layer.initialStateId}" does not exist in this layer.`,
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const transitionIds = new Set<string>();
|
|
294
|
-
layer.transitions.forEach((transition, transitionIndex) => {
|
|
295
|
-
const transitionPath = `${layerPath}.transitions[${transitionIndex}]`;
|
|
296
|
-
validateNonEmptyString(context, transition.id, `${transitionPath}.id`);
|
|
297
|
-
if (transitionIds.has(transition.id)) {
|
|
298
|
-
issue(
|
|
299
|
-
context,
|
|
300
|
-
'duplicate-id',
|
|
301
|
-
`${transitionPath}.id`,
|
|
302
|
-
`Duplicate transition id "${transition.id}".`,
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
transitionIds.add(transition.id);
|
|
306
|
-
if (transition.from !== '*' && !stateIds.has(transition.from)) {
|
|
307
|
-
issue(
|
|
308
|
-
context,
|
|
309
|
-
'missing-reference',
|
|
310
|
-
`${transitionPath}.from`,
|
|
311
|
-
`Source state "${transition.from}" does not exist in this layer.`,
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
if (!stateIds.has(transition.to)) {
|
|
315
|
-
issue(
|
|
316
|
-
context,
|
|
317
|
-
'missing-reference',
|
|
318
|
-
`${transitionPath}.to`,
|
|
319
|
-
`Destination state "${transition.to}" does not exist in this layer.`,
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
validateNonNegativeFinite(context, transition.duration, `${transitionPath}.duration`);
|
|
323
|
-
if (
|
|
324
|
-
transition.hasExitTime !== undefined
|
|
325
|
-
&& typeof transition.hasExitTime !== 'boolean'
|
|
326
|
-
) {
|
|
327
|
-
issue(
|
|
328
|
-
context,
|
|
329
|
-
'invalid-value',
|
|
330
|
-
`${transitionPath}.hasExitTime`,
|
|
331
|
-
'hasExitTime must be boolean.',
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
if (transition.hasExitTime === true && transition.exitTime === undefined) {
|
|
335
|
-
issue(
|
|
336
|
-
context,
|
|
337
|
-
'invalid-value',
|
|
338
|
-
`${transitionPath}.exitTime`,
|
|
339
|
-
'exitTime is required when hasExitTime is true.',
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
if (transition.exitTime !== undefined) {
|
|
343
|
-
validateNonNegativeFinite(context, transition.exitTime, `${transitionPath}.exitTime`);
|
|
344
|
-
}
|
|
345
|
-
if (transition.destinationOffset !== undefined) {
|
|
346
|
-
validateNonNegativeFinite(
|
|
347
|
-
context,
|
|
348
|
-
transition.destinationOffset,
|
|
349
|
-
`${transitionPath}.destinationOffset`,
|
|
350
|
-
);
|
|
351
|
-
}
|
|
352
|
-
if (
|
|
353
|
-
transition.interruption !== undefined
|
|
354
|
-
&& !INTERRUPTION_VALUES.includes(transition.interruption)
|
|
355
|
-
) {
|
|
356
|
-
issue(
|
|
357
|
-
context,
|
|
358
|
-
'invalid-value',
|
|
359
|
-
`${transitionPath}.interruption`,
|
|
360
|
-
'Unknown transition interruption strategy.',
|
|
361
|
-
);
|
|
362
|
-
}
|
|
363
|
-
transition.conditions.forEach((condition, conditionIndex) => {
|
|
364
|
-
validateCondition(
|
|
365
|
-
context,
|
|
366
|
-
condition,
|
|
367
|
-
`${transitionPath}.conditions[${conditionIndex}]`,
|
|
368
|
-
);
|
|
369
|
-
});
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
return Object.freeze(issues);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
export function compileAnimationStateMachineDefinition(
|
|
377
|
-
definition: SupportedAnimationStateMachineDefinition,
|
|
378
|
-
): CompiledAnimation3DStateMachine {
|
|
379
|
-
const issues = validateAnimationStateMachineDefinition(definition);
|
|
380
|
-
if (issues.length > 0) throw new AnimationStateMachineValidationError(issues);
|
|
381
|
-
|
|
382
|
-
const parameterIndexByName = new Map<string, number>();
|
|
383
|
-
const parameters: CompiledAnimation3DParameter[] = definition.parameters.map(
|
|
384
|
-
(parameter, index) => {
|
|
385
|
-
parameterIndexByName.set(parameter.name, index);
|
|
386
|
-
return Object.freeze({
|
|
387
|
-
index,
|
|
388
|
-
name: parameter.name,
|
|
389
|
-
type: parameter.type,
|
|
390
|
-
defaultValue: parameter.type === 'trigger'
|
|
391
|
-
? 0
|
|
392
|
-
: parameter.type === 'boolean'
|
|
393
|
-
? (parameter.defaultValue ? 1 : 0)
|
|
394
|
-
: parameter.defaultValue,
|
|
395
|
-
});
|
|
396
|
-
},
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
const layerIndexById = new Map<string, number>();
|
|
400
|
-
const layers: CompiledAnimation3DLayer[] = definition.layers.map((layer, layerIndex) => {
|
|
401
|
-
layerIndexById.set(layer.id, layerIndex);
|
|
402
|
-
const stateIndexById = new Map<string, number>();
|
|
403
|
-
layer.states.forEach((state, stateIndex) => stateIndexById.set(state.id, stateIndex));
|
|
404
|
-
const states: CompiledAnimation3DState[] = layer.states.map((state, stateIndex) =>
|
|
405
|
-
Object.freeze({
|
|
406
|
-
index: stateIndex,
|
|
407
|
-
id: state.id,
|
|
408
|
-
name: state.name,
|
|
409
|
-
motion: compileMotion(state.motion, parameterIndexByName),
|
|
410
|
-
speed: state.speed ?? 1,
|
|
411
|
-
speedParameterIndex: state.speedParameter === undefined
|
|
412
|
-
? -1
|
|
413
|
-
: parameterIndexByName.get(state.speedParameter)!,
|
|
414
|
-
loop: state.loop ?? 'repeat',
|
|
415
|
-
}),
|
|
416
|
-
);
|
|
417
|
-
const transitions: CompiledAnimation3DTransition[] = layer.transitions.map(
|
|
418
|
-
(transition, transitionIndex) => {
|
|
419
|
-
const conditions = transition.conditions.map(condition =>
|
|
420
|
-
compileCondition(condition, parameterIndexByName));
|
|
421
|
-
const triggerParameterIndices = conditions
|
|
422
|
-
.filter(condition => condition.operator === 'triggered')
|
|
423
|
-
.map(condition => condition.parameterIndex);
|
|
424
|
-
return Object.freeze({
|
|
425
|
-
index: transitionIndex,
|
|
426
|
-
id: transition.id,
|
|
427
|
-
fromStateIndex: transition.from === '*'
|
|
428
|
-
? -1
|
|
429
|
-
: stateIndexById.get(transition.from)!,
|
|
430
|
-
toStateIndex: stateIndexById.get(transition.to)!,
|
|
431
|
-
conditions: Object.freeze(conditions),
|
|
432
|
-
triggerParameterIndices: Object.freeze(triggerParameterIndices),
|
|
433
|
-
duration: transition.duration,
|
|
434
|
-
hasExitTime: transition.hasExitTime ?? false,
|
|
435
|
-
exitTime: transition.exitTime ?? 0,
|
|
436
|
-
destinationOffset: transition.destinationOffset ?? 0,
|
|
437
|
-
interruption: transition.interruption ?? 'none',
|
|
438
|
-
});
|
|
439
|
-
},
|
|
440
|
-
);
|
|
441
|
-
return Object.freeze({
|
|
442
|
-
index: layerIndex,
|
|
443
|
-
id: layer.id,
|
|
444
|
-
name: layer.name,
|
|
445
|
-
initialStateIndex: stateIndexById.get(layer.initialStateId)!,
|
|
446
|
-
states: Object.freeze(states),
|
|
447
|
-
transitions: Object.freeze(transitions),
|
|
448
|
-
blendMode: layer.blendMode ?? 'override',
|
|
449
|
-
weight: layer.weight ?? 1,
|
|
450
|
-
mask: compileMask(layer.mask),
|
|
451
|
-
stateIndexById,
|
|
452
|
-
});
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
return Object.freeze({
|
|
456
|
-
format: 'haiyue-animation-state-machine-compiled@1',
|
|
457
|
-
id: definition.id,
|
|
458
|
-
name: definition.name,
|
|
459
|
-
parameters: Object.freeze(parameters),
|
|
460
|
-
layers: Object.freeze(layers),
|
|
461
|
-
parameterIndexByName,
|
|
462
|
-
layerIndexById,
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
/** Compatibility aliases for the original 3D-prefixed runtime API. */
|
|
467
|
-
export {
|
|
468
|
-
AnimationStateMachineValidationError as Animation3DStateMachineValidationError,
|
|
469
|
-
};
|
|
470
|
-
export const validateAnimation3DStateMachineDefinition =
|
|
471
|
-
validateAnimationStateMachineDefinition;
|
|
472
|
-
export const compileAnimation3DStateMachineDefinition =
|
|
473
|
-
compileAnimationStateMachineDefinition;
|
|
474
|
-
export const compileAnimation3DStateMachine =
|
|
475
|
-
compileAnimationStateMachineDefinition;
|
|
476
|
-
|
|
477
|
-
function validateMotion(
|
|
478
|
-
context: ValidationContext,
|
|
479
|
-
motion: Animation3DMotionDefinition,
|
|
480
|
-
path: string,
|
|
481
|
-
): void {
|
|
482
|
-
if (typeof motion !== 'object' || motion === null) {
|
|
483
|
-
issue(context, 'invalid-value', path, 'Motion must be an object.');
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
486
|
-
if (context.motionStack.has(motion)) {
|
|
487
|
-
issue(context, 'recursive-motion', path, 'Recursive motion cycle detected.');
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
context.motionStack.add(motion);
|
|
491
|
-
if (motion.kind === 'clip') {
|
|
492
|
-
validateNonEmptyString(context, motion.clipId, `${path}.clipId`);
|
|
493
|
-
} else if (motion.kind === 'blend-1d') {
|
|
494
|
-
validateNumericParameter(context, motion.parameter, `${path}.parameter`);
|
|
495
|
-
if (motion.children.length === 0) {
|
|
496
|
-
issue(context, 'empty-blend-tree', `${path}.children`, '1D blend tree cannot be empty.');
|
|
497
|
-
}
|
|
498
|
-
let previousThreshold = -Infinity;
|
|
499
|
-
motion.children.forEach((child, childIndex) => {
|
|
500
|
-
const childPath = `${path}.children[${childIndex}]`;
|
|
501
|
-
validateFinite(context, child.threshold, `${childPath}.threshold`);
|
|
502
|
-
if (childIndex > 0 && child.threshold <= previousThreshold) {
|
|
503
|
-
issue(
|
|
504
|
-
context,
|
|
505
|
-
'invalid-thresholds',
|
|
506
|
-
`${childPath}.threshold`,
|
|
507
|
-
child.threshold === previousThreshold
|
|
508
|
-
? '1D blend thresholds must be unique.'
|
|
509
|
-
: '1D blend thresholds must be strictly increasing.',
|
|
510
|
-
);
|
|
511
|
-
}
|
|
512
|
-
previousThreshold = child.threshold;
|
|
513
|
-
validateMotion(context, child.motion, `${childPath}.motion`);
|
|
514
|
-
});
|
|
515
|
-
} else if (motion.kind === 'blend-2d') {
|
|
516
|
-
validateNumericParameter(context, motion.parameterX, `${path}.parameterX`);
|
|
517
|
-
validateNumericParameter(context, motion.parameterY, `${path}.parameterY`);
|
|
518
|
-
if (motion.algorithm !== 'cartesian' && motion.algorithm !== 'directional') {
|
|
519
|
-
issue(context, 'invalid-value', `${path}.algorithm`, 'Unknown 2D blend algorithm.');
|
|
520
|
-
}
|
|
521
|
-
if (motion.children.length === 0) {
|
|
522
|
-
issue(context, 'empty-blend-tree', `${path}.children`, '2D blend tree cannot be empty.');
|
|
523
|
-
}
|
|
524
|
-
const positions = new Set<string>();
|
|
525
|
-
motion.children.forEach((child, childIndex) => {
|
|
526
|
-
const childPath = `${path}.children[${childIndex}]`;
|
|
527
|
-
const x = child.position[0];
|
|
528
|
-
const y = child.position[1];
|
|
529
|
-
validateFinite(context, x, `${childPath}.position[0]`);
|
|
530
|
-
validateFinite(context, y, `${childPath}.position[1]`);
|
|
531
|
-
const key = `${x}\u0000${y}`;
|
|
532
|
-
if (positions.has(key)) {
|
|
533
|
-
issue(
|
|
534
|
-
context,
|
|
535
|
-
'invalid-value',
|
|
536
|
-
`${childPath}.position`,
|
|
537
|
-
'2D blend child positions must be unique.',
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
positions.add(key);
|
|
541
|
-
validateMotion(context, child.motion, `${childPath}.motion`);
|
|
542
|
-
});
|
|
543
|
-
} else {
|
|
544
|
-
issue(context, 'invalid-value', `${path}.kind`, 'Unknown motion kind.');
|
|
545
|
-
}
|
|
546
|
-
context.motionStack.delete(motion);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
function validateCondition(
|
|
550
|
-
context: ValidationContext,
|
|
551
|
-
condition: Animation3DTransitionCondition,
|
|
552
|
-
path: string,
|
|
553
|
-
): void {
|
|
554
|
-
const parameter = context.parameterByName.get(condition.parameter);
|
|
555
|
-
if (!parameter) {
|
|
556
|
-
issue(
|
|
557
|
-
context,
|
|
558
|
-
'missing-reference',
|
|
559
|
-
`${path}.parameter`,
|
|
560
|
-
`Parameter "${condition.parameter}" does not exist.`,
|
|
561
|
-
);
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
const operator = condition.operator;
|
|
565
|
-
if (parameter.type === 'float' || parameter.type === 'integer') {
|
|
566
|
-
const valid = operator === 'greater'
|
|
567
|
-
|| operator === 'greater-or-equal'
|
|
568
|
-
|| operator === 'less'
|
|
569
|
-
|| operator === 'less-or-equal'
|
|
570
|
-
|| operator === 'equal'
|
|
571
|
-
|| operator === 'not-equal';
|
|
572
|
-
if (!valid) {
|
|
573
|
-
issue(
|
|
574
|
-
context,
|
|
575
|
-
'invalid-operator',
|
|
576
|
-
`${path}.operator`,
|
|
577
|
-
`Operator "${operator}" is invalid for ${parameter.type} parameters.`,
|
|
578
|
-
);
|
|
579
|
-
return;
|
|
580
|
-
}
|
|
581
|
-
const value = 'value' in condition ? condition.value : undefined;
|
|
582
|
-
if (
|
|
583
|
-
typeof value !== 'number'
|
|
584
|
-
|| !Number.isFinite(value)
|
|
585
|
-
|| (parameter.type === 'integer' && !Number.isSafeInteger(value))
|
|
586
|
-
) {
|
|
587
|
-
issue(
|
|
588
|
-
context,
|
|
589
|
-
'parameter-type-mismatch',
|
|
590
|
-
`${path}.value`,
|
|
591
|
-
parameter.type === 'integer'
|
|
592
|
-
? 'Integer conditions require a safe integer value.'
|
|
593
|
-
: 'Float conditions require a finite numeric value.',
|
|
594
|
-
);
|
|
595
|
-
}
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
if (parameter.type === 'boolean') {
|
|
599
|
-
if (
|
|
600
|
-
operator !== 'equal'
|
|
601
|
-
&& operator !== 'not-equal'
|
|
602
|
-
&& operator !== 'is-true'
|
|
603
|
-
&& operator !== 'is-false'
|
|
604
|
-
) {
|
|
605
|
-
issue(
|
|
606
|
-
context,
|
|
607
|
-
'invalid-operator',
|
|
608
|
-
`${path}.operator`,
|
|
609
|
-
`Operator "${operator}" is invalid for boolean parameters.`,
|
|
610
|
-
);
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
if (
|
|
614
|
-
(operator === 'equal' || operator === 'not-equal')
|
|
615
|
-
&& (!('value' in condition) || typeof condition.value !== 'boolean')
|
|
616
|
-
) {
|
|
617
|
-
issue(
|
|
618
|
-
context,
|
|
619
|
-
'parameter-type-mismatch',
|
|
620
|
-
`${path}.value`,
|
|
621
|
-
'Boolean equality conditions require a boolean value.',
|
|
622
|
-
);
|
|
623
|
-
}
|
|
624
|
-
return;
|
|
625
|
-
}
|
|
626
|
-
if (operator !== 'triggered') {
|
|
627
|
-
issue(
|
|
628
|
-
context,
|
|
629
|
-
'invalid-operator',
|
|
630
|
-
`${path}.operator`,
|
|
631
|
-
`Operator "${operator}" is invalid for trigger parameters.`,
|
|
632
|
-
);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
function validateNumericParameter(
|
|
637
|
-
context: ValidationContext,
|
|
638
|
-
parameterName: string,
|
|
639
|
-
path: string,
|
|
640
|
-
): void {
|
|
641
|
-
const parameter = context.parameterByName.get(parameterName);
|
|
642
|
-
if (!parameter) {
|
|
643
|
-
issue(
|
|
644
|
-
context,
|
|
645
|
-
'missing-reference',
|
|
646
|
-
path,
|
|
647
|
-
`Parameter "${parameterName}" does not exist.`,
|
|
648
|
-
);
|
|
649
|
-
} else if (parameter.type !== 'float' && parameter.type !== 'integer') {
|
|
650
|
-
issue(
|
|
651
|
-
context,
|
|
652
|
-
'parameter-type-mismatch',
|
|
653
|
-
path,
|
|
654
|
-
`Parameter "${parameterName}" must be float or integer.`,
|
|
655
|
-
);
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
function compileMotion(
|
|
660
|
-
motion: Animation3DMotionDefinition,
|
|
661
|
-
parameterIndexByName: ReadonlyMap<string, number>,
|
|
662
|
-
): CompiledAnimation3DMotion {
|
|
663
|
-
if (motion.kind === 'clip') {
|
|
664
|
-
return Object.freeze({ kind: 'clip', clipId: motion.clipId });
|
|
665
|
-
}
|
|
666
|
-
if (motion.kind === 'blend-1d') {
|
|
667
|
-
return Object.freeze({
|
|
668
|
-
kind: 'blend-1d',
|
|
669
|
-
parameterIndex: parameterIndexByName.get(motion.parameter)!,
|
|
670
|
-
children: Object.freeze(motion.children.map(child => Object.freeze({
|
|
671
|
-
threshold: child.threshold,
|
|
672
|
-
motion: compileMotion(child.motion, parameterIndexByName),
|
|
673
|
-
}))),
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
return Object.freeze({
|
|
677
|
-
kind: 'blend-2d',
|
|
678
|
-
algorithm: motion.algorithm,
|
|
679
|
-
parameterXIndex: parameterIndexByName.get(motion.parameterX)!,
|
|
680
|
-
parameterYIndex: parameterIndexByName.get(motion.parameterY)!,
|
|
681
|
-
children: Object.freeze(motion.children.map((child, declarationIndex) =>
|
|
682
|
-
Object.freeze({
|
|
683
|
-
position: Object.freeze([child.position[0], child.position[1]]) as readonly [number, number],
|
|
684
|
-
motion: compileMotion(child.motion, parameterIndexByName),
|
|
685
|
-
declarationIndex,
|
|
686
|
-
}))),
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
function compileCondition(
|
|
691
|
-
condition: Animation3DTransitionCondition,
|
|
692
|
-
parameterIndexByName: ReadonlyMap<string, number>,
|
|
693
|
-
): CompiledAnimation3DCondition {
|
|
694
|
-
const rawValue = 'value' in condition ? condition.value : 0;
|
|
695
|
-
return Object.freeze({
|
|
696
|
-
parameterIndex: parameterIndexByName.get(condition.parameter)!,
|
|
697
|
-
operator: condition.operator,
|
|
698
|
-
value: typeof rawValue === 'boolean' ? (rawValue ? 1 : 0) : rawValue,
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
function compileMask(
|
|
703
|
-
mask: Animation3DBindingMask | undefined,
|
|
704
|
-
): Animation3DBindingMask | null {
|
|
705
|
-
if (!mask) return null;
|
|
706
|
-
return Object.freeze({
|
|
707
|
-
...(mask.include === undefined
|
|
708
|
-
? {}
|
|
709
|
-
: { include: Object.freeze([...mask.include]) }),
|
|
710
|
-
...(mask.exclude === undefined
|
|
711
|
-
? {}
|
|
712
|
-
: { exclude: Object.freeze([...mask.exclude]) }),
|
|
713
|
-
});
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
function validateNonEmptyString(
|
|
717
|
-
context: ValidationContext,
|
|
718
|
-
value: string,
|
|
719
|
-
path: string,
|
|
720
|
-
): void {
|
|
721
|
-
if (typeof value !== 'string' || value.length === 0) {
|
|
722
|
-
issue(context, 'invalid-value', path, 'Expected a non-empty string.');
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
function validateFinite(
|
|
727
|
-
context: ValidationContext,
|
|
728
|
-
value: number,
|
|
729
|
-
path: string,
|
|
730
|
-
): void {
|
|
731
|
-
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
732
|
-
issue(context, 'invalid-value', path, 'Expected a finite number.');
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
function validateNonNegativeFinite(
|
|
737
|
-
context: ValidationContext,
|
|
738
|
-
value: number,
|
|
739
|
-
path: string,
|
|
740
|
-
): void {
|
|
741
|
-
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
|
|
742
|
-
issue(context, 'invalid-value', path, 'Expected a finite number greater than or equal to zero.');
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
function validateUnitWeight(
|
|
747
|
-
context: ValidationContext,
|
|
748
|
-
value: number,
|
|
749
|
-
path: string,
|
|
750
|
-
): void {
|
|
751
|
-
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 1) {
|
|
752
|
-
issue(context, 'invalid-value', path, 'Layer weight must be a finite number in [0, 1].');
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
function issue(
|
|
757
|
-
context: ValidationContext,
|
|
758
|
-
code: Animation3DStateMachineValidationCode,
|
|
759
|
-
path: string,
|
|
760
|
-
message: string,
|
|
761
|
-
): void {
|
|
762
|
-
context.issues.push(Object.freeze({ code, path, message }));
|
|
763
|
-
}
|