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:
@ -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)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user