@braccato/core 1.16.5 → 1.16.6
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/engine.js +43 -16
- package/package.json +1 -1
package/dist/engine.js
CHANGED
|
@@ -436,7 +436,7 @@ function mirrorImageHighlightAnimations(part, animations) {
|
|
|
436
436
|
mirror.currentTime = animation.currentTime;
|
|
437
437
|
const timing = animationTimingTracks.get(animation);
|
|
438
438
|
if (timing)
|
|
439
|
-
animationTimingTracks.set(mirror, timing);
|
|
439
|
+
animationTimingTracks.set(mirror, { ...timing, skipDriftSample: true });
|
|
440
440
|
mirrors.push(mirror);
|
|
441
441
|
}
|
|
442
442
|
return mirrors;
|
|
@@ -529,8 +529,11 @@ function timingValueToMs(value) {
|
|
|
529
529
|
function animationCurrentTimeMs(animation) {
|
|
530
530
|
return timingValueToMs(animation.currentTime);
|
|
531
531
|
}
|
|
532
|
-
|
|
533
|
-
|
|
532
|
+
// A finished animation's currentTime stops at its end time, which counts the delay, so that is where
|
|
533
|
+
// the expected time has to stop too. Clamping to the active duration alone saturates a delayed
|
|
534
|
+
// animation as soon as it is created and hides any drift in it.
|
|
535
|
+
function animationEndTimeMs(animation) {
|
|
536
|
+
return timingValueToMs(animation.effect?.getComputedTiming().endTime);
|
|
534
537
|
}
|
|
535
538
|
function wrappedTimingOffsetMs(actualTimeMs, expectedTimeMs, wrapDurationMs) {
|
|
536
539
|
return positiveModulo(actualTimeMs - expectedTimeMs + wrapDurationMs / 2, wrapDurationMs) - wrapDurationMs / 2;
|
|
@@ -542,18 +545,18 @@ function normalizeAnimationTimeMs(animation, timeMs, timing) {
|
|
|
542
545
|
if (timing.wrapDurationMs && timing.wrapDurationMs > 0) {
|
|
543
546
|
return positiveModulo(timeMs, timing.wrapDurationMs);
|
|
544
547
|
}
|
|
545
|
-
const
|
|
546
|
-
if (
|
|
547
|
-
return Math.min(timeMs,
|
|
548
|
+
const endTimeMs = animationEndTimeMs(animation);
|
|
549
|
+
if (endTimeMs !== null && Number.isFinite(endTimeMs)) {
|
|
550
|
+
return Math.min(timeMs, endTimeMs);
|
|
548
551
|
}
|
|
549
552
|
return timeMs;
|
|
550
553
|
}
|
|
551
554
|
function animationTimingSample(part, animation, currentTime) {
|
|
552
|
-
|
|
555
|
+
const timing = animationTimingTracks.get(animation);
|
|
556
|
+
if (!timing || timing.skipDriftSample) {
|
|
553
557
|
return null;
|
|
554
558
|
}
|
|
555
|
-
|
|
556
|
-
if (!timing) {
|
|
559
|
+
if (animation.playState === "idle") {
|
|
557
560
|
return null;
|
|
558
561
|
}
|
|
559
562
|
const actualTimeMs = animationCurrentTimeMs(animation);
|
|
@@ -887,7 +890,11 @@ function startRichSyncedHighlightAnimations(engine, part, config, swipeTimeMs, w
|
|
|
887
890
|
offset: frame.offset,
|
|
888
891
|
maskPosition: frame.maskPosition,
|
|
889
892
|
WebkitMaskPosition: frame.maskPosition,
|
|
890
|
-
})), { duration: sweep.durationMs, delay: sweep.delayMs, easing: sweep.easing, fill: "both" }),
|
|
893
|
+
})), { duration: sweep.durationMs, delay: sweep.delayMs, easing: sweep.easing, fill: "both" }),
|
|
894
|
+
// The last letter's sweep ends last, so it alone covers the whole word.
|
|
895
|
+
index === sweeps.length - 1 && target === highlightLetters[index]
|
|
896
|
+
? swipeTiming
|
|
897
|
+
: { ...swipeTiming, skipDriftSample: true });
|
|
891
898
|
animation.currentTime = swipeCurrentTimeMs;
|
|
892
899
|
if (index === 0)
|
|
893
900
|
swipeAnimation = animation;
|
|
@@ -1042,20 +1049,40 @@ function startWordAnimations(engine, part, config, currentTime, appliedTimingOff
|
|
|
1042
1049
|
// as the wave running behind once it finishes. Run the wave's clock ahead by the head start
|
|
1043
1050
|
// instead, the way the swipe carries its lead, so every delay stays at zero or above.
|
|
1044
1051
|
const waveLeadMs = Math.max(0, -Math.min(...waves.map(wave => wave.delayMs)));
|
|
1045
|
-
const
|
|
1052
|
+
const waveEndsMs = waves.map(wave => wave.delayMs + wave.durationMs);
|
|
1053
|
+
const lastWaveEndMs = Math.max(...waveEndsMs);
|
|
1054
|
+
const lastEndingWaveIndex = waveEndsMs.lastIndexOf(lastWaveEndMs);
|
|
1055
|
+
const cascadeDurationMs = waveLeadMs + lastWaveEndMs;
|
|
1046
1056
|
const floatStartMs = correctedAnimationTimeMs(wordTimeMs + waveLeadMs, appliedTimingOffsetMs, cascadeDurationMs);
|
|
1047
1057
|
const floatKeyframeSignature = JSON.stringify(floatKeyframes);
|
|
1048
|
-
|
|
1049
|
-
|
|
1058
|
+
// Glow letters only show while the glow does: never when it is off or renders nothing for this
|
|
1059
|
+
// word, and not once it has faded out. Their waves stop there instead of running to the end.
|
|
1060
|
+
const glowLetters = config.enabled.highlightGlow && !part.glowSuppressed ? part.imageLayers?.glowLetters : undefined;
|
|
1061
|
+
const glowEndMs = Number.parseFloat(config.highlight.imageGlowOpacityTo) === 0 ? waveLeadMs + glowDurationMs : Infinity;
|
|
1062
|
+
const animateLetters = (letters, endMs, sampled) => {
|
|
1063
|
+
letters?.forEach((letterElement, index) => {
|
|
1064
|
+
const delayMs = waves[index].delayMs + waveLeadMs;
|
|
1065
|
+
if (delayMs >= endMs)
|
|
1066
|
+
return;
|
|
1067
|
+
const endDelayMs = Math.min(0, endMs - delayMs - waves[index].durationMs);
|
|
1050
1068
|
const animation = trackLyricAnimationTiming(engine, acquireWaveAnimation(engine, letterElement, floatKeyframes, floatKeyframeSignature, {
|
|
1051
1069
|
duration: waves[index].durationMs,
|
|
1052
|
-
delay:
|
|
1070
|
+
delay: delayMs,
|
|
1071
|
+
endDelay: endDelayMs,
|
|
1053
1072
|
fill: "forwards",
|
|
1054
|
-
}), {
|
|
1073
|
+
}), {
|
|
1074
|
+
appliedTimingOffsetMs,
|
|
1075
|
+
offsetMs: waveLeadMs,
|
|
1076
|
+
// The wave that ends last covers the whole word. A theme's swipe ramp can make that an early letter.
|
|
1077
|
+
skipDriftSample: !sampled || index !== lastEndingWaveIndex,
|
|
1078
|
+
});
|
|
1055
1079
|
animation.currentTime = floatStartMs;
|
|
1056
1080
|
wobbleAnimations.push(animation);
|
|
1057
1081
|
});
|
|
1058
|
-
}
|
|
1082
|
+
};
|
|
1083
|
+
animateLetters(part.letterElements, Infinity, true);
|
|
1084
|
+
animateLetters(part.highlightLetterElements, Infinity, false);
|
|
1085
|
+
animateLetters(glowLetters, glowEndMs, false);
|
|
1059
1086
|
}
|
|
1060
1087
|
}
|
|
1061
1088
|
part.animations = [
|