diff --git a/src/components/video-editor/SettingsPanel.tsx b/src/components/video-editor/SettingsPanel.tsx index 70c38c4..92ddec4 100644 --- a/src/components/video-editor/SettingsPanel.tsx +++ b/src/components/video-editor/SettingsPanel.tsx @@ -92,8 +92,8 @@ interface SettingsPanelProps { onShadowCommit?: () => void; showBlur?: boolean; onBlurChange?: (showBlur: boolean) => void; - motionBlurEnabled?: boolean; - onMotionBlurChange?: (enabled: boolean) => void; + motionBlurAmount?: number; + onMotionBlurChange?: (amount: number) => void; borderRadius?: number; onBorderRadiusChange?: (radius: number) => void; onBorderRadiusCommit?: () => void; @@ -157,7 +157,7 @@ export function SettingsPanel({ onShadowCommit, showBlur, onBlurChange, - motionBlurEnabled = false, + motionBlurAmount = 0, onMotionBlurChange, borderRadius = 0, onBorderRadiusChange, @@ -574,14 +574,6 @@ export function SettingsPanel({
-
-
Motion Blur
- -
Blur BG
+
+
+
Motion Blur
+ + {motionBlurAmount === 0 ? "off" : motionBlurAmount.toFixed(2)} + +
+ onMotionBlurChange?.(values[0])} + onValueCommit={(values) => onMotionBlurChange?.(values[0])} + min={0} + max={1} + step={0.01} + className="w-full [&_[role=slider]]:bg-[#34B27B] [&_[role=slider]]:border-[#34B27B] [&_[role=slider]]:h-3 [&_[role=slider]]:w-3" + /> +
Shadow
diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx index 46e4998..cae81a4 100644 --- a/src/components/video-editor/VideoEditor.tsx +++ b/src/components/video-editor/VideoEditor.tsx @@ -70,7 +70,7 @@ export default function VideoEditor() { wallpaper, shadowIntensity, showBlur, - motionBlurEnabled, + motionBlurAmount, borderRadius, padding, aspectRatio, @@ -139,7 +139,7 @@ export default function VideoEditor() { wallpaper: normalizedEditor.wallpaper, shadowIntensity: normalizedEditor.shadowIntensity, showBlur: normalizedEditor.showBlur, - motionBlurEnabled: normalizedEditor.motionBlurEnabled, + motionBlurAmount: normalizedEditor.motionBlurAmount, borderRadius: normalizedEditor.borderRadius, padding: normalizedEditor.padding, cropRegion: normalizedEditor.cropRegion, @@ -198,7 +198,7 @@ export default function VideoEditor() { wallpaper, shadowIntensity, showBlur, - motionBlurEnabled, + motionBlurAmount, borderRadius, padding, cropRegion, @@ -220,7 +220,7 @@ export default function VideoEditor() { wallpaper, shadowIntensity, showBlur, - motionBlurEnabled, + motionBlurAmount, borderRadius, padding, cropRegion, @@ -294,7 +294,7 @@ export default function VideoEditor() { wallpaper, shadowIntensity, showBlur, - motionBlurEnabled, + motionBlurAmount, borderRadius, padding, cropRegion, @@ -347,7 +347,7 @@ export default function VideoEditor() { wallpaper, shadowIntensity, showBlur, - motionBlurEnabled, + motionBlurAmount, borderRadius, padding, cropRegion, @@ -933,7 +933,7 @@ export default function VideoEditor() { showShadow: shadowIntensity > 0, shadowIntensity, showBlur, - motionBlurEnabled, + motionBlurAmount, borderRadius, padding, videoPadding: padding, @@ -1060,7 +1060,7 @@ export default function VideoEditor() { showShadow: shadowIntensity > 0, shadowIntensity, showBlur, - motionBlurEnabled, + motionBlurAmount, borderRadius, padding, cropRegion, @@ -1121,7 +1121,7 @@ export default function VideoEditor() { speedRegions, shadowIntensity, showBlur, - motionBlurEnabled, + motionBlurAmount, borderRadius, padding, cropRegion, @@ -1270,7 +1270,7 @@ export default function VideoEditor() { showShadow={shadowIntensity > 0} shadowIntensity={shadowIntensity} showBlur={showBlur} - motionBlurEnabled={motionBlurEnabled} + motionBlurAmount={motionBlurAmount} borderRadius={borderRadius} padding={padding} cropRegion={cropRegion} @@ -1369,8 +1369,8 @@ export default function VideoEditor() { onShadowCommit={commitState} showBlur={showBlur} onBlurChange={(v) => pushState({ showBlur: v })} - motionBlurEnabled={motionBlurEnabled} - onMotionBlurChange={(v) => pushState({ motionBlurEnabled: v })} + motionBlurAmount={motionBlurAmount} + onMotionBlurChange={(v) => pushState({ motionBlurAmount: v })} borderRadius={borderRadius} onBorderRadiusChange={(v) => updateState({ borderRadius: v })} onBorderRadiusCommit={commitState} diff --git a/src/components/video-editor/VideoPlayback.tsx b/src/components/video-editor/VideoPlayback.tsx index 7998e6d..877173d 100644 --- a/src/components/video-editor/VideoPlayback.tsx +++ b/src/components/video-editor/VideoPlayback.tsx @@ -70,7 +70,7 @@ interface VideoPlaybackProps { showShadow?: boolean; shadowIntensity?: number; showBlur?: boolean; - motionBlurEnabled?: boolean; + motionBlurAmount?: number; borderRadius?: number; padding?: number; cropRegion?: import("./types").CropRegion; @@ -113,7 +113,7 @@ const VideoPlayback = forwardRef( showShadow, shadowIntensity = 0, showBlur, - motionBlurEnabled = false, + motionBlurAmount = 0, borderRadius = 0, padding = 50, cropRegion, @@ -128,7 +128,6 @@ const VideoPlayback = forwardRef( }, ref, ) => { - const ZOOM_MOTION_BLUR_AMOUNT = 0.35; const videoRef = useRef(null); const containerRef = useRef(null); const appRef = useRef(null); @@ -169,7 +168,7 @@ const VideoPlayback = forwardRef( const layoutVideoContentRef = useRef<(() => void) | null>(null); const trimRegionsRef = useRef([]); const speedRegionsRef = useRef([]); - const motionBlurEnabledRef = useRef(motionBlurEnabled); + const motionBlurAmountRef = useRef(motionBlurAmount); const motionBlurStateRef = useRef(createMotionBlurState()); const onTimeUpdateRef = useRef(onTimeUpdate); const onPlayStateChangeRef = useRef(onPlayStateChange); @@ -400,8 +399,8 @@ const VideoPlayback = forwardRef( }, [speedRegions]); useEffect(() => { - motionBlurEnabledRef.current = motionBlurEnabled; - }, [motionBlurEnabled]); + motionBlurAmountRef.current = motionBlurAmount; + }, [motionBlurAmount]); useEffect(() => { onTimeUpdateRef.current = onTimeUpdate; @@ -475,7 +474,7 @@ const VideoPlayback = forwardRef( focusY: DEFAULT_FOCUS.cy, motionIntensity: 0, isPlaying: false, - motionBlurAmount: motionBlurEnabledRef.current ? ZOOM_MOTION_BLUR_AMOUNT : 0, + motionBlurAmount: motionBlurAmountRef.current, }); requestAnimationFrame(() => { @@ -739,7 +738,7 @@ const VideoPlayback = forwardRef( motionIntensity, motionVector, isPlaying: isPlayingRef.current, - motionBlurAmount: motionBlurEnabledRef.current ? ZOOM_MOTION_BLUR_AMOUNT : 0, + motionBlurAmount: motionBlurAmountRef.current, transformOverride: transform, motionBlurState: motionBlurStateRef.current, frameTimeMs: performance.now(), diff --git a/src/components/video-editor/projectPersistence.ts b/src/components/video-editor/projectPersistence.ts index a73a1a8..feecabe 100644 --- a/src/components/video-editor/projectPersistence.ts +++ b/src/components/video-editor/projectPersistence.ts @@ -28,7 +28,7 @@ export interface ProjectEditorState { wallpaper: string; shadowIntensity: number; showBlur: boolean; - motionBlurEnabled: boolean; + motionBlurAmount: number; borderRadius: number; padding: number; cropRegion: CropRegion; @@ -302,8 +302,13 @@ export function normalizeProjectEditor(editor: Partial): Pro wallpaper: typeof editor.wallpaper === "string" ? editor.wallpaper : WALLPAPER_PATHS[0], shadowIntensity: typeof editor.shadowIntensity === "number" ? editor.shadowIntensity : 0, showBlur: typeof editor.showBlur === "boolean" ? editor.showBlur : false, - motionBlurEnabled: - typeof editor.motionBlurEnabled === "boolean" ? editor.motionBlurEnabled : false, + motionBlurAmount: isFiniteNumber(editor.motionBlurAmount) + ? clamp(editor.motionBlurAmount, 0, 1) + : typeof (editor as { motionBlurEnabled?: unknown }).motionBlurEnabled === "boolean" + ? (editor as { motionBlurEnabled?: boolean }).motionBlurEnabled + ? 0.35 + : 0 + : 0, borderRadius: typeof editor.borderRadius === "number" ? editor.borderRadius : 0, padding: isFiniteNumber(editor.padding) ? clamp(editor.padding, 0, 100) : 50, cropRegion: { diff --git a/src/hooks/useEditorHistory.ts b/src/hooks/useEditorHistory.ts index 38a1d4a..5b43a13 100644 --- a/src/hooks/useEditorHistory.ts +++ b/src/hooks/useEditorHistory.ts @@ -20,7 +20,7 @@ export interface EditorState { wallpaper: string; shadowIntensity: number; showBlur: boolean; - motionBlurEnabled: boolean; + motionBlurAmount: number; borderRadius: number; padding: number; aspectRatio: AspectRatio; @@ -35,7 +35,7 @@ export const INITIAL_EDITOR_STATE: EditorState = { wallpaper: "/wallpapers/wallpaper1.jpg", shadowIntensity: 0, showBlur: false, - motionBlurEnabled: false, + motionBlurAmount: 0, borderRadius: 0, padding: 50, aspectRatio: "16:9", diff --git a/src/lib/exporter/frameRenderer.ts b/src/lib/exporter/frameRenderer.ts index a4003ef..4ac0404 100644 --- a/src/lib/exporter/frameRenderer.ts +++ b/src/lib/exporter/frameRenderer.ts @@ -40,7 +40,7 @@ interface FrameRenderConfig { showShadow: boolean; shadowIntensity: number; showBlur: boolean; - motionBlurEnabled?: boolean; + motionBlurAmount?: number; borderRadius?: number; padding?: number; cropRegion: CropRegion; @@ -351,7 +351,7 @@ export class FrameRenderer { focusY: this.animationState.focusY, motionIntensity: maxMotionIntensity, isPlaying: true, - motionBlurAmount: this.config.motionBlurEnabled ? 0.35 : 0, + motionBlurAmount: this.config.motionBlurAmount ?? 0, motionBlurState: this.motionBlurState, frameTimeMs: timeMs, }); diff --git a/src/lib/exporter/gifExporter.ts b/src/lib/exporter/gifExporter.ts index 36f5758..8cf2478 100644 --- a/src/lib/exporter/gifExporter.ts +++ b/src/lib/exporter/gifExporter.ts @@ -32,7 +32,7 @@ interface GifExporterConfig { showShadow: boolean; shadowIntensity: number; showBlur: boolean; - motionBlurEnabled?: boolean; + motionBlurAmount?: number; borderRadius?: number; padding?: number; videoPadding?: number; @@ -106,7 +106,7 @@ export class GifExporter { showShadow: this.config.showShadow, shadowIntensity: this.config.shadowIntensity, showBlur: this.config.showBlur, - motionBlurEnabled: this.config.motionBlurEnabled, + motionBlurAmount: this.config.motionBlurAmount, borderRadius: this.config.borderRadius, padding: this.config.padding, cropRegion: this.config.cropRegion, diff --git a/src/lib/exporter/videoExporter.ts b/src/lib/exporter/videoExporter.ts index ef01001..2560841 100644 --- a/src/lib/exporter/videoExporter.ts +++ b/src/lib/exporter/videoExporter.ts @@ -20,7 +20,7 @@ interface VideoExporterConfig extends ExportConfig { showShadow: boolean; shadowIntensity: number; showBlur: boolean; - motionBlurEnabled?: boolean; + motionBlurAmount?: number; borderRadius?: number; padding?: number; videoPadding?: number; @@ -70,7 +70,7 @@ export class VideoExporter { showShadow: this.config.showShadow, shadowIntensity: this.config.shadowIntensity, showBlur: this.config.showBlur, - motionBlurEnabled: this.config.motionBlurEnabled, + motionBlurAmount: this.config.motionBlurAmount, borderRadius: this.config.borderRadius, padding: this.config.padding, cropRegion: this.config.cropRegion,