Fix zoom callback on camera controls (#3924)

This commit is contained in:
Jonathan Tran
2024-09-19 17:26:27 -04:00
committed by GitHub
parent dabf256e2b
commit d8236dd8da
3 changed files with 39 additions and 15 deletions

View File

@ -444,8 +444,19 @@ export class CameraControls {
} }
onMouseWheel = (event: WheelEvent) => { onMouseWheel = (event: WheelEvent) => {
const interaction = this.getInteractionType(event)
if (interaction === 'none') return
event.preventDefault()
if (this.syncDirection === 'engineToClient') { if (this.syncDirection === 'engineToClient') {
this.zoomDataFromLastFrame = event.deltaY if (interaction === 'zoom') {
this.zoomDataFromLastFrame = event.deltaY
} 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}`
)
}
return return
} }
@ -455,8 +466,16 @@ export class CameraControls {
// zoom commands to engine. This means dropping some zoom // zoom commands to engine. This means dropping some zoom
// commands too. // commands too.
// From onMouseMove zoom handling which seems to be really smooth // From onMouseMove zoom handling which seems to be really smooth
this.handleStart() this.handleStart()
this.pendingZoom = 1 + (event.deltaY / window.devicePixelRatio) * 0.001 if (interaction === 'zoom') {
this.pendingZoom = 1 + (event.deltaY / window.devicePixelRatio) * 0.001
} 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.handleEnd() this.handleEnd()
} }
@ -1123,7 +1142,7 @@ export class CameraControls {
this.deferReactUpdate(this.reactCameraProperties) this.deferReactUpdate(this.reactCameraProperties)
Object.values(this._camChangeCallbacks).forEach((cb) => cb()) Object.values(this._camChangeCallbacks).forEach((cb) => cb())
} }
getInteractionType = (event: any) => getInteractionType = (event: MouseEvent) =>
_getInteractionType( _getInteractionType(
this.interactionGuards, this.interactionGuards,
event, event,
@ -1231,16 +1250,21 @@ function _lookAt(position: Vector3, target: Vector3, up: Vector3): Quaternion {
function _getInteractionType( function _getInteractionType(
interactionGuards: MouseGuard, interactionGuards: MouseGuard,
event: any, event: MouseEvent | WheelEvent,
enablePan: boolean, enablePan: boolean,
enableRotate: boolean, enableRotate: boolean,
enableZoom: boolean enableZoom: boolean
): interactionType | 'none' { ): interactionType | 'none' {
let state: interactionType | 'none' = 'none' if (event instanceof WheelEvent) {
if (enablePan && interactionGuards.pan.callback(event)) return 'pan' if (enableZoom && interactionGuards.zoom.scrollCallback(event))
if (enableRotate && interactionGuards.rotate.callback(event)) return 'rotate' return 'zoom'
if (enableZoom && interactionGuards.zoom.dragCallback(event)) return 'zoom' } else {
return state if (enablePan && interactionGuards.pan.callback(event)) return 'pan'
if (enableRotate && interactionGuards.rotate.callback(event))
return 'rotate'
if (enableZoom && interactionGuards.zoom.dragCallback(event)) return 'zoom'
}
return 'none'
} }
/** /**

View File

@ -260,7 +260,7 @@ export const Stream = () => {
if (state.matches('Sketch')) return if (state.matches('Sketch')) return
if (state.matches({ idle: 'showPlanes' })) return if (state.matches({ idle: 'showPlanes' })) return
if (btnName(e).left) { if (btnName(e.nativeEvent).left) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises // eslint-disable-next-line @typescript-eslint/no-floating-promises
sendSelectEventToEngine(e, videoRef.current) sendSelectEventToEngine(e, videoRef.current)
} }

View File

@ -6,7 +6,7 @@ const META =
PLATFORM === 'macos' ? 'Cmd' : PLATFORM === 'windows' ? 'Win' : 'Super' PLATFORM === 'macos' ? 'Cmd' : PLATFORM === 'windows' ? 'Win' : 'Super'
const ALT = PLATFORM === 'macos' ? 'Option' : 'Alt' const ALT = PLATFORM === 'macos' ? 'Option' : 'Alt'
const noModifiersPressed = (e: React.MouseEvent) => const noModifiersPressed = (e: MouseEvent) =>
!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey
export type CameraSystem = export type CameraSystem =
@ -53,14 +53,14 @@ export function mouseControlsToCameraSystem(
interface MouseGuardHandler { interface MouseGuardHandler {
description: string description: string
callback: (e: React.MouseEvent) => boolean callback: (e: MouseEvent) => boolean
lenientDragStartButton?: number lenientDragStartButton?: number
} }
interface MouseGuardZoomHandler { interface MouseGuardZoomHandler {
description: string description: string
dragCallback: (e: React.MouseEvent) => boolean dragCallback: (e: MouseEvent) => boolean
scrollCallback: (e: React.MouseEvent) => boolean scrollCallback: (e: WheelEvent) => boolean
lenientDragStartButton?: number lenientDragStartButton?: number
} }
@ -70,7 +70,7 @@ export interface MouseGuard {
rotate: MouseGuardHandler rotate: MouseGuardHandler
} }
export const btnName = (e: React.MouseEvent) => ({ export const btnName = (e: MouseEvent) => ({
middle: !!(e.buttons & 4) || e.button === 1, middle: !!(e.buttons & 4) || e.button === 1,
right: !!(e.buttons & 2) || e.button === 2, right: !!(e.buttons & 2) || e.button === 2,
left: !!(e.buttons & 1) || e.button === 0, left: !!(e.buttons & 1) || e.button === 0,