summaryrefslogtreecommitdiff
path: root/apps/web/src/animation/channel-data.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-29 10:37:39 +0200
committerMaze Winther <mazewinther@gmail.com>2026-05-02 03:27:23 +0200
commit401cc35743aafc4c8bdfb8055501650390bde88b (patch)
tree98385fb2f252ff6bb227a844d96b664a8fe87835 /apps/web/src/animation/channel-data.ts
parentb8d08df244b97b1d3131cb2d076166838189eeb0 (diff)
downloadopencut-401cc35743aafc4c8bdfb8055501650390bde88b.tar.gz
refactor: animate params over time
Diffstat (limited to 'apps/web/src/animation/channel-data.ts')
-rw-r--r--apps/web/src/animation/channel-data.ts57
1 files changed, 57 insertions, 0 deletions
diff --git a/apps/web/src/animation/channel-data.ts b/apps/web/src/animation/channel-data.ts
new file mode 100644
index 00000000..2fc08b5c
--- /dev/null
+++ b/apps/web/src/animation/channel-data.ts
@@ -0,0 +1,57 @@
+import type {
+ AnimationChannel,
+ ChannelData,
+ CompositeChannelData,
+} from "@/animation/types";
+
+const LEGACY_ANIMATION_STORAGE_KEYS = new Set(["bindings", "channels"]);
+
+function isRecord(value: unknown): value is Record<string, unknown> {
+ return typeof value === "object" && value !== null;
+}
+
+export function isLeafChannelData(
+ data: ChannelData | undefined,
+): data is AnimationChannel {
+ return isRecord(data) && Array.isArray(data.keys);
+}
+
+export function isCompositeChannelData(
+ data: ChannelData | undefined,
+): data is CompositeChannelData {
+ return isRecord(data) && !Array.isArray(data.keys);
+}
+
+export function getChannelsFromData({
+ data,
+}: {
+ data: ChannelData | undefined;
+}): AnimationChannel[] {
+ if (isLeafChannelData(data)) {
+ return [data];
+ }
+ if (!isCompositeChannelData(data)) {
+ return [];
+ }
+ return Object.values(data).filter(isLeafChannelData);
+}
+
+export function getChannelEntriesFromData({
+ data,
+}: {
+ data: ChannelData | undefined;
+}): Array<[string, AnimationChannel]> {
+ if (isLeafChannelData(data)) {
+ return [["value", data]];
+ }
+ if (!isCompositeChannelData(data)) {
+ return [];
+ }
+ return Object.entries(data).flatMap(([componentKey, channel]) =>
+ isLeafChannelData(channel) ? [[componentKey, channel]] : [],
+ );
+}
+
+export function isAnimationStorageKey({ key }: { key: string }): boolean {
+ return !LEGACY_ANIMATION_STORAGE_KEYS.has(key);
+}