Bugfix: update sketch mode colors on theme change (#3849)

* Update client-side scene mesh base colors properly

* Add E2E test

* Remove use of `as`
This commit is contained in:
Frank Noirot
2024-09-10 13:30:39 -04:00
committed by GitHub
parent 5b2738f826
commit 900bac999c
3 changed files with 93 additions and 2 deletions

View File

@ -552,4 +552,70 @@ test.describe('Testing settings', () => {
await changeUnitOfMeasureInGizmo('m', 'Meters') await changeUnitOfMeasureInGizmo('m', 'Meters')
}) })
}) })
test('Changing theme in sketch mode', async ({ page }) => {
const u = await getUtils(page)
await page.addInitScript(() => {
localStorage.setItem(
'persistCode',
`const sketch001 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([5, 0], %)
|> line([0, 5], %)
|> line([-5, 0], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
const extrude001 = extrude(5, sketch001)
`
)
})
await page.setViewportSize({ width: 1200, height: 500 })
// Selectors and constants
const editSketchButton = page.getByRole('button', { name: 'Edit Sketch' })
const lineToolButton = page.getByTestId('line')
const segmentOverlays = page.getByTestId('segment-overlay')
const sketchOriginLocation = { x: 600, y: 250 }
const darkThemeSegmentColor: [number, number, number] = [215, 215, 215]
const lightThemeSegmentColor: [number, number, number] = [90, 90, 90]
await test.step(`Get into sketch mode`, async () => {
await u.waitForAuthSkipAppStart()
await page.mouse.click(700, 200)
await expect(editSketchButton).toBeVisible()
await editSketchButton.click()
// We use the line tool as a proxy for sketch mode
await expect(lineToolButton).toBeVisible()
await expect(segmentOverlays).toHaveCount(4)
// but we allow more time to pass for animating to the sketch
await page.waitForTimeout(1000)
})
await test.step(`Check the sketch line color before`, async () => {
await expect
.poll(() =>
u.getGreatestPixDiff(sketchOriginLocation, darkThemeSegmentColor)
)
.toBeLessThan(15)
})
await test.step(`Change theme to light using command palette`, async () => {
await page.keyboard.press('ControlOrMeta+K')
await page.getByRole('option', { name: 'theme' }).click()
await page.getByRole('option', { name: 'light' }).click()
await expect(page.getByText('theme to "light"')).toBeVisible()
// Make sure we haven't left sketch mode
await expect(lineToolButton).toBeVisible()
})
await test.step(`Check the sketch line color after`, async () => {
await expect
.poll(() =>
u.getGreatestPixDiff(sketchOriginLocation, lightThemeSegmentColor)
)
.toBeLessThan(15)
})
})
}) })

View File

@ -102,7 +102,7 @@ import {
getRectangleCallExpressions, getRectangleCallExpressions,
updateRectangleSketch, updateRectangleSketch,
} from 'lib/rectangleTool' } from 'lib/rectangleTool'
import { getThemeColorForThreeJs } from 'lib/theme' import { getThemeColorForThreeJs, Themes } from 'lib/theme'
import { err, reportRejection, trap } from 'lib/trap' import { err, reportRejection, trap } from 'lib/trap'
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer' import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { Point3d } from 'wasm-lib/kcl/bindings/Point3d' import { Point3d } from 'wasm-lib/kcl/bindings/Point3d'
@ -1473,6 +1473,25 @@ export class SceneEntities {
to, to,
}) })
} }
/**
* Update the base color of each of the THREEjs meshes
* that represent each of the sketch segments, to get the
* latest value from `sceneInfra._theme`
*/
updateSegmentBaseColor(newColor: Themes.Light | Themes.Dark) {
const newColorThreeJs = getThemeColorForThreeJs(newColor)
Object.values(this.activeSegments).forEach((group) => {
group.userData.baseColor = newColorThreeJs
group.traverse((child) => {
if (
child instanceof Mesh &&
child.material instanceof MeshBasicMaterial
) {
child.material.color.set(newColorThreeJs)
}
})
})
}
removeSketchGrid() { removeSketchGrid() {
if (this.axisGroup) this.scene.remove(this.axisGroup) if (this.axisGroup) this.scene.remove(this.axisGroup)
} }

View File

@ -17,7 +17,12 @@ import decamelize from 'decamelize'
import { Actor, AnyStateMachine, ContextFrom, Prop, StateFrom } from 'xstate' import { Actor, AnyStateMachine, ContextFrom, Prop, StateFrom } from 'xstate'
import { isDesktop } from 'lib/isDesktop' import { isDesktop } from 'lib/isDesktop'
import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig' import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig'
import { kclManager, sceneInfra, engineCommandManager } from 'lib/singletons' import {
kclManager,
sceneInfra,
engineCommandManager,
sceneEntitiesManager,
} from 'lib/singletons'
import { uuidv4 } from 'lib/utils' import { uuidv4 } from 'lib/utils'
import { IndexLoaderData } from 'lib/types' import { IndexLoaderData } from 'lib/types'
import { settings } from 'lib/settings/initialSettings' import { settings } from 'lib/settings/initialSettings'
@ -137,6 +142,7 @@ export const SettingsAuthProviderBase = ({
setClientTheme: ({ context }) => { setClientTheme: ({ context }) => {
const opposingTheme = getOppositeTheme(context.app.theme.current) const opposingTheme = getOppositeTheme(context.app.theme.current)
sceneInfra.theme = opposingTheme sceneInfra.theme = opposingTheme
sceneEntitiesManager.updateSegmentBaseColor(opposingTheme)
}, },
setEngineEdges: ({ context }) => { setEngineEdges: ({ context }) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises // eslint-disable-next-line @typescript-eslint/no-floating-promises