diff --git a/e2e/playwright/test-utils.ts b/e2e/playwright/test-utils.ts index e74f4c192..7cd2e9844 100644 --- a/e2e/playwright/test-utils.ts +++ b/e2e/playwright/test-utils.ts @@ -337,6 +337,18 @@ export async function getUtils(page: Page, test_?: typeof test) { browserType !== 'chromium' ? null : await page.context().newCDPSession(page) const util = { + async getCenterOfModelViewArea() { + const windowInnerWidth = await page.evaluate(() => window.innerWidth) + const windowInnerHeight = await page.evaluate(() => window.innerHeight) + + const panes = page.getByTestId('pane-section') + const bb = await panes.boundingBox() + const goRightPx = bb.width > 0 ? (windowInnerWidth - bb.width) / 2 : 0 + return { + x: windowInnerWidth / 2 + goRightPx, + y: windowInnerHeight / 2, + } + }, waitForAuthSkipAppStart: () => waitForAuthAndLsp(page), waitForPageLoad: () => waitForPageLoad(page), waitForPageLoadWithRetry: () => waitForPageLoadWithRetry(page), diff --git a/e2e/playwright/testing-settings.spec.ts b/e2e/playwright/testing-settings.spec.ts index 1f5a4ac49..b494124e0 100644 --- a/e2e/playwright/testing-settings.spec.ts +++ b/e2e/playwright/testing-settings.spec.ts @@ -715,31 +715,19 @@ extrude001 = extrude(5, sketch001) ` ) }) - const viewport = { width: 1200, height: 500 } - await page.setViewportSize(viewport) + await page.setViewportSize({ width: 1200, height: 500 }) await u.waitForAuthSkipAppStart() - const getMiddleOfModelingArea = async (viewport) => { - const panes = page.getByTestId('pane-section') - const bb = await panes.boundingBox() - const goRightPx = bb.width > 0 ? (viewport.width - bb.width) / 2 : 0 - return { - x: viewport.width / 2 + goRightPx, - y: viewport.height / 2, - } - } - // Selectors and constants const editSketchButton = page.getByRole('button', { name: 'Edit Sketch' }) const lineToolButton = page.getByTestId('line') const segmentOverlays = page.getByTestId('segment-overlay') - const sketchOriginLocation = await getMiddleOfModelingArea(viewport) + const sketchOriginLocation = await u.getCenterOfModelViewArea() const darkThemeSegmentColor: [number, number, number] = [215, 215, 215] const lightThemeSegmentColor: [number, number, number] = [90, 90, 90] await test.step(`Get into sketch mode`, async () => { - const aLineToClickOn = await u.getBoundingBox('[data-overlay-index="0"]') - await page.mouse.move(aLineToClickOn.x, aLineToClickOn.y) + await page.mouse.click(sketchOriginLocation.x, sketchOriginLocation.y) await expect(editSketchButton).toBeVisible() await editSketchButton.click() @@ -751,12 +739,20 @@ extrude001 = extrude(5, sketch001) await page.waitForTimeout(1000) }) + const line1 = await u.getSegmentBodyCoords(`[data-overlay-index="${0}"]`, 0) + + // Our lines are translucent (surprise!), so we need to get on portion + // of the line that is only on the background, and not on top of something + // like the axis lines. + line1.x -= 1 + line1.y -= 1 + await test.step(`Check the sketch line color before`, async () => { await expect .poll(() => - u.getGreatestPixDiff(sketchOriginLocation, darkThemeSegmentColor) + u.getGreatestPixDiff(line1, darkThemeSegmentColor) ) - .toBeLessThan(15) + .toBeLessThanOrEqual(34) }) await test.step(`Change theme to light using command palette`, async () => { @@ -772,9 +768,9 @@ extrude001 = extrude(5, sketch001) await test.step(`Check the sketch line color after`, async () => { await expect .poll(() => - u.getGreatestPixDiff(sketchOriginLocation, lightThemeSegmentColor) + u.getGreatestPixDiff(line1, lightThemeSegmentColor) ) - .toBeLessThan(15) + .toBeLessThanOrEqual(34) }) }) diff --git a/e2e/playwright/various.spec.ts b/e2e/playwright/various.spec.ts index f606055f5..7f3e46e26 100644 --- a/e2e/playwright/various.spec.ts +++ b/e2e/playwright/various.spec.ts @@ -498,14 +498,11 @@ test('Sketch on face', async ({ page }) => { let previousCodeContent = await page.locator('.cm-content').innerText() - await u.openAndClearDebugPanel() - await u.doAndWaitForCmd( - () => page.mouse.click(625, 165), - 'default_camera_get_settings', - true - ) - await page.waitForTimeout(150) - await u.closeDebugPanel() + const center = await u.getCenterOfModelViewArea() + + await page.mouse.move(center.x, 180) + await page.mouse.click(center.x, 180) + await page.mouse.click(center.x, 180) const firstClickPosition = [612, 238] const secondClickPosition = [661, 242] diff --git a/src/clientSideScene/CameraControls.ts b/src/clientSideScene/CameraControls.ts index d8e1343f8..30c0160a6 100644 --- a/src/clientSideScene/CameraControls.ts +++ b/src/clientSideScene/CameraControls.ts @@ -956,7 +956,7 @@ export class CameraControls { if (!panes) return const panesWidth = panes.offsetWidth + panes.offsetLeft - const goRightPx = panesWidth > 0 ? (window.innerWidth - panesWidth) / 2 : 0 + const goRightPx = panesWidth > 0 ? panesWidth / 2 : 0 // Originally I had tried to use the default_camera_look_at endpoint and // some quaternion math to move the camera right, but it ended up being @@ -975,7 +975,7 @@ export class CameraControls { cmd: { type: 'zoom_to_fit', object_ids: zoomObjectId ? [zoomObjectId] : [], // leave empty to zoom to all objects - padding: panesWidth > 0 ? window.innerWidth / panesWidth : 0.2, // padding around the objects + padding: 0.2, // padding around the objects }, }, { diff --git a/src/components/EngineStream.tsx b/src/components/EngineStream.tsx index 48987c82c..45ce64265 100644 --- a/src/components/EngineStream.tsx +++ b/src/components/EngineStream.tsx @@ -17,6 +17,8 @@ import useEngineStreamContext, { EngineStreamState, EngineStreamTransition, } from 'hooks/useEngineStreamContext' +import { REASONABLE_TIME_TO_REFRESH_STREAM_SIZE } from 'lib/timings' + export const EngineStream = () => { const { setAppState } = useAppState() @@ -24,6 +26,7 @@ export const EngineStream = () => { const { overallState } = useNetworkContext() const { settings } = useSettingsAuthContext() const { file } = useRouteLoaderData(PATHS.FILE) as IndexLoaderData + const last = useRef(Date.now()) const settingsEngine = { theme: settings.context.app.theme.current, @@ -40,10 +43,6 @@ export const EngineStream = () => { const streamIdleMode = settings.context.app.streamIdleMode.current - // 0.25s is the average visual reaction time for humans so we'll go a bit more - // so those exception people don't see. - const REASONABLE_TIME_TO_REFRESH_STREAM_SIZE = 100 - const configure = () => { engineStreamActor.send({ type: EngineStreamTransition.StartOrReconfigureEngine, @@ -81,13 +80,14 @@ export const EngineStream = () => { }, []) useEffect(() => { - if (!streamIdleMode) return + const video = engineStreamState.context.videoRef?.current + if (!video) return + const canvas = engineStreamState.context.canvasRef?.current + if (!canvas) return - const s = setInterval(() => { - const video = engineStreamState.context.videoRef?.current - if (!video) return - const canvas = engineStreamState.context.canvasRef?.current - if (!canvas) return + new ResizeObserver(() => { + if (Date.now() - last.current < REASONABLE_TIME_TO_REFRESH_STREAM_SIZE) return + last.current = Date.now() if ( Math.abs(video.width - window.innerWidth) > 4 || @@ -96,12 +96,9 @@ export const EngineStream = () => { timeoutStart.current = Date.now() configure() } - }, REASONABLE_TIME_TO_REFRESH_STREAM_SIZE) + }).observe(document.body) - return () => { - clearInterval(s) - } - }, [streamIdleMode, engineStreamState.value]) + }, [engineStreamState.value]) // When the video and canvas element references are set, start the engine. useEffect(() => { diff --git a/src/components/ModelingSidebar/ModelingSidebar.tsx b/src/components/ModelingSidebar/ModelingSidebar.tsx index 6a1f053f5..cddaab77a 100644 --- a/src/components/ModelingSidebar/ModelingSidebar.tsx +++ b/src/components/ModelingSidebar/ModelingSidebar.tsx @@ -24,6 +24,7 @@ import { IconDefinition } from '@fortawesome/free-solid-svg-icons' import { useKclContext } from 'lang/KclProvider' import { MachineManagerContext } from 'components/MachineManagerProvider' import { sceneInfra } from 'lib/singletons' +import { REASONABLE_TIME_TO_REFRESH_STREAM_SIZE } from 'lib/timings' interface ModelingSidebarProps { paneOpacity: '' | 'opacity-20' | 'opacity-40' @@ -174,6 +175,20 @@ export const ModelingSidebar = forwardRef< void sceneInfra.camControls.centerModelRelativeToPanes() }, [context.store?.openPanes]) + + // If the panes are resized then center the model also + useEffect(() => { + let width = ref.current.offsetWidth + let last = Date.now() + new ResizeObserver(() => { + if (width === ref.current.offsetWidth) return + if (Date.now() - last < REASONABLE_TIME_TO_REFRESH_STREAM_SIZE) return + last = Date.now() + width = ref.current.offsetWidth + void sceneInfra.camControls.centerModelRelativeToPanes() + }).observe(ref.current) + }, []) + return (