summaryrefslogtreecommitdiff
path: root/apps/web/src/animation/interpolation.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/animation/interpolation.ts')
-rw-r--r--apps/web/src/animation/interpolation.ts91
1 files changed, 66 insertions, 25 deletions
diff --git a/apps/web/src/animation/interpolation.ts b/apps/web/src/animation/interpolation.ts
index 5d5212a6..cdb8bcc9 100644
--- a/apps/web/src/animation/interpolation.ts
+++ b/apps/web/src/animation/interpolation.ts
@@ -1,13 +1,14 @@
import type {
AnimationChannel,
AnimationInterpolation,
- AnimationValue,
+ Channel,
DiscreteAnimationChannel,
DiscreteValue,
ScalarAnimationChannel,
ScalarAnimationKey,
ScalarSegmentType,
} from "@/animation/types";
+import type { ParamValue } from "@/params";
import { mediaTime } from "@/wasm";
import {
getBezierPoint,
@@ -111,7 +112,7 @@ function normalizeScalarKey({
};
}
-function normalizeScalarChannel({
+export function normalizeScalarChannel({
channel,
}: {
channel: ScalarAnimationChannel;
@@ -154,17 +155,11 @@ function normalizeScalarChannel({
};
}
-export function normalizeChannel<TChannel extends AnimationChannel>({
+export function normalizeDiscreteChannel({
channel,
}: {
- channel: TChannel;
-}): TChannel {
- if (channel.kind === "scalar") {
- return normalizeScalarChannel({
- channel,
- }) as TChannel;
- }
-
+ channel: DiscreteAnimationChannel;
+}): DiscreteAnimationChannel {
return {
...channel,
keys: [...channel.keys].sort((leftKeyframe, rightKeyframe) =>
@@ -173,7 +168,39 @@ export function normalizeChannel<TChannel extends AnimationChannel>({
rightTime: rightKeyframe.time,
}),
),
- } as TChannel;
+ };
+}
+
+export function isScalarChannel(channel: AnimationChannel): channel is ScalarAnimationChannel {
+ return (
+ "extrapolation" in channel ||
+ channel.keys.some((keyframe) => "segmentToNext" in keyframe)
+ );
+}
+
+export function normalizeChannel({
+ channel,
+}: {
+ channel: ScalarAnimationChannel;
+}): ScalarAnimationChannel;
+export function normalizeChannel({
+ channel,
+}: {
+ channel: DiscreteAnimationChannel;
+}): DiscreteAnimationChannel;
+export function normalizeChannel({
+ channel,
+}: {
+ channel: AnimationChannel;
+}): AnimationChannel;
+export function normalizeChannel({
+ channel,
+}: {
+ channel: AnimationChannel;
+}): AnimationChannel {
+ return isScalarChannel(channel)
+ ? normalizeScalarChannel({ channel })
+ : normalizeDiscreteChannel({ channel });
}
function extrapolateScalarEdge({
@@ -216,7 +243,7 @@ export function getScalarChannelValueAtTime({
time,
fallbackValue,
}: {
- channel: ScalarAnimationChannel | undefined;
+ channel: Channel<number> | undefined;
time: number;
fallbackValue: number;
}): number {
@@ -224,9 +251,7 @@ export function getScalarChannelValueAtTime({
return fallbackValue;
}
- const normalizedChannel = normalizeChannel({
- channel,
- });
+ const normalizedChannel = normalizeScalarChannel({ channel });
const firstKey = normalizedChannel.keys[0];
const lastKey = normalizedChannel.keys[normalizedChannel.keys.length - 1];
if (!firstKey || !lastKey) {
@@ -328,7 +353,7 @@ export function getDiscreteChannelValueAtTime({
time,
fallbackValue,
}: {
- channel: DiscreteAnimationChannel | undefined;
+ channel: Channel<DiscreteValue> | undefined;
time: number;
fallbackValue: DiscreteValue;
}): DiscreteValue {
@@ -336,9 +361,7 @@ export function getDiscreteChannelValueAtTime({
return fallbackValue;
}
- const normalizedChannel = normalizeChannel({
- channel,
- });
+ const normalizedChannel = normalizeDiscreteChannel({ channel });
let currentValue = fallbackValue;
for (const key of normalizedChannel.keys) {
if (time < key.time) {
@@ -354,16 +377,34 @@ export function getChannelValueAtTime({
time,
fallbackValue,
}: {
+ channel: Channel<number> | undefined;
+ time: number;
+ fallbackValue: number;
+}): number;
+export function getChannelValueAtTime<TValue extends DiscreteValue>({
+ channel,
+ time,
+ fallbackValue,
+}: {
+ channel: DiscreteAnimationChannel | undefined;
+ time: number;
+ fallbackValue: TValue;
+}): TValue;
+export function getChannelValueAtTime({
+ channel,
+ time,
+ fallbackValue,
+}: {
channel: AnimationChannel | undefined;
time: number;
- fallbackValue: AnimationValue;
-}): AnimationValue {
+ fallbackValue: ParamValue;
+}): ParamValue {
if (!channel || channel.keys.length === 0) {
return fallbackValue;
}
- if (channel.kind === "scalar") {
- return typeof fallbackValue === "number"
+ if (typeof fallbackValue === "number") {
+ return isScalarChannel(channel)
? getScalarChannelValueAtTime({
channel,
time,
@@ -377,7 +418,7 @@ export function getChannelValueAtTime({
}
return getDiscreteChannelValueAtTime({
- channel,
+ channel: isScalarChannel(channel) ? undefined : channel,
time,
fallbackValue,
});