Files
modeling-app/src/lib/cameraControls.ts
Frank Noirot c5cb0e2fd4 Add "Trackpad Friendly" camera control setting inspired by Blender (#431)
* Refactor: rename CADProgram to CameraSystem

* Fix buttonDownInStream always set to 0
This is problematic because the left mouse
button ID is actually 0. If no button is
pressed we should set back to undefined.

* Fix: middle mouse button ID is 1, not 3

* Add "Trackpad Friendly" camera system setting

Signed off by Frank Noirot <frank@kittycad.io>

* Allow camera configs to be lenient on first click
2023-09-11 16:21:23 -04:00

157 lines
4.2 KiB
TypeScript

const noModifiersPressed = (e: React.MouseEvent) =>
!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey
export type CameraSystem =
| 'KittyCAD'
| 'OnShape'
| 'Trackpad Friendly'
| 'Solidworks'
| 'NX'
| 'Creo'
| 'AutoCAD'
export const cameraSystems: CameraSystem[] = [
'KittyCAD',
'OnShape',
'Trackpad Friendly',
'Solidworks',
'NX',
'Creo',
'AutoCAD',
]
interface MouseGuardHandler {
description: string
callback: (e: React.MouseEvent) => boolean
lenientDragStartButton?: number
}
interface MouseGuardZoomHandler {
description: string
dragCallback: (e: React.MouseEvent) => boolean
scrollCallback: (e: React.MouseEvent) => boolean
lenientDragStartButton?: number
}
interface MouseGuard {
pan: MouseGuardHandler
zoom: MouseGuardZoomHandler
rotate: MouseGuardHandler
}
export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
KittyCAD: {
pan: {
description: 'Right click + Shift + drag or middle click + drag',
callback: (e) =>
(e.button === 1 && noModifiersPressed(e)) ||
(e.button === 2 && e.shiftKey),
},
zoom: {
description: 'Scroll wheel or Right click + Ctrl + drag',
dragCallback: (e) => e.button === 2 && e.ctrlKey,
scrollCallback: () => true,
},
rotate: {
description: 'Right click + drag',
callback: (e) => e.button === 2 && noModifiersPressed(e),
},
},
OnShape: {
pan: {
description: 'Right click + Ctrl + drag or middle click + drag',
callback: (e) =>
(e.button === 2 && e.ctrlKey) ||
(e.button === 1 && noModifiersPressed(e)),
},
zoom: {
description: 'Scroll wheel',
dragCallback: () => false,
scrollCallback: () => true,
},
rotate: {
description: 'Right click + drag',
callback: (e) => e.button === 2 && noModifiersPressed(e),
},
},
'Trackpad Friendly': {
pan: {
description: 'Left click + Alt + Shift + drag or middle click + drag',
callback: (e) =>
(e.button === 0 && e.altKey && e.shiftKey && !e.metaKey) ||
(e.button === 1 && noModifiersPressed(e)),
},
zoom: {
description: 'Scroll wheel or Left click + Alt + OS + drag',
dragCallback: (e) => e.button === 0 && e.altKey && e.metaKey,
scrollCallback: () => true,
},
rotate: {
description: 'Left click + Alt + drag',
callback: (e) => e.button === 0 && e.altKey && !e.shiftKey && !e.metaKey,
lenientDragStartButton: 0,
},
},
Solidworks: {
pan: {
description: 'Right click + Ctrl + drag',
callback: (e) => e.button === 2 && e.ctrlKey,
lenientDragStartButton: 2,
},
zoom: {
description: 'Scroll wheel or Middle click + Shift + drag',
dragCallback: (e) => e.button === 1 && e.shiftKey,
scrollCallback: () => true,
},
rotate: {
description: 'Middle click + drag',
callback: (e) => e.button === 1 && noModifiersPressed(e),
},
},
NX: {
pan: {
description: 'Middle click + Shift + drag',
callback: (e) => e.button === 1 && e.shiftKey,
},
zoom: {
description: 'Scroll wheel or Middle click + Ctrl + drag',
dragCallback: (e) => e.button === 1 && e.ctrlKey,
scrollCallback: () => true,
},
rotate: {
description: 'Middle click + drag',
callback: (e) => e.button === 1 && noModifiersPressed(e),
},
},
Creo: {
pan: {
description: 'Middle click + Shift + drag',
callback: (e) => e.button === 1 && e.shiftKey,
},
zoom: {
description: 'Scroll wheel or Middle click + Ctrl + drag',
dragCallback: (e) => e.button === 1 && e.ctrlKey,
scrollCallback: () => true,
},
rotate: {
description: 'Middle click + drag',
callback: (e) => e.button === 1 && noModifiersPressed(e),
},
},
AutoCAD: {
pan: {
description: 'Middle click + drag',
callback: (e) => e.button === 1 && noModifiersPressed(e),
},
zoom: {
description: 'Scroll wheel',
dragCallback: () => false,
scrollCallback: () => true,
},
rotate: {
description: 'Middle click + Shift + drag',
callback: (e) => e.button === 1 && e.shiftKey,
},
},
}