profile start constrain overlays (#6795)

* constrain profile start

* add test

* make sure it works on segment drag too, fix tests

* remove old log

* some tests fixes

* Bump more segment counters

* Two more fixes

* Two more test fixes

* small test fix

* moretest fixes

* another test

---------

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Pierre Jacquier <pierre@zoo.dev>
This commit is contained in:
Kurt Hutten
2025-05-10 12:29:41 +10:00
committed by GitHub
parent 85469f2d7d
commit 39f512d32d
15 changed files with 497 additions and 145 deletions

View File

@ -138,7 +138,9 @@ extrude001 = extrude(sketch001, length = 5)`
// Ensure badge is present
const codePaneButtonHolder = page.locator('#code-button-holder')
await expect(codePaneButtonHolder).toContainText('notification')
await expect(codePaneButtonHolder).toContainText('notification', {
timeout: 20_000,
})
// Ensure we have no errors in the gutter, since error out of view.
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()

View File

@ -1180,6 +1180,8 @@ sketch001 = startSketchOn(XZ)
page,
homePage,
editor,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
@ -1198,9 +1200,7 @@ sketch001 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
await scene.settled(cmdBar)
await page.waitForTimeout(100)
await u.openAndClearDebugPanel()
@ -1236,7 +1236,7 @@ sketch001 = startSketchOn(XZ)
await page.waitForTimeout(400)
let prevContent = await page.locator('.cm-content').innerText()
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
await expect(page.getByTestId('segment-overlay')).toHaveCount(3)
// drag startProfileAt handle
await page.dragAndDrop('#stream', '#stream', {
@ -1278,9 +1278,9 @@ sketch001 = startSketchOn(XZ)
// expect the code to have changed
await editor.expectEditor.toContain(
`sketch001 = startSketchOn(XZ)
|> startProfile(at = [2.71, -2.71])
|> line(end = [15.4, -2.78])
|> tangentialArc(endAbsolute = [27.6, -3.05])
|> startProfile(at = [5.36, -5.36])
|> line(end = [12.73, -0.09])
|> tangentialArc(endAbsolute = [24.95, -0.38])
|> close()
|> extrude(length = 5)`,
{ shouldNormalise: true }
@ -1294,7 +1294,7 @@ sketch001 = startSketchOn(XZ)
await editor.expectEditor.toContain(
`sketch001 = startSketchOn(XZ)
|> startProfile(at = [2.71, -2.71])
|> line(end = [15.4, -2.78])
|> line(end = [12.73, -0.09])
|> tangentialArc(endAbsolute = [24.95, -0.38])
|> close()
|> extrude(length = 5)`,
@ -1308,7 +1308,7 @@ sketch001 = startSketchOn(XZ)
await editor.expectEditor.toContain(
`sketch001 = startSketchOn(XZ)
|> startProfile(at = [2.71, -2.71])
|> startProfile(at = [4.61, -10.01])
|> line(end = [12.73, -0.09])
|> tangentialArc(endAbsolute = [24.95, -0.38])
|> close()
@ -1505,7 +1505,7 @@ sketch001 = startSketchOn(XZ)
await page.waitForTimeout(1000)
// Verify segment is selected (you can check for visual indicators or state)
const element = page.locator('[data-overlay-index="1"]')
const element = page.locator('[data-overlay-index="2"]')
await expect(element).toHaveAttribute('data-overlay-visible', 'true')
})

View File

