Make scroll mouse controls not fire if buttons are pressed (#4053)
* Make scroll mouse controls not fire if buttons are pressed * Add an E2E test
This commit is contained in:
@ -343,4 +343,140 @@ test.describe('Testing Camera Movement', () => {
|
||||
timeout: 10_000,
|
||||
})
|
||||
})
|
||||
|
||||
test(`Zoom by scroll should not fire while orbiting`, async ({ page }) => {
|
||||
/**
|
||||
* Currently we only allow zooming by scroll when no other camera movement is happening,
|
||||
* set within cameraMouseDragGuards in cameraControls.ts,
|
||||
* until the engine supports unifying multiple camera movements.
|
||||
* This verifies that scrollCallback's guard is working as expected.
|
||||
*/
|
||||
const u = await getUtils(page)
|
||||
|
||||
// Constants and locators
|
||||
const settingsLink = page.getByTestId('settings-link')
|
||||
const settingsDialogHeading = page.getByRole('heading', {
|
||||
name: 'Settings',
|
||||
exact: true,
|
||||
})
|
||||
const userSettingsTab = page.getByRole('radio', { name: 'User' })
|
||||
const mouseControlsSetting = page
|
||||
.locator('#mouseControls')
|
||||
.getByRole('combobox')
|
||||
const mouseControlSuccesToast = page.getByText(
|
||||
'Set mouse controls to "Solidworks"'
|
||||
)
|
||||
const settingsCloseButton = page.getByTestId('settings-close-button')
|
||||
const gizmo = page.locator('[aria-label*=gizmo]')
|
||||
const resetCameraButton = page.getByRole('button', { name: 'Reset view' })
|
||||
const orbitMouseStart = { x: 800, y: 130 }
|
||||
const orbitMouseEnd = { x: 0, y: 130 }
|
||||
const mid = (v1: number, v2: number) => v1 + (v2 - v1) / 2
|
||||
type Point = { x: number; y: number }
|
||||
const midPoint = (p1: Point, p2: Point) => ({
|
||||
x: mid(p1.x, p2.x),
|
||||
y: mid(p1.y, p2.y),
|
||||
})
|
||||
const orbitMouseStepOne = midPoint(orbitMouseStart, orbitMouseEnd)
|
||||
const expectedStartCamZPosition = 64.0
|
||||
const expectedZoomCamZPosition = 32.0
|
||||
const expectedOrbitCamZPosition = 64.0
|
||||
|
||||
await test.step(`Test setup`, async () => {
|
||||
await u.waitForAuthSkipAppStart()
|
||||
await u.closeKclCodePanel()
|
||||
// This test requires the mouse controls to be set to Solidworks
|
||||
await u.openDebugPanel()
|
||||
await test.step(`Set mouse controls setting to Solidworks`, async () => {
|
||||
await settingsLink.click()
|
||||
await expect(settingsDialogHeading).toBeVisible()
|
||||
await userSettingsTab.click()
|
||||
await mouseControlsSetting.selectOption({ label: 'Solidworks' })
|
||||
await expect(mouseControlSuccesToast).toBeVisible()
|
||||
await settingsCloseButton.click()
|
||||
})
|
||||
})
|
||||
|
||||
await test.step(`Test scrolling zoom works`, async () => {
|
||||
await resetCamera()
|
||||
await page.mouse.move(orbitMouseStart.x, orbitMouseStart.y)
|
||||
await page.mouse.wheel(0, -100)
|
||||
await test.step(`Force a refresh of the camera position`, async () => {
|
||||
await u.openAndClearDebugPanel()
|
||||
await u.sendCustomCmd({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_get_settings',
|
||||
},
|
||||
})
|
||||
await u.waitForCmdReceive('default_camera_get_settings')
|
||||
})
|
||||
|
||||
await expect
|
||||
.poll(getCameraZValue, {
|
||||
message: 'Camera should be at expected position after zooming',
|
||||
})
|
||||
.toEqual(expectedZoomCamZPosition)
|
||||
})
|
||||
|
||||
await test.step(`Test orbiting works`, async () => {
|
||||
await doOrbitWith()
|
||||
})
|
||||
|
||||
await test.step(`Test scrolling while orbiting doesn't zoom`, async () => {
|
||||
await doOrbitWith(async () => {
|
||||
await page.mouse.wheel(0, -100)
|
||||
})
|
||||
})
|
||||
|
||||
// Helper functions
|
||||
async function resetCamera() {
|
||||
await test.step(`Reset camera`, async () => {
|
||||
await u.openDebugPanel()
|
||||
await u.clearCommandLogs()
|
||||
await u.doAndWaitForCmd(async () => {
|
||||
await gizmo.click({ button: 'right' })
|
||||
await resetCameraButton.click()
|
||||
}, 'zoom_to_fit')
|
||||
await expect
|
||||
.poll(getCameraZValue, {
|
||||
message: 'Camera Z should be at expected position after reset',
|
||||
})
|
||||
.toEqual(expectedStartCamZPosition)
|
||||
})
|
||||
}
|
||||
|
||||
async function getCameraZValue() {
|
||||
return page
|
||||
.getByTestId('cam-z-position')
|
||||
.inputValue()
|
||||
.then((value) => parseFloat(value))
|
||||
}
|
||||
|
||||
async function doOrbitWith(callback = async () => {}) {
|
||||
await resetCamera()
|
||||
|
||||
await test.step(`Perform orbit`, async () => {
|
||||
await page.mouse.move(orbitMouseStart.x, orbitMouseStart.y)
|
||||
await page.mouse.down({ button: 'middle' })
|
||||
await page.mouse.move(orbitMouseStepOne.x, orbitMouseStepOne.y, {
|
||||
steps: 3,
|
||||
})
|
||||
await callback()
|
||||
await page.mouse.move(orbitMouseEnd.x, orbitMouseEnd.y, {
|
||||
steps: 3,
|
||||
})
|
||||
})
|
||||
|
||||
await test.step(`Verify orbit`, async () => {
|
||||
await expect
|
||||
.poll(getCameraZValue, {
|
||||
message: 'Camera should be at expected position after orbiting',
|
||||
})
|
||||
.toEqual(expectedOrbitCamZPosition)
|
||||
await page.mouse.up({ button: 'middle' })
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -87,7 +87,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
zoom: {
|
||||
description: 'Scroll or Ctrl + Right click drag',
|
||||
dragCallback: (e) => !!(e.buttons & 2) && e.ctrlKey,
|
||||
scrollCallback: () => true,
|
||||
scrollCallback: (e) => e.buttons === 0,
|
||||
},
|
||||
rotate: {
|
||||
description: 'Right click drag',
|
||||
@ -104,7 +104,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
zoom: {
|
||||
description: 'Scroll',
|
||||
dragCallback: () => false,
|
||||
scrollCallback: () => true,
|
||||
scrollCallback: (e) => e.buttons === 0,
|
||||
},
|
||||
rotate: {
|
||||
description: 'Right click drag',
|
||||
@ -121,7 +121,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
zoom: {
|
||||
description: `Scroll or ${ALT} + ${META} + Left click drag`,
|
||||
dragCallback: (e) => btnName(e).left && e.altKey && e.metaKey,
|
||||
scrollCallback: () => true,
|
||||
scrollCallback: (e) => e.buttons === 0,
|
||||
},
|
||||
rotate: {
|
||||
description: `${ALT} + Left click drag`,
|
||||
@ -138,7 +138,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
zoom: {
|
||||
description: 'Scroll or Shift + Middle click drag',
|
||||
dragCallback: (e) => btnName(e).middle && e.shiftKey,
|
||||
scrollCallback: () => true,
|
||||
scrollCallback: (e) => e.buttons === 0,
|
||||
},
|
||||
rotate: {
|
||||
description: 'Middle click drag',
|
||||
@ -153,7 +153,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
zoom: {
|
||||
description: 'Scroll or Ctrl + Middle click drag',
|
||||
dragCallback: (e) => btnName(e).middle && e.ctrlKey,
|
||||
scrollCallback: () => true,
|
||||
scrollCallback: (e) => e.buttons === 0,
|
||||
},
|
||||
rotate: {
|
||||
description: 'Middle click drag',
|
||||
@ -168,7 +168,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
zoom: {
|
||||
description: 'Scroll or Ctrl + Right click drag',
|
||||
dragCallback: (e) => btnName(e).right && !btnName(e).left && e.ctrlKey,
|
||||
scrollCallback: () => true,
|
||||
scrollCallback: (e) => e.buttons === 0,
|
||||
},
|
||||
rotate: {
|
||||
description: 'Ctrl + Middle (or Left + Right) click drag',
|
||||
@ -186,7 +186,7 @@ export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||
zoom: {
|
||||
description: 'Scroll',
|
||||
dragCallback: () => false,
|
||||
scrollCallback: () => true,
|
||||
scrollCallback: (e) => e.buttons === 0,
|
||||
},
|
||||
rotate: {
|
||||
description: 'Shift + Middle click drag',
|
||||
|
Reference in New Issue
Block a user