@aura3d/animation 1.4.0 → 1.4.2

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 (46) hide show
  1. package/package.json +36 -3
  2. package/src/AnimationAction.ts +0 -166
  3. package/src/AnimationClip.ts +0 -63
  4. package/src/AnimationClipEvents.ts +0 -501
  5. package/src/AnimationClipRegistry.ts +0 -404
  6. package/src/AnimationController.ts +0 -1017
  7. package/src/AnimationEvents.ts +0 -34
  8. package/src/AnimationLayer.ts +0 -73
  9. package/src/AnimationMixer.ts +0 -402
  10. package/src/AnimationStateGraph.ts +0 -105
  11. package/src/AnimationStateMachine.ts +0 -265
  12. package/src/AnimationTrack.ts +0 -176
  13. package/src/BlendTree.ts +0 -89
  14. package/src/Bone.ts +0 -40
  15. package/src/CrowdAnimation.ts +0 -25
  16. package/src/ECSAnimationBridge.ts +0 -30
  17. package/src/FighterAnimationAdapter.ts +0 -124
  18. package/src/FootIk.ts +0 -251
  19. package/src/HumanoidBoneInference.ts +0 -323
  20. package/src/HumanoidRetargeting.ts +0 -700
  21. package/src/IK.ts +0 -117
  22. package/src/Inertialization.ts +0 -269
  23. package/src/Keyframe.ts +0 -159
  24. package/src/LocomotionController.ts +0 -155
  25. package/src/LocomotionKit.ts +0 -89
  26. package/src/MotionMatchingFixtures.ts +0 -254
  27. package/src/MotionQuality.ts +0 -182
  28. package/src/RigQuality.ts +0 -101
  29. package/src/RootMotion.ts +0 -124
  30. package/src/SceneAnimationBridge.ts +0 -80
  31. package/src/SecondaryAnimationFixtures.ts +0 -210
  32. package/src/Skeleton.ts +0 -78
  33. package/src/Skinning.ts +0 -18
  34. package/src/SpringBones.ts +0 -243
  35. package/src/browser-index.ts +0 -66
  36. package/src/index.ts +0 -66
  37. package/src/library/performanceStateGraph.ts +0 -173
  38. package/src/library/standardHumanoidClips.ts +0 -659
  39. package/src/threejs-compatibility/AnimationAction.ts +0 -27
  40. package/src/threejs-compatibility/AnimationClip.ts +0 -16
  41. package/src/threejs-compatibility/AnimationDiagnostics.ts +0 -42
  42. package/src/threejs-compatibility/AnimationMixer.ts +0 -24
  43. package/src/threejs-compatibility/MorphTargetMixer.ts +0 -16
  44. package/src/threejs-compatibility/Skeleton.ts +0 -9
  45. package/src/threejs-compatibility/SkinnedMesh.ts +0 -12
  46. package/src/threejs-compatibility/index.ts +0 -11
