diff --git a/src/components/nodes/EaseCurveNode.tsx b/src/components/nodes/EaseCurveNode.tsx index cea3ab84..ae8e6a0c 100644 --- a/src/components/nodes/EaseCurveNode.tsx +++ b/src/components/nodes/EaseCurveNode.tsx @@ -9,10 +9,9 @@ import { EaseCurveNodeData } from "@/types"; import { checkEncoderSupport } from "@/hooks/useStitchVideos"; import { CubicBezierEditor } from "@/components/CubicBezierEditor"; import { - PRESET_BEZIERS, EASING_PRESETS, - DEFAULT_CUSTOM_BEZIER, getPresetBezier, + getEasingBezier, } from "@/lib/easing-presets"; import { getAllEasingNames, getEasingFunction } from "@/lib/easing-functions"; @@ -117,13 +116,9 @@ export function EaseCurveNode({ id, data, selected }: NodeProps { - // For presets in PRESET_BEZIERS, use those handles. For others, use DEFAULT_CUSTOM_BEZIER. - const handles = PRESET_NAMES.has(name as any) - ? getPresetBezier(name) - : ([...DEFAULT_CUSTOM_BEZIER] as [number, number, number, number]); updateNodeData(id, { easingPreset: name, - bezierHandles: handles, + bezierHandles: getEasingBezier(name), }); setShowPresets(false); }, @@ -262,7 +257,7 @@ export function EaseCurveNode({ id, data, selected }: NodeProps setActiveTab("editor")} @@ -272,7 +267,7 @@ export function EaseCurveNode({ id, data, selected }: NodeProps setActiveTab("video")} @@ -284,8 +279,8 @@ export function EaseCurveNode({ id, data, selected }: NodeProps - {/* Bezier curve editor */} -
+ {/* Bezier curve editor - fills available width */} +
- +
+ {nodeData.easingPreset}
@@ -347,7 +342,7 @@ export function EaseCurveNode({ id, data, selected }: NodeProps handleSelectPreset(name)} @@ -360,7 +355,7 @@ export function EaseCurveNode({ id, data, selected }: NodeProps handleSelectEasing(name)} @@ -401,7 +396,7 @@ export function EaseCurveNode({ id, data, selected }: NodeProps
+ + {/* Apply button */} +
+ +
)} diff --git a/src/lib/easing-presets.ts b/src/lib/easing-presets.ts index a71fc504..e639ae1a 100644 --- a/src/lib/easing-presets.ts +++ b/src/lib/easing-presets.ts @@ -2,10 +2,10 @@ export const DEFAULT_CUSTOM_BEZIER: [number, number, number, number] = [0.42, 0, export const PRESET_BEZIERS = { easeInExpoOutCubic: [0.85, 0, 0.15, 1], - easeInOutExpo: [1, 0, 0, 1], + easeInOutExpo: [0.87, 0, 0.13, 1], easeInQuartOutQuad: [0.8, 0, 0.2, 1], - easeInOutCubic: [0.645, 0.045, 0.355, 1], - easeInOutSine: [0.445, 0.05, 0.55, 0.95], + easeInOutCubic: [0.65, 0, 0.35, 1], + easeInOutSine: [0.37, 0, 0.63, 1], } as const satisfies Record; export type EasingPresetName = keyof typeof PRESET_BEZIERS; @@ -14,8 +14,40 @@ export const EASING_PRESETS: EasingPresetName[] = [ 'easeInExpoOutCubic', 'easeInOutExpo', 'easeInQuartOutQuad', 'easeInOutCubic', 'easeInOutSine', ]; +// Cubic-bezier values for standard easings from easings.net (ai/easings.net). +// Hybrid easings (easeInExpoOutCubic, easeInQuartOutQuad) are approximations +// since asymmetric compositions can't be exactly represented by a single cubic bezier. +const EASING_BEZIER_MAP: Record = { + ...PRESET_BEZIERS, + linear: [0, 0, 1, 1], + easeInSine: [0.12, 0, 0.39, 0], + easeOutSine: [0.61, 1, 0.88, 1], + easeInQuad: [0.11, 0, 0.5, 0], + easeOutQuad: [0.5, 1, 0.89, 1], + easeInOutQuad: [0.45, 0, 0.55, 1], + easeInCubic: [0.32, 0, 0.67, 0], + easeOutCubic: [0.33, 1, 0.68, 1], + easeInQuart: [0.5, 0, 0.75, 0], + easeOutQuart: [0.25, 1, 0.5, 1], + easeInOutQuart: [0.76, 0, 0.24, 1], + easeInQuint: [0.64, 0, 0.78, 0], + easeOutQuint: [0.22, 1, 0.36, 1], + easeInOutQuint: [0.83, 0, 0.17, 1], + easeInExpo: [0.7, 0, 0.84, 0], + easeOutExpo: [0.16, 1, 0.3, 1], + easeInCirc: [0.55, 0, 1, 0.45], + easeOutCirc: [0, 0.55, 0.45, 1], + easeInOutCirc: [0.85, 0, 0.15, 1], +}; + export function getPresetBezier(preset?: string | null): [number, number, number, number] { const handles = preset ? PRESET_BEZIERS[preset as EasingPresetName] : null; const source = handles ?? DEFAULT_CUSTOM_BEZIER; return [...source] as [number, number, number, number]; } + +export function getEasingBezier(name?: string | null): [number, number, number, number] { + const handles = name ? EASING_BEZIER_MAP[name] : null; + const source = handles ?? DEFAULT_CUSTOM_BEZIER; + return [...source] as [number, number, number, number]; +}