Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Point-and-Click Deletion for Fillets and Chamfers #5098

Merged
merged 79 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
eac331f
ast mod
max-mrgrsk Jan 17, 2025
586c90b
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 17, 2025
ca80b71
point and click test
max-mrgrsk Jan 17, 2025
b0a4f61
tsc
max-mrgrsk Jan 17, 2025
8e47438
test test
max-mrgrsk Jan 17, 2025
8ee40fb
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 17, 2025
e35ca12
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 19, 2025
de7edf0
unit test edit
max-mrgrsk Jan 19, 2025
817e571
Merge branch 'max-click-delete-chamfers' of https://github.com/KittyC…
max-mrgrsk Jan 19, 2025
c3896cb
topLevelRange
max-mrgrsk Jan 19, 2025
b521c70
disable unit test
max-mrgrsk Jan 19, 2025
b3ccd00
remove bad imports
max-mrgrsk Jan 19, 2025
beb8e7c
fix typo
max-mrgrsk Jan 19, 2025
8de23c3
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 20, 2025
25aa006
Fix cyclic dependency hell with getNodePathFromSourceRange
lf94 Jan 21, 2025
648fdd8
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 21, 2025
68faf2a
tsc
max-mrgrsk Jan 21, 2025
64e7870
fix ImportStatement
max-mrgrsk Jan 21, 2025
e93e9d5
fix isValueZero
max-mrgrsk Jan 21, 2025
bd4ef9a
pre-emptively ==> preemptively
max-mrgrsk Jan 21, 2025
852e849
yarn fmt-check
max-mrgrsk Jan 21, 2025
787c05a
reenable the unit test
max-mrgrsk Jan 22, 2025
f7b1660
fmt
max-mrgrsk Jan 22, 2025
e40b464
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 22, 2025
4c3074a
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 22, 2025
285fa79
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 22, 2025
0c0b0ef
Trigger CI
max-mrgrsk Jan 22, 2025
357002a
Merge branch 'max-click-delete-chamfers' of https://github.com/KittyC…
max-mrgrsk Jan 22, 2025
9a78397
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 22, 2025
bf1abef
Trigger CI
max-mrgrsk Jan 22, 2025
f1e6029
Merge branch 'max-click-delete-chamfers' of https://github.com/KittyC…
max-mrgrsk Jan 22, 2025
ee6b245
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 23, 2025
42a505b
add test
max-mrgrsk Jan 23, 2025
21cc7f4
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 23, 2025
92c4962
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 23, 2025
34970e9
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 24, 2025
216203f
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 24, 2025
892b8ab
Trigger CI
max-mrgrsk Jan 24, 2025
e5e4052
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 24, 2025
badf724
Trigger CI
max-mrgrsk Jan 24, 2025
3ca9add
several treatments
max-mrgrsk Jan 25, 2025
145aea3
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 25, 2025
159b3a8
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 28, 2025
36c3b6e
consolidate
max-mrgrsk Jan 28, 2025
9432020
typos
max-mrgrsk Jan 28, 2025
2e06458
fix imports, consolidate
max-mrgrsk Jan 28, 2025
186b3f9
consolidate import
max-mrgrsk Jan 28, 2025
ec2f1cd
fix imports
max-mrgrsk Jan 28, 2025
9716b83
add tests
max-mrgrsk Jan 28, 2025
a322313
stress test CI
max-mrgrsk Jan 28, 2025
45f08df
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 28, 2025
6db036d
fix test
max-mrgrsk Jan 28, 2025
dbac228
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 28, 2025
d32fc90
Trigger CI
max-mrgrsk Jan 28, 2025
1f0e478
Merge branch 'max-click-delete-chamfers' of https://github.com/KittyC…
max-mrgrsk Jan 28, 2025
850d14a
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 28, 2025
a410b36
Trigger CI
max-mrgrsk Jan 28, 2025
16b7dd0
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 29, 2025
e17aca9
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 29, 2025
0ce767f
Trigger CI
max-mrgrsk Jan 29, 2025
1f84ffe
Merge branch 'max-click-delete-chamfers' of https://github.com/KittyC…
max-mrgrsk Jan 29, 2025
eadb48a
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 29, 2025
a884afa
Trigger CI
max-mrgrsk Jan 29, 2025
8935f9a
fix tests
max-mrgrsk Jan 30, 2025
dd28111
clean test for fillets
max-mrgrsk Jan 30, 2025
7abbe48
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 30, 2025
ded6c1a
Trigger CI
max-mrgrsk Jan 30, 2025
d614ab2
Merge branch 'max-click-delete-chamfers' of https://github.com/KittyC…
max-mrgrsk Jan 30, 2025
fe6388f
A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubunt…
github-actions[bot] Jan 30, 2025
8d606cc
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Jan 31, 2025
3f67d8b
test chamfers
max-mrgrsk Feb 2, 2025
b3229c7
comments
max-mrgrsk Feb 2, 2025
d168c4e
simplify main tests
max-mrgrsk Feb 2, 2025
ef06863
Merge branch 'max-click-delete-chamfers' of https://github.com/KittyC…
max-mrgrsk Feb 2, 2025
878f3ed
Merge branch 'main' into max-click-delete-chamfers
max-mrgrsk Feb 2, 2025
84ba859
typo
max-mrgrsk Feb 2, 2025
db0085d
typo2
max-mrgrsk Feb 2, 2025
0889d9b
remove import
max-mrgrsk Feb 2, 2025
112a170
clean up comments
max-mrgrsk Feb 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
318 changes: 318 additions & 0 deletions e2e/playwright/point-click.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,167 @@ extrude001 = extrude(-12, sketch001)
lowTolerance
)
})

