diff --git a/e2e/playwright/snapshot-tests.spec.ts b/e2e/playwright/snapshot-tests.spec.ts index f056dc68e..e792b7901 100644 --- a/e2e/playwright/snapshot-tests.spec.ts +++ b/e2e/playwright/snapshot-tests.spec.ts @@ -796,3 +796,83 @@ test('Zoom to fit on load - solid 3d', async ({ page, context }) => { maxDiffPixels: 100, }) }) + +test.describe('Grid visibility', () => { + test('Grid turned off', async ({ page }) => { + const u = await getUtils(page) + const stream = page.getByTestId('stream') + const mask = [ + page.locator('#app-header'), + page.locator('#sidebar-top-ribbon'), + page.locator('#sidebar-bottom-ribbon'), + ] + + await page.setViewportSize({ width: 1200, height: 500 }) + await page.goto('/') + await u.waitForAuthSkipAppStart() + + await u.openDebugPanel() + // wait for execution done + await expect( + page.locator('[data-message-type="execution-done"]') + ).toHaveCount(2) + await u.closeDebugPanel() + await u.closeKclCodePanel() + // TODO: Find a way to truly know that the objects have finished + // rendering, because an execution-done message is not sufficient. + await page.waitForTimeout(1000) + + await expect(stream).toHaveScreenshot({ + maxDiffPixels: 100, + mask, + }) + }) + + test('Grid turned on', async ({ page }) => { + await page.addInitScript( + async ({ settingsKey, settings }) => { + localStorage.setItem(settingsKey, settings) + }, + { + settingsKey: TEST_SETTINGS_KEY, + settings: TOML.stringify({ + settings: { + ...TEST_SETTINGS, + modeling: { + ...TEST_SETTINGS.modeling, + showScaleGrid: true, + }, + }, + }), + } + ) + + const u = await getUtils(page) + const stream = page.getByTestId('stream') + const mask = [ + page.locator('#app-header'), + page.locator('#sidebar-top-ribbon'), + page.locator('#sidebar-bottom-ribbon'), + ] + + await page.setViewportSize({ width: 1200, height: 500 }) + await page.goto('/') + await u.waitForAuthSkipAppStart() + + await u.openDebugPanel() + // wait for execution done + await expect( + page.locator('[data-message-type="execution-done"]') + ).toHaveCount(2) + await u.closeDebugPanel() + await u.closeKclCodePanel() + // TODO: Find a way to truly know that the objects have finished + // rendering, because an execution-done message is not sufficient. + await page.waitForTimeout(1000) + + await expect(stream).toHaveScreenshot({ + maxDiffPixels: 100, + mask, + }) + }) +}) diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-1-Google-Chrome-linux.png new file mode 100644 index 000000000..e39e0e14d Binary files /dev/null and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-off-1-Google-Chrome-linux.png differ diff --git a/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-on-1-Google-Chrome-linux.png b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-on-1-Google-Chrome-linux.png new file mode 100644 index 000000000..e27248a38 Binary files /dev/null and b/e2e/playwright/snapshot-tests.spec.ts-snapshots/Grid-visibility-Grid-turned-on-1-Google-Chrome-linux.png differ diff --git a/src/components/AppHeader.tsx b/src/components/AppHeader.tsx index 52a598223..997106b76 100644 --- a/src/components/AppHeader.tsx +++ b/src/components/AppHeader.tsx @@ -26,6 +26,7 @@ export const AppHeader = ({ return (
({ htmlRef: s.htmlRef, diff --git a/src/components/ModelingSidebar/ModelingSidebar.tsx b/src/components/ModelingSidebar/ModelingSidebar.tsx index cbd7a6b77..2c97ca505 100644 --- a/src/components/ModelingSidebar/ModelingSidebar.tsx +++ b/src/components/ModelingSidebar/ModelingSidebar.tsx @@ -1,6 +1,6 @@ import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext' import { Resizable } from 're-resizable' -import { useCallback, useEffect, useState } from 'react' +import { HTMLAttributes, useCallback, useEffect, useState } from 'react' import { useHotkeys } from 'react-hotkeys-hook' import { useStore } from 'useStore' import { Tab } from '@headlessui/react' @@ -56,15 +56,19 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) { bottomRight: 'hidden', }} > -
- - +
+ +
) } -interface ModelingSidebarSectionProps { +interface ModelingSidebarSectionProps extends HTMLAttributes { panes: SidebarPane[] alignButtons?: 'start' | 'end' } @@ -72,6 +76,8 @@ interface ModelingSidebarSectionProps { function ModelingSidebarSection({ panes, alignButtons = 'start', + className, + ...props }: ModelingSidebarSectionProps) { const { settings } = useSettingsAuthContext() const showDebugPanel = settings.context.modeling.showDebugPanel @@ -123,7 +129,7 @@ function ModelingSidebarSection({ }, [showDebugPanel.current, togglePane, openPanes]) return ( -
+
{ + engineCommandManager.setScaleGridVisibility( + context.modeling.showScaleGrid.current + ) + }, setClientTheme: (context) => { const opposingTheme = getOppositeTheme(context.app.theme.current) sceneInfra.theme = opposingTheme diff --git a/src/hooks/useSetupEngineManager.ts b/src/hooks/useSetupEngineManager.ts index 31fe7ae30..eb7e23632 100644 --- a/src/hooks/useSetupEngineManager.ts +++ b/src/hooks/useSetupEngineManager.ts @@ -13,11 +13,13 @@ export function useSetupEngineManager( theme: Themes.System, highlightEdges: true, enableSSAO: true, + showScaleGrid: false, } as { pool: string | null theme: Themes highlightEdges: boolean enableSSAO: boolean + showScaleGrid: boolean } ) { const { diff --git a/src/lang/std/engineConnection.ts b/src/lang/std/engineConnection.ts index eecada939..2f6462478 100644 --- a/src/lang/std/engineConnection.ts +++ b/src/lang/std/engineConnection.ts @@ -1158,6 +1158,7 @@ export class EngineCommandManager extends EventTarget { theme: Themes.Dark, highlightEdges: true, enableSSAO: true, + showScaleGrid: false, }, }: { setMediaStream: (stream: MediaStream) => void @@ -1172,6 +1173,7 @@ export class EngineCommandManager extends EventTarget { theme: Themes highlightEdges: boolean enableSSAO: boolean + showScaleGrid: boolean } }) { this.makeDefaultPlanes = makeDefaultPlanes @@ -1254,7 +1256,7 @@ export class EngineCommandManager extends EventTarget { // We want modify the grid first because we don't want it to flash. // Ideally these would already be default hidden in engine (TODO do // that) https://github.com/KittyCAD/engine/issues/2282 - this.modifyGrid(true)?.then(async () => { + this.modifyGrid(!settings.showScaleGrid)?.then(async () => { await this.initPlanes() this.resolveReady() setIsStreamReady(true) @@ -2074,4 +2076,12 @@ export class EngineCommandManager extends EventTarget { }, }) } + + /** + * Set the visibility of the scale grid in the engine scene. + * @param visible - whether to show or hide the scale grid + */ + setScaleGridVisibility(visible: boolean) { + this.modifyGrid(!visible) + } } diff --git a/src/lib/settings/initialSettings.tsx b/src/lib/settings/initialSettings.tsx index 10ca5a86e..aec9d9361 100644 --- a/src/lib/settings/initialSettings.tsx +++ b/src/lib/settings/initialSettings.tsx @@ -325,6 +325,18 @@ export function createSettings() { }, hideOnLevel: 'project', }), + /** + * Whether to show a scale grid in the 3D modeling view + */ + showScaleGrid: new Setting({ + defaultValue: false, + description: 'Whether to show a scale grid in the 3D modeling view', + validate: (v) => typeof v === 'boolean', + commandConfig: { + inputType: 'boolean', + }, + hideOnLevel: 'project', + }), /** * Whether to show the debug panel, which lets you see * various states of the app to aid in development diff --git a/src/lib/settings/settingsUtils.ts b/src/lib/settings/settingsUtils.ts index daf4af47e..88b326db0 100644 --- a/src/lib/settings/settingsUtils.ts +++ b/src/lib/settings/settingsUtils.ts @@ -48,6 +48,7 @@ function configurationToSettingsPayload( ), highlightEdges: configuration?.settings?.modeling?.highlight_edges, showDebugPanel: configuration?.settings?.modeling?.show_debug_panel, + showScaleGrid: configuration?.settings?.modeling?.show_scale_grid, }, textEditor: { textWrapping: configuration?.settings?.text_editor?.text_wrapping, diff --git a/src/machines/settingsMachine.ts b/src/machines/settingsMachine.ts index f9fe822f9..951d7ac0f 100644 --- a/src/machines/settingsMachine.ts +++ b/src/machines/settingsMachine.ts @@ -11,7 +11,7 @@ import { export const settingsMachine = createMachine( { - /** @xstate-layout N4IgpgJg5mDOIC5QGUwBc0EsB2VYDpMIAbMAYlnXwEMAHW-Ae2wCNHqAnCHKZNatAFdYAbQAMAXUShajWJizNpIAB6IALAFYAnPgBMARgDsBsQDY969QGYjmzQBoQAT0SnrADnwePY61r0PAwNtMyMAX3CnVAweAiJSCio6BjQACzAAWzAAYUZiRg5xKSQQWXlFbGU1BD1PfFtfE3UzTUNNaydXBCD1b209PTEPTTMtdQNNSOj0LFx4knJKNHxMxggwYh58DYAzakFiNABVbAVi5XKFTCVSmsGxfCMPM08PQaDNU0cXRG1tLwedTaKxif7+UJTKIgGJzPCERZJFYpfDpLJgC6lK6VaqIEx6fBmCw2Do2IJ6MxdRDvTT4MRDdRGEzWbQ6ELTGGzOIIxLLVbrTbbNKYKBpLaitAAUWgcExMjk11uoBqVgM3jMYhsAIMrVs6ipPWChOeYhC9KMFhGHNh3IS5AASnB0AACZZw0SSS4KnF3PFafADTV1YZ2IxiH7dNpGfCaIzAgE+IzWMzBa1c+Y88gxZ3UYjEV3pvBysrem5VX0IFq0y3aTXWOp6JmU34IKMxuz0joGEYWsxp2IZu1kABUxexZdxtRG+EmQMZmne3dNBs0jKewLBsbCwI81n77vwtDAHHksDhBYHeDIEGYYEI2AAbowANZ3o8nzBnm3zMelpWqRAAFp62sJ4jEsZ4AT0UJGwjPFzH6cwNW0AwWXpbRImhbABXgUpvzwL0KgnCtgJMMCII8KCYLsA11EGOkXneDxmXMCk92hfCFlIQjFXLZUgLjddWhaFkgRCaxOhbEYzBnXwXkmOjAjjfduXfU9zzdOIeJ9fiEEA6ckwMClQ2BFpmJXMF9DjYI6hZfxmMw8IgA */ + /** @xstate-layout N4IgpgJg5mDOIC5QGUwBc0EsB2VYDpMIAbMAYlnXwEMAHW-Ae2wCNHqAnCHKZNatAFdYAbQAMAXUShajWJizNpIAB6IALAFYAnPgBMARgDsBsQDY969QGYjmzQBoQAT0SnrADnwePY61r0PAwNtMyMAX3CnVAweAiJSCio6BjQACzAAWzAAYUZiRg5xKSQQWXlFbGU1BD1PfFtfE3UzTUNNaydXBCD1b209PTEPTTMtdQNNSOj0LFx4knJKNHxMxggwYh58DYAzakFiNABVbAVi5XKFTCVSmusxPXx7bRt1DzMxI3UjD3UutwhAz4MyeHxiV5+AYRKIgGJzPCERZJFYpfDpLJgC6lK6VaqIExPMwWGwdGxBPRmAE9PSafCPMQ-EzWbQ6ELTOGzOJIxLLVbrTbbNKYKBpLaitAAUWgcGxMjk11uoBqVmBH0ZLKCrVs-xciCCwLCvhCjyMFhGHPh3IS5AASnB0AACZYI0SSS4KvF3AlafADRl1YZ2IxiRx6hBtIzPb7abQ+DxGaxmYKWrnzHnkGKO6jEYjOtN4OVlT03KrehAtOnm7Qaup6Ixm6mR6OaR4dAwjM1mVOxdM2lH8jZbXD4WBpRgAd2QAGMc2AAOIcIhF3Gl-EIRPA6yGcyh4whSnU0xGJ5GAat0OfFowma9xH9gBUK5LStUiECdMmfx+mg8hmNTY-PgMYQpoZoxh41g9q6+C0GAHDyLACL5nesBkBAzBgIQ2AAG6MAA1lhcEIZgSFWvMz4VGu5YALTbtYwEnj8HhxnooT1mG3QhmY-TmJ82gGCyjzaJEsLYAK8ClOReAelRr41HRJiMZYvysexdjUuohh+poBiGDuXzGKy0HWossmKmWyqIDR3zAZWLSahM2jWJ04YjDxHbDMmmhaYE3wmemxGIchLpxOZXpWQgNEjMB1h6WEYHqK8ZgJk2EL6N8wR1Cy-gJqJ4RAA */ id: 'Settings', predictableActionArguments: true, context: {} as ReturnType, @@ -32,6 +32,7 @@ export const settingsMachine = createMachine( // No toast actions: ['setSettingAtLevel'], }, + 'set.app.themeColor': { target: 'persisting settings', @@ -93,6 +94,15 @@ export const settingsMachine = createMachine( 'setClientTheme', ], }, + + 'set.modeling.showScaleGrid': { + target: 'persisting settings', + actions: [ + 'setSettingAtLevel', + 'toastSuccess', + 'setEngineScaleGridVisibility', + ], + }, }, }, diff --git a/src/wasm-lib/kcl/src/settings/types/mod.rs b/src/wasm-lib/kcl/src/settings/types/mod.rs index b37609d70..61ade9c4b 100644 --- a/src/wasm-lib/kcl/src/settings/types/mod.rs +++ b/src/wasm-lib/kcl/src/settings/types/mod.rs @@ -379,6 +379,9 @@ pub struct ModelingSettings { /// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled. #[serde(default, skip_serializing_if = "is_default")] pub enable_ssao: DefaultTrue, + /// Whether or not to show a scale grid in the 3D modeling view + #[serde(default, alias = "showScaleGrid", skip_serializing_if = "is_default")] + pub show_scale_grid: bool, } #[derive(Debug, Copy, Clone, Deserialize, Serialize, JsonSchema, ts_rs::TS, PartialEq, Eq)] @@ -654,7 +657,8 @@ textWrapping = true mouse_controls: Default::default(), highlight_edges: Default::default(), show_debug_panel: true, - enable_ssao: false.into() + enable_ssao: false.into(), + show_scale_grid: false, }, text_editor: TextEditorSettings { text_wrapping: true.into(), @@ -712,7 +716,8 @@ includeSettings = false mouse_controls: Default::default(), highlight_edges: Default::default(), show_debug_panel: true, - enable_ssao: true.into() + enable_ssao: true.into(), + show_scale_grid: false, }, text_editor: TextEditorSettings { text_wrapping: false.into(), @@ -775,7 +780,8 @@ defaultProjectName = "projects-$nnn" mouse_controls: Default::default(), highlight_edges: Default::default(), show_debug_panel: true, - enable_ssao: true.into() + enable_ssao: true.into(), + show_scale_grid: false, }, text_editor: TextEditorSettings { text_wrapping: false.into(), @@ -850,7 +856,8 @@ projectDirectory = "/Users/macinatormax/Documents/kittycad-modeling-projects""#; mouse_controls: Default::default(), highlight_edges: true.into(), show_debug_panel: false, - enable_ssao: true.into() + enable_ssao: true.into(), + show_scale_grid: false, }, text_editor: TextEditorSettings { text_wrapping: true.into(), diff --git a/src/wasm-lib/kcl/src/settings/types/project.rs b/src/wasm-lib/kcl/src/settings/types/project.rs index 26c2d7c36..36a329980 100644 --- a/src/wasm-lib/kcl/src/settings/types/project.rs +++ b/src/wasm-lib/kcl/src/settings/types/project.rs @@ -129,7 +129,8 @@ includeSettings = false mouse_controls: Default::default(), highlight_edges: Default::default(), show_debug_panel: true, - enable_ssao: true.into() + enable_ssao: true.into(), + show_scale_grid: false, }, text_editor: TextEditorSettings { text_wrapping: false.into(),