@@ -1,404 +0,0 @@
1
- import {
2
- normalizeClipEvents,
3
- type AnimationClipEvent
4
- } from "./AnimationClipEvents.js";
5
-
6
- export type AnimationClipId = string;
7
-
8
- export type AnimationTrackTarget =
9
- | "translation"
10
- | "rotation"
11
- | "scale"
12
- | "morph"
13
- | "material"
14
- | "visibility"
15
- | (string & {});
16
-
17
- export interface AnimationKeyframe<TValue = unknown> {
18
- readonly time: number;
19
- readonly value: TValue;
20
- readonly easing?: string;
21
- }
22
-
23
- export interface AnimationTrack<TValue = unknown> {
24
- readonly id?: string;
25
- readonly target: string;
26
- readonly property?: AnimationTrackTarget;
27
- readonly keyframes?: readonly AnimationKeyframe<TValue>[];
28
- readonly metadata?: Record<string, unknown>;
29
- }
30
-
31
- export interface AnimationClipSampleContext<
32
- TClipId extends string = string,
33
- TEvent extends AnimationClipEvent = AnimationClipEvent
34
- > {
35
- readonly clip: RegisteredAnimationClip<TClipId, TEvent>;
36
- readonly time: number;
37
- readonly normalizedTime: number;
38
- readonly playbackState?: unknown;
39
- }
40
-
41
- export type AnimationClipSampler<
42
- TPose = unknown,
43
- TClipId extends string = string,
44
- TEvent extends AnimationClipEvent = AnimationClipEvent
45
- > = (context: AnimationClipSampleContext<TClipId, TEvent>) => TPose;
46
-
47
- export interface AnimationClipDefinition<
48
- TClipId extends string = string,
49
- TEvent extends AnimationClipEvent = AnimationClipEvent,
50
- TPose = unknown
51
- > {
52
- readonly id: TClipId;
53
- readonly name?: string;
54
- readonly duration: number;
55
- readonly frameRate?: number;
56
- readonly loop?: boolean;
57
- readonly tags?: readonly string[];
58
- readonly tracks?: readonly AnimationTrack[];
59
- readonly events?: readonly TEvent[];
60
- readonly sample?: AnimationClipSampler<TPose, TClipId, TEvent>;
61
- readonly source?: string;
62
- readonly metadata?: Record<string, unknown>;
63
- }
64
-
65
- export interface RegisteredAnimationClip<
66
- TClipId extends string = string,
67
- TEvent extends AnimationClipEvent = AnimationClipEvent,
68
- TPose = unknown
69
- > extends AnimationClipDefinition<TClipId, TEvent, TPose> {
70
- readonly duration: number;
71
- readonly loop: boolean;
72
- readonly tags: readonly string[];
73
- readonly tracks: readonly AnimationTrack[];
74
- readonly events: readonly TEvent[];
75
- readonly registryIndex: number;
76
- }
77
-
78
- export interface AnimationClipRegistryOptions {
79
- readonly replace?: boolean;
80
- }
81
-
82
- export type AnimationClipRegistryDiagnosticSeverity = "info" | "warning" | "error";
83
-
84
- export interface AnimationClipRegistryDiagnostic<TClipId extends string = string> {
85
- readonly severity: AnimationClipRegistryDiagnosticSeverity;
86
- readonly code: string;
87
- readonly message: string;
88
- readonly clipId?: TClipId;
89
- }
90
-
91
- export interface AnimationClipMapReadinessOptions<TClipId extends string = string> {
92
- readonly requiredActions?: readonly string[] | undefined;
93
- readonly clipMap: Readonly<Record<string, TClipId | readonly TClipId[] | undefined>>;
94
- readonly aliases?: Readonly<Record<string, string>> | undefined;
95
- readonly segmentedFallbackDeclared?: boolean | undefined;
96
- }
97
-
98
- export interface AnimationClipMapReadiness<TClipId extends string = string> {
99
- readonly ok: boolean;
100
- readonly segmentedFallbackDeclared: boolean;
101
- readonly requiredActions: readonly string[];
102
- readonly missingActions: readonly string[];
103
- readonly missingClipIds: readonly TClipId[];
104
- readonly aliasActions: readonly string[];
105
- readonly diagnostics: readonly AnimationClipRegistryDiagnostic<TClipId>[];
106
- }
107
-
108
- export interface AnimationClipManifest<
109
- TClipId extends string = string,
110
- TEvent extends AnimationClipEvent = AnimationClipEvent,
111
- TPose = unknown
112
- > {
113
- readonly clips: readonly AnimationClipDefinition<TClipId, TEvent, TPose>[];
114
- }
115
-
116
- export class AnimationClipRegistry<
117
- TClipId extends string = string,
118
- TEvent extends AnimationClipEvent = AnimationClipEvent,
119
- TPose = unknown
120
- > {
121
- private readonly clips = new Map<TClipId, RegisteredAnimationClip<TClipId, TEvent, TPose>>();
122
- private nextRegistryIndex = 0;
123
-
124
- constructor(
125
- clips: readonly AnimationClipDefinition<TClipId, TEvent, TPose>[] = [],
126
- options: AnimationClipRegistryOptions = {}
127
- ) {
128
- this.registerMany(clips, options);
129
- }
130
-
131
- static fromManifest<
132
- TClipId extends string = string,
133
- TEvent extends AnimationClipEvent = AnimationClipEvent,
134
- TPose = unknown
135
- >(
136
- manifest: AnimationClipManifest<TClipId, TEvent, TPose>,
137
- options: AnimationClipRegistryOptions = {}
138
- ): AnimationClipRegistry<TClipId, TEvent, TPose> {
139
- return new AnimationClipRegistry(manifest.clips, options);
140
- }
141
-
142
- register(
143
- definition: AnimationClipDefinition<TClipId, TEvent, TPose>,
144
- options: AnimationClipRegistryOptions = {}
145
- ): RegisteredAnimationClip<TClipId, TEvent, TPose> {
146
- validateClipDefinition(definition);
147
-
148
- if (!options.replace && this.clips.has(definition.id)) {
149
- throw new Error(`Animation clip "${definition.id}" is already registered.`);
150
- }
151
-
152
- const registered: RegisteredAnimationClip<TClipId, TEvent, TPose> = {
153
- ...definition,
154
- duration: sanitizeDuration(definition.duration),
155
- loop: definition.loop ?? true,
156
- tags: [...(definition.tags ?? [])],
157
- tracks: [...(definition.tracks ?? [])],
158
- events: normalizeClipEvents(definition.events),
159
- registryIndex: this.nextRegistryIndex
160
- };
161
-
162
- this.nextRegistryIndex += 1;
163
- this.clips.set(registered.id, registered);
164
- return registered;
165
- }
166
-
167
- registerMany(
168
- definitions: readonly AnimationClipDefinition<TClipId, TEvent, TPose>[],
169
- options: AnimationClipRegistryOptions = {}
170
- ): readonly RegisteredAnimationClip<TClipId, TEvent, TPose>[] {
171
- return definitions.map((definition) => this.register(definition, options));
172
- }
173
-
174
- get(id: TClipId): RegisteredAnimationClip<TClipId, TEvent, TPose> | undefined {
175
- return this.clips.get(id);
176
- }
177
-
178
- require(id: TClipId): RegisteredAnimationClip<TClipId, TEvent, TPose> {
179
- const clip = this.get(id);
180
- if (!clip) {
181
- throw new Error(`Animation clip "${id}" is not registered.`);
182
- }
183
-
184
- return clip;
185
- }
186
-
187
- has(id: TClipId): boolean {
188
- return this.clips.has(id);
189
- }
190
-
191
- remove(id: TClipId): boolean {
192
- return this.clips.delete(id);
193
- }
194
-
195
- clear(): void {
196
- this.clips.clear();
197
- }
198
-
199
- ids(): readonly TClipId[] {
200
- return [...this.clips.keys()];
201
- }
202
-
203
- list(): readonly RegisteredAnimationClip<TClipId, TEvent, TPose>[] {
204
- return [...this.clips.values()].sort((a, b) => a.registryIndex - b.registryIndex);
205
- }
206
-
207
- findByTag(tag: string): readonly RegisteredAnimationClip<TClipId, TEvent, TPose>[] {
208
- return this.list().filter((clip) => clip.tags.includes(tag));
209
- }
210
-
211
- toManifest(): AnimationClipManifest<TClipId, TEvent, TPose> {
212
- return {
213
- clips: this.list()
214
- };
215
- }
216
-
217
- diagnose(): readonly AnimationClipRegistryDiagnostic<TClipId>[] {
218
- const diagnostics: AnimationClipRegistryDiagnostic<TClipId>[] = [];
219
-
220
- if (this.clips.size === 0) {
221
- diagnostics.push({
222
- severity: "warning",
223
- code: "ANIMATION_REGISTRY_EMPTY",
224
- message: "No animation clips are registered."
225
- });
226
- return diagnostics;
227
- }
228
-
229
- for (const clip of this.list()) {
230
- if (clip.duration <= 0) {
231
- diagnostics.push({
232
- severity: "error",
233
- code: "ANIMATION_CLIP_DURATION_INVALID",
234
- message: `Animation clip "${clip.id}" must have a positive duration.`,
235
- clipId: clip.id
236
- });
237
- }
238
-
239
- if (clip.frameRate !== undefined && (!Number.isFinite(clip.frameRate) || clip.frameRate <= 0)) {
240
- diagnostics.push({
241
- severity: "warning",
242
- code: "ANIMATION_CLIP_FRAME_RATE_INVALID",
243
- message: `Animation clip "${clip.id}" has an invalid frame rate.`,
244
- clipId: clip.id
245
- });
246
- }
247
-
248
- if (clip.tracks.length === 0 && !clip.sample) {
249
- diagnostics.push({
250
- severity: "info",
251
- code: "ANIMATION_CLIP_NO_SAMPLE_SOURCE",
252
- message: `Animation clip "${clip.id}" has no tracks or sampler. capturePose() will return an empty pose for it.`,
253
- clipId: clip.id
254
- });
255
- }
256
-
257
- for (const event of clip.events) {
258
- if (!Number.isFinite(event.time) || event.time < 0 || event.time > clip.duration) {
259
- diagnostics.push({
260
- severity: "warning",
261
- code: "ANIMATION_CLIP_EVENT_TIME_OUT_OF_RANGE",
262
- message: `Animation event "${event.name}" is outside the duration of clip "${clip.id}".`,
263
- clipId: clip.id
264
- });
265
- }
266
- }
267
- }
268
-
269
- return diagnostics;
270
- }
271
- }
272
-
273
- export function createAnimationClipRegistry<
274
- TClipId extends string = string,
275
- TEvent extends AnimationClipEvent = AnimationClipEvent,
276
- TPose = unknown
277
- >(
278
- clips: readonly AnimationClipDefinition<TClipId, TEvent, TPose>[] = [],
279
- options: AnimationClipRegistryOptions = {}
280
- ): AnimationClipRegistry<TClipId, TEvent, TPose> {
281
- return new AnimationClipRegistry(clips, options);
282
- }
283
-
284
- export function validateAnimationClipMap<
285
- TClipId extends string = string,
286
- TEvent extends AnimationClipEvent = AnimationClipEvent,
287
- TPose = unknown
288
- >(
289
- registry: AnimationClipRegistry<TClipId, TEvent, TPose>,
290
- options: AnimationClipMapReadinessOptions<TClipId>
291
- ): AnimationClipMapReadiness<TClipId> {
292
- const requiredActions = options.requiredActions ?? ["speak", "listen", "gesture", "walk", "action"];
293
- const missingActions: string[] = [];
294
- const missingClipIds: TClipId[] = [];
295
- const aliasActions: string[] = [];
296
- const diagnostics: AnimationClipRegistryDiagnostic<TClipId>[] = [];
297
-
298
- for (const action of requiredActions) {
299
- const mapped = options.clipMap[action] ?? options.clipMap[options.aliases?.[action] ?? ""];
300
- if (options.aliases?.[action]) aliasActions.push(action);
301
- const clipIds = Array.isArray(mapped) ? mapped : mapped ? [mapped] : [];
302
- if (clipIds.length === 0) {
303
- missingActions.push(action);
304
- diagnostics.push({
305
- severity: options.segmentedFallbackDeclared ? "warning" : "error",
306
- code: "ANIMATION_CLIP_ACTION_MISSING",
307
- message: `Animation action "${action}" is missing a clip map entry.`
308
- });
309
- continue;
310
- }
311
- for (const clipId of clipIds) {
312
- if (!registry.has(clipId)) {
313
- missingClipIds.push(clipId);
314
- diagnostics.push({
315
- severity: options.segmentedFallbackDeclared ? "warning" : "error",
316
- code: "ANIMATION_CLIP_ID_MISSING",
317
- message: `Animation action "${action}" references missing clip "${clipId}".`,
318
- clipId
319
- });
320
- }
321
- }
322
- }
323
-
324
- return {
325
- ok: options.segmentedFallbackDeclared ? missingActions.length === 0 : diagnostics.every((diagnostic) => diagnostic.severity !== "error"),
326
- segmentedFallbackDeclared: options.segmentedFallbackDeclared === true,
327
- requiredActions,
328
- missingActions,
329
- missingClipIds,
330
- aliasActions,
331
- diagnostics
332
- };
333
- }
334
-
335
- /**
336
- * Generic (non-animation) clip-map readiness validator for locomotion / fighter / Animation Studio
337
- * clip sets. Same readiness shape as {@link validateAnimationClipMap} but with neutral diagnostic
338
- * codes and a configurable required-action set (defaults to a locomotion set).
339
- */
340
- export function validateAnimationStudioClipMap<
341
- TClipId extends string = string,
342
- TEvent extends AnimationClipEvent = AnimationClipEvent,
343
- TPose = unknown
344
- >(
345
- registry: AnimationClipRegistry<TClipId, TEvent, TPose>,
346
- options: AnimationClipMapReadinessOptions<TClipId>
347
- ): AnimationClipMapReadiness<TClipId> {
348
- const requiredActions = options.requiredActions ?? ["idle", "walk", "run"];
349
- const missingActions: string[] = [];
350
- const missingClipIds: TClipId[] = [];
351
- const aliasActions: string[] = [];
352
- const diagnostics: AnimationClipRegistryDiagnostic<TClipId>[] = [];
353
-
354
- for (const action of requiredActions) {
355
- const mapped = options.clipMap[action] ?? options.clipMap[options.aliases?.[action] ?? ""];
356
- if (options.aliases?.[action]) aliasActions.push(action);
357
- const clipIds = Array.isArray(mapped) ? mapped : mapped ? [mapped] : [];
358
- if (clipIds.length === 0) {
359
- missingActions.push(action);
360
- diagnostics.push({
361
- severity: options.segmentedFallbackDeclared ? "warning" : "error",
362
- code: "ANIMATION_CLIP_ACTION_MISSING",
363
- message: `Required action "${action}" is missing a clip map entry.`
364
- });
365
- continue;
366
- }
367
- for (const clipId of clipIds) {
368
- if (!registry.has(clipId)) {
369
- missingClipIds.push(clipId);
370
- diagnostics.push({
371
- severity: options.segmentedFallbackDeclared ? "warning" : "error",
372
- code: "ANIMATION_CLIP_ID_MISSING",
373
- message: `Required action "${action}" references missing clip "${clipId}".`,
374
- clipId
375
- });
376
- }
377
- }
378
- }
379
-
380
- return {
381
- ok: options.segmentedFallbackDeclared ? missingActions.length === 0 : diagnostics.every((diagnostic) => diagnostic.severity !== "error"),
382
- segmentedFallbackDeclared: options.segmentedFallbackDeclared === true,
383
- requiredActions,
384
- missingActions,
385
- missingClipIds,
386
- aliasActions,
387
- diagnostics
388
- };
389
- }
390
-
391
- function validateClipDefinition(definition: AnimationClipDefinition): void {
392
- if (!definition.id) {
393
- throw new Error("Animation clips must have a stable id.");
394
- }
395
-
396
- if (!Number.isFinite(definition.duration) || definition.duration < 0) {
397
- throw new Error(`Animation clip "${definition.id}" has an invalid duration.`);
398
- }
399
- }
400
-
401
- function sanitizeDuration(duration: number): number {
402
- if (!Number.isFinite(duration) || duration < 0) return 0;
403
- return duration;
404
- }