// Test 3: Delete fillets
await test.step('Delete fillet via feature tree selection', async () => {
await test.step('Open Feature Tree Pane', async () => {
await toolbar.openPane('feature-tree')
await page.waitForTimeout(500)
})
await test.step('Delete fillet via feature tree selection', async () => {
await editor.expectEditor.toContain(secondFilletDeclaration)
const operationButton = await toolbar.getFeatureTreeOperation('Fillet', 1)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await page.waitForTimeout(500)
await scene.expectPixelColor(edgeColorWhite, secondEdgeLocation, 15) // deleted
await editor.expectEditor.not.toContain(secondFilletDeclaration)
await scene.expectPixelColor(filletColor, firstEdgeLocation, 15) // stayed
})
})
})

test(`Fillet point-and-click delete`, async ({
context,
page,
homePage,
scene,
editor,
toolbar,
}) => {
// Code samples
const initialCode = `sketch001 = startSketchOn('XY')
|> startProfileAt([-12, -6], %)
|> line([0, 12], %)
|> line([24, 0], %, $seg02)
|> line([0, -12], %)
|> lineTo([profileStartX(%), profileStartY(%)], %, $seg01)
|> close(%)
extrude001 = extrude(-12, sketch001)
|> fillet({ radius = 5, tags = [seg01] }, %) // fillet01
|> fillet({ radius = 5, tags = [seg02] }, %) // fillet02
fillet03 = fillet({ radius = 5, tags = [getOppositeEdge(seg01)]}, extrude001)
fillet04 = fillet({ radius = 5, tags = [getOppositeEdge(seg02)]}, extrude001)
`
const pipedFilletDeclaration = 'fillet({ radius = 5, tags = [seg01] }, %)'
const secondPipedFilletDeclaration =
'fillet({ radius = 5, tags = [seg02] }, %)'
const standaloneFilletDeclaration =
'fillet03 = fillet({ radius = 5, tags = [getOppositeEdge(seg01)]}, extrude001)'
const secondStandaloneFilletDeclaration =
'fillet04 = fillet({ radius = 5, tags = [getOppositeEdge(seg02)]}, extrude001)'

// Locators
const pipedFilletEdgeLocation = { x: 600, y: 193 }
const standaloneFilletEdgeLocation = { x: 600, y: 383 }
const bodyLocation = { x: 630, y: 290 }

// Colors
const edgeColorWhite: [number, number, number] = [248, 248, 248]
const bodyColor: [number, number, number] = [155, 155, 155]
const filletColor: [number, number, number] = [127, 127, 127]
const backgroundColor: [number, number, number] = [30, 30, 30]
const lowTolerance = 20
const highTolerance = 40

// Setup
await test.step(`Initial test setup`, async () => {
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()

// verify modeling scene is loaded
await scene.expectPixelColor(
backgroundColor,
standaloneFilletEdgeLocation,
lowTolerance
)

// wait for stream to load
await scene.expectPixelColor(bodyColor, bodyLocation, highTolerance)
})

// Test
await test.step('Delete fillet via feature tree selection', async () => {
await test.step('Open Feature Tree Pane', async () => {
await toolbar.openPane('feature-tree')
await page.waitForTimeout(500)
})

await test.step('Delete piped fillet via feature tree selection', async () => {
await test.step('Verify all fillets are present in the editor', async () => {
await editor.expectEditor.toContain(pipedFilletDeclaration)
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
await editor.expectEditor.toContain(standaloneFilletDeclaration)
await editor.expectEditor.toContain(secondStandaloneFilletDeclaration)
})
await test.step('Verify test fillets are present in the scene', async () => {
await scene.expectPixelColor(
filletColor,
pipedFilletEdgeLocation,
lowTolerance
)
await scene.expectPixelColor(
backgroundColor,
standaloneFilletEdgeLocation,
lowTolerance
)
})
await test.step('Delete piped fillet', async () => {
const operationButton = await toolbar.getFeatureTreeOperation(
'Fillet',
0
)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await page.waitForTimeout(500)
})
await test.step('Verify piped fillet is deleted but other fillets are not (in the editor)', async () => {
await editor.expectEditor.not.toContain(pipedFilletDeclaration)
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
await editor.expectEditor.toContain(standaloneFilletDeclaration)
await editor.expectEditor.toContain(secondStandaloneFilletDeclaration)
})
await test.step('Verify piped fillet is deleted but non-piped is not (in the scene)', async () => {
await scene.expectPixelColor(
edgeColorWhite, // you see edge because fillet is deleted
pipedFilletEdgeLocation,
lowTolerance
)
await scene.expectPixelColor(
backgroundColor, // you see background because fillet is not deleted
standaloneFilletEdgeLocation,
lowTolerance
)
})
})

await test.step('Delete non-piped fillet via feature tree selection', async () => {
await test.step('Delete non-piped fillet', async () => {
const operationButton = await toolbar.getFeatureTreeOperation(
'Fillet',
1
)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await page.waitForTimeout(500)
})
await test.step('Verify non-piped fillet is deleted but other two fillets are not (in the editor)', async () => {
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
await editor.expectEditor.not.toContain(standaloneFilletDeclaration)
await editor.expectEditor.toContain(secondStandaloneFilletDeclaration)
})
await test.step('Verify non-piped fillet is deleted but piped is not (in the scene)', async () => {
await scene.expectPixelColor(
edgeColorWhite,
standaloneFilletEdgeLocation,
lowTolerance
)
})
})
})
})

test(`Chamfer point-and-click`, async ({
Expand Down Expand Up @@ -1511,6 +1672,163 @@ extrude001 = extrude(-12, sketch001)
lowTolerance
)
})

// Test 3: Delete chamfer via feature tree selection
await test.step('Open Feature Tree Pane', async () => {
await toolbar.openPane('feature-tree')
await page.waitForTimeout(500)
})
await test.step('Delete chamfer via feature tree selection', async () => {
const operationButton = await toolbar.getFeatureTreeOperation('Chamfer', 1)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await page.waitForTimeout(500)
await scene.expectPixelColor(edgeColorWhite, secondEdgeLocation, 15) // deleted
await scene.expectPixelColor(chamferColor, firstEdgeLocation, 15) // stayed
})
})

test(`Chamfer point-and-click delete`, async ({
context,
page,
homePage,
scene,
editor,
toolbar,
}) => {
// Code samples
const initialCode = `sketch001 = startSketchOn('XY')
|> startProfileAt([-12, -6], %)
|> line([0, 12], %)
|> line([24, 0], %, $seg02)
|> line([0, -12], %)
|> lineTo([profileStartX(%), profileStartY(%)], %, $seg01)
|> close(%)
extrude001 = extrude(-12, sketch001)
|> chamfer({ length = 5, tags = [seg01] }, %) // chamfer01
|> chamfer({ length = 5, tags = [seg02] }, %) // chamfer02
chamfer03 = chamfer({ length = 5, tags = [getOppositeEdge(seg01)]}, extrude001)
chamfer04 = chamfer({ length = 5, tags = [getOppositeEdge(seg02)]}, extrude001)
`
const pipedChamferDeclaration = 'chamfer({ length = 5, tags = [seg01] }, %)'
const secondPipedChamferDeclaration =
'chamfer({ length = 5, tags = [seg02] }, %)'
const standaloneChamferDeclaration =
'chamfer03 = chamfer({ length = 5, tags = [getOppositeEdge(seg01)]}, extrude001)'
const secondStandaloneChamferDeclaration =
'chamfer04 = chamfer({ length = 5, tags = [getOppositeEdge(seg02)]}, extrude001)'

// Locators
const pipedChamferEdgeLocation = { x: 600, y: 193 }
const standaloneChamferEdgeLocation = { x: 600, y: 383 }
const bodyLocation = { x: 630, y: 290 }

// Colors
const edgeColorWhite: [number, number, number] = [248, 248, 248]
const bodyColor: [number, number, number] = [155, 155, 155]
const chamferColor: [number, number, number] = [168, 168, 168]
const backgroundColor: [number, number, number] = [30, 30, 30]
const lowTolerance = 20
const highTolerance = 40

// Setup
await test.step(`Initial test setup`, async () => {
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()

// verify modeling scene is loaded
await scene.expectPixelColor(
backgroundColor,
standaloneChamferEdgeLocation,
lowTolerance
)

// wait for stream to load
await scene.expectPixelColor(bodyColor, bodyLocation, highTolerance)
})

// Test
await test.step('Delete chamfer via feature tree selection', async () => {
await test.step('Open Feature Tree Pane', async () => {
await toolbar.openPane('feature-tree')
await page.waitForTimeout(500)
})

await test.step('Delete piped chamfer via feature tree selection', async () => {
await test.step('Verify all chamfers are present in the editor', async () => {
await editor.expectEditor.toContain(pipedChamferDeclaration)
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
await editor.expectEditor.toContain(standaloneChamferDeclaration)
await editor.expectEditor.toContain(secondStandaloneChamferDeclaration)
})
await test.step('Verify test chamfers are present in the scene', async () => {
await scene.expectPixelColor(
chamferColor,
pipedChamferEdgeLocation,
lowTolerance
)
await scene.expectPixelColor(
backgroundColor,
standaloneChamferEdgeLocation,
lowTolerance
)
})
await test.step('Delete piped chamfer', async () => {
const operationButton = await toolbar.getFeatureTreeOperation(
'Chamfer',
0
)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await page.waitForTimeout(500)
})
await test.step('Verify piped chamfer is deleted but other chamfers are not (in the editor)', async () => {
await editor.expectEditor.not.toContain(pipedChamferDeclaration)
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
await editor.expectEditor.toContain(standaloneChamferDeclaration)
await editor.expectEditor.toContain(secondStandaloneChamferDeclaration)
})
await test.step('Verify piped chamfer is deleted but non-piped is not (in the scene)', async () => {
await scene.expectPixelColor(
edgeColorWhite, // you see edge color because chamfer is deleted
pipedChamferEdgeLocation,
lowTolerance
)
await scene.expectPixelColor(
backgroundColor, // you see background color instead of edge because it's chamfered
standaloneChamferEdgeLocation,
lowTolerance
)
})
})

await test.step('Delete non-piped chamfer via feature tree selection', async () => {
await test.step('Delete non-piped chamfer', async () => {
const operationButton = await toolbar.getFeatureTreeOperation(
'Chamfer',
1
)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await page.waitForTimeout(500)
})
await test.step('Verify non-piped chamfer is deleted but other two chamfers are not (in the editor)', async () => {
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
await editor.expectEditor.not.toContain(standaloneChamferDeclaration)
await editor.expectEditor.toContain(secondStandaloneChamferDeclaration)
})
await test.step('Verify non-piped chamfer is deleted but piped is not (in the scene)', async () => {
await scene.expectPixelColor(
edgeColorWhite,
standaloneChamferEdgeLocation,
lowTolerance
)
})
})
})
})

const shellPointAndClickCapCases = [
Expand Down
3 changes: 3 additions & 0 deletions src/lang/modifyAst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { Models } from '@kittycad/lib'
import { ExtrudeFacePlane } from 'machines/modelingMachine'
import { Node } from 'wasm-lib/kcl/bindings/Node'
import { KclExpressionWithVariable } from 'lib/commandTypes'
import { deleteEdgeTreatment } from './modifyAst/addEdgeTreatment'

export function startSketchOnDefault(
node: Node<Program>,
Expand Down Expand Up @@ -1371,6 +1372,8 @@ export async function deleteFromSelection(
}
// await prom
return astClone
} else if (selection.artifact?.type === 'edgeCut') {
return deleteEdgeTreatment(astClone, selection)
} else if (varDec.node.init.type === 'PipeExpression') {
const pipeBody = varDec.node.init.body
if (
Expand Down
Loading
Loading