[BUG] offsetPlane back-side startSketchOn (#7622)
offset backPlane selection bug
This commit is contained in:
@ -5,6 +5,7 @@ import { uuidv4 } from '@src/lib/utils'
|
||||
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
|
||||
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
||||
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||
import { getUtils } from '@e2e/playwright/test-utils'
|
||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
|
||||
@ -14,13 +15,18 @@ test.describe('Can create sketches on all planes and their back sides', () => {
|
||||
homePage: HomePageFixture,
|
||||
scene: SceneFixture,
|
||||
toolbar: ToolbarFixture,
|
||||
cmdBar: CmdBarFixture,
|
||||
plane: string,
|
||||
clickCoords: { x: number; y: number }
|
||||
) => {
|
||||
const u = await getUtils(page)
|
||||
// await page.addInitScript(() => {
|
||||
// localStorage.setItem('persistCode', '@settings(defaultLengthUnit = in)')
|
||||
// })
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
// await scene.settled(cmdBar)
|
||||
const XYPlanRed: [number, number, number] = [98, 50, 51]
|
||||
await scene.expectPixelColor(XYPlanRed, { x: 700, y: 300 }, 15)
|
||||
|
||||
@ -119,12 +125,166 @@ test.describe('Can create sketches on all planes and their back sides', () => {
|
||||
]
|
||||
|
||||
for (const config of planeConfigs) {
|
||||
test(config.plane, async ({ page, homePage, scene, toolbar }) => {
|
||||
test(config.plane, async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
||||
await sketchOnPlaneAndBackSideTest(
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
config.plane,
|
||||
config.coords
|
||||
)
|
||||
})
|
||||
}
|
||||
})
|
||||
test.describe('Can create sketches on offset planes and their back sides', () => {
|
||||
const sketchOnPlaneAndBackSideTest = async (
|
||||
page: Page,
|
||||
homePage: HomePageFixture,
|
||||
scene: SceneFixture,
|
||||
toolbar: ToolbarFixture,
|
||||
cmdbar: CmdBarFixture,
|
||||
plane: string,
|
||||
clickCoords: { x: number; y: number }
|
||||
) => {
|
||||
const u = await getUtils(page)
|
||||
await page.addInitScript(() => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`@settings(defaultLengthUnit = in)
|
||||
xyPlane = offsetPlane(XY, offset = 0.05)
|
||||
xzPlane = offsetPlane(XZ, offset = 0.05)
|
||||
yzPlane = offsetPlane(YZ, offset = 0.05)
|
||||
`
|
||||
)
|
||||
})
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
// await scene.settled(cmdbar)
|
||||
const XYPlanRed: [number, number, number] = [74, 74, 74]
|
||||
await scene.expectPixelColor(XYPlanRed, { x: 700, y: 300 }, 15)
|
||||
|
||||
await u.openDebugPanel()
|
||||
|
||||
const coord =
|
||||
plane === '-XY' || plane === '-YZ' || plane === 'XZ' ? -100 : 100
|
||||
const camCommand: EngineCommand = {
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_look_at',
|
||||
center: { x: 0, y: 0, z: 0 },
|
||||
vantage: { x: coord, y: coord, z: coord },
|
||||
up: { x: 0, y: 0, z: 1 },
|
||||
},
|
||||
}
|
||||
const updateCamCommand: EngineCommand = {
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_get_settings',
|
||||
},
|
||||
}
|
||||
|
||||
const prefix = plane.length === 3 ? '-' : ''
|
||||
const planeName = plane
|
||||
.slice(plane.length === 3 ? 1 : 0)
|
||||
.toLocaleLowerCase()
|
||||
|
||||
const codeLine1 = `sketch001 = startSketchOn(${prefix}${planeName}Plane)`
|
||||
const codeLine2 = `profile001 = startProfile(sketch001, at = [${0.91 + (plane[0] === '-' ? 0.01 : 0)}, -${1.21 + (plane[0] === '-' ? 0.01 : 0)}])`
|
||||
|
||||
await u.openDebugPanel()
|
||||
|
||||
await u.clearCommandLogs()
|
||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||
|
||||
await u.sendCustomCmd(camCommand)
|
||||
await page.waitForTimeout(100)
|
||||
await u.sendCustomCmd(updateCamCommand)
|
||||
|
||||
await u.closeDebugPanel()
|
||||
|
||||
await toolbar.openFeatureTreePane()
|
||||
await toolbar.getDefaultPlaneVisibilityButton('XY').click()
|
||||
await toolbar.getDefaultPlaneVisibilityButton('XZ').click()
|
||||
await toolbar.getDefaultPlaneVisibilityButton('YZ').click()
|
||||
await expect(
|
||||
toolbar
|
||||
.getDefaultPlaneVisibilityButton('YZ')
|
||||
.locator('[aria-label="eye crossed out"]')
|
||||
).toBeVisible()
|
||||
|
||||
await page.mouse.click(clickCoords.x, clickCoords.y)
|
||||
await page.waitForTimeout(600) // wait for animation
|
||||
|
||||
await toolbar.waitUntilSketchingReady()
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'line Line', exact: true })
|
||||
).toBeVisible()
|
||||
|
||||
await u.closeDebugPanel()
|
||||
await page.mouse.click(707, 393)
|
||||
|
||||
await expect(page.locator('.cm-content')).toContainText(codeLine1)
|
||||
await expect(page.locator('.cm-content')).toContainText(codeLine2)
|
||||
|
||||
await page
|
||||
.getByRole('button', { name: 'line Line', exact: true })
|
||||
.first()
|
||||
.click()
|
||||
await u.openAndClearDebugPanel()
|
||||
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||
|
||||
await u.clearCommandLogs()
|
||||
await u.removeCurrentCode()
|
||||
}
|
||||
|
||||
const planeConfigs = [
|
||||
{
|
||||
plane: 'XY',
|
||||
coords: { x: 600, y: 388 },
|
||||
description: 'red plane',
|
||||
},
|
||||
{
|
||||
plane: 'YZ',
|
||||
coords: { x: 700, y: 250 },
|
||||
description: 'green plane',
|
||||
},
|
||||
{
|
||||
plane: 'XZ',
|
||||
coords: { x: 684, y: 427 },
|
||||
description: 'blue plane',
|
||||
},
|
||||
{
|
||||
plane: '-XY',
|
||||
coords: { x: 600, y: 118 },
|
||||
description: 'back of red plane',
|
||||
},
|
||||
{
|
||||
plane: '-YZ',
|
||||
coords: { x: 700, y: 219 },
|
||||
description: 'back of green plane',
|
||||
},
|
||||
{
|
||||
plane: '-XZ',
|
||||
coords: { x: 700, y: 80 },
|
||||
description: 'back of blue plane',
|
||||
},
|
||||
]
|
||||
|
||||
for (const config of planeConfigs) {
|
||||
test(config.plane, async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
||||
await sketchOnPlaneAndBackSideTest(
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
config.plane,
|
||||
config.coords
|
||||
)
|
||||
|
@ -274,6 +274,13 @@ export class ToolbarFixture {
|
||||
.nth(operationIndex)
|
||||
}
|
||||
|
||||
getDefaultPlaneVisibilityButton(plane: 'XY' | 'XZ' | 'YZ' = 'XY') {
|
||||
const index = plane === 'XZ' ? 0 : plane === 'XY' ? 1 : 2
|
||||
return this.featureTreePane
|
||||
.getByTestId('feature-tree-visibility-toggle')
|
||||
.nth(index)
|
||||
}
|
||||
|
||||
/**
|
||||
* View source on a specific operation in the Feature Tree pane.
|
||||
* @param operationName The name of the operation type
|
||||
|
@ -107,7 +107,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
beaker: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="beaker"
|
||||
>
|
||||
<path
|
||||
d="M13.4747 4.1582L12.5353 6.97363L15.8322 14.3906L15.9015 14.5781C16.1808 15.5181 15.4786 16.5 14.4611 16.5H5.61828C4.50321 16.5 3.77781 15.3265 4.27649 14.3291L7.96008 6.96191L7.02551 4.1582L7.50012 3.5H13.0001L13.4747 4.1582ZM13.6183 11.873C13.2276 11.7045 12.8282 11.6908 12.38 11.7686C11.8504 11.8605 11.3185 12.0648 10.6671 12.2764C9.48553 12.6601 8.08344 12.9938 6.49133 12.1348L5.17102 14.7764C5.00479 15.1088 5.24659 15.5 5.61828 15.5H14.4611C14.8002 15.5 15.0346 15.1727 14.9415 14.8594L14.9181 14.7969L13.6183 11.873ZM8.97473 6.8418L9.04016 7.03809L6.9386 11.2402C8.17525 11.9192 9.24713 11.6862 10.3585 11.3252C10.9385 11.1368 11.5865 10.8913 12.2091 10.7832C12.5041 10.732 12.8059 10.7103 13.1124 10.7344L11.5431 7.20312L11.464 7.02539L11.5255 6.8418L12.3058 4.5H8.19445L8.97473 6.8418Z"
|
||||
fill="currentColor"
|
||||
@ -190,7 +195,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
chat: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="chat"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -326,6 +336,7 @@ const CustomIconMap = {
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="command"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
@ -351,7 +362,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
elephant: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="elephant"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -417,7 +433,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
eyeOpen: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="eye open"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -427,7 +448,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
eyeCrossedOut: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="eye crossed out"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -563,7 +589,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
helix: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="helix"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -588,7 +619,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
hollow: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="hollow"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -666,6 +702,7 @@ const CustomIconMap = {
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="download"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
@ -749,7 +786,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
loading: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="loading"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -864,7 +906,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
model: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="model"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -889,7 +936,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
play: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="play"
|
||||
>
|
||||
<path
|
||||
d="M14.2842 9.83887L14.2617 10.6758L7.76172 14.6758L7 14.25V5.75L7.78418 5.33887L14.2842 9.83887ZM8 13.3555L13.0859 10.2246L8 6.70312V13.3555Z"
|
||||
fill="currentColor"
|
||||
@ -901,7 +953,7 @@ const CustomIconMap = {
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="move"
|
||||
aria-label="rotate"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
@ -916,7 +968,7 @@ const CustomIconMap = {
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="move"
|
||||
aria-label="clone"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
@ -972,7 +1024,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
patternCircular2d: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="pattern circular 2d"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -982,7 +1039,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
patternCircular3d: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="pattern circular 3d"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -998,7 +1060,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
patternLinear2d: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="pattern linear 2d"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -1008,7 +1075,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
patternLinear3d: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="pattern linear 3d"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -1231,7 +1303,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
sparkles: (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="sparkles"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
@ -1404,6 +1481,7 @@ const CustomIconMap = {
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="stopwatch"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
@ -1425,7 +1503,7 @@ const CustomIconMap = {
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="y-relative"
|
||||
aria-label="glasses"
|
||||
>
|
||||
<path
|
||||
d="M13.9814 7C15.6383 7 16.9814 8.34317 16.9814 10C16.9814 11.6569 15.6383 13 13.9814 13C12.3764 12.9999 11.0656 11.7394 10.9854 10.1543L10.9814 10L10.9707 9.85352C10.9635 9.80499 10.9527 9.75695 10.9385 9.70996L10.9053 9.61719C10.8676 9.52625 10.8171 9.44105 10.7549 9.36523L10.6885 9.29297C10.5957 9.20021 10.4855 9.1264 10.3643 9.07617C10.243 9.02598 10.1127 9 9.98145 9C9.88308 9.00002 9.7852 9.01454 9.69141 9.04297L9.59863 9.07617C9.50772 9.11387 9.42249 9.16435 9.34668 9.22656L9.27441 9.29297C9.20485 9.36255 9.14585 9.44188 9.09961 9.52832L9.05762 9.61719C9.02796 9.6888 9.00749 9.76366 8.99512 9.83984C8.99791 9.89289 9 9.94626 9 10C9 11.6569 7.65685 13 6 13C4.3432 12.9999 3 11.6568 3 10C3.00003 8.34321 4.34322 7.00007 6 7C7.12596 7 8.10505 7.62155 8.61816 8.53906L8.71289 8.4541C8.86453 8.32967 9.03396 8.22772 9.21582 8.15234L9.40137 8.08594C9.58903 8.02906 9.78464 8.00002 9.98145 8C10.244 8 10.5045 8.0519 10.7471 8.15234L10.9248 8.23633C11.0819 8.32036 11.2268 8.42596 11.3564 8.54883C11.8679 7.6256 12.8513 7.00009 13.9814 7ZM6 8C4.89551 8.00007 4.00003 8.8955 4 10C4 11.1045 4.89549 11.9999 6 12C7.0357 12 7.88804 11.2128 7.99023 10.2041L8 10H7.98145C7.98145 9.93633 7.98419 9.87275 7.99023 9.80957C7.89427 8.79439 7.04029 8 6 8ZM13.9814 8C12.877 8.00013 11.9815 8.89554 11.9814 10C11.9814 11.1045 12.877 11.9999 13.9814 12C15.086 12 15.9814 11.1046 15.9814 10C15.9814 8.89546 15.086 8 13.9814 8Z"
|
||||
@ -1434,7 +1512,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
infinity: (
|
||||
<svg viewBox="0 0 13 6" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 13 6"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="infinity"
|
||||
>
|
||||
<path
|
||||
d="M10 0C11.6567 0.000169571 12.9999 1.34331 13 3C13 4.65671 11.6567 5.99983 10 6C9.08871 6 8.27123 5.59359 7.72168 4.95312V4.95215L6.58398 3.64941L5.43262 4.95703L5.43164 4.95605C4.88213 5.59421 4.06758 6 3.1582 6C1.50144 5.99992 0.15825 4.65677 0.158203 3C0.158279 1.34326 1.50146 7.54041e-05 3.1582 0C4.06727 0 4.88213 0.405203 5.43164 1.04297H5.43262L6.58496 2.34961L7.72461 1.04492C8.27414 0.406002 9.08999 0 10 0ZM3.1582 0.857422C1.97485 0.857497 1.0157 1.81664 1.01562 3C1.01567 4.18338 1.97483 5.1425 3.1582 5.14258C3.80891 5.14258 4.3915 4.85326 4.78516 4.39453L4.78906 4.38965L6.01562 3L4.78906 1.61035L4.78516 1.60547C4.3915 1.1468 3.80885 0.857422 3.1582 0.857422ZM10 0.857422C9.34921 0.857422 8.76573 1.14664 8.37207 1.60547L8.37012 1.6084L7.15527 3L8.37012 4.3916L8.37305 4.39453H8.37207C8.76573 4.85333 9.34924 5.14258 10 5.14258C11.1833 5.14241 12.1425 4.18332 12.1426 3C12.1425 1.8167 11.1833 0.857591 10 0.857422Z"
|
||||
fill="currentColor"
|
||||
@ -1442,7 +1525,12 @@ const CustomIconMap = {
|
||||
</svg>
|
||||
),
|
||||
star: (
|
||||
<svg viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
viewBox="0 0 14 15"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-label="star"
|
||||
>
|
||||
<path
|
||||
d="M8.93445 5.33667H13.6571L13.951 6.24097L10.1298 9.01636L11.5897 13.5085L10.8202 14.0671L6.99988 11.2908L3.17957 14.0671L2.41003 13.5085L3.86902 9.01636L0.0487061 6.24097L0.342651 5.33667H5.06531L6.52429 0.845459H7.47546L8.93445 5.33667ZM5.90417 5.99097L5.42859 6.33667H1.88074L4.75085 8.42163L4.9325 8.98022L3.83582 12.3533L6.70593 10.2693H7.29382L10.163 12.3533L9.06726 8.98022L9.2489 8.42163L12.119 6.33667H8.57117L8.09558 5.99097L6.99988 2.61792L5.90417 5.99097Z"
|
||||
fill="currentColor"
|
||||
|
@ -485,7 +485,11 @@ export const ModelingMachineProvider = ({
|
||||
input.extrudePathToNode,
|
||||
input.faceInfo
|
||||
)
|
||||
: sketchOnOffsetPlane(kclManager.ast, input.pathToNode)
|
||||
: sketchOnOffsetPlane(
|
||||
kclManager.ast,
|
||||
input.pathToNode,
|
||||
input.negated
|
||||
)
|
||||
if (err(sketched)) {
|
||||
const sketchedError = new Error(
|
||||
'Incompatible face, please try another'
|
||||
|
@ -222,7 +222,11 @@ const VisibilityToggle = (props: VisibilityToggleProps) => {
|
||||
}, [props.onVisibilityChange])
|
||||
|
||||
return (
|
||||
<button onClick={handleToggleVisible} className="p-0 m-0">
|
||||
<button
|
||||
onClick={handleToggleVisible}
|
||||
className="p-0 m-0"
|
||||
data-testid="feature-tree-visibility-toggle"
|
||||
>
|
||||
<CustomIcon
|
||||
name={visible ? 'eyeOpen' : 'eyeCrossedOut'}
|
||||
className="w-5 h-5"
|
||||
@ -265,6 +269,7 @@ const OperationItemWrapper = ({
|
||||
<div
|
||||
ref={menuRef}
|
||||
className={`flex select-none items-center group/item my-0 py-0.5 px-1 ${selectable ? 'focus-within:bg-primary/10 hover:bg-primary/5' : ''}`}
|
||||
data-testid="feature-tree-operation-item"
|
||||
>
|
||||
<button
|
||||
{...props}
|
||||
|
@ -164,20 +164,49 @@ export function useEngineConnectionSubscriptions() {
|
||||
if (artifact?.type === 'plane') {
|
||||
const planeInfo =
|
||||
await sceneEntitiesManager.getFaceDetails(planeOrFaceId)
|
||||
|
||||
// Apply camera-based orientation logic similar to default planes
|
||||
let zAxis: [number, number, number] = [
|
||||
planeInfo.z_axis.x,
|
||||
planeInfo.z_axis.y,
|
||||
planeInfo.z_axis.z,
|
||||
]
|
||||
let yAxis: [number, number, number] = [
|
||||
planeInfo.y_axis.x,
|
||||
planeInfo.y_axis.y,
|
||||
planeInfo.y_axis.z,
|
||||
]
|
||||
|
||||
// Get camera vector to determine which side of the plane we're viewing from
|
||||
const camVector = sceneInfra.camControls.camera.position
|
||||
.clone()
|
||||
.sub(sceneInfra.camControls.target)
|
||||
|
||||
// Determine the canonical (absolute) plane orientation
|
||||
const absZAxis: [number, number, number] = [
|
||||
Math.abs(zAxis[0]),
|
||||
Math.abs(zAxis[1]),
|
||||
Math.abs(zAxis[2]),
|
||||
]
|
||||
|
||||
// Find the dominant axis (like default planes do)
|
||||
const maxComponent = Math.max(...absZAxis)
|
||||
const dominantAxisIndex = absZAxis.indexOf(maxComponent)
|
||||
|
||||
// Check camera position against canonical orientation (like default planes)
|
||||
const cameraComponents = [camVector.x, camVector.y, camVector.z]
|
||||
let negated = cameraComponents[dominantAxisIndex] < 0
|
||||
if (dominantAxisIndex === 1) {
|
||||
// offset of the XZ is being weird, not sure if this is a camera bug
|
||||
negated = !negated
|
||||
}
|
||||
|
||||
sceneInfra.modelingSend({
|
||||
type: 'Select sketch plane',
|
||||
data: {
|
||||
type: 'offsetPlane',
|
||||
zAxis: [
|
||||
planeInfo.z_axis.x,
|
||||
planeInfo.z_axis.y,
|
||||
planeInfo.z_axis.z,
|
||||
],
|
||||
yAxis: [
|
||||
planeInfo.y_axis.x,
|
||||
planeInfo.y_axis.y,
|
||||
planeInfo.y_axis.z,
|
||||
],
|
||||
zAxis,
|
||||
yAxis,
|
||||
position: [
|
||||
planeInfo.origin.x,
|
||||
planeInfo.origin.y,
|
||||
@ -189,6 +218,7 @@ export function useEngineConnectionSubscriptions() {
|
||||
],
|
||||
planeId: planeOrFaceId,
|
||||
pathToNode: artifact.codeRef.pathToNode,
|
||||
negated,
|
||||
},
|
||||
})
|
||||
return
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
createLiteral,
|
||||
createLocalName,
|
||||
createPipeExpression,
|
||||
createUnaryExpression,
|
||||
createVariableDeclaration,
|
||||
findUniqueName,
|
||||
} from '@src/lang/create'
|
||||
@ -713,7 +714,8 @@ export function insertNamedConstant({
|
||||
*/
|
||||
export function sketchOnOffsetPlane(
|
||||
node: Node<Program>,
|
||||
offsetPathToNode: PathToNode
|
||||
offsetPathToNode: PathToNode,
|
||||
negated: boolean = false
|
||||
) {
|
||||
let _node = { ...node }
|
||||
|
||||
@ -728,6 +730,11 @@ export function sketchOnOffsetPlane(
|
||||
const { node: offsetPlaneNode } = offsetPlaneDeclarator
|
||||
const offsetPlaneName = offsetPlaneNode.id.name
|
||||
|
||||
// Create the plane argument - either the plane name or negated plane name
|
||||
const planeArgument = negated
|
||||
? createUnaryExpression(createLocalName(offsetPlaneName), '-')
|
||||
: createLocalName(offsetPlaneName)
|
||||
|
||||
// Create a new sketch declaration
|
||||
const newSketchName = findUniqueName(
|
||||
node,
|
||||
@ -735,11 +742,7 @@ export function sketchOnOffsetPlane(
|
||||
)
|
||||
const newSketch = createVariableDeclaration(
|
||||
newSketchName,
|
||||
createCallExpressionStdLibKw(
|
||||
'startSketchOn',
|
||||
createLocalName(offsetPlaneName),
|
||||
[]
|
||||
),
|
||||
createCallExpressionStdLibKw('startSketchOn', planeArgument, []),
|
||||
undefined,
|
||||
'const'
|
||||
)
|
||||
|
@ -280,6 +280,7 @@ export type OffsetPlane = {
|
||||
pathToNode: PathToNode
|
||||
zAxis: [number, number, number]
|
||||
yAxis: [number, number, number]
|
||||
negated: boolean
|
||||
}
|
||||
|
||||
export type SegmentOverlayPayload =
|
||||
|
Reference in New Issue
Block a user