From 3e89d2998588f8e35c524e523ba2ee853f0f6475 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 20 Apr 2026 11:31:17 +0200 Subject: refactor: restructure files to their domains, new preview overlay system, and dep graph --- apps/web/src/animation/effect-param-channel.ts | 100 +++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 apps/web/src/animation/effect-param-channel.ts (limited to 'apps/web/src/animation/effect-param-channel.ts') diff --git a/apps/web/src/animation/effect-param-channel.ts b/apps/web/src/animation/effect-param-channel.ts new file mode 100644 index 00000000..c635bb82 --- /dev/null +++ b/apps/web/src/animation/effect-param-channel.ts @@ -0,0 +1,100 @@ +import type { ParamValues } from "@/params"; +import type { Effect } from "@/effects/types"; +import type { + ElementAnimations, + EffectParamPath, +} from "@/animation/types"; +import { removeElementKeyframe } from "./keyframes"; +import { resolveAnimationPathValueAtTime } from "./resolve"; + +export const EFFECT_PARAM_PATH_PREFIX = "effects."; +export const EFFECT_PARAM_PATH_SUFFIX = ".params."; + +export function buildEffectParamPath({ + effectId, + paramKey, +}: { + effectId: string; + paramKey: string; +}): EffectParamPath { + return `${EFFECT_PARAM_PATH_PREFIX}${effectId}${EFFECT_PARAM_PATH_SUFFIX}${paramKey}`; +} + +export function isEffectParamPath( + propertyPath: string, +): propertyPath is EffectParamPath { + return ( + propertyPath.startsWith(EFFECT_PARAM_PATH_PREFIX) && + propertyPath.includes(EFFECT_PARAM_PATH_SUFFIX) + ); +} + +export function parseEffectParamPath({ + propertyPath, +}: { + propertyPath: string; +}): { effectId: string; paramKey: string } | null { + if (!isEffectParamPath(propertyPath)) { + return null; + } + + const withoutPrefix = propertyPath.slice(EFFECT_PARAM_PATH_PREFIX.length); + const separatorIndex = withoutPrefix.indexOf(EFFECT_PARAM_PATH_SUFFIX); + if (separatorIndex <= 0) { + return null; + } + + const effectId = withoutPrefix.slice(0, separatorIndex); + const paramKey = withoutPrefix.slice( + separatorIndex + EFFECT_PARAM_PATH_SUFFIX.length, + ); + if (!effectId || !paramKey) { + return null; + } + + return { effectId, paramKey }; +} + +export function resolveEffectParamsAtTime({ + effect, + animations, + localTime, +}: { + effect: Effect; + animations: ElementAnimations | undefined; + localTime: number; +}): ParamValues { + const resolved: ParamValues = {}; + + for (const [paramKey, staticValue] of Object.entries(effect.params)) { + const path = buildEffectParamPath({ effectId: effect.id, paramKey }); + resolved[paramKey] = animations?.bindings[path] + ? resolveAnimationPathValueAtTime({ + animations, + propertyPath: path, + localTime, + fallbackValue: staticValue, + }) + : staticValue; + } + + return resolved; +} + +export function removeEffectParamKeyframe({ + animations, + effectId, + paramKey, + keyframeId, +}: { + animations: ElementAnimations | undefined; + effectId: string; + paramKey: string; + keyframeId: string; +}): ElementAnimations | undefined { + return removeElementKeyframe({ + animations, + propertyPath: buildEffectParamPath({ effectId, paramKey }), + keyframeId, + }); +} -- cgit v1.3.1