Skip to content
Open
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
13 changes: 13 additions & 0 deletions src/components/video-editor/SettingsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,8 @@ interface SettingsPanelProps {
onShowCursorChange?: (enabled: boolean) => void;
loopCursor?: boolean;
onLoopCursorChange?: (enabled: boolean) => void;
alwaysUsePointerCursor?: boolean;
onAlwaysUsePointerCursorChange?: (enabled: boolean) => void;
cursorStyle?: CursorStyle;
onCursorStyleChange?: (style: CursorStyle) => void;
cursorSize?: number;
Expand Down Expand Up @@ -923,6 +925,8 @@ export function SettingsPanel({
onShowCursorChange,
loopCursor = false,
onLoopCursorChange,
alwaysUsePointerCursor = false,
onAlwaysUsePointerCursorChange,
cursorStyle = DEFAULT_CURSOR_STYLE,
onCursorStyleChange,
cursorSize = 5,
Expand Down Expand Up @@ -1435,6 +1439,7 @@ export function SettingsPanel({
const resetCursorSection = () => {
onShowCursorChange?.(initialEditorPreferences.showCursor);
onLoopCursorChange?.(initialEditorPreferences.loopCursor);
onAlwaysUsePointerCursorChange?.(initialEditorPreferences.alwaysUsePointerCursor);
onCursorStyleChange?.(initialEditorPreferences.cursorStyle);
onCursorSizeChange?.(initialEditorPreferences.cursorSize);
onCursorSmoothingChange?.(initialEditorPreferences.cursorSmoothing);
Expand Down Expand Up @@ -2837,6 +2842,14 @@ export function SettingsPanel({
onCheckedChange={onLoopCursorChange}
/>
</label>
<label className="flex items-center justify-between gap-3 text-xs text-muted-foreground">
<span>{tSettings("effects.alwaysUsePointerCursor")}</span>
<Switch
aria-label={tSettings("effects.alwaysUsePointerCursor")}
checked={alwaysUsePointerCursor}
onCheckedChange={onAlwaysUsePointerCursorChange}
/>
</label>
</div>
)}
</div>
Expand Down
10 changes: 10 additions & 0 deletions src/components/video-editor/VideoPlayback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ interface VideoPlaybackProps {
onAnnotationSizeChange?: (id: string, size: { width: number; height: number }) => void;
cursorTelemetry?: CursorTelemetryPoint[];
showCursor?: boolean;
alwaysUsePointerCursor?: boolean;
cursorStyle?: CursorStyle;
cursorSize?: number;
cursorSmoothing?: number;
Expand Down Expand Up @@ -347,6 +348,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
onAnnotationSizeChange,
cursorTelemetry = [],
showCursor = false,
alwaysUsePointerCursor = false,
cursorStyle = DEFAULT_CURSOR_STYLE,
cursorSize = DEFAULT_CURSOR_SIZE,
cursorSmoothing = DEFAULT_CURSOR_SMOOTHING,
Expand Down Expand Up @@ -492,6 +494,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
const cursorOverlayRef = useRef<PixiCursorOverlay | null>(null);
const cursorTelemetryRef = useRef<CursorTelemetryPoint[]>([]);
const showCursorRef = useRef(showCursor);
const alwaysUsePointerCursorRef = useRef(alwaysUsePointerCursor);
const cursorSizeRef = useRef(cursorSize);
const cursorStyleRef = useRef(cursorStyle);
const cursorSmoothingRef = useRef(cursorSmoothing);
Expand Down Expand Up @@ -1427,6 +1430,12 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
requestPausedFrameRefresh();
}, [cursorStyle, requestPausedFrameRefresh]);

useEffect(() => {
alwaysUsePointerCursorRef.current = alwaysUsePointerCursor;
cursorOverlayRef.current?.setAlwaysUsePointerCursor(alwaysUsePointerCursor);
requestPausedFrameRefresh();
}, [alwaysUsePointerCursor, requestPausedFrameRefresh]);

useEffect(() => {
cursorSizeRef.current = cursorSize;
requestPausedFrameRefresh();
Expand Down Expand Up @@ -1794,6 +1803,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
dotRadius: DEFAULT_CURSOR_CONFIG.dotRadius * cursorSizeRef.current,
minViewportScale: 0,
style: cursorStyleRef.current,
alwaysUsePointerCursor: alwaysUsePointerCursorRef.current,
smoothingFactor: cursorSmoothingRef.current,
springTuning: {
stiffnessMultiplier: cursorSpringStiffnessMultiplierRef.current,
Expand Down
5 changes: 5 additions & 0 deletions src/components/video-editor/editorPreferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type PersistedEditorControls = Pick<
| "connectedZoomEasing"
| "showCursor"
| "loopCursor"
| "alwaysUsePointerCursor"
| "cursorStyle"
| "cursorSize"
| "cursorSmoothing"
Expand Down Expand Up @@ -103,6 +104,7 @@ export const DEFAULT_EDITOR_PREFERENCES: EditorPreferences = {
connectedZoomEasing: DEFAULT_EDITOR_CONTROLS.connectedZoomEasing,
showCursor: DEFAULT_EDITOR_CONTROLS.showCursor,
loopCursor: DEFAULT_EDITOR_CONTROLS.loopCursor,
alwaysUsePointerCursor: DEFAULT_EDITOR_CONTROLS.alwaysUsePointerCursor,
cursorStyle: DEFAULT_EDITOR_CONTROLS.cursorStyle,
cursorSize: DEFAULT_EDITOR_CONTROLS.cursorSize,
cursorSmoothing: DEFAULT_EDITOR_CONTROLS.cursorSmoothing,
Expand Down Expand Up @@ -287,6 +289,8 @@ function normalizeEditorControls(
connectedZoomEasing: sanitizedRaw.connectedZoomEasing ?? fallback.connectedZoomEasing,
showCursor: sanitizedRaw.showCursor ?? fallback.showCursor,
loopCursor: sanitizedRaw.loopCursor ?? fallback.loopCursor,
alwaysUsePointerCursor:
sanitizedRaw.alwaysUsePointerCursor ?? fallback.alwaysUsePointerCursor,
cursorStyle: sanitizedRaw.cursorStyle ?? fallback.cursorStyle,
cursorSize: sanitizedRaw.cursorSize ?? fallback.cursorSize,
cursorSmoothing: sanitizedRaw.cursorSmoothing ?? fallback.cursorSmoothing,
Expand Down Expand Up @@ -343,6 +347,7 @@ function normalizeEditorControls(
connectedZoomEasing: normalized.connectedZoomEasing,
showCursor: normalized.showCursor,
loopCursor: normalized.loopCursor,
alwaysUsePointerCursor: normalized.alwaysUsePointerCursor,
cursorStyle: normalized.cursorStyle,
cursorSize: normalized.cursorSize,
cursorSmoothing: normalized.cursorSmoothing,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export function buildExportRenderOptions({
zoomRegions: effectiveZoomRegions,
cursorTelemetry: effectiveCursorTelemetry,
showCursor: effectiveShowCursor,
alwaysUsePointerCursor: appearance.alwaysUsePointerCursor,
cursorStyle: appearance.cursorStyle,
cursorSize: appearance.cursorSize,
cursorSmoothing: appearance.cursorSmoothing,
Expand Down
1 change: 1 addition & 0 deletions src/components/video-editor/layout/EditorVideoPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export function EditorVideoPreview({
selectedAnnotationId={timeline.selectedAnnotationId}
cursorTelemetry={effectiveCursorTelemetry}
showCursor={effectiveShowCursor}
alwaysUsePointerCursor={appearance.alwaysUsePointerCursor}
cursorStyle={appearance.cursorStyle}
cursorSize={appearance.cursorSize}
cursorSmoothing={appearance.cursorSmoothing}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ export function useEditorSettingsPanelProps(input: Input): ComponentProps<typeof
onShowCursorChange: handleShowCursorChange,
loopCursor: appearance.loopCursor,
onLoopCursorChange: appearance.setLoopCursor,
alwaysUsePointerCursor: appearance.alwaysUsePointerCursor,
onAlwaysUsePointerCursorChange: appearance.setAlwaysUsePointerCursor,
cursorStyle: appearance.cursorStyle,
onCursorStyleChange: appearance.setCursorStyle,
cursorSize: appearance.cursorSize,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export function useEditorPreferencesPersistence({
connectedZoomEasing: appearance.connectedZoomEasing,
showCursor: appearance.showCursor,
loopCursor: appearance.loopCursor,
alwaysUsePointerCursor: appearance.alwaysUsePointerCursor,
cursorStyle: appearance.cursorStyle,
cursorSize: appearance.cursorSize,
cursorSmoothing: appearance.cursorSmoothing,
Expand Down Expand Up @@ -78,6 +79,7 @@ export function useEditorPreferencesPersistence({
appearance.connectedZoomEasing,
appearance.showCursor,
appearance.loopCursor,
appearance.alwaysUsePointerCursor,
appearance.cursorStyle,
appearance.cursorSize,
appearance.cursorSmoothing,
Expand Down
2 changes: 2 additions & 0 deletions src/components/video-editor/presets/useVideoEditorPresets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export function useVideoEditorPresets({
connectedZoomEasing: appearance.connectedZoomEasing,
showCursor: appearance.showCursor,
loopCursor: appearance.loopCursor,
alwaysUsePointerCursor: appearance.alwaysUsePointerCursor,
cursorStyle: appearance.cursorStyle,
cursorSize: appearance.cursorSize,
cursorSmoothing: appearance.cursorSmoothing,
Expand Down Expand Up @@ -91,6 +92,7 @@ export function useVideoEditorPresets({
appearance.setConnectedZoomEasing(snapshot.connectedZoomEasing);
appearance.setShowCursor(snapshot.showCursor);
appearance.setLoopCursor(snapshot.loopCursor);
appearance.setAlwaysUsePointerCursor(snapshot.alwaysUsePointerCursor);
appearance.setCursorStyle(snapshot.cursorStyle);
appearance.setCursorSize(snapshot.cursorSize);
appearance.setCursorSmoothing(snapshot.cursorSmoothing);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function useProjectLibraryController({
}: Input) {
const { setProjectLibraryEntries, setProjectLibraryLoading } = project;
const {
alwaysUsePointerCursor,
backgroundBlur,
borderRadius,
connectZooms,
Expand Down Expand Up @@ -226,6 +227,7 @@ export function useProjectLibraryController({
previewHeight,
cursorTelemetry,
showCursor: effectiveShowCursor,
alwaysUsePointerCursor,
cursorStyle,
cursorSize,
cursorSmoothing,
Expand Down Expand Up @@ -274,6 +276,7 @@ export function useProjectLibraryController({
annotationRegions,
autoCaptionSettings,
autoCaptions,
alwaysUsePointerCursor,
backgroundBlur,
borderRadius,
connectZooms,
Expand Down
1 change: 1 addition & 0 deletions src/components/video-editor/project/useProjectLifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export function useProjectLifecycle(input: Input) {
appearance.setConnectedZoomEasing(editor.connectedZoomEasing);
appearance.setShowCursor(editor.showCursor);
appearance.setLoopCursor(editor.loopCursor);
appearance.setAlwaysUsePointerCursor(editor.alwaysUsePointerCursor);
appearance.setCursorStyle(editor.cursorStyle);
appearance.setCursorSize(editor.cursorSize);
appearance.setCursorSmoothing(editor.cursorSmoothing);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export function useProjectSnapshotModel({
connectedZoomEasing: appearance.connectedZoomEasing,
showCursor: appearance.showCursor,
loopCursor: appearance.loopCursor,
alwaysUsePointerCursor: appearance.alwaysUsePointerCursor,
cursorStyle: appearance.cursorStyle,
cursorSize: appearance.cursorSize,
cursorSmoothing: appearance.cursorSmoothing,
Expand Down Expand Up @@ -137,6 +138,7 @@ export function useProjectSnapshotModel({
appearance.connectedZoomEasing,
appearance.showCursor,
appearance.loopCursor,
appearance.alwaysUsePointerCursor,
appearance.cursorStyle,
appearance.cursorSize,
appearance.cursorSmoothing,
Expand Down
5 changes: 5 additions & 0 deletions src/components/video-editor/projectPersistence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export interface ProjectEditorState {
connectedZoomEasing: ZoomTransitionEasing;
showCursor: boolean;
loopCursor: boolean;
alwaysUsePointerCursor: boolean;
cursorStyle: CursorStyle;
cursorClickEffect: CursorClickEffectStyle;
cursorClickEffectColor: string;
Expand Down Expand Up @@ -853,6 +854,10 @@ export function normalizeProjectEditor(editor: Partial<ProjectEditorState>): Pro
),
showCursor: typeof editor.showCursor === "boolean" ? editor.showCursor : true,
loopCursor: typeof editor.loopCursor === "boolean" ? editor.loopCursor : false,
alwaysUsePointerCursor:
typeof editor.alwaysUsePointerCursor === "boolean"
? editor.alwaysUsePointerCursor
: false,
cursorStyle: normalizedCursorStyle,
cursorClickEffect: normalizeCursorClickEffectStyle(
(editor as Partial<ProjectEditorState>).cursorClickEffect,
Expand Down
5 changes: 5 additions & 0 deletions src/components/video-editor/state/useAppearanceState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ export function useAppearanceState(preferences: EditorPreferences) {
);
const [showCursor, setShowCursor] = useState(preferences.showCursor);
const [loopCursor, setLoopCursor] = useState(preferences.loopCursor);
const [alwaysUsePointerCursor, setAlwaysUsePointerCursor] = useState(
preferences.alwaysUsePointerCursor,
);
const [cursorStyle, setCursorStyle] = useState<CursorStyle>(
preferences.cursorStyle ?? DEFAULT_CURSOR_STYLE,
);
Expand Down Expand Up @@ -150,6 +153,8 @@ export function useAppearanceState(preferences: EditorPreferences) {
setShowCursor,
loopCursor,
setLoopCursor,
alwaysUsePointerCursor,
setAlwaysUsePointerCursor,
cursorStyle,
setCursorStyle,
cursorSize,
Expand Down
36 changes: 28 additions & 8 deletions src/components/video-editor/videoPlayback/cursorRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ export interface CursorRenderConfig {
sway: number;
/** Cursor visual style. */
style: CursorStyle;
/** Render every sample as the default arrow cursor. */
alwaysUsePointerCursor: boolean;
}

const MIN_CURSOR_VIEWPORT_SCALE = 0;
Expand Down Expand Up @@ -154,6 +156,7 @@ export const DEFAULT_CURSOR_CONFIG: CursorRenderConfig = {
clickEffectDurationMs: DEFAULT_CURSOR_CLICK_EFFECT_DURATION_MS,
sway: 0,
style: DEFAULT_CURSOR_STYLE,
alwaysUsePointerCursor: false,
};
let cursorAssetsPromise: Promise<void> | null = null;
let cursorPackAssetsPromise: Promise<void> | null = null;
Expand Down Expand Up @@ -1236,6 +1239,10 @@ export class PixiCursorOverlay {
this.config.sway = clamp(sway, 0, 2);
}

setAlwaysUsePointerCursor(enabled: boolean) {
this.config.alwaysUsePointerCursor = enabled;
}

setStyle(style: CursorStyle) {
this.config.style = style;
if (isStatefulCursorStyle(style)) {
Expand Down Expand Up @@ -1321,13 +1328,20 @@ export class PixiCursorOverlay {
const h =
this.config.dotRadius *
getCursorViewportScale(viewport.width, this.config.minViewportScale);
const { cursorType, clickSample, clickBounceProgress, clickProgress } =
getCursorVisualState(
samples,
timeMs,
this.config.clickBounceDuration,
this.config.clickEffectDurationMs,
);
const {
cursorType: rawCursorType,
clickSample,
clickBounceProgress,
clickProgress,
} = getCursorVisualState(
samples,
timeMs,
this.config.clickBounceDuration,
this.config.clickEffectDurationMs,
);
const cursorType: CursorAssetKey = this.config.alwaysUsePointerCursor
? "arrow"
: rawCursorType;
const projectedClickSample = clickSample
? projectCursorPositionToViewport(clickSample, viewport.sourceCrop)
: null;
Expand Down Expand Up @@ -1630,12 +1644,18 @@ export function drawCursorOnCanvas(
const px = viewport.x + smoothedState.x * viewport.width;
const py = viewport.y + smoothedState.y * viewport.height;
const h = config.dotRadius * getCursorViewportScale(viewport.width, config.minViewportScale);
const { cursorType, clickSample, clickBounceProgress, clickProgress } = getCursorVisualState(
const {
cursorType: rawCursorType,
clickSample,
clickBounceProgress,
clickProgress,
} = getCursorVisualState(
samples,
timeMs,
config.clickBounceDuration,
config.clickEffectDurationMs,
);
const cursorType: CursorAssetKey = config.alwaysUsePointerCursor ? "arrow" : rawCursorType;
const projectedClickSample = clickSample
? projectCursorPositionToViewport(clickSample, viewport.sourceCrop)
: null;
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/de/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"show": "Anzeigen",
"showCursor": "Cursor anzeigen",
"loopCursor": "Cursor wiederholen",
"alwaysUsePointerCursor": "Immer Standardcursor verwenden",
"cursorStyle": "Cursorstil",
"cursorStyleOptions": {
"macos": "macOS",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/en/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"show": "Show",
"showCursor": "Show Cursor",
"loopCursor": "Loop cursor",
"alwaysUsePointerCursor": "Always use default cursor",
"cursorStyle": "Cursor Style",
"cursorStyleOptions": {
"macos": "macOS",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/es/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"show": "Mostrar",
"showCursor": "Mostrar cursor",
"loopCursor": "Cursor en bucle",
"alwaysUsePointerCursor": "Usar siempre el cursor predeterminado",
"cursorStyle": "Estilo del cursor",
"cursorStyleOptions": {
"macos": "macOS",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/fr/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"show": "Afficher",
"showCursor": "Afficher le curseur",
"loopCursor": "Boucler le curseur",
"alwaysUsePointerCursor": "Toujours utiliser le curseur par défaut",
"cursorStyle": "Style du curseur",
"cursorStyleOptions": {
"macos": "macOS",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/it/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"show": "Mostra",
"showCursor": "Mostra cursore",
"loopCursor": "Cursore in loop",
"alwaysUsePointerCursor": "Usa sempre il cursore predefinito",
"cursorStyle": "Stile cursore",
"cursorStyleOptions": {
"macos": "macOS",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/ko/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"show": "표시",
"showCursor": "커서 표시",
"loopCursor": "커서 반복",
"alwaysUsePointerCursor": "항상 기본 커서 사용",
"cursorStyle": "커서 스타일",
"cursorStyleOptions": {
"macos": "macOS",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/nl/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"show": "Tonen",
"showCursor": "Cursor tonen",
"loopCursor": "Cursor herhalen",
"alwaysUsePointerCursor": "Altijd standaardcursor gebruiken",
"cursorStyle": "Cursorstijl",
"cursorStyleOptions": {
"macos": "macOS",
Expand Down
Loading