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:
@ -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()
|
||||
|
@ -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')
|
||||
})
|
||||
|
||||
|
@ -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 }
|
||||
|
@ -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', () => {
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -1648,7 +1648,7 @@ function getTransformMapPathKw(
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (name === 'startProfile') {
|
||||
if (name === 'startProfile' || name === 'startSketchOn') {
|
||||
return false
|
||||
}
|
||||
const tooltip = fnNameToTooltip(allLabels(sketchFnExp), name)
|
||||
|
@ -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
|
||||
|
@ -314,7 +314,6 @@ export type ModelingMachineEvent =
|
||||
type: 'Delete selection'
|
||||
}
|
||||
| { type: 'Sketch no face' }
|
||||
| { type: 'Toggle gui mode' }
|
||||
| { type: 'Cancel'; cleanup?: () => void }
|
||||
| { type: 'CancelSketch' }
|
||||
| {
|
||||
|
Reference in New Issue
Block a user