Fix sketchOnFace point&click for booleans (#6713)

* fix bool sketchOnFace

* fix chamfer test

* add test

* Kurt composite attempt (#6722)

* composite attempt

* Add forward edge to CSG artifacts in artifact graph

* Fix comment

* Move the doc comments above the attributes

* Fix to update the correct field of Path

* Update output

---------

Co-authored-by: Jonathan Tran <jonnytran@gmail.com>

* use rust defined composite solid edges instead

* Update src/hooks/useEngineConnectionSubscriptions.ts

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

* Revert PNG screenshots

* Fix TS formatting

---------

Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
This commit is contained in:
Kurt Hutten
2025-05-07 08:25:12 +10:00
committed by GitHub
parent 996517f5c4
commit d187a29e55
17 changed files with 256 additions and 73 deletions

View File

@ -241,6 +241,12 @@ export class ToolbarFixture {
async openFeatureTreePane() {
return this.openPane(this.featureTreeId)
}
async waitForFeatureTreeToBeBuilt() {
await this.openFeatureTreePane()
await expect(this.page.getByText('Building feature tree')).not.toBeVisible()
await this.closeFeatureTreePane()
}
async closeFeatureTreePane() {
await this.closePane(this.featureTreeId)
}

View File

@ -244,6 +244,7 @@ test.describe('Point-and-click tests', () => {
await scene.moveCameraTo(cameraPos, cameraTarget)
await test.step('check chamfer selection changes cursor position', async () => {
await toolbar.waitForFeatureTreeToBeBuilt()
await expect(async () => {
// sometimes initial click doesn't register
await clickChamfer()
@ -283,6 +284,7 @@ test.describe('Point-and-click tests', () => {
highlightedCode: '',
diagnostics: [],
})
await toolbar.waitForFeatureTreeToBeBuilt()
})
}
test('works on all edge selections and can break up multi edges in a chamfer array', async ({
@ -402,6 +404,7 @@ test.describe('Point-and-click tests', () => {
await test.step('verify at the end of the test that final code is what is expected', async () => {
await editor.expectEditor.toContain(
`@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ)
|> startProfile(at = [75.8, 317.2]) // [$startCapTag, $EndCapTag]
|> angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)
@ -414,18 +417,11 @@ extrude001 = extrude(sketch001, length = 100)
|> chamfer(length = 30, tags = [seg01], tag = $seg04)
|> chamfer(length = 30, tags = [getNextAdjacentEdge(seg02)], tag = $seg05)
|> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)], tag = $seg06)
sketch005 = startSketchOn(extrude001, face = seg06)
profile004=startProfile(sketch005, at = [-23.43,19.69])
|> angledLine(angle = 0, length = 9.1, tag = $rectangleSegmentA005)
|> angledLine(angle = segAng(rectangleSegmentA005) - 90, length = 84.07)
|> angledLine(angle = segAng(rectangleSegmentA005), length = -segLen(rectangleSegmentA005))
|> line(endAbsolute=[profileStartX(%), profileStartY(%)])
|> close()
sketch004 = startSketchOn(extrude001, face = seg05)
profile003 = startProfile(sketch004, at = [82.57, 322.96])
|> angledLine(angle = 0, length = 11.16, tag = $rectangleSegmentA004)
|> angledLine(angle = segAng(rectangleSegmentA004) - 90, length = 103.07)
|> angledLine(angle = segAng(rectangleSegmentA004), length = -segLen(rectangleSegmentA004))
sketch002 = startSketchOn(extrude001, face = seg03)
profile001 = startProfile(sketch002, at = [205.96, 254.59])
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26)
|> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
sketch003 = startSketchOn(extrude001, face = seg04)
@ -435,11 +431,18 @@ profile002 = startProfile(sketch003, at = [-209.64, 255.28])
|> angledLine(angle = segAng(rectangleSegmentA003), length = -segLen(rectangleSegmentA003))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
sketch002 = startSketchOn(extrude001, face = seg03)
profile001 = startProfile(sketch002, at = [205.96, 254.59])
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26)
|> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002))
sketch004 = startSketchOn(extrude001, face = seg05)
profile003 = startProfile(sketch004, at = [82.57, 322.96])
|> angledLine(angle = 0, length = 11.16, tag = $rectangleSegmentA004)
|> angledLine(angle = segAng(rectangleSegmentA004) - 90, length = 103.07)
|> angledLine(angle = segAng(rectangleSegmentA004), length = -segLen(rectangleSegmentA004))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
sketch005 = startSketchOn(extrude001, face = seg06)
profile004 = startProfile(sketch005, at = [-23.43, 19.69])
|> angledLine(angle = 0, length = 9.1, tag = $rectangleSegmentA005)
|> angledLine(angle = segAng(rectangleSegmentA005) - 90, length = 84.07)
|> angledLine(angle = segAng(rectangleSegmentA005), length = -segLen(rectangleSegmentA005))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
`,

View File

@ -1260,6 +1260,97 @@ profile001 = startProfile(sketch001, at = [299.72, 230.82])
}).toPass({ timeout: 40_000, intervals: [1_000] })
})
test('sketch on face of a boolean works', async ({
page,
homePage,
scene,
cmdBar,
toolbar,
editor,
}) => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`@settings(defaultLengthUnit = mm)
myVar = 50
sketch001 = startSketchOn(XZ)
profile001 = circle(sketch001, center = [myVar, 43.9], radius = 41.05)
extrude001 = extrude(profile001, length = 200)
|> translate(x = 3.14, y = 3.14, z = -50.154)
sketch002 = startSketchOn(XY)
profile002 = startProfile(sketch002, at = [72.2, -52.05])
|> angledLine(angle = 0, length = 181.26, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 21.54)
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $mySeg)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg01)
|> close()
extrude002 = extrude(profile002, length = 151)
|> chamfer(
%,
length = 15,
tags = [mySeg],
tag = $seg02,
)
solid001 = subtract([extrude001], tools = [extrude002])
`
)
})
const [selectChamferFaceClk] = scene.makeMouseHelpers(671, 283)
const [circleCenterClk] = scene.makeMouseHelpers(700, 272)
const [circleRadiusClk] = scene.makeMouseHelpers(694, 264)
await test.step('Setup', async () => {
await homePage.goToModelingScene()
await scene.settled(cmdBar)
await scene.moveCameraTo(
{ x: 180, y: -75, z: 116 },
{ x: 67, y: -114, z: -15 }
)
})
await test.step('sketch on chamfer face that is part of a boolean', async () => {
await toolbar.startSketchPlaneSelection()
await selectChamferFaceClk()
await expect
.poll(async () => {
const lineBtn = page.getByRole('button', { name: 'line Line' })
return lineBtn.getAttribute('aria-pressed')
})
.toBe('true')
await editor.expectEditor.toContain(
'startSketchOn(solid001, face = seg02)'
)
})
await test.step('verify sketching still works', async () => {
await toolbar.circleBtn.click()
await expect
.poll(async () => {
const circleBtn = page.getByRole('button', { name: 'circle Circle' })
return circleBtn.getAttribute('aria-pressed')
})
.toBe('true')
await circleCenterClk()
await editor.expectEditor.toContain(
'profile003 = circle(sketch003, center'
)
await circleRadiusClk()
await editor.expectEditor.toContain(
'profile003 = circle(sketch003, center = [119.41, -56.05], radius = 1.82)'
)
})
})
test('Can sketch on face when user defined function was used in the sketch', async ({
page,
homePage,