Add Apple Trackpad camera controls
This commit is contained in:
@ -390,28 +390,7 @@ export class CameraControls {
|
||||
return
|
||||
}
|
||||
|
||||
// Implement camera movement logic here based on deltaMove
|
||||
// For example, for rotating the camera around the target:
|
||||
if (interaction === 'rotate') {
|
||||
this.pendingRotation = this.pendingRotation
|
||||
? this.pendingRotation
|
||||
: new Vector2()
|
||||
this.pendingRotation.x += deltaMove.x
|
||||
this.pendingRotation.y += deltaMove.y
|
||||
} else if (interaction === 'zoom') {
|
||||
this.pendingZoom = this.pendingZoom ? this.pendingZoom : 1
|
||||
this.pendingZoom *= 1 + deltaMove.y * 0.01
|
||||
} else if (interaction === 'pan') {
|
||||
this.pendingPan = this.pendingPan ? this.pendingPan : new Vector2()
|
||||
let distance = this.camera.position.distanceTo(this.target)
|
||||
if (this.camera instanceof OrthographicCamera) {
|
||||
const zoomFudgeFactor = 2280
|
||||
distance = zoomFudgeFactor / (this.camera.zoom * 45)
|
||||
}
|
||||
const panSpeed = (distance / 1000 / 45) * this.perspectiveFovBeforeOrtho
|
||||
this.pendingPan.x += -deltaMove.x * panSpeed
|
||||
this.pendingPan.y += deltaMove.y * panSpeed
|
||||
}
|
||||
this.moveCamera(interaction, deltaMove)
|
||||
} else {
|
||||
/**
|
||||
* If we're not in sketch mode and not dragging, we can highlight entities
|
||||
@ -433,6 +412,31 @@ export class CameraControls {
|
||||
}
|
||||
}
|
||||
|
||||
moveCamera(interaction: interactionType, deltaMove: Vector2) {
|
||||
// Implement camera movement logic here based on deltaMove
|
||||
// For example, for rotating the camera around the target:
|
||||
if (interaction === 'rotate') {
|
||||
this.pendingRotation = this.pendingRotation
|
||||
? this.pendingRotation
|
||||
: new Vector2()
|
||||
this.pendingRotation.x += deltaMove.x
|
||||
this.pendingRotation.y += deltaMove.y
|
||||
} else if (interaction === 'zoom') {
|
||||
this.pendingZoom = this.pendingZoom ? this.pendingZoom : 1
|
||||
this.pendingZoom *= 1 + deltaMove.y * 0.01
|
||||
} else if (interaction === 'pan') {
|
||||
this.pendingPan = this.pendingPan ? this.pendingPan : new Vector2()
|
||||
let distance = this.camera.position.distanceTo(this.target)
|
||||
if (this.camera instanceof OrthographicCamera) {
|
||||
const zoomFudgeFactor = 2280
|
||||
distance = zoomFudgeFactor / (this.camera.zoom * 45)
|
||||
}
|
||||
const panSpeed = (distance / 1000 / 45) * this.perspectiveFovBeforeOrtho
|
||||
this.pendingPan.x += -deltaMove.x * panSpeed
|
||||
this.pendingPan.y += deltaMove.y * panSpeed
|
||||
}
|
||||
}
|
||||
|
||||
onMouseUp = (event: PointerEvent) => {
|
||||
this.domElement.releasePointerCapture(event.pointerId)
|
||||
this.isDragging = false
|
||||
@ -457,14 +461,56 @@ export class CameraControls {
|
||||
if (interaction === 'none') return
|
||||
event.preventDefault()
|
||||
|
||||
const zoomDirection = this.interactionGuards.zoom.scrollReverseY ? -1 : 1
|
||||
if (this.syncDirection === 'engineToClient') {
|
||||
if (interaction === 'zoom') {
|
||||
this.zoomDataFromLastFrame = event.deltaY
|
||||
this.zoomDataFromLastFrame = event.deltaY * zoomDirection
|
||||
} else {
|
||||
// This case will get handled when we add pan and rotate using Apple trackpad.
|
||||
console.error(
|
||||
`Unexpected interaction type for engineToClient wheel event: ${interaction}`
|
||||
)
|
||||
this.isDragging = true
|
||||
this.handleStart()
|
||||
|
||||
this.engineCommandManager
|
||||
.sendSceneCommand({
|
||||
type: 'modeling_cmd_batch_req',
|
||||
batch_id: uuidv4(),
|
||||
requests: [
|
||||
{
|
||||
cmd: {
|
||||
type: 'camera_drag_start',
|
||||
interaction,
|
||||
window: { x: event.clientX, y: event.clientY },
|
||||
},
|
||||
cmd_id: uuidv4(),
|
||||
},
|
||||
{
|
||||
cmd: {
|
||||
type: 'camera_drag_move',
|
||||
interaction,
|
||||
window: {
|
||||
x: event.clientX - event.deltaX,
|
||||
y: event.clientY - event.deltaY,
|
||||
},
|
||||
},
|
||||
cmd_id: uuidv4(),
|
||||
},
|
||||
{
|
||||
cmd: {
|
||||
type: 'camera_drag_end',
|
||||
interaction,
|
||||
window: {
|
||||
x: event.clientX - event.deltaX,
|
||||
y: event.clientY - event.deltaY,
|
||||
},
|
||||
},
|
||||
cmd_id: uuidv4(),
|
||||
},
|
||||
],
|
||||
responses: false,
|
||||
})
|
||||
.catch(reportRejection)
|
||||
|
||||
this.isDragging = false
|
||||
this.handleEnd()
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -478,12 +524,19 @@ export class CameraControls {
|
||||
|
||||
this.handleStart()
|
||||
if (interaction === 'zoom') {
|
||||
this.pendingZoom = 1 + (event.deltaY / window.devicePixelRatio) * 0.001
|
||||
this.pendingZoom =
|
||||
1 + (event.deltaY / window.devicePixelRatio) * 0.001 * zoomDirection
|
||||
} else {
|
||||
// This case will get handled when we add pan and rotate using Apple trackpad.
|
||||
console.error(
|
||||
`Unexpected interaction type for wheel event: ${interaction}`
|
||||
this.isDragging = true
|
||||
this.mouseDownPosition.set(event.clientX, event.clientY)
|
||||
|
||||
this.moveCamera(interaction, new Vector2(-event.deltaX, -event.deltaY))
|
||||
|
||||
this.mouseDownPosition.set(
|
||||
event.clientX + event.deltaX,
|
||||
event.clientY + event.deltaY
|
||||
)
|
||||
this.isDragging = false
|
||||
}
|
||||
this.handleEnd()
|
||||
}
|
||||
@ -1266,6 +1319,9 @@ function _getInteractionType(
|
||||
enableZoom: boolean
|
||||
): interactionType | 'none' {
|
||||
if (event instanceof WheelEvent) {
|
||||
if (enablePan && interactionGuards.pan.scrollCallback(event)) return 'pan'
|
||||
if (enableRotate && interactionGuards.rotate.scrollCallback(event))
|
||||
return 'rotate'
|
||||
if (enableZoom && interactionGuards.zoom.scrollCallback(event))
|
||||
return 'zoom'
|
||||
} else {
|
||||
|
@ -13,6 +13,7 @@ export type CameraSystem =
|
||||
| 'KittyCAD'
|
||||
| 'OnShape'
|
||||
| 'Trackpad Friendly'
|
||||
| 'Apple Trackpad'
|
||||
| 'Solidworks'
|
||||
| 'NX'
|
||||
| 'Creo'
|
||||
@ -22,6 +23,7 @@ export const cameraSystems: CameraSystem[] = [
|
||||
'KittyCAD',
|
||||
'OnShape',
|
||||
'Trackpad Friendly',
|
||||
'Apple Trackpad',
|
||||
'Solidworks',
|
||||
'NX',
|
||||
'Creo',
|
||||
@ -38,6 +40,8 @@ export function mouseControlsToCameraSystem(
|
||||
return 'OnShape'
|
||||
case 'trackpad_friendly':
|
||||
return 'Trackpad Friendly'
|
||||
case 'apple_trackpad':
|
||||
return 'Apple Trackpad'
|
||||
case 'solidworks':
|
||||
return 'Solidworks'
|
||||
case 'nx':
|
||||
@ -54,6 +58,7 @@ export function mouseControlsToCameraSystem(
|
||||
interface MouseGuardHandler {
|
||||
description: string
|
||||
callback: (e: MouseEvent) => boolean
|
||||
scrollCallback: (e: WheelEvent) => boolean
|
||||
lenientDragStartButton?: number
|
||||
}
|
||||
|
||||
@ -61,6 +66,7 @@ interface MouseGuardZoomHandler {
|
||||
description: string
|
||||
dragCallback: (e: MouseEvent) => boolean
|
||||
scrollCallback: (e: WheelEvent) => boolean
|
||||
scrollReverseY?: boolean
|
||||
lenientDragStartButton?: number
|
||||
}
|
||||
|
||||
@ -83,6 +89,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
callback: (e) =>
|
||||
(btnName(e).middle && noModifiersPressed(e)) ||
|
||||
(btnName(e).right && e.shiftKey),
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
zoom: {
|
||||
description: 'Scroll or Ctrl + Right click drag',
|
||||
@ -92,6 +99,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
rotate: {
|
||||
description: 'Right click drag',
|
||||
callback: (e) => btnName(e).right && noModifiersPressed(e),
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
},
|
||||
OnShape: {
|
||||
@ -100,6 +108,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
callback: (e) =>
|
||||
(btnName(e).right && e.ctrlKey) ||
|
||||
(btnName(e).middle && noModifiersPressed(e)),
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
zoom: {
|
||||
description: 'Scroll',
|
||||
@ -109,6 +118,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
rotate: {
|
||||
description: 'Right click drag',
|
||||
callback: (e) => btnName(e).right && noModifiersPressed(e),
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
},
|
||||
'Trackpad Friendly': {
|
||||
@ -117,6 +127,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
callback: (e) =>
|
||||
(btnName(e).left && e.altKey && e.shiftKey && !e.metaKey) ||
|
||||
(btnName(e).middle && noModifiersPressed(e)),
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
zoom: {
|
||||
description: `Scroll or ${ALT} + ${META} + Left click drag`,
|
||||
@ -126,13 +137,44 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
rotate: {
|
||||
description: `${ALT} + Left click drag`,
|
||||
callback: (e) => btnName(e).left && e.altKey && !e.shiftKey && !e.metaKey,
|
||||
scrollCallback: () => false,
|
||||
lenientDragStartButton: 0,
|
||||
},
|
||||
},
|
||||
'Apple Trackpad': {
|
||||
pan: {
|
||||
description: `Scroll or one finger drag`,
|
||||
callback: (e) => btnName(e).left && noModifiersPressed(e),
|
||||
scrollCallback: (e) => e.deltaMode === 0 && noModifiersPressed(e),
|
||||
lenientDragStartButton: 0,
|
||||
},
|
||||
zoom: {
|
||||
description: `Shift + Scroll`,
|
||||
dragCallback: (e) => false,
|
||||
scrollCallback: (e) =>
|
||||
e.deltaMode === 0 &&
|
||||
e.shiftKey &&
|
||||
!e.ctrlKey &&
|
||||
!e.altKey &&
|
||||
!e.metaKey,
|
||||
scrollReverseY: true,
|
||||
},
|
||||
rotate: {
|
||||
description: `${ALT} + Scroll`,
|
||||
callback: (e) => false,
|
||||
scrollCallback: (e) =>
|
||||
e.deltaMode === 0 &&
|
||||
e.altKey &&
|
||||
!e.ctrlKey &&
|
||||
!e.shiftKey &&
|
||||
!e.metaKey,
|
||||
},
|
||||
},
|
||||
Solidworks: {
|
||||
pan: {
|
||||
description: 'Ctrl + Right click drag',
|
||||
callback: (e) => btnName(e).right && e.ctrlKey,
|
||||
scrollCallback: () => false,
|
||||
lenientDragStartButton: 2,
|
||||
},
|
||||
zoom: {
|
||||
@ -143,12 +185,14 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
rotate: {
|
||||
description: 'Middle click drag',
|
||||
callback: (e) => btnName(e).middle && noModifiersPressed(e),
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
},
|
||||
NX: {
|
||||
pan: {
|
||||
description: 'Shift + Middle click drag',
|
||||
callback: (e) => btnName(e).middle && e.shiftKey,
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
zoom: {
|
||||
description: 'Scroll or Ctrl + Middle click drag',
|
||||
@ -158,12 +202,14 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
rotate: {
|
||||
description: 'Middle click drag',
|
||||
callback: (e) => btnName(e).middle && noModifiersPressed(e),
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
},
|
||||
Creo: {
|
||||
pan: {
|
||||
description: 'Ctrl + Left click drag',
|
||||
callback: (e) => btnName(e).left && !btnName(e).right && e.ctrlKey,
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
zoom: {
|
||||
description: 'Scroll or Ctrl + Right click drag',
|
||||
@ -176,12 +222,14 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
const b = btnName(e)
|
||||
return (b.middle || (b.left && b.right)) && e.ctrlKey
|
||||
},
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
},
|
||||
AutoCAD: {
|
||||
pan: {
|
||||
description: 'Middle click drag',
|
||||
callback: (e) => btnName(e).middle && noModifiersPressed(e),
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
zoom: {
|
||||
description: 'Scroll',
|
||||
@ -191,6 +239,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
rotate: {
|
||||
description: 'Shift + Middle click drag',
|
||||
callback: (e) => btnName(e).middle && e.shiftKey,
|
||||
scrollCallback: () => false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -389,6 +389,8 @@ pub enum MouseControlType {
|
||||
OnShape,
|
||||
#[serde(alias = "Trackpad Friendly")]
|
||||
TrackpadFriendly,
|
||||
#[serde(alias = "Apple Trackpad")]
|
||||
AppleTrackpad,
|
||||
#[serde(alias = "Solidworks")]
|
||||
Solidworks,
|
||||
#[serde(alias = "NX")]
|
||||
|
Reference in New Issue
Block a user