@ -543,6 +543,9 @@ sketch001 = startSketchOn(XZ)
page,
homePage,
editor,
toolbar,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
@ -559,10 +562,12 @@ sketch001 = startSketchOn(XZ)
})
await homePage.goToModelingScene()
await toolbar.waitForFeatureTreeToBeBuilt()
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
).not.toBeDisabled({ timeout: 10_000 })
await page.waitForTimeout(100)
await u.openAndClearDebugPanel()
@ -598,7 +603,7 @@ sketch001 = startSketchOn(XZ)
await page.waitForTimeout(400)
let prevContent = await page.locator('.cm-content').innerText()
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
await expect(page.getByTestId('segment-overlay')).toHaveCount(3)
// drag startProfileAt handle
await page.dragAndDrop('#stream', '#stream', {
@ -612,7 +617,7 @@ sketch001 = startSketchOn(XZ)
// drag line handle
await page.waitForTimeout(100)
const lineEnd = await u.getBoundingBox('[data-overlay-index="0"]')
const lineEnd = await u.getBoundingBox('[data-overlay-index="1"]')
await page.dragAndDrop('#stream', '#stream', {
sourcePosition: { x: lineEnd.x - 15, y: lineEnd.y },
targetPosition: { x: lineEnd.x, y: lineEnd.y + 15 },
@ -622,7 +627,7 @@ sketch001 = startSketchOn(XZ)
prevContent = await page.locator('.cm-content').innerText()
// drag tangentialArc handle
const tangentEnd = await u.getBoundingBox('[data-overlay-index="1"]')
const tangentEnd = await u.getBoundingBox('[data-overlay-index="0"]')
await page.dragAndDrop('#stream', '#stream', {
sourcePosition: { x: tangentEnd.x + 10, y: tangentEnd.y - 5 },
targetPosition: {
@ -638,7 +643,7 @@ sketch001 = startSketchOn(XZ)
`sketch001 = startSketchOn(XZ)
|> startProfile(at = [7.12, -12.68])
|> line(end = [12.68, -1.09])
|> tangentialArc(endAbsolute = [24.89, 0.68])
|> tangentialArc(endAbsolute = [24.95, -0.38])
|> close()
|> extrude(length = 5)`,
{ shouldNormalise: true }
@ -709,7 +714,7 @@ sketch001 = startSketchOn(XZ)
const step5 = { steps: 5 }
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
await expect(page.getByTestId('segment-overlay')).toHaveCount(3)
// drag startProfileAt handle
await page.mouse.move(startPX[0], startPX[1])
@ -744,10 +749,10 @@ sketch001 = startSketchOn(XZ)
// expect the code to have changed
await editor.expectEditor.toContain(
`sketch001 = startSketchOn(XZ)
|> startProfile(at = [6.44, -12.07])
|> line(end = [14.72, 1.97])
|> startProfile(at = [8.41, -9.97])
|> line(end = [12.73, -0.09])
|> line(end = [1.99, 2.06])
|> tangentialArc(endAbsolute = [24.95, -5.38])
|> line(end = [1.97, 2.06])
|> close()
|> revolve(axis = X)`,
{ shouldNormalise: true }

View File

@ -108,7 +108,7 @@ test.describe('Testing constraints', () => {
// Wait for overlays to populate
await page.waitForTimeout(1000)
const line3 = await u.getSegmentBodyCoords(`[data-overlay-index="${2}"]`)
const line3 = await u.getSegmentBodyCoords(`[data-overlay-index="${3}"]`)
await page.mouse.click(line3.x, line3.y)
await page.waitForTimeout(100) // this wait is needed for webkit - not sure why
@ -127,7 +127,7 @@ test.describe('Testing constraints', () => {
)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
})
test.describe('Test perpendicular distance constraint', () => {
const cases = [
@ -174,8 +174,8 @@ test.describe('Testing constraints', () => {
await page.waitForTimeout(1000)
const [line1, line3] = await Promise.all([
u.getSegmentBodyCoords(`[data-overlay-index="${0}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${2}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${1}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${3}"]`),
])
await page.mouse.click(line1.x, line1.y)
@ -223,7 +223,7 @@ test.describe('Testing constraints', () => {
)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
})
}
})
@ -289,8 +289,8 @@ test.describe('Testing constraints', () => {
await page.waitForTimeout(1000)
const [line1, line3] = await Promise.all([
u.getSegmentBodyCoords(`[data-overlay-index="${0}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${2}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${1}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${3}"]`),
])
await page.mouse.click(line1.x, line1.y)
@ -335,7 +335,7 @@ test.describe('Testing constraints', () => {
)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
})
}
})
@ -405,7 +405,7 @@ test.describe('Testing constraints', () => {
await page.waitForTimeout(1000)
const [line3] = await Promise.all([
u.getSegmentBodyCoords(`[data-overlay-index="${2}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${3}"]`),
])
if (constraint === 'Absolute X') {
@ -454,7 +454,7 @@ test.describe('Testing constraints', () => {
)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
})
}
})
@ -519,8 +519,8 @@ test.describe('Testing constraints', () => {
await page.waitForTimeout(1000)
const [line1, line3] = await Promise.all([
u.getSegmentBodyCoords(`[data-overlay-index="${0}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${2}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${1}"]`),
u.getSegmentBodyCoords(`[data-overlay-index="${3}"]`),
])
if (axisSelect) {
@ -569,7 +569,7 @@ test.describe('Testing constraints', () => {
)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
})
}
})
@ -622,7 +622,7 @@ test.describe('Testing constraints', () => {
await page.waitForTimeout(1000)
const line3 = await u.getSegmentBodyCoords(
`[data-overlay-index="${2}"]`
`[data-overlay-index="${3}"]`
)
await page.mouse.click(line3.x, line3.y)
@ -647,7 +647,7 @@ test.describe('Testing constraints', () => {
await expect(page.locator('.cm-activeLine')).toHaveText(changedCode)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
})
}
})
@ -715,7 +715,7 @@ part002 = startSketchOn(XZ)
await page.getByRole('button', { name: 'Edit Sketch' }).click()
const line3 = await u.getSegmentBodyCoords(
`[data-overlay-index="${2}"]`
`[data-overlay-index="${3}"]`
)
await page.mouse.click(line3.x, line3.y)
@ -733,16 +733,17 @@ part002 = startSketchOn(XZ)
})
}
await expect(cmdBarKclInput).toHaveText('78.33')
await cmdBarSubmitButton.click()
await page.waitForTimeout(500)
const [ang, len] = value.split(', ')
const changedCode = `|> angledLine(angle = ${ang}, length = ${len})`
await cmdBarSubmitButton.click()
await expect(page.locator('.cm-content')).toContainText(changedCode)
// checking active assures the cursor is where it should be
await expect(page.locator('.cm-activeLine')).toHaveText(changedCode)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
})
}
})
@ -799,13 +800,13 @@ part002 = startSketchOn(XZ)
await page.waitForTimeout(1000)
const line1 = await u.getSegmentBodyCoords(
`[data-overlay-index="${0}"]`
`[data-overlay-index="${1}"]`
)
const line3 = await u.getSegmentBodyCoords(
`[data-overlay-index="${2}"]`
`[data-overlay-index="${3}"]`
)
const line4 = await u.getSegmentBodyCoords(
`[data-overlay-index="${3}"]`
`[data-overlay-index="${4}"]`
)
// select two segments by holding down shift
@ -899,8 +900,8 @@ part002 = startSketchOn(XZ)
// Wait for overlays to populate
await page.waitForTimeout(1000)
const line1 = await u.getBoundingBox(`[data-overlay-index="${0}"]`)
const line3 = await u.getBoundingBox(`[data-overlay-index="${2}"]`)
const line1 = await u.getBoundingBox(`[data-overlay-index="${1}"]`)
const line3 = await u.getBoundingBox(`[data-overlay-index="${3}"]`)
// select two segments by holding down shift
await page.mouse.click(line1.x - 20, line1.y + 20)
@ -981,7 +982,7 @@ part002 = startSketchOn(XZ)
// Wait for overlays to populate
await page.waitForTimeout(1000)
const line3 = await u.getBoundingBox(`[data-overlay-index="${2}"]`)
const line3 = await u.getBoundingBox(`[data-overlay-index="${3}"]`)
// select segment and axis by holding down shift
await page.mouse.click(line3.x - 3, line3.y + 20)
@ -1044,7 +1045,7 @@ part002 = startSketchOn(XZ)
await page.waitForTimeout(100)
const lineBefore = await u.getSegmentBodyCoords(
`[data-overlay-index="1"]`,
`[data-overlay-index="2"]`,
0
)
expect(
@ -1075,15 +1076,15 @@ part002 = startSketchOn(XZ)
// If the overlay-angle is updated the THREE.js scene is in a good state
await expect(
await page.locator('[data-overlay-index="1"]')
await page.locator('[data-overlay-index="2"]')
).toHaveAttribute('data-overlay-angle', '0')
const lineAfter = await u.getSegmentBodyCoords(
`[data-overlay-index="1"]`,
`[data-overlay-index="2"]`,
0
)
const linebb = await u.getBoundingBox('[data-overlay-index="1"]')
const linebb = await u.getBoundingBox('[data-overlay-index="2"]')
await page.mouse.move(linebb.x, linebb.y, { steps: 25 })
await page.mouse.click(linebb.x, linebb.y)
@ -1097,6 +1098,7 @@ part002 = startSketchOn(XZ)
await page.waitForTimeout(200)
// await page.getByRole('button', { name: 'length', exact: true }).click()
await page.getByTestId('constraint-length').click()
await page.waitForTimeout(500)
await page.getByTestId('cmd-bar-arg-value').getByRole('textbox').fill('10')
await page
@ -1112,7 +1114,7 @@ part002 = startSketchOn(XZ)
)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
await expect(page.getByTestId('segment-overlay')).toHaveCount(3)
})
})
test.describe('Electron constraint tests', () => {

View File

@ -691,7 +691,13 @@ test.describe('Testing segment overlays', () => {
locator: '[data-overlay-toolbar-index="11"]',
})
})
test('for segment [tangentialArc]', async ({ page, editor, homePage }) => {
test('for segment [tangentialArc]', async ({
page,
editor,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -719,6 +725,7 @@ test.describe('Testing segment overlays', () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.settled(cmdBar)
// wait for execution done
await u.openDebugPanel()
@ -730,13 +737,13 @@ test.describe('Testing segment overlays', () => {
await page.getByRole('button', { name: 'Edit Sketch' }).click()
await page.waitForTimeout(500)
await expect(page.getByTestId('segment-overlay')).toHaveCount(13)
await expect(page.getByTestId('segment-overlay')).toHaveCount(14)
const clickUnconstrained = _clickUnconstrained(page, editor)
const clickConstrained = _clickConstrained(page, editor)
const tangentialArc = await u.getBoundingBox('[data-overlay-index="12"]')
let ang = await u.getAngle('[data-overlay-index="12"]')
const tangentialArc = await u.getBoundingBox('[data-overlay-index="13"]')
let ang = await u.getAngle('[data-overlay-index="13"]')
console.log('tangentialArc')
await clickConstrained({
hoverPos: { x: tangentialArc.x, y: tangentialArc.y },
@ -747,7 +754,7 @@ test.describe('Testing segment overlays', () => {
expectFinal: 'tangentialArc(endAbsolute = [xAbs001, -3.14])',
ang: ang + 180,
steps: 6,
locator: '[data-overlay-toolbar-index="12"]',
locator: '[data-overlay-toolbar-index="13"]',
})
console.log('tangentialArc2')
await clickUnconstrained({
@ -760,7 +767,7 @@ test.describe('Testing segment overlays', () => {
expectFinal: 'tangentialArc(endAbsolute = [xAbs001, -3.14])',
ang: ang + 180,
steps: 10,
locator: '[data-overlay-toolbar-index="12"]',
locator: '[data-overlay-toolbar-index="13"]',
})
})
test('for segment [arcTo]', async ({
@ -983,7 +990,7 @@ part001 = startSketchOn(XZ)
'persistCode',
`@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|>startProfile(at = [0, 0])
|> startProfile(at = [0, 0])
|> line(end = [0.5, -14 + 0])
|> angledLine(angle = 3 + 0, length = 32 + 0)
|> line(endAbsolute = [33, 11.5 + 0])
@ -1017,141 +1024,167 @@ part001 = startSketchOn(XZ)
await page.getByRole('button', { name: 'Edit Sketch' }).click()
await page.waitForTimeout(500)
await expect(page.getByTestId('segment-overlay')).toHaveCount(16)
await expect(page.getByTestId('segment-overlay')).toHaveCount(17)
const deleteSegmentSequence = _deleteSegmentSequence(page, editor)
let segmentToDelete
let ang = 0
const getOverlayByIndex = (index: number) =>
u.getBoundingBox(`[data-overlay-index="${index}"]`)
segmentToDelete = await getOverlayByIndex(14)
let ang = await u.getAngle('[data-overlay-index="14"]')
await editor.scrollToText('angleEnd')
let overlayIndex = 15
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: `arc(angleStart = 40.27, angleEnd = -38.05, radius = 9.03)`,
stdLibFnName: 'arc',
ang: ang + 180,
steps: 6,
locator: '[data-overlay-toolbar-index="14"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(13)
ang = await u.getAngle('[data-overlay-index="13"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: `arc(interiorAbsolute = [16.25, 5.12], endAbsolute = [21.61, 4.15])`,
stdLibFnName: 'arc',
ang: ang,
steps: 6,
locator: '[data-overlay-toolbar-index="13"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(12)
ang = await u.getAngle('[data-overlay-index="12"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'tangentialArc(endAbsolute = [3.14 + 13, 1.14])',
stdLibFnName: 'tangentialArc',
ang: ang + 180,
steps: 6,
locator: '[data-overlay-toolbar-index="12"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(11)
ang = await u.getAngle('[data-overlay-index="11"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: `angledLineThatIntersects(angle = 4.14, intersectTag = a, offset = 9)`,
stdLibFnName: 'angledLineThatIntersects',
ang: ang + 180,
steps: 7,
locator: '[data-overlay-toolbar-index="11"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(10)
ang = await u.getAngle('[data-overlay-index="10"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'angledLine(angle = 89, endAbsoluteY = 9.14 + 0)',
stdLibFnName: 'angledLineToY',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="10"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(9)
ang = await u.getAngle('[data-overlay-index="9"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'angledLine(angle = 3 + 0, endAbsoluteX = 26)',
stdLibFnName: 'angledLineToX',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="9"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(8)
ang = await u.getAngle('[data-overlay-index="8"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'angledLine(angle = -91, lengthY = 19 + 0)',
stdLibFnName: 'angledLineOfYLength',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="8"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(7)
ang = await u.getAngle('[data-overlay-index="7"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'angledLine(angle = 181 + 0, lengthX = 23.14)',
stdLibFnName: 'angledLineOfXLength',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="7"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(6)
ang = await u.getAngle('[data-overlay-index="6"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'yLine(length = 21.14 + 0)',
stdLibFnName: 'yLine',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="6"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(5)
ang = await u.getAngle('[data-overlay-index="5"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'xLine(length = 26.04)',
stdLibFnName: 'xLine',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="5"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(4)
ang = await u.getAngle('[data-overlay-index="4"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'yLine(endAbsolute = -10.77, tag = $a)',
stdLibFnName: 'yLineTo',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="4"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(3)
ang = await u.getAngle('[data-overlay-index="3"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'xLine(endAbsolute = 9 - 5)',
stdLibFnName: 'xLineTo',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="3"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(2)
ang = await u.getAngle('[data-overlay-index="2"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await expect(page.getByText('Added variable')).not.toBeVisible()
const hoverPos = { x: segmentToDelete.x, y: segmentToDelete.y }
@ -1167,7 +1200,7 @@ part001 = startSketchOn(XZ)
ang,
10,
5,
'[data-overlay-toolbar-index="2"]'
`[data-overlay-toolbar-index="${overlayIndex}"]`
)
await page.mouse.move(hoverPos.x, hoverPos.y)
@ -1183,18 +1216,22 @@ part001 = startSketchOn(XZ)
shouldNormalise: true,
})
segmentToDelete = await getOverlayByIndex(1)
ang = await u.getAngle('[data-overlay-index="1"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'angledLine(angle = 3 + 0, length = 32 + 0)',
stdLibFnName: 'angledLine',
ang: ang + 180,
locator: '[data-overlay-toolbar-index="1"]',
locator: `[data-overlay-toolbar-index="${overlayIndex}"]`,
})
segmentToDelete = await getOverlayByIndex(0)
ang = await u.getAngle('[data-overlay-index="0"]')
overlayIndex--
segmentToDelete = await getOverlayByIndex(overlayIndex)
ang = await u.getAngle(`[data-overlay-index="${overlayIndex}"]`)
await deleteSegmentSequence({
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
codeToBeDeleted: 'line(end = [0.5, -14 + 0])',
@ -1414,11 +1451,11 @@ part001 = startSketchOn(XZ)
await page.getByRole('button', { name: 'Edit Sketch' }).click()
await page.waitForTimeout(500)
await expect(page.getByTestId('segment-overlay')).toHaveCount(3)
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
await expect(page.getByText('Added variable')).not.toBeVisible()
const hoverPos = await u.getBoundingBox(`[data-overlay-index="0"]`)
let ang = await u.getAngle('[data-overlay-index="0"]')
const hoverPos = await u.getBoundingBox(`[data-overlay-index="1"]`)
let ang = await u.getAngle('[data-overlay-index="1"]')
ang += 180
await page.mouse.move(0, 0)
@ -1437,7 +1474,7 @@ part001 = startSketchOn(XZ)
ang,
10,
5,
'[data-overlay-toolbar-index="0"]'
'[data-overlay-toolbar-index="1"]'
)
await page.mouse.move(x, y)
@ -1451,7 +1488,7 @@ part001 = startSketchOn(XZ)
// check the cursor was left in the correct place after transform
await expect(page.locator('.cm-activeLine')).toHaveText('|> ' + after)
await expect(page.getByTestId('segment-overlay')).toHaveCount(3)
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
})
}
})
@ -1587,6 +1624,87 @@ profile002 = circle(sketch001, center = [345, 0], radius = 238.38)
)
})
})
test('startProfile x y overlays', async ({
page,
editor,
homePage,
scene,
cmdBar,
toolbar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn(XZ)
profile001 = startProfile(sketch001, at = [15, 15])
|> line(end = [114.78, 232])
|> line(end = [228.75, -208.39])
`
)
// Set flag to always show overlays without hover
localStorage.setItem('showAllOverlays', 'true')
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await toolbar.waitForFeatureTreeToBeBuilt()
await toolbar.editSketch(0)
await page.waitForTimeout(600)
await expect(page.getByTestId('segment-overlay')).toHaveCount(3)
// 1. constrain x coordinate
const xConstraintBtn = page.locator(
'[data-constraint-type="xAbsolute"][data-is-constrained="false"]'
)
await expect(xConstraintBtn).toBeVisible()
await xConstraintBtn.click()
await expect(
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain('at = [xAbs001, 15]', {
shouldNormalise: true,
})
// 2. constrain y coordinate
const yConstraintBtn = page.locator(
'[data-constraint-type="yAbsolute"][data-is-constrained="false"]'
)
await expect(yConstraintBtn).toBeVisible()
await yConstraintBtn.click()
await expect(
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain('at = [xAbs001, yAbs001]', {
shouldNormalise: true,
})
// 3. unconstrain x coordinate
const constrainedXBtn = page.locator(
'[data-constraint-type="xAbsolute"][data-is-constrained="true"]'
)
await expect(constrainedXBtn).toBeVisible()
await constrainedXBtn.click()
await editor.expectEditor.toContain('at = [15, yAbs001]', {
shouldNormalise: true,
})
// 4. unconstrain y coordinate
const constrainedYBtn = page.locator(
'[data-constraint-type="yAbsolute"][data-is-constrained="true"]'
)
await expect(constrainedYBtn).toBeVisible()
await constrainedYBtn.click()
await editor.expectEditor.toContain('at = [15, 15]', {
shouldNormalise: true,
})
})
test('arc with interiorAbsolute and endAbsolute kwargs overlay constraints', async ({
page,
editor,
@ -1605,7 +1723,7 @@ profile001 = circleThreePoint(
p2 = [445.16, 116.92],
p3 = [546.85, 103],
)
profile003 = startProfileAt([64.39, 35.16], sketch001)
profile003 = startProfile(sketch001, at = [64.39, 35.16])
|> line(end = [60.69, 23.02])
|> arc(interiorAbsolute = [159.26, 100.58], endAbsolute = [237.05, 84.07])
|> line(end = [70.31, 42.28])`
@ -1628,7 +1746,7 @@ profile003 = startProfileAt([64.39, 35.16], sketch001)
// Verify overlays are visible
// 3 for the three point arc, and 4 for the 3 segments (arc has two)
await expect(page.getByTestId('segment-overlay')).toHaveCount(7)
await expect(page.getByTestId('segment-overlay')).toHaveCount(8)
// ---- Testing interior point constraints ----
@ -1637,7 +1755,7 @@ profile003 = startProfileAt([64.39, 35.16], sketch001)
.locator(
'[data-constraint-type="xAbsolute"][data-is-constrained="false"]'
)
.nth(3)
.nth(4)
await expect(interiorXConstraintBtn).toBeVisible()
await interiorXConstraintBtn.click()
@ -1660,7 +1778,7 @@ profile003 = startProfileAt([64.39, 35.16], sketch001)
.locator(
'[data-constraint-type="yAbsolute"][data-is-constrained="false"]'
)
.nth(3)
.nth(4)
await expect(interiorYConstraintBtn).toBeVisible()
await interiorYConstraintBtn.click()
@ -1685,7 +1803,7 @@ profile003 = startProfileAt([64.39, 35.16], sketch001)
.locator(
'[data-constraint-type="xAbsolute"][data-is-constrained="false"]'
)
.nth(3) // still number 3 because the interior ones are now constrained
.nth(4) // still number 3 because the interior ones are now constrained
await expect(endXConstraintBtn).toBeVisible()
await endXConstraintBtn.click()
@ -1705,7 +1823,7 @@ profile003 = startProfileAt([64.39, 35.16], sketch001)
.locator(
'[data-constraint-type="yAbsolute"][data-is-constrained="false"]'
)
.nth(3) // still number 3 because the interior ones are now constrained
.nth(4) // still number 3 because the interior ones are now constrained
await expect(endYConstraintBtn).toBeVisible()
await endYConstraintBtn.click()

View File

@ -797,7 +797,7 @@ test.describe(
// We use the line tool as a proxy for sketch mode
await expect(lineToolButton).toBeVisible()
await expect(segmentOverlays).toHaveCount(4)
await expect(segmentOverlays).toHaveCount(5)
// but we allow more time to pass for animating to the sketch
await page.waitForTimeout(1000)
})

View File

@ -318,8 +318,9 @@ const Overlay = ({
this will likely change soon when we implement multi-profile so we'll leave it for now
issue: https://github.com/KittyCAD/modeling-app/issues/3910
*/}
{callExpression?.callee?.name.name !== 'circle' &&
callExpression?.callee?.name.name !== 'circleThreePoint' && (
{!['circleThreePoint', 'circle', 'startProfile'].includes(
callExpression?.callee?.name.name
) && (
<SegmentMenu
verticalPosition={
overlay.windowCoords[1] > window.innerHeight / 2

View File

@ -321,6 +321,18 @@ export class SceneEntities {
callBack && !err(callBack) && callbacks.push(callBack)
if (segment.name === PROFILE_START) {
segment.scale.set(factor, factor, factor)
const startProfileCallBack: () => SegmentOverlayPayload | null = () => {
return this.sceneInfra.updateOverlayDetails({
handle: segment,
group: segment,
isHandlesVisible: true,
from: segment.userData.from,
to: segment.userData.to,
hasThreeDotMenu: false,
})
}
callbacks.push(startProfileCallBack)
}
})
if (this.axisGroup) {
@ -702,10 +714,7 @@ export class SceneEntities {
maybeModdedAst,
sourceRangeFromRust(sketch.start.__geoMeta.sourceRange)
)
if (
['Circle', 'CircleThreePoint'].includes(sketch?.paths?.[0]?.type) ===
false
) {
if (!['Circle', 'CircleThreePoint'].includes(sketch?.paths?.[0]?.type)) {
const _profileStart = createProfileStartHandle({
from: sketch.start.from,
id: sketch.start.__geoMeta.id,
@ -723,6 +732,18 @@ export class SceneEntities {
}
group.add(_profileStart)
this.activeSegments[JSON.stringify(segPathToNode)] = _profileStart
const startProfileCallBack: () => SegmentOverlayPayload | null = () => {
return this.sceneInfra.updateOverlayDetails({
handle: _profileStart,
group: _profileStart,
isHandlesVisible: true,
from: sketch.start.from,
to: sketch.start.to,
hasThreeDotMenu: true,
})
}
callbacks.push(startProfileCallBack)
}
sketch.paths.forEach((segment, index) => {
const isLastInProfile =
@ -3086,7 +3107,7 @@ export class SceneEntities {
variables,
kclManager: this.kclManager,
})
const callBacks: (() => SegmentOverlayPayload | null)[] = []
const callbacks: (() => SegmentOverlayPayload | null)[] = []
for (const sketchInfo of sketchesInfo) {
const { sketch, pathToNode: _pathToNode } = sketchInfo
const varDecIndex = Number(_pathToNode[1][0])
@ -3106,7 +3127,19 @@ export class SceneEntities {
snappedToTangent
)
callBacks.push(
const startProfileCallBack: () => SegmentOverlayPayload | null = () => {
return this.sceneInfra.updateOverlayDetails({
handle: group,
group: group,
isHandlesVisible: true,
from: sketch.start.from,
to: sketch.start.to,
hasThreeDotMenu: true,
})
}
callbacks.push(startProfileCallBack)
callbacks.push(
...sgPaths.map((group, index) =>
this.updateSegment(
group,
@ -3120,7 +3153,7 @@ export class SceneEntities {
)
)
}
this.sceneInfra.overlayCallbacks(callBacks)
this.sceneInfra.overlayCallbacks(callbacks)
})().catch(reportRejection)
}

View File

@ -47,6 +47,7 @@ import type {
MouseState,
SegmentOverlayPayload,
} from '@src/machines/modelingMachine'
import { PROFILE_START } from '@src/clientSideScene/sceneConstants'
type SendType = ReturnType<typeof useModelingContext>['send']
@ -230,7 +231,10 @@ export class SceneInfra {
// Project that position to screen space
vector.project(this.camControls.camera)
const _angle = typeof angle === 'number' ? angle : getAngle(from, to)
let _angle = 45
if (group.name !== PROFILE_START) {
_angle = typeof angle === 'number' ? angle : getAngle(from, to)
}
const x = (vector.x * 0.5 + 0.5) * window.innerWidth
const y = (-vector.y * 0.5 + 0.5) * window.innerHeight

View File

@ -26,7 +26,7 @@ import {
applyConstraintLength,
} from '@src/components/Toolbar/setAngleLength'
import {
SEGMENT_BODIES,
SEGMENT_BODIES_PLUS_PROFILE_START,
getParentGroup,
} from '@src/clientSideScene/sceneConstants'
import { useFileContext } from '@src/hooks/useFileContext'
@ -222,14 +222,15 @@ export const ModelingMachineProvider = ({
if (event.type !== 'Set mouse state') return {}
const nextSegmentHoverMap = () => {
if (event.data.type === 'isHovering') {
const parent = getParentGroup(event.data.on, SEGMENT_BODIES)
const parent = getParentGroup(
event.data.on,
SEGMENT_BODIES_PLUS_PROFILE_START
)
const pathToNode = parent?.userData?.pathToNode
const pathToNodeString = JSON.stringify(pathToNode)
if (!parent || !pathToNode) return context.segmentHoverMap
if (context.segmentHoverMap[pathToNodeString] !== undefined)
clearTimeout(
context.segmentHoverMap[JSON.stringify(pathToNode)]
)
clearTimeout(context.segmentHoverMap[pathToNodeString])
return {
...context.segmentHoverMap,
[pathToNodeString]: 0,
@ -240,7 +241,7 @@ export const ModelingMachineProvider = ({
) {
const mouseOnParent = getParentGroup(
context.mouseState.on,
SEGMENT_BODIES
SEGMENT_BODIES_PLUS_PROFILE_START
)
if (!mouseOnParent || !mouseOnParent?.userData?.pathToNode)
return context.segmentHoverMap
@ -276,10 +277,11 @@ export const ModelingMachineProvider = ({
'Set Segment Overlays': assign({
segmentOverlays: ({ context: { segmentOverlays }, event }) => {
if (event.type !== 'Set Segment Overlays') return {}
if (event.data.type === 'set-many')
if (event.data.type === 'set-many') {
return {
...event.data.overlays,
}
}
if (event.data.type === 'set-one')
return {
...segmentOverlays,

View File

@ -28,6 +28,7 @@ export type ToolTip =
| 'circleThreePoint'
| 'arcTo'
| 'arc'
| 'startProfile'
export const toolTips: Array<ToolTip> = [
'line',
@ -46,6 +47,7 @@ export const toolTips: Array<ToolTip> = [
'circleThreePoint',
'arc',
'arcTo',
'startProfile',
]
interface ExecutionResult {

View File

@ -1187,6 +1187,159 @@ export const tangentialArc: SketchLineHelperKw = {
return constraints
},
}
export const startProfile: SketchLineHelperKw = {
updateArgs: ({ node, pathToNode, input }) => {
if (input.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR
const { to } = input
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpressionKw>(_node, pathToNode)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const toArrExp = createArrayExpression([
createLiteral(roundOff(to[0], 2)),
createLiteral(roundOff(to[1], 2)),
])
mutateKwArg(ARG_AT, callExpression, toArrExp)
return {
modifiedAst: _node,
pathToNode,
}
},
getTag: getTagKwArg(),
addTag: addTagKw(),
add: ({ node, pathToNode, replaceExistingCallback, segmentInput }) => {
console.log('segmentInput', segmentInput)
if (segmentInput.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR
const { to } = segmentInput
const _node = structuredClone(node)
const nodeMeta = getNodeFromPath<PipeExpression | CallExpressionKw>(
_node,
pathToNode,
'PipeExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: pipe } = nodeMeta
const nodeMeta2 = getNodeFromPath<VariableDeclarator>(
_node,
pathToNode,
'VariableDeclarator'
)
if (err(nodeMeta2)) return nodeMeta2
const newXVal = createLiteral(roundOff(to[0], 2))
const newYVal = createLiteral(roundOff(to[1], 2))
if (!replaceExistingCallback && pipe.type === 'PipeExpression') {
const callExp = createCallExpressionStdLibKw('line', null, [
createLabeledArg(ARG_AT, createArrayExpression([newXVal, newYVal])),
])
const pathToNodeIndex = pathToNode.findIndex(
(x) => x[1] === 'PipeExpression'
)
const pipeIndex = pathToNode[pathToNodeIndex + 1][0]
if (typeof pipeIndex === 'undefined' || typeof pipeIndex === 'string') {
return new Error('pipeIndex is wrong')
}
pipe.body = [
...pipe.body.slice(0, pipeIndex),
callExp,
...pipe.body.slice(pipeIndex),
]
return {
modifiedAst: _node,
pathToNode,
}
}
if (replaceExistingCallback && pipe.type === 'PipeExpression') {
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
const result = replaceExistingCallback([
{
type: 'labeledArgArrayItem',
key: ARG_AT,
index: 0,
argType: 'xAbsolute',
expr: newXVal,
},
{
type: 'labeledArgArrayItem',
key: ARG_AT,
index: 1,
argType: 'yAbsolute',
expr: newYVal,
},
])
if (err(result)) return result
const { callExp, valueUsedInTransform } = result
pipe.body[callIndex] = callExp
return {
modifiedAst: _node,
pathToNode: [...pathToNode],
valueUsedInTransform,
}
}
return {
modifiedAst: _node,
pathToNode,
}
},
getConstraintInfo: (callExp, code, pathToNode) => {
if (callExp.type !== 'CallExpressionKw') return []
if (callExp.callee.name.name !== 'startProfile') return []
const expr = findKwArgWithIndex(ARG_AT, callExp)?.expr
if (expr?.type !== 'ArrayExpression') {
return []
}
const argIndex = findKwArgAnyIndex([ARG_AT], callExp)
if (argIndex === undefined) {
return []
}
const pathToXYArray: PathToNode = [
...pathToNode,
['arguments', 'CallExpressionKw'],
[argIndex, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD],
['elements', 'ArrayExpression'],
]
const xArg = expr.elements[0]
const yArg = expr.elements[1]
const constraints: ConstrainInfo[] = [
{
stdLibFnName: 'startProfile',
type: 'xAbsolute',
isConstrained: isNotLiteralArrayOrStatic(xArg),
sourceRange: topLevelRange(xArg.start, xArg.end),
pathToNode: [...pathToXYArray, [0, 'index']],
value: code.slice(xArg.start, xArg.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 0,
key: ARG_AT,
},
},
{
stdLibFnName: 'startProfile',
type: 'yAbsolute',
isConstrained: isNotLiteralArrayOrStatic(yArg),
sourceRange: topLevelRange(yArg.start, yArg.end),
pathToNode: [...pathToXYArray, [1, 'index']],
value: code.slice(yArg.start, yArg.end),
argPosition: {
type: 'labeledArgArrayItem',
index: 1,
key: ARG_AT,
},
},
]
return constraints
},
}
export const circle: SketchLineHelperKw = {
add: ({ node, pathToNode, segmentInput, replaceExistingCallback }) => {
if (segmentInput.type !== 'arc-segment') return ARC_SEGMENT_ERR()
@ -3123,6 +3276,7 @@ export const sketchLineHelperMapKw: { [key: string]: SketchLineHelperKw } = {
angledLineToX,
angledLineToY,
tangentialArc,
startProfile,
} as const
export function changeSketchArguments(
@ -3215,6 +3369,7 @@ export function fnNameToToolTipFromSegment(
case 'circle':
case 'tangentialArc':
case 'angledLine':
case 'startProfile':
return fnName
default:
const err = `Unknown sketch line function ${fnName}`
@ -3254,6 +3409,7 @@ export function fnNameToTooltip(
case 'circleThreePoint':
case 'circle':
case 'tangentialArc':
case 'startProfile':
return fnName
case 'angledLine': {
const argmap: Record<string, ToolTip> = {
@ -3878,6 +4034,28 @@ export const getArc = (
)
}
export const getStartProfile = (
callExp: CallExpressionKw
):
| {
val: [Expr, Expr]
tag?: Expr
}
| Error => {
const absoluteCoords = findKwArg('at', callExp)
const tag = findKwArg(ARG_TAG, callExp)
if (absoluteCoords) {
if (absoluteCoords.type === 'ArrayExpression') {
console.log('absoluteCoords', absoluteCoords)
return {
val: [absoluteCoords.elements[0], absoluteCoords.elements[1]],
tag,
}
}
}
return new Error('expected the arguments to be for a start profile')
}
/**
Given a line call, return whether it's using absolute or relative end.
*/
@ -3916,6 +4094,8 @@ export function isAbsoluteLine(lineCall: CallExpressionKw): boolean | Error {
findKwArgAny([ARG_END_ABSOLUTE_X, ARG_END_ABSOLUTE_Y], lineCall) !==
undefined
)
case 'startProfile':
return true
}
return new Error(`Unknown sketch function ${name}`)
}
@ -3946,6 +4126,8 @@ export function getArgForEnd(lineCall: CallExpressionKw):
return getAngledLineThatIntersects(lineCall)
case 'arc':
return getArc(lineCall)
case 'startProfile':
return getStartProfile(lineCall)
case 'yLine':
case 'xLine': {
const arg = findKwArgAny(DETERMINING_ARGS, lineCall)

View File

@ -1648,7 +1648,7 @@ function getTransformMapPathKw(
}
return false
}
if (name === 'startProfile') {
if (name === 'startProfile' || name === 'startSketchOn') {
return false
}
const tooltip = fnNameToTooltip(allLabels(sketchFnExp), name)

View File

@ -1,6 +1,7 @@
import type { Node } from '@rust/kcl-lib/bindings/Node'
import type {
ARG_AT,
ARG_END_ABSOLUTE,
ARG_END_ABSOLUTE_X,
ARG_END_ABSOLUTE_Y,
@ -116,6 +117,7 @@ export type InputArgKeys =
| 'p2'
| 'p3'
| 'end'
| typeof ARG_AT
| typeof ARG_INTERIOR_ABSOLUTE
| typeof ARG_END_ABSOLUTE
| typeof ARG_END_ABSOLUTE_X

View File

@ -314,7 +314,6 @@ export type ModelingMachineEvent =
type: 'Delete selection'
}
| { type: 'Sketch no face' }
| { type: 'Toggle gui mode' }
| { type: 'Cancel'; cleanup?: () => void }
| { type: 'CancelSketch' }
| {