@lovelace_lol/loom3 1.0.35 → 1.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +490 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +491 -76
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
-
import { Vector3, Clock, Box3, Quaternion, AdditiveAnimationBlendMode, NormalAnimationBlendMode, LoopPingPong, LoopOnce, LoopRepeat, QuaternionKeyframeTrack, NumberKeyframeTrack, AnimationClip, AnimationMixer, Mesh } from 'three';
|
|
2
|
+
import { Vector3, Clock, Box3, Quaternion, AdditiveAnimationBlendMode, NormalAnimationBlendMode, LoopPingPong, LoopOnce, LoopRepeat, QuaternionKeyframeTrack, NumberKeyframeTrack, AnimationClip, AnimationMixer, Mesh, PropertyBinding } from 'three';
|
|
3
3
|
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -58,6 +58,119 @@ function resolveCurveBalance(curveId, globalBalance, balanceMap) {
|
|
|
58
58
|
}
|
|
59
59
|
return clampBalance(globalBalance);
|
|
60
60
|
}
|
|
61
|
+
var RUNTIME_CLIP_PREFIX = "__loom3_baked_partition__/";
|
|
62
|
+
var FACE_SAFE_TARGET_RE = /(head|neck|jaw|eye|brow|lid|mouth|lip|face|cheek|nose|tongue|teeth)/i;
|
|
63
|
+
var BODY_LIKE_TARGET_RE = /(root|armature|hips?|pelvis|spine|waist|chest|torso|shoulder|arm|forearm|hand|finger|leg|thigh|calf|knee|foot|toe|tail|wing|fin|body|abdomen|clavicle)/i;
|
|
64
|
+
var SCENE_LIKE_TARGET_RE = /(camera|cam|scene|world|global|origin|pivot|cube)/i;
|
|
65
|
+
var CHANNEL_ORDER = ["face", "body", "scene"];
|
|
66
|
+
function getRuntimeClipName(sourceClipName, channel) {
|
|
67
|
+
return `${RUNTIME_CLIP_PREFIX}${sourceClipName}/${channel}`;
|
|
68
|
+
}
|
|
69
|
+
function parseTrackTarget(trackName, model) {
|
|
70
|
+
let parsed;
|
|
71
|
+
try {
|
|
72
|
+
parsed = PropertyBinding.parseTrackName(trackName);
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const targetKey = parsed.objectName === "bones" && parsed.objectIndex ? String(parsed.objectIndex) : parsed.nodeName;
|
|
77
|
+
const target = targetKey ? model.getObjectByProperty("uuid", targetKey) ?? PropertyBinding.findNode(model, targetKey) : null;
|
|
78
|
+
return {
|
|
79
|
+
propertyName: parsed.propertyName,
|
|
80
|
+
target,
|
|
81
|
+
targetName: target?.name ?? parsed.nodeName ?? ""
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function isSceneTrackTarget(target, targetName) {
|
|
85
|
+
if (!target) return true;
|
|
86
|
+
if (target.isCamera) return true;
|
|
87
|
+
return SCENE_LIKE_TARGET_RE.test(targetName);
|
|
88
|
+
}
|
|
89
|
+
function isFaceSafeTransformTarget(target, targetName, safeTransformTargets) {
|
|
90
|
+
if (target && safeTransformTargets.has(target)) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
if (!targetName) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
if (BODY_LIKE_TARGET_RE.test(targetName) || SCENE_LIKE_TARGET_RE.test(targetName)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return FACE_SAFE_TARGET_RE.test(targetName);
|
|
100
|
+
}
|
|
101
|
+
function classifyBakedTrack(track, model, bones) {
|
|
102
|
+
const parsed = parseTrackTarget(track.name, model);
|
|
103
|
+
if (!parsed) {
|
|
104
|
+
return "scene";
|
|
105
|
+
}
|
|
106
|
+
if (parsed.propertyName === "morphTargetInfluences" || parsed.propertyName === "weights") {
|
|
107
|
+
return "face";
|
|
108
|
+
}
|
|
109
|
+
if (isSceneTrackTarget(parsed.target, parsed.targetName)) {
|
|
110
|
+
return "scene";
|
|
111
|
+
}
|
|
112
|
+
if (parsed.propertyName === "quaternion") {
|
|
113
|
+
const safeTransformTargets = new Set(
|
|
114
|
+
Object.values(bones).map((entry) => entry?.obj).filter((entry) => !!entry)
|
|
115
|
+
);
|
|
116
|
+
if (isFaceSafeTransformTarget(parsed.target, parsed.targetName, safeTransformTargets)) {
|
|
117
|
+
return "face";
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return "body";
|
|
121
|
+
}
|
|
122
|
+
function resolveBakedChannelBlendMode(channel, requestedBlendMode) {
|
|
123
|
+
if (channel === "face") {
|
|
124
|
+
return requestedBlendMode === "additive" ? "additive" : "replace";
|
|
125
|
+
}
|
|
126
|
+
if (channel === "body") {
|
|
127
|
+
return "replace";
|
|
128
|
+
}
|
|
129
|
+
return void 0;
|
|
130
|
+
}
|
|
131
|
+
function resolveBakedAggregateBlendMode(channels, requestedBlendMode) {
|
|
132
|
+
if (requestedBlendMode !== "additive") {
|
|
133
|
+
return "replace";
|
|
134
|
+
}
|
|
135
|
+
return channels.some((channel) => channel.channel === "face" && channel.playable && channel.trackCount > 0) ? "additive" : "replace";
|
|
136
|
+
}
|
|
137
|
+
function partitionBakedClip(clip, model, bones) {
|
|
138
|
+
const tracksByChannel = new Map(
|
|
139
|
+
CHANNEL_ORDER.map((channel) => [channel, []])
|
|
140
|
+
);
|
|
141
|
+
for (const track of clip.tracks) {
|
|
142
|
+
const channel = classifyBakedTrack(track, model, bones);
|
|
143
|
+
tracksByChannel.get(channel)?.push(track.clone());
|
|
144
|
+
}
|
|
145
|
+
const runtimeClips = [];
|
|
146
|
+
const channels = [];
|
|
147
|
+
for (const channel of CHANNEL_ORDER) {
|
|
148
|
+
const tracks = tracksByChannel.get(channel) ?? [];
|
|
149
|
+
if (tracks.length === 0) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const playable = channel !== "scene";
|
|
153
|
+
const blendMode = resolveBakedChannelBlendMode(channel, "additive");
|
|
154
|
+
channels.push({
|
|
155
|
+
channel,
|
|
156
|
+
trackCount: tracks.length,
|
|
157
|
+
playable,
|
|
158
|
+
blendMode
|
|
159
|
+
});
|
|
160
|
+
if (!playable) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
runtimeClips.push({
|
|
164
|
+
channel,
|
|
165
|
+
clip: new AnimationClip(getRuntimeClipName(clip.name, channel), clip.duration, tracks)
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
sourceClip: clip,
|
|
170
|
+
channels,
|
|
171
|
+
runtimeClips
|
|
172
|
+
};
|
|
173
|
+
}
|
|
61
174
|
|
|
62
175
|
// src/engines/three/AnimationThree.ts
|
|
63
176
|
var easeInOutQuad = (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
@@ -163,6 +276,10 @@ var BakedAnimationController = class {
|
|
|
163
276
|
__publicField(this, "animationMixer", null);
|
|
164
277
|
__publicField(this, "mixerFinishedListenerAttached", false);
|
|
165
278
|
__publicField(this, "animationClips", []);
|
|
279
|
+
__publicField(this, "bakedSourceClips", /* @__PURE__ */ new Map());
|
|
280
|
+
__publicField(this, "bakedRuntimeActions", /* @__PURE__ */ new Map());
|
|
281
|
+
__publicField(this, "bakedActionGroups", /* @__PURE__ */ new Map());
|
|
282
|
+
__publicField(this, "bakedRuntimeClipToSource", /* @__PURE__ */ new Map());
|
|
166
283
|
__publicField(this, "animationActions", /* @__PURE__ */ new Map());
|
|
167
284
|
__publicField(this, "animationFinishedCallbacks", /* @__PURE__ */ new Map());
|
|
168
285
|
__publicField(this, "clipActions", /* @__PURE__ */ new Map());
|
|
@@ -191,6 +308,7 @@ var BakedAnimationController = class {
|
|
|
191
308
|
const rawWeight = options?.weight ?? options?.intensity ?? clipOptions?.mixerWeight ?? 1;
|
|
192
309
|
const weight = Number.isFinite(rawWeight) ? Math.max(0, rawWeight) : 1;
|
|
193
310
|
const loopMode = options?.loopMode ?? (typeof options?.loop === "boolean" ? options.loop ? "repeat" : "once" : defaults.loop ? "repeat" : "once");
|
|
311
|
+
const requestedBlendMode = options?.blendMode ?? (clipOptions?.mixerAdditive ? "additive" : "replace");
|
|
194
312
|
return {
|
|
195
313
|
source: options?.source ?? defaults.source,
|
|
196
314
|
loop: loopMode !== "once",
|
|
@@ -200,7 +318,8 @@ var BakedAnimationController = class {
|
|
|
200
318
|
playbackRate,
|
|
201
319
|
weight,
|
|
202
320
|
balance: Number.isFinite(options?.balance) ? options?.balance ?? 0 : 0,
|
|
203
|
-
|
|
321
|
+
requestedBlendMode,
|
|
322
|
+
blendMode: requestedBlendMode,
|
|
204
323
|
easing: options?.easing ?? "linear"
|
|
205
324
|
};
|
|
206
325
|
}
|
|
@@ -260,15 +379,49 @@ var BakedAnimationController = class {
|
|
|
260
379
|
next.balance = Math.max(-1, Math.min(1, options.balance));
|
|
261
380
|
}
|
|
262
381
|
if (options.blendMode) {
|
|
263
|
-
next.
|
|
382
|
+
next.requestedBlendMode = options.blendMode;
|
|
264
383
|
} else if (typeof clipOptions?.mixerAdditive === "boolean") {
|
|
265
|
-
next.
|
|
384
|
+
next.requestedBlendMode = clipOptions.mixerAdditive ? "additive" : "replace";
|
|
266
385
|
}
|
|
386
|
+
next.blendMode = next.requestedBlendMode;
|
|
267
387
|
if (options.easing) {
|
|
268
388
|
next.easing = options.easing;
|
|
269
389
|
}
|
|
270
390
|
return next;
|
|
271
391
|
}
|
|
392
|
+
isBakedSourceClip(clipName) {
|
|
393
|
+
return this.bakedSourceClips.has(clipName);
|
|
394
|
+
}
|
|
395
|
+
getBakedSourceClip(clipName) {
|
|
396
|
+
return this.bakedSourceClips.get(clipName);
|
|
397
|
+
}
|
|
398
|
+
getBakedChannelInfo(clipName, playbackState) {
|
|
399
|
+
const bakedClip = this.getBakedSourceClip(clipName);
|
|
400
|
+
if (!bakedClip) {
|
|
401
|
+
return void 0;
|
|
402
|
+
}
|
|
403
|
+
const requestedBlendMode = playbackState?.requestedBlendMode ?? "replace";
|
|
404
|
+
return bakedClip.channels.map((channel) => ({
|
|
405
|
+
...channel,
|
|
406
|
+
blendMode: resolveBakedChannelBlendMode(channel.channel, requestedBlendMode)
|
|
407
|
+
}));
|
|
408
|
+
}
|
|
409
|
+
getBakedAggregateBlendMode(clipName, playbackState) {
|
|
410
|
+
const channels = this.getBakedChannelInfo(clipName, playbackState);
|
|
411
|
+
if (!channels) {
|
|
412
|
+
return playbackState?.requestedBlendMode ?? playbackState?.blendMode ?? "replace";
|
|
413
|
+
}
|
|
414
|
+
return resolveBakedAggregateBlendMode(
|
|
415
|
+
channels,
|
|
416
|
+
playbackState?.requestedBlendMode ?? "replace"
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
applyPlaybackStateToBakedAction(action, state, channel) {
|
|
420
|
+
this.applyPlaybackState(action, {
|
|
421
|
+
...state,
|
|
422
|
+
blendMode: resolveBakedChannelBlendMode(channel, state.requestedBlendMode) ?? "replace"
|
|
423
|
+
});
|
|
424
|
+
}
|
|
272
425
|
resolveStartTime(duration, state, explicitStartTime) {
|
|
273
426
|
if (typeof explicitStartTime === "number" && Number.isFinite(explicitStartTime)) {
|
|
274
427
|
return Math.max(0, Math.min(duration, explicitStartTime));
|
|
@@ -278,8 +431,13 @@ var BakedAnimationController = class {
|
|
|
278
431
|
}
|
|
279
432
|
return 0;
|
|
280
433
|
}
|
|
281
|
-
|
|
282
|
-
const
|
|
434
|
+
getOrCreateBakedRuntimeAction(sourceClipName, channel) {
|
|
435
|
+
const bakedClip = this.getBakedSourceClip(sourceClipName);
|
|
436
|
+
const runtimeClip = bakedClip?.runtimeClips.find((entry) => entry.channel === channel)?.clip;
|
|
437
|
+
if (!runtimeClip) {
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
const existing = this.bakedRuntimeActions.get(runtimeClip.name);
|
|
283
441
|
if (existing) {
|
|
284
442
|
return existing;
|
|
285
443
|
}
|
|
@@ -287,13 +445,44 @@ var BakedAnimationController = class {
|
|
|
287
445
|
if (!this.animationMixer) {
|
|
288
446
|
return null;
|
|
289
447
|
}
|
|
290
|
-
const
|
|
291
|
-
|
|
448
|
+
const action = this.animationMixer.clipAction(runtimeClip);
|
|
449
|
+
this.bakedRuntimeActions.set(runtimeClip.name, action);
|
|
450
|
+
return action;
|
|
451
|
+
}
|
|
452
|
+
getRepresentativeBakedAction(clipName) {
|
|
453
|
+
const group = this.bakedActionGroups.get(clipName);
|
|
454
|
+
if (!group) {
|
|
292
455
|
return null;
|
|
293
456
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
457
|
+
return group.channelActions.values().next().value ?? null;
|
|
458
|
+
}
|
|
459
|
+
createBakedActionGroup(clipName, playbackState) {
|
|
460
|
+
const bakedClip = this.getBakedSourceClip(clipName);
|
|
461
|
+
if (!bakedClip) {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
const channelActions = /* @__PURE__ */ new Map();
|
|
465
|
+
for (const runtimeClip of bakedClip.runtimeClips) {
|
|
466
|
+
const action = this.getOrCreateBakedRuntimeAction(clipName, runtimeClip.channel);
|
|
467
|
+
if (action) {
|
|
468
|
+
channelActions.set(runtimeClip.channel, action);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (channelActions.size === 0) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
let resolveFinished = () => {
|
|
475
|
+
};
|
|
476
|
+
const finishedPromise = new Promise((resolve) => {
|
|
477
|
+
resolveFinished = resolve;
|
|
478
|
+
});
|
|
479
|
+
return {
|
|
480
|
+
actionId: makeActionId(),
|
|
481
|
+
channelActions,
|
|
482
|
+
pendingFinishedChannels: playbackState.loopMode === "once" ? new Set(channelActions.keys()) : /* @__PURE__ */ new Set(),
|
|
483
|
+
finishedPromise,
|
|
484
|
+
resolveFinished
|
|
485
|
+
};
|
|
297
486
|
}
|
|
298
487
|
getMeshNamesForAU(auId, config, explicitMeshNames) {
|
|
299
488
|
if (explicitMeshNames && explicitMeshNames.length > 0) {
|
|
@@ -333,6 +522,10 @@ var BakedAnimationController = class {
|
|
|
333
522
|
this.animationMixer = null;
|
|
334
523
|
}
|
|
335
524
|
this.animationClips = [];
|
|
525
|
+
this.bakedSourceClips.clear();
|
|
526
|
+
this.bakedRuntimeActions.clear();
|
|
527
|
+
this.bakedActionGroups.clear();
|
|
528
|
+
this.bakedRuntimeClipToSource.clear();
|
|
336
529
|
this.animationActions.clear();
|
|
337
530
|
this.animationFinishedCallbacks.clear();
|
|
338
531
|
this.clipActions.clear();
|
|
@@ -341,17 +534,47 @@ var BakedAnimationController = class {
|
|
|
341
534
|
this.playbackState.clear();
|
|
342
535
|
}
|
|
343
536
|
loadAnimationClips(clips) {
|
|
344
|
-
|
|
537
|
+
const model = this.host.getModel();
|
|
538
|
+
if (!model) {
|
|
345
539
|
console.warn("Loom3: Cannot load animation clips before calling onReady()");
|
|
346
540
|
return;
|
|
347
541
|
}
|
|
542
|
+
for (const clipName of this.bakedSourceClips.keys()) {
|
|
543
|
+
this.stopAnimation(clipName);
|
|
544
|
+
}
|
|
545
|
+
if (this.animationMixer) {
|
|
546
|
+
for (const bakedClip of this.bakedSourceClips.values()) {
|
|
547
|
+
for (const runtimeClip of bakedClip.runtimeClips) {
|
|
548
|
+
try {
|
|
549
|
+
this.animationMixer.uncacheAction(runtimeClip.clip);
|
|
550
|
+
} catch {
|
|
551
|
+
}
|
|
552
|
+
try {
|
|
553
|
+
this.animationMixer.uncacheClip(runtimeClip.clip);
|
|
554
|
+
} catch {
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
for (const clipName of this.bakedSourceClips.keys()) {
|
|
560
|
+
this.playbackState.delete(clipName);
|
|
561
|
+
this.clipSources.delete(clipName);
|
|
562
|
+
}
|
|
563
|
+
this.bakedSourceClips.clear();
|
|
564
|
+
this.bakedRuntimeActions.clear();
|
|
565
|
+
this.bakedActionGroups.clear();
|
|
566
|
+
this.bakedRuntimeClipToSource.clear();
|
|
348
567
|
this.ensureMixer();
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
568
|
+
const partitionedClips = clips.map((clip) => partitionBakedClip(clip, model, this.host.getBones()));
|
|
569
|
+
this.animationClips = partitionedClips.map((clip) => clip.sourceClip);
|
|
570
|
+
for (const bakedClip of partitionedClips) {
|
|
571
|
+
this.bakedSourceClips.set(bakedClip.sourceClip.name, bakedClip);
|
|
572
|
+
this.clipSources.set(bakedClip.sourceClip.name, "baked");
|
|
573
|
+
for (const runtimeClip of bakedClip.runtimeClips) {
|
|
574
|
+
this.bakedRuntimeClipToSource.set(runtimeClip.clip.name, {
|
|
575
|
+
sourceClipName: bakedClip.sourceClip.name,
|
|
576
|
+
channel: runtimeClip.channel
|
|
577
|
+
});
|
|
355
578
|
}
|
|
356
579
|
}
|
|
357
580
|
}
|
|
@@ -360,84 +583,91 @@ var BakedAnimationController = class {
|
|
|
360
583
|
name: clip.name,
|
|
361
584
|
duration: clip.duration,
|
|
362
585
|
trackCount: clip.tracks.length,
|
|
363
|
-
source: this.clipSources.get(clip.name) ?? "baked"
|
|
586
|
+
source: this.clipSources.get(clip.name) ?? "baked",
|
|
587
|
+
channels: this.getBakedSourceClip(clip.name)?.channels
|
|
364
588
|
}));
|
|
365
589
|
}
|
|
366
590
|
removeAnimationClip(clipName) {
|
|
367
|
-
const
|
|
368
|
-
if (!
|
|
591
|
+
const bakedClip = this.getBakedSourceClip(clipName);
|
|
592
|
+
if (!bakedClip) {
|
|
369
593
|
return false;
|
|
370
594
|
}
|
|
371
|
-
const relatedActions = /* @__PURE__ */ new Set();
|
|
372
|
-
const bakedAction = this.animationActions.get(clipName);
|
|
373
|
-
const clipAction = this.clipActions.get(clipName);
|
|
374
|
-
if (bakedAction) relatedActions.add(bakedAction);
|
|
375
|
-
if (clipAction) relatedActions.add(clipAction);
|
|
376
595
|
this.stopAnimation(clipName);
|
|
377
596
|
if (this.animationMixer) {
|
|
378
|
-
for (const
|
|
597
|
+
for (const runtimeClip of bakedClip.runtimeClips) {
|
|
598
|
+
const action = this.bakedRuntimeActions.get(runtimeClip.clip.name);
|
|
379
599
|
try {
|
|
380
|
-
this.animationMixer.uncacheAction(clip);
|
|
600
|
+
this.animationMixer.uncacheAction(runtimeClip.clip);
|
|
381
601
|
} catch {
|
|
382
602
|
}
|
|
383
603
|
try {
|
|
384
|
-
this.animationMixer.uncacheClip(clip);
|
|
604
|
+
this.animationMixer.uncacheClip(runtimeClip.clip);
|
|
385
605
|
} catch {
|
|
386
606
|
}
|
|
607
|
+
this.bakedRuntimeActions.delete(runtimeClip.clip.name);
|
|
608
|
+
this.bakedRuntimeClipToSource.delete(runtimeClip.clip.name);
|
|
387
609
|
const actionId = this.getActionId(action);
|
|
388
|
-
if (actionId) {
|
|
610
|
+
if (actionId && action) {
|
|
389
611
|
this.actionIdToClip.delete(actionId);
|
|
612
|
+
this.actionIds.delete(action);
|
|
390
613
|
}
|
|
391
|
-
this.actionIds.delete(action);
|
|
392
614
|
}
|
|
393
615
|
}
|
|
394
616
|
this.animationClips = this.animationClips.filter((entry) => entry.name !== clipName);
|
|
395
|
-
this.
|
|
396
|
-
this.
|
|
397
|
-
this.clipHandles.delete(clipName);
|
|
398
|
-
this.animationFinishedCallbacks.delete(clipName);
|
|
617
|
+
this.bakedSourceClips.delete(clipName);
|
|
618
|
+
this.bakedActionGroups.delete(clipName);
|
|
399
619
|
this.playbackState.delete(clipName);
|
|
400
620
|
this.clipSources.delete(clipName);
|
|
401
621
|
return true;
|
|
402
622
|
}
|
|
403
623
|
playAnimation(clipName, options = {}) {
|
|
404
|
-
const
|
|
405
|
-
if (!
|
|
624
|
+
const bakedClip = this.getBakedSourceClip(clipName);
|
|
625
|
+
if (!bakedClip) {
|
|
406
626
|
console.warn(`Loom3: Animation clip "${clipName}" not found`);
|
|
407
627
|
return null;
|
|
408
628
|
}
|
|
409
|
-
if (!this.getActionId(action)) {
|
|
410
|
-
this.setActionId(action, clipName);
|
|
411
|
-
}
|
|
412
629
|
const playbackState = this.mergePlaybackOptions(
|
|
413
630
|
this.getPlaybackStateSnapshot(clipName, { loop: true, source: "baked" }),
|
|
414
631
|
options
|
|
415
632
|
);
|
|
633
|
+
playbackState.blendMode = this.getBakedAggregateBlendMode(clipName, playbackState);
|
|
634
|
+
const actionGroup = this.createBakedActionGroup(clipName, playbackState);
|
|
635
|
+
if (!actionGroup) {
|
|
636
|
+
console.warn(`Loom3: Animation clip "${clipName}" has no character-runtime channels to play`);
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
416
639
|
const crossfadeDuration = options.crossfadeDuration ?? 0;
|
|
417
640
|
const clampWhenFinished = options.clampWhenFinished ?? playbackState.loopMode === "once";
|
|
418
|
-
const startTime = this.resolveStartTime(
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
641
|
+
const startTime = this.resolveStartTime(bakedClip.sourceClip.duration, playbackState, options.startTime);
|
|
642
|
+
for (const [channel, action] of actionGroup.channelActions) {
|
|
643
|
+
this.applyPlaybackStateToBakedAction(action, playbackState, channel);
|
|
644
|
+
action.clampWhenFinished = clampWhenFinished;
|
|
645
|
+
if (crossfadeDuration > 0) {
|
|
646
|
+
action.reset();
|
|
647
|
+
action.fadeIn(crossfadeDuration);
|
|
648
|
+
} else {
|
|
649
|
+
action.reset();
|
|
650
|
+
}
|
|
651
|
+
action.time = startTime;
|
|
652
|
+
action.play();
|
|
426
653
|
}
|
|
427
|
-
|
|
428
|
-
action.play();
|
|
429
|
-
this.animationActions.set(clipName, action);
|
|
654
|
+
this.bakedActionGroups.set(clipName, actionGroup);
|
|
430
655
|
this.setPlaybackState(clipName, playbackState);
|
|
431
|
-
|
|
432
|
-
const finishedPromise = new Promise((resolve) => {
|
|
433
|
-
resolveFinished = resolve;
|
|
434
|
-
});
|
|
435
|
-
if (playbackState.loopMode === "once") {
|
|
436
|
-
this.animationFinishedCallbacks.set(clipName, () => resolveFinished());
|
|
437
|
-
}
|
|
438
|
-
return this.createAnimationHandle(clipName, action, finishedPromise);
|
|
656
|
+
return this.createBakedAnimationHandle(clipName, actionGroup);
|
|
439
657
|
}
|
|
440
658
|
stopAnimation(clipName) {
|
|
659
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
660
|
+
if (bakedGroup) {
|
|
661
|
+
for (const action2 of bakedGroup.channelActions.values()) {
|
|
662
|
+
action2.stop();
|
|
663
|
+
try {
|
|
664
|
+
action2.paused = false;
|
|
665
|
+
} catch {
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
this.bakedActionGroups.delete(clipName);
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
441
671
|
const action = this.animationActions.get(clipName);
|
|
442
672
|
if (action) {
|
|
443
673
|
const isBaked = (this.clipSources.get(clipName) ?? "baked") === "baked";
|
|
@@ -485,6 +715,7 @@ var BakedAnimationController = class {
|
|
|
485
715
|
}
|
|
486
716
|
stopAllAnimations() {
|
|
487
717
|
for (const clipName of /* @__PURE__ */ new Set([
|
|
718
|
+
...this.bakedActionGroups.keys(),
|
|
488
719
|
...this.animationActions.keys(),
|
|
489
720
|
...this.clipActions.keys()
|
|
490
721
|
])) {
|
|
@@ -492,18 +723,39 @@ var BakedAnimationController = class {
|
|
|
492
723
|
}
|
|
493
724
|
}
|
|
494
725
|
pauseAnimation(clipName) {
|
|
726
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
727
|
+
if (bakedGroup) {
|
|
728
|
+
for (const action2 of bakedGroup.channelActions.values()) {
|
|
729
|
+
action2.paused = true;
|
|
730
|
+
}
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
495
733
|
const action = this.animationActions.get(clipName);
|
|
496
734
|
if (action) {
|
|
497
735
|
action.paused = true;
|
|
498
736
|
}
|
|
499
737
|
}
|
|
500
738
|
resumeAnimation(clipName) {
|
|
739
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
740
|
+
if (bakedGroup) {
|
|
741
|
+
for (const action2 of bakedGroup.channelActions.values()) {
|
|
742
|
+
action2.paused = false;
|
|
743
|
+
}
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
501
746
|
const action = this.animationActions.get(clipName);
|
|
502
747
|
if (action) {
|
|
503
748
|
action.paused = false;
|
|
504
749
|
}
|
|
505
750
|
}
|
|
506
751
|
pauseAllAnimations() {
|
|
752
|
+
for (const group of this.bakedActionGroups.values()) {
|
|
753
|
+
for (const action of group.channelActions.values()) {
|
|
754
|
+
if (action.isRunning()) {
|
|
755
|
+
action.paused = true;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
507
759
|
for (const action of this.animationActions.values()) {
|
|
508
760
|
if (action.isRunning()) {
|
|
509
761
|
action.paused = true;
|
|
@@ -511,6 +763,13 @@ var BakedAnimationController = class {
|
|
|
511
763
|
}
|
|
512
764
|
}
|
|
513
765
|
resumeAllAnimations() {
|
|
766
|
+
for (const group of this.bakedActionGroups.values()) {
|
|
767
|
+
for (const action of group.channelActions.values()) {
|
|
768
|
+
if (action.paused) {
|
|
769
|
+
action.paused = false;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
514
773
|
for (const action of this.animationActions.values()) {
|
|
515
774
|
if (action.paused) {
|
|
516
775
|
action.paused = false;
|
|
@@ -518,76 +777,161 @@ var BakedAnimationController = class {
|
|
|
518
777
|
}
|
|
519
778
|
}
|
|
520
779
|
setAnimationSpeed(clipName, speed) {
|
|
521
|
-
|
|
522
|
-
if (action) {
|
|
780
|
+
if (this.isBakedSourceClip(clipName)) {
|
|
523
781
|
const next = this.getPlaybackStateSnapshot(clipName, {
|
|
524
782
|
loop: true,
|
|
525
783
|
source: this.clipSources.get(clipName) ?? "baked"
|
|
526
784
|
});
|
|
527
785
|
next.playbackRate = Number.isFinite(speed) ? Math.max(0, Math.abs(speed)) : 1;
|
|
786
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
787
|
+
if (bakedGroup) {
|
|
788
|
+
for (const [channel, action2] of bakedGroup.channelActions) {
|
|
789
|
+
this.applyPlaybackStateToBakedAction(action2, next, channel);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
this.setPlaybackState(clipName, next);
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
const action = this.animationActions.get(clipName);
|
|
796
|
+
if (action) {
|
|
797
|
+
const next = this.getPlaybackStateSnapshot(clipName, {
|
|
798
|
+
loop: true,
|
|
799
|
+
source: this.clipSources.get(clipName) ?? "clip"
|
|
800
|
+
});
|
|
801
|
+
next.playbackRate = Number.isFinite(speed) ? Math.max(0, Math.abs(speed)) : 1;
|
|
528
802
|
this.applyPlaybackState(action, next);
|
|
529
803
|
this.setPlaybackState(clipName, next);
|
|
530
804
|
}
|
|
531
805
|
}
|
|
532
806
|
setAnimationIntensity(clipName, intensity) {
|
|
533
|
-
|
|
534
|
-
if (action) {
|
|
807
|
+
if (this.isBakedSourceClip(clipName)) {
|
|
535
808
|
const next = this.getPlaybackStateSnapshot(clipName, {
|
|
536
809
|
loop: true,
|
|
537
810
|
source: this.clipSources.get(clipName) ?? "baked"
|
|
538
811
|
});
|
|
539
812
|
next.weight = Number.isFinite(intensity) ? Math.max(0, intensity) : 1;
|
|
813
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
814
|
+
if (bakedGroup) {
|
|
815
|
+
for (const [channel, action2] of bakedGroup.channelActions) {
|
|
816
|
+
this.applyPlaybackStateToBakedAction(action2, next, channel);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
this.setPlaybackState(clipName, next);
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
const action = this.animationActions.get(clipName);
|
|
823
|
+
if (action) {
|
|
824
|
+
const next = this.getPlaybackStateSnapshot(clipName, {
|
|
825
|
+
loop: true,
|
|
826
|
+
source: this.clipSources.get(clipName) ?? "clip"
|
|
827
|
+
});
|
|
828
|
+
next.weight = Number.isFinite(intensity) ? Math.max(0, intensity) : 1;
|
|
540
829
|
action.setEffectiveWeight(next.weight);
|
|
541
830
|
this.setPlaybackState(clipName, next);
|
|
542
831
|
}
|
|
543
832
|
}
|
|
544
833
|
setAnimationLoopMode(clipName, loopMode) {
|
|
545
|
-
const action = this.getOrCreateBakedAction(clipName);
|
|
546
|
-
if (!action) return;
|
|
547
834
|
const next = this.getPlaybackStateSnapshot(clipName, {
|
|
548
835
|
loop: true,
|
|
549
|
-
source: this.clipSources.get(clipName) ?? "baked"
|
|
836
|
+
source: this.clipSources.get(clipName) ?? (this.isBakedSourceClip(clipName) ? "baked" : "clip")
|
|
550
837
|
});
|
|
551
838
|
next.loopMode = loopMode;
|
|
552
839
|
next.loop = loopMode !== "once";
|
|
840
|
+
if (this.isBakedSourceClip(clipName)) {
|
|
841
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
842
|
+
if (bakedGroup) {
|
|
843
|
+
for (const [channel, action2] of bakedGroup.channelActions) {
|
|
844
|
+
this.applyPlaybackStateToBakedAction(action2, next, channel);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
this.setPlaybackState(clipName, next);
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
const action = this.animationActions.get(clipName);
|
|
851
|
+
if (!action) return;
|
|
553
852
|
this.applyPlaybackState(action, next);
|
|
554
853
|
this.setPlaybackState(clipName, next);
|
|
555
854
|
}
|
|
556
855
|
setAnimationRepeatCount(clipName, repeatCount) {
|
|
557
|
-
const action = this.getOrCreateBakedAction(clipName);
|
|
558
|
-
if (!action) return;
|
|
559
856
|
const next = this.getPlaybackStateSnapshot(clipName, {
|
|
560
857
|
loop: true,
|
|
561
|
-
source: this.clipSources.get(clipName) ?? "baked"
|
|
858
|
+
source: this.clipSources.get(clipName) ?? (this.isBakedSourceClip(clipName) ? "baked" : "clip")
|
|
562
859
|
});
|
|
563
860
|
next.repeatCount = typeof repeatCount === "number" && Number.isFinite(repeatCount) ? Math.max(0, repeatCount) : void 0;
|
|
861
|
+
if (this.isBakedSourceClip(clipName)) {
|
|
862
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
863
|
+
if (bakedGroup) {
|
|
864
|
+
for (const [channel, action2] of bakedGroup.channelActions) {
|
|
865
|
+
this.applyPlaybackStateToBakedAction(action2, next, channel);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
this.setPlaybackState(clipName, next);
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const action = this.animationActions.get(clipName);
|
|
872
|
+
if (!action) return;
|
|
564
873
|
this.applyPlaybackState(action, next);
|
|
565
874
|
this.setPlaybackState(clipName, next);
|
|
566
875
|
}
|
|
567
876
|
setAnimationReverse(clipName, reverse) {
|
|
568
|
-
const action = this.getOrCreateBakedAction(clipName);
|
|
569
|
-
if (!action) return;
|
|
570
877
|
const next = this.getPlaybackStateSnapshot(clipName, {
|
|
571
878
|
loop: true,
|
|
572
|
-
source: this.clipSources.get(clipName) ?? "baked"
|
|
879
|
+
source: this.clipSources.get(clipName) ?? (this.isBakedSourceClip(clipName) ? "baked" : "clip")
|
|
573
880
|
});
|
|
574
881
|
next.reverse = !!reverse;
|
|
882
|
+
if (this.isBakedSourceClip(clipName)) {
|
|
883
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
884
|
+
if (bakedGroup) {
|
|
885
|
+
for (const [channel, action2] of bakedGroup.channelActions) {
|
|
886
|
+
this.applyPlaybackStateToBakedAction(action2, next, channel);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
this.setPlaybackState(clipName, next);
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
const action = this.animationActions.get(clipName);
|
|
893
|
+
if (!action) return;
|
|
575
894
|
this.applyPlaybackState(action, next);
|
|
576
895
|
this.setPlaybackState(clipName, next);
|
|
577
896
|
}
|
|
578
897
|
setAnimationBlendMode(clipName, blendMode) {
|
|
579
|
-
const action = this.getOrCreateBakedAction(clipName);
|
|
580
|
-
if (!action) return;
|
|
581
898
|
const next = this.getPlaybackStateSnapshot(clipName, {
|
|
582
899
|
loop: true,
|
|
583
|
-
source: this.clipSources.get(clipName) ?? "baked"
|
|
900
|
+
source: this.clipSources.get(clipName) ?? (this.isBakedSourceClip(clipName) ? "baked" : "clip")
|
|
584
901
|
});
|
|
902
|
+
next.requestedBlendMode = blendMode;
|
|
903
|
+
if (this.isBakedSourceClip(clipName)) {
|
|
904
|
+
next.blendMode = this.getBakedAggregateBlendMode(clipName, next);
|
|
905
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
906
|
+
if (bakedGroup) {
|
|
907
|
+
for (const [channel, action2] of bakedGroup.channelActions) {
|
|
908
|
+
this.applyPlaybackStateToBakedAction(action2, next, channel);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
this.setPlaybackState(clipName, next);
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
585
914
|
next.blendMode = blendMode;
|
|
915
|
+
const action = this.animationActions.get(clipName);
|
|
916
|
+
if (!action) return;
|
|
586
917
|
this.applyPlaybackState(action, next);
|
|
587
918
|
this.setPlaybackState(clipName, next);
|
|
588
919
|
}
|
|
589
920
|
seekAnimation(clipName, time) {
|
|
590
|
-
const
|
|
921
|
+
const bakedGroup = this.bakedActionGroups.get(clipName);
|
|
922
|
+
if (bakedGroup) {
|
|
923
|
+
const duration2 = this.getBakedSourceClip(clipName)?.sourceClip.duration ?? 0;
|
|
924
|
+
const clamped = Math.max(0, Math.min(duration2, Number.isFinite(time) ? time : 0));
|
|
925
|
+
for (const action2 of bakedGroup.channelActions.values()) {
|
|
926
|
+
action2.time = clamped;
|
|
927
|
+
}
|
|
928
|
+
try {
|
|
929
|
+
this.animationMixer?.update(0);
|
|
930
|
+
} catch {
|
|
931
|
+
}
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
const action = this.animationActions.get(clipName);
|
|
591
935
|
if (!action) return;
|
|
592
936
|
const duration = action.getClip().duration;
|
|
593
937
|
action.time = Math.max(0, Math.min(duration, Number.isFinite(time) ? time : 0));
|
|
@@ -602,6 +946,40 @@ var BakedAnimationController = class {
|
|
|
602
946
|
}
|
|
603
947
|
}
|
|
604
948
|
getAnimationState(clipName) {
|
|
949
|
+
const bakedClip = this.getBakedSourceClip(clipName);
|
|
950
|
+
if (bakedClip) {
|
|
951
|
+
const state2 = this.playbackState.get(clipName);
|
|
952
|
+
const action2 = this.getRepresentativeBakedAction(clipName);
|
|
953
|
+
if (!state2 && !action2) {
|
|
954
|
+
return null;
|
|
955
|
+
}
|
|
956
|
+
const loopMode2 = state2?.loopMode ?? (action2?.loop === LoopPingPong ? "pingpong" : action2?.loop === LoopOnce ? "once" : "repeat");
|
|
957
|
+
const playbackRate2 = state2?.playbackRate ?? Math.abs(action2?.getEffectiveTimeScale?.() ?? 1);
|
|
958
|
+
const reverse2 = state2?.reverse ?? (action2?.getEffectiveTimeScale?.() ?? 1) < 0;
|
|
959
|
+
const pausedValues = this.bakedActionGroups.get(clipName) ? Array.from(this.bakedActionGroups.get(clipName).channelActions.values()).map((entry) => entry.paused) : [];
|
|
960
|
+
return {
|
|
961
|
+
name: bakedClip.sourceClip.name,
|
|
962
|
+
actionId: this.bakedActionGroups.get(clipName)?.actionId,
|
|
963
|
+
source: state2?.source ?? this.clipSources.get(clipName) ?? "baked",
|
|
964
|
+
isPlaying: this.bakedActionGroups.get(clipName) ? Array.from(this.bakedActionGroups.get(clipName).channelActions.values()).some((entry) => entry.isRunning() && !entry.paused) : false,
|
|
965
|
+
isPaused: pausedValues.length > 0 ? pausedValues.every(Boolean) : false,
|
|
966
|
+
time: action2?.time ?? 0,
|
|
967
|
+
duration: bakedClip.sourceClip.duration,
|
|
968
|
+
speed: playbackRate2,
|
|
969
|
+
playbackRate: playbackRate2,
|
|
970
|
+
reverse: reverse2,
|
|
971
|
+
weight: state2?.weight ?? action2?.getEffectiveWeight?.() ?? 1,
|
|
972
|
+
balance: state2?.balance ?? 0,
|
|
973
|
+
requestedBlendMode: state2?.requestedBlendMode ?? "replace",
|
|
974
|
+
blendMode: this.getBakedAggregateBlendMode(clipName, state2),
|
|
975
|
+
channels: this.getBakedChannelInfo(clipName, state2),
|
|
976
|
+
easing: state2?.easing ?? "linear",
|
|
977
|
+
loop: loopMode2 !== "once",
|
|
978
|
+
loopMode: loopMode2,
|
|
979
|
+
repeatCount: state2?.repeatCount,
|
|
980
|
+
isLooping: loopMode2 !== "once"
|
|
981
|
+
};
|
|
982
|
+
}
|
|
605
983
|
const action = this.animationActions.get(clipName);
|
|
606
984
|
if (!action) return null;
|
|
607
985
|
const clip = action.getClip();
|
|
@@ -622,7 +1000,9 @@ var BakedAnimationController = class {
|
|
|
622
1000
|
reverse,
|
|
623
1001
|
weight: state?.weight ?? action.getEffectiveWeight(),
|
|
624
1002
|
balance: state?.balance ?? 0,
|
|
1003
|
+
requestedBlendMode: state?.requestedBlendMode ?? state?.blendMode ?? "replace",
|
|
625
1004
|
blendMode: state?.blendMode ?? "replace",
|
|
1005
|
+
channels: state?.source === "baked" ? this.getBakedChannelInfo(clipName, state) : void 0,
|
|
626
1006
|
easing: state?.easing ?? "linear",
|
|
627
1007
|
loop: loopMode !== "once",
|
|
628
1008
|
loopMode,
|
|
@@ -632,6 +1012,12 @@ var BakedAnimationController = class {
|
|
|
632
1012
|
}
|
|
633
1013
|
getPlayingAnimations() {
|
|
634
1014
|
const playing = [];
|
|
1015
|
+
for (const name of this.bakedActionGroups.keys()) {
|
|
1016
|
+
const state = this.getAnimationState(name);
|
|
1017
|
+
if (state?.isPlaying) {
|
|
1018
|
+
playing.push(state);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
635
1021
|
for (const [name, action] of this.animationActions) {
|
|
636
1022
|
if (action.isRunning()) {
|
|
637
1023
|
const state = this.getAnimationState(name);
|
|
@@ -641,6 +1027,13 @@ var BakedAnimationController = class {
|
|
|
641
1027
|
return playing;
|
|
642
1028
|
}
|
|
643
1029
|
crossfadeTo(clipName, duration = 0.3, options = {}) {
|
|
1030
|
+
for (const group of this.bakedActionGroups.values()) {
|
|
1031
|
+
for (const action of group.channelActions.values()) {
|
|
1032
|
+
if (action.isRunning()) {
|
|
1033
|
+
action.fadeOut(duration);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
644
1037
|
for (const action of this.animationActions.values()) {
|
|
645
1038
|
if (action.isRunning()) {
|
|
646
1039
|
action.fadeOut(duration);
|
|
@@ -1166,6 +1559,14 @@ var BakedAnimationController = class {
|
|
|
1166
1559
|
this.animationMixer.addEventListener("finished", (event) => {
|
|
1167
1560
|
const action = event.action;
|
|
1168
1561
|
const clip = action.getClip();
|
|
1562
|
+
const bakedRuntime = this.bakedRuntimeClipToSource.get(clip.name);
|
|
1563
|
+
if (bakedRuntime) {
|
|
1564
|
+
const group = this.bakedActionGroups.get(bakedRuntime.sourceClipName);
|
|
1565
|
+
if (group && group.pendingFinishedChannels.delete(bakedRuntime.channel) && group.pendingFinishedChannels.size === 0) {
|
|
1566
|
+
group.resolveFinished();
|
|
1567
|
+
}
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1169
1570
|
const callback = this.animationFinishedCallbacks.get(clip.name);
|
|
1170
1571
|
if (callback) {
|
|
1171
1572
|
callback();
|
|
@@ -1190,6 +1591,20 @@ var BakedAnimationController = class {
|
|
|
1190
1591
|
finished: finishedPromise
|
|
1191
1592
|
};
|
|
1192
1593
|
}
|
|
1594
|
+
createBakedAnimationHandle(clipName, group) {
|
|
1595
|
+
return {
|
|
1596
|
+
actionId: group.actionId,
|
|
1597
|
+
stop: () => this.stopAnimation(clipName),
|
|
1598
|
+
pause: () => this.pauseAnimation(clipName),
|
|
1599
|
+
resume: () => this.resumeAnimation(clipName),
|
|
1600
|
+
setSpeed: (speed) => this.setAnimationSpeed(clipName, speed),
|
|
1601
|
+
setWeight: (weight) => this.setAnimationIntensity(clipName, weight),
|
|
1602
|
+
seekTo: (time) => this.seekAnimation(clipName, time),
|
|
1603
|
+
getState: () => this.getAnimationState(clipName),
|
|
1604
|
+
crossfadeTo: (targetClip, dur) => this.crossfadeTo(targetClip, dur),
|
|
1605
|
+
finished: group.finishedPromise
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1193
1608
|
};
|
|
1194
1609
|
|
|
1195
1610
|
// src/presets/cc4.ts
|