Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/compositor/src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use anyhow::{Context, Result};

// Paramètres de suivi auto — parité stricte avec
// `src/components/video-editor/videoPlayback/constants.ts` (AUTO_FOLLOW_PARAMS), partagés
// `src/lib/zoomMath/constants.ts` (AUTO_FOLLOW_PARAMS), partagés
// là-bas entre preview et export pour que la caméra suive le curseur à l'identique.
const AUTO_FOLLOW_MIN_FACTOR: f32 = 0.1;
const AUTO_FOLLOW_MAX_FACTOR: f32 = 0.25;
Expand Down
2 changes: 1 addition & 1 deletion src/components/ai-edition/PreviewCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import {
type WebcamMaskShape,
type ZoomFocus,
} from "@/components/video-editor/types";
import { computeCameraFullscreenProgress } from "@/components/video-editor/videoPlayback/cameraFullscreenUtils";
import { useScopedT } from "@/contexts/I18nContext";
import { resolveAspectRatioValue } from "@/lib/ai-edition/document/outputFormat";
import type {
Expand All @@ -52,6 +51,7 @@ import {
} from "@/lib/compositeLayout";
import { classifyWallpaper, resolveImageWallpaperUrl } from "@/lib/wallpaper";
import { getCssClipPath } from "@/lib/webcamMaskShapes";
import { computeCameraFullscreenProgress } from "@/lib/zoomMath/cameraFullscreenUtils";
import { clamp, clamp01 } from "@/utils/math";
import { AnnotationLayer } from "./AnnotationLayer";
import { NativeCompositorOverlay } from "./NativeCompositorOverlay";
Expand Down
2 changes: 1 addition & 1 deletion src/components/ai-edition/ZoomFocusOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import type { PointerEvent as ReactPointerEvent } from "react";
import { useCallback, useRef } from "react";
import { getZoomScale, type ZoomFocus } from "@/components/video-editor/types";
import { getFocusBoundsForScale } from "@/components/video-editor/videoPlayback/focusUtils";
import type { AxcutZoomRegion } from "@/lib/ai-edition/schema";
import { getFocusBoundsForScale } from "@/lib/zoomMath/focusUtils";
import { clamp01 } from "@/utils/math";
import styles from "./ZoomFocusOverlay.module.css";

Expand Down
4 changes: 2 additions & 2 deletions src/lib/ai-edition/timeline/zoom-preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import type {
ZoomRegion as LegacyZoomRegion,
} from "@/components/video-editor/types";
import { getZoomScale } from "@/components/video-editor/types";
import { findDominantRegion } from "@/components/video-editor/videoPlayback/zoomRegionUtils";
import { computeZoomTransform } from "@/components/video-editor/videoPlayback/zoomTransform";
import type { AxcutZoomRegion } from "@/lib/ai-edition/schema";
import { findDominantRegion } from "@/lib/zoomMath/zoomRegionUtils";
import { computeZoomTransform } from "@/lib/zoomMath/zoomTransform";

export interface ZoomPreviewTransform {
scale: number;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/cursor/cursorPathSmoothing.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getCursorSpringConfig } from "@/components/video-editor/videoPlayback/motionSmoothing";
import { getCursorSpringConfig } from "@/lib/zoomMath/motionSmoothing";
import type { CursorRecordingData, CursorRecordingSample } from "@/native/contracts";
import { clamp } from "@/utils/math";

Expand Down
2 changes: 1 addition & 1 deletion src/lib/cursor/pixiCursorRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
getCursorSpringConfig,
resetSpringState,
stepSpringValue,
} from "@/components/video-editor/videoPlayback/motionSmoothing";
} from "@/lib/zoomMath/motionSmoothing";
import { clamp } from "@/utils/math";
import { UPLOADED_CURSOR_SAMPLE_SIZE, uploadedCursorAssets } from "./uploadedCursorAssets";

Expand Down
33 changes: 13 additions & 20 deletions src/lib/exporter/frameRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,6 @@ import {
isRotation3DIdentity,
lerpRotation3D,
} from "@/components/video-editor/types";
import { computeCameraFullscreenProgress } from "@/components/video-editor/videoPlayback/cameraFullscreenUtils";
import {
AUTO_FOLLOW_PARAMS,
DEFAULT_FOCUS,
} from "@/components/video-editor/videoPlayback/constants";
import { advanceFollowFocus } from "@/components/video-editor/videoPlayback/cursorFollowUtils";
import { clampFocusToScale } from "@/components/video-editor/videoPlayback/focusUtils";
import { findDominantRegion } from "@/components/video-editor/videoPlayback/zoomRegionUtils";
import {
createZoomSpringState,
resetZoomSpring,
stepZoomSpring,
} from "@/components/video-editor/videoPlayback/zoomSpring";
import {
applyZoomTransform,
computeFocusFromTransform,
computeZoomTransform,
createMotionBlurState,
type MotionBlurState,
} from "@/components/video-editor/videoPlayback/zoomTransform";
import {
computeCameraFullscreenRect,
computeCompositeLayout,
Expand All @@ -66,6 +46,19 @@ import {
} from "@/lib/cursor/nativeCursor";
import { BackgroundLoadError, classifyWallpaper, resolveImageWallpaperUrl } from "@/lib/wallpaper";
import { drawCanvasClipPath } from "@/lib/webcamMaskShapes";
import { computeCameraFullscreenProgress } from "@/lib/zoomMath/cameraFullscreenUtils";
import { AUTO_FOLLOW_PARAMS, DEFAULT_FOCUS } from "@/lib/zoomMath/constants";
import { advanceFollowFocus } from "@/lib/zoomMath/cursorFollowUtils";
import { clampFocusToScale } from "@/lib/zoomMath/focusUtils";
import { findDominantRegion } from "@/lib/zoomMath/zoomRegionUtils";
import { createZoomSpringState, resetZoomSpring, stepZoomSpring } from "@/lib/zoomMath/zoomSpring";
import {
applyZoomTransform,
computeFocusFromTransform,
computeZoomTransform,
createMotionBlurState,
type MotionBlurState,
} from "@/lib/zoomMath/zoomTransform";
import type { CursorRecordingData } from "@/native/contracts";
import { renderAnnotations } from "./annotationRenderer";
import {
Expand Down
30 changes: 12 additions & 18 deletions src/lib/exporter/wgsl/evaluate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,6 @@ import type {
ZoomRegion,
} from "@/components/video-editor/types";
import { DEFAULT_ROTATION_3D, getZoomScale, lerpRotation3D } from "@/components/video-editor/types";
import { computeCameraFullscreenProgress } from "@/components/video-editor/videoPlayback/cameraFullscreenUtils";
import {
AUTO_FOLLOW_PARAMS,
DEFAULT_FOCUS,
} from "@/components/video-editor/videoPlayback/constants";
import { advanceFollowFocus } from "@/components/video-editor/videoPlayback/cursorFollowUtils";
import { clampFocusToScale } from "@/components/video-editor/videoPlayback/focusUtils";
import { findDominantRegion } from "@/components/video-editor/videoPlayback/zoomRegionUtils";
import {
createZoomSpringState,
resetZoomSpring,
stepZoomSpring,
type ZoomSpringState,
} from "@/components/video-editor/videoPlayback/zoomSpring";
import {
computeFocusFromTransform,
computeZoomTransform,
} from "@/components/video-editor/videoPlayback/zoomTransform";
import {
computeCameraFullscreenRect,
computeCompositeLayout,
Expand All @@ -52,6 +34,18 @@ import {
type WebcamLayoutPreset,
type WebcamSizePreset,
} from "@/lib/compositeLayout";
import { computeCameraFullscreenProgress } from "@/lib/zoomMath/cameraFullscreenUtils";
import { AUTO_FOLLOW_PARAMS, DEFAULT_FOCUS } from "@/lib/zoomMath/constants";
import { advanceFollowFocus } from "@/lib/zoomMath/cursorFollowUtils";
import { clampFocusToScale } from "@/lib/zoomMath/focusUtils";
import { findDominantRegion } from "@/lib/zoomMath/zoomRegionUtils";
import {
createZoomSpringState,
resetZoomSpring,
stepZoomSpring,
type ZoomSpringState,
} from "@/lib/zoomMath/zoomSpring";
import { computeFocusFromTransform, computeZoomTransform } from "@/lib/zoomMath/zoomTransform";

/** Everything about the document that does not depend on `t`. */
export interface EvaluateScene {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import type { CameraFullscreenRegion } from "../types";
import type { CameraFullscreenRegion } from "@/components/video-editor/types";
import { computeCameraFullscreenProgress } from "./cameraFullscreenUtils";
import { TRANSITION_WINDOW_MS } from "./constants";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { CameraFullscreenRegion } from "../types";
import type { CameraFullscreenRegion } from "@/components/video-editor/types";
import { TRANSITION_WINDOW_MS } from "./constants";
import { easeOutScreenStudio } from "./mathUtils";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ZoomFocus } from "../types";
import type { ZoomFocus } from "@/components/video-editor/types";

export const DEFAULT_FOCUS: ZoomFocus = { cx: 0.5, cy: 0.5 };
export const TRANSITION_WINDOW_MS = 1015.05;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { CursorTelemetryPoint, ZoomFocus } from "../types";
import type { CursorTelemetryPoint, ZoomFocus } from "@/components/video-editor/types";

/** Binary-search the sorted telemetry and lerp the cursor position at the given playback time. */
export function interpolateCursorAt(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import {
clampFocusToDepth,
ZOOM_DEPTH_SCALES,
type ZoomDepth,
type ZoomFocus,
} from "@/components/video-editor/types";
import { clamp } from "@/utils/math";
import { clampFocusToDepth, ZOOM_DEPTH_SCALES, type ZoomDepth, type ZoomFocus } from "../types";

interface StageSize {
width: number;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import type {
CursorTelemetryPoint,
Rotation3D,
ZoomFocus,
ZoomRegion,
} from "@/components/video-editor/types";
import {
DEFAULT_ROTATION_3D,
getRotation3D,
getZoomScale,
lerpRotation3D,
} from "@/components/video-editor/types";
import { clamp01 } from "@/utils/math";
import type { CursorTelemetryPoint, Rotation3D, ZoomFocus, ZoomRegion } from "../types";
import { DEFAULT_ROTATION_3D, getRotation3D, getZoomScale, lerpRotation3D } from "../types";
import { TRANSITION_WINDOW_MS, ZOOM_IN_TRANSITION_WINDOW_MS } from "./constants";
import { interpolateCursorAt } from "./cursorFollowUtils";
import { clampFocusToScale } from "./focusUtils";
Expand Down
2 changes: 1 addition & 1 deletion src/native/sceneDescription.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import {
getZoomScale,
ZOOM_DEPTH_SCALES,
} from "@/components/video-editor/types";
import { getFocusBoundsForScale } from "@/components/video-editor/videoPlayback/focusUtils";
import type {
AxcutAsset,
AxcutClip,
AxcutDocument,
AxcutZoomRegion,
} from "@/lib/ai-edition/schema";
import { getFocusBoundsForScale } from "@/lib/zoomMath/focusUtils";
import { buildSceneDescription } from "./sceneDescription";

// --- Fixture helpers --------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion technical-documentation/architecture/cursor.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ The cursor settings pane is `CursorPane` in `src/components/ai-edition/RightPane

## Auto-follow

Cursor telemetry also drives camera focus for auto-follow zooms. `src/components/video-editor/videoPlayback/cursorFollowUtils.ts` interpolates the cursor at content time and applies distance-adaptive, frame-rate-independent smoothing. The zoom-region utilities use that focus for preview, while the export frame renderer uses the corresponding focus during export. The native compositor keeps a raw track for cursor placement and derives a separately smoothed follow track (`crates/compositor/src/cursor.rs:16-24,126-136`), preventing camera motion from changing the cursor's actual recorded position.
Cursor telemetry also drives camera focus for auto-follow zooms. `src/lib/zoomMath/cursorFollowUtils.ts` interpolates the cursor at content time and applies distance-adaptive, frame-rate-independent smoothing. The zoom-region utilities use that focus for preview, while the export frame renderer uses the corresponding focus during export. The native compositor keeps a raw track for cursor placement and derives a separately smoothed follow track (`crates/compositor/src/cursor.rs:16-24,126-136`), preventing camera motion from changing the cursor's actual recorded position.

## Bundled assets

Expand Down
Loading