Add support for sweepEdge and tests
This commit is contained in:
		@ -1068,7 +1068,7 @@ openSketch = startSketchOn('XY')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('Helix point-and-click', async ({
 | 
			
		||||
  test('Helix point-and-click on default axis', async ({
 | 
			
		||||
    context,
 | 
			
		||||
    page,
 | 
			
		||||
    homePage,
 | 
			
		||||
@ -1084,9 +1084,6 @@ openSketch = startSketchOn('XY')
 | 
			
		||||
 | 
			
		||||
    await homePage.goToModelingScene()
 | 
			
		||||
 | 
			
		||||
    // await test.step(`Look for the red of the default plane`, async () => {
 | 
			
		||||
    //   await scene.expectPixelColor([96, 52, 52], testPoint, 15)
 | 
			
		||||
    // })
 | 
			
		||||
    await test.step(`Go through the command bar flow`, async () => {
 | 
			
		||||
      await toolbar.helixButton.click()
 | 
			
		||||
      await cmdBar.expectState({
 | 
			
		||||
@ -1177,6 +1174,165 @@ openSketch = startSketchOn('XY')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const helixCases = [
 | 
			
		||||
    {
 | 
			
		||||
      selectionType: 'segment',
 | 
			
		||||
      testPoint: { x: 513, y: 221 },
 | 
			
		||||
      expectedOutput: `helix001 = helix(  revolutions = 20,  angleStart = 0,  counterClockWise = true,  radius = 1,  axis = seg01,  length = 100,)`,
 | 
			
		||||
      expectedEditedOutput: `helix001 = helix(  revolutions = 20,  angleStart = 0,  counterClockWise = true,  radius = 1,  axis = seg01,  length = 50,)`,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      selectionType: 'sweepEdge',
 | 
			
		||||
      testPoint: { x: 564, y: 364 },
 | 
			
		||||
      expectedOutput: `helix001 = helix(  revolutions = 20,  angleStart = 0,  counterClockWise = true,  radius = 1,  axis =   getOppositeEdge(seg01),  length = 100,)`,
 | 
			
		||||
      expectedEditedOutput: `helix001 = helix(  revolutions = 20,  angleStart = 0,  counterClockWise = true,  radius = 1,  axis =   getOppositeEdge(seg01),  length = 50,)`,
 | 
			
		||||
    },
 | 
			
		||||
  ]
 | 
			
		||||
  helixCases.map(
 | 
			
		||||
    ({ selectionType, testPoint, expectedOutput, expectedEditedOutput }) => {
 | 
			
		||||
      test(`Helix point-and-click around ${selectionType}`, async ({
 | 
			
		||||
        context,
 | 
			
		||||
        page,
 | 
			
		||||
        homePage,
 | 
			
		||||
        scene,
 | 
			
		||||
        editor,
 | 
			
		||||
        toolbar,
 | 
			
		||||
        cmdBar,
 | 
			
		||||
      }) => {
 | 
			
		||||
        page.on('console', console.log)
 | 
			
		||||
        const initialCode = `sketch001 = startSketchOn('XZ')
 | 
			
		||||
  profile001 = startProfileAt([0, 0], sketch001)
 | 
			
		||||
    |> yLine(length = 100)
 | 
			
		||||
    |> line(endAbsolute = [100, 0])
 | 
			
		||||
    |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
 | 
			
		||||
    |> close()
 | 
			
		||||
  extrude001 = extrude(profile001, length = 100)`
 | 
			
		||||
 | 
			
		||||
        // One dumb hardcoded screen pixel value
 | 
			
		||||
        const [clickOnEdge] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
 | 
			
		||||
 | 
			
		||||
        await context.addInitScript((initialCode) => {
 | 
			
		||||
          localStorage.setItem('persistCode', initialCode)
 | 
			
		||||
        }, initialCode)
 | 
			
		||||
        await page.setBodyDimensions({ width: 1000, height: 500 })
 | 
			
		||||
        await homePage.goToModelingScene()
 | 
			
		||||
 | 
			
		||||
        await test.step(`Go through the command bar flow`, async () => {
 | 
			
		||||
          await toolbar.closePane('code')
 | 
			
		||||
          await toolbar.helixButton.click()
 | 
			
		||||
          await cmdBar.expectState({
 | 
			
		||||
            stage: 'arguments',
 | 
			
		||||
            currentArgKey: 'axisOrEdge',
 | 
			
		||||
            currentArgValue: '',
 | 
			
		||||
            headerArguments: {
 | 
			
		||||
              AngleStart: '',
 | 
			
		||||
              AxisOrEdge: '',
 | 
			
		||||
              CounterClockWise: '',
 | 
			
		||||
              Length: '',
 | 
			
		||||
              Radius: '',
 | 
			
		||||
              Revolutions: '',
 | 
			
		||||
            },
 | 
			
		||||
            highlightedHeaderArg: 'axisOrEdge',
 | 
			
		||||
            commandName: 'Helix',
 | 
			
		||||
          })
 | 
			
		||||
          await cmdBar.selectOption({ name: 'Edge' }).click()
 | 
			
		||||
          await clickOnEdge()
 | 
			
		||||
          await cmdBar.progressCmdBar()
 | 
			
		||||
          await cmdBar.argumentInput.focus()
 | 
			
		||||
          await page.keyboard.insertText('20')
 | 
			
		||||
          await cmdBar.progressCmdBar()
 | 
			
		||||
          await page.keyboard.insertText('0')
 | 
			
		||||
          await cmdBar.progressCmdBar()
 | 
			
		||||
          await cmdBar.selectOption({ name: 'True' }).click()
 | 
			
		||||
          await page.keyboard.insertText('1')
 | 
			
		||||
          await cmdBar.progressCmdBar()
 | 
			
		||||
          await page.keyboard.insertText('100')
 | 
			
		||||
          await cmdBar.progressCmdBar()
 | 
			
		||||
          await cmdBar.expectState({
 | 
			
		||||
            stage: 'review',
 | 
			
		||||
            headerArguments: {
 | 
			
		||||
              AngleStart: '0',
 | 
			
		||||
              AxisOrEdge: 'Edge',
 | 
			
		||||
              Edge: `1 ${selectionType}`,
 | 
			
		||||
              CounterClockWise: '',
 | 
			
		||||
              Length: '100',
 | 
			
		||||
              Radius: '1',
 | 
			
		||||
              Revolutions: '20',
 | 
			
		||||
            },
 | 
			
		||||
            commandName: 'Helix',
 | 
			
		||||
          })
 | 
			
		||||
          await cmdBar.progressCmdBar()
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
 | 
			
		||||
          await toolbar.openPane('code')
 | 
			
		||||
          await editor.expectEditor.toContain(expectedOutput)
 | 
			
		||||
          await toolbar.closePane('code')
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        await test.step(`Edit helix through the feature tree`, async () => {
 | 
			
		||||
          await toolbar.openPane('feature-tree')
 | 
			
		||||
          const operationButton = await toolbar.getFeatureTreeOperation(
 | 
			
		||||
            'Helix',
 | 
			
		||||
            0
 | 
			
		||||
          )
 | 
			
		||||
          await operationButton.dblclick()
 | 
			
		||||
          const initialInput = '100'
 | 
			
		||||
          const newInput = '50'
 | 
			
		||||
          await cmdBar.expectState({
 | 
			
		||||
            commandName: 'Helix',
 | 
			
		||||
            stage: 'arguments',
 | 
			
		||||
            currentArgKey: 'length',
 | 
			
		||||
            currentArgValue: initialInput,
 | 
			
		||||
            headerArguments: {
 | 
			
		||||
              AngleStart: '0',
 | 
			
		||||
              CounterClockWise: '',
 | 
			
		||||
              Length: initialInput,
 | 
			
		||||
              Radius: '1',
 | 
			
		||||
              Revolutions: '20',
 | 
			
		||||
            },
 | 
			
		||||
            highlightedHeaderArg: 'length',
 | 
			
		||||
          })
 | 
			
		||||
          await expect(cmdBar.currentArgumentInput).toBeVisible()
 | 
			
		||||
          await cmdBar.currentArgumentInput
 | 
			
		||||
            .locator('.cm-content')
 | 
			
		||||
            .fill(newInput)
 | 
			
		||||
          await cmdBar.progressCmdBar()
 | 
			
		||||
          await cmdBar.expectState({
 | 
			
		||||
            stage: 'review',
 | 
			
		||||
            headerArguments: {
 | 
			
		||||
              AngleStart: '0',
 | 
			
		||||
              CounterClockWise: '',
 | 
			
		||||
              Length: newInput,
 | 
			
		||||
              Radius: '1',
 | 
			
		||||
              Revolutions: '20',
 | 
			
		||||
            },
 | 
			
		||||
            commandName: 'Helix',
 | 
			
		||||
          })
 | 
			
		||||
          await cmdBar.progressCmdBar()
 | 
			
		||||
          await toolbar.closePane('feature-tree')
 | 
			
		||||
          await toolbar.openPane('code')
 | 
			
		||||
          await editor.expectEditor.toContain(expectedEditedOutput)
 | 
			
		||||
          await toolbar.closePane('code')
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        await test.step('Delete helix via feature tree selection', async () => {
 | 
			
		||||
          await toolbar.openPane('feature-tree')
 | 
			
		||||
          const operationButton = await toolbar.getFeatureTreeOperation(
 | 
			
		||||
            'Helix',
 | 
			
		||||
            0
 | 
			
		||||
          )
 | 
			
		||||
          await operationButton.click({ button: 'left' })
 | 
			
		||||
          await page.keyboard.press('Delete')
 | 
			
		||||
          await editor.expectEditor.not.toContain(expectedEditedOutput)
 | 
			
		||||
          expect(
 | 
			
		||||
            await toolbar.getFeatureTreeOperation('Helix', 0)
 | 
			
		||||
          ).not.toBeVisible()
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const loftPointAndClickCases = [
 | 
			
		||||
    { shouldPreselect: true },
 | 
			
		||||
    { shouldPreselect: false },
 | 
			
		||||
 | 
			
		||||
@ -529,9 +529,8 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
 | 
			
		||||
            commandContext.argumentsToSubmit.axisOrEdge as string
 | 
			
		||||
          ),
 | 
			
		||||
        inputType: 'selection',
 | 
			
		||||
        selectionTypes: ['segment', 'sweepEdge', 'edgeCutEdge'],
 | 
			
		||||
        selectionTypes: ['segment', 'sweepEdge'],
 | 
			
		||||
        multiple: false,
 | 
			
		||||
        skip: true,
 | 
			
		||||
        hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
 | 
			
		||||
      },
 | 
			
		||||
      revolutions: {
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@ import {
 | 
			
		||||
  Artifact,
 | 
			
		||||
  getArtifactOfTypes,
 | 
			
		||||
  getCapCodeRef,
 | 
			
		||||
  getSweepEdgeCodeRef,
 | 
			
		||||
} from 'lang/std/artifactGraph'
 | 
			
		||||
import { Operation } from '@rust/kcl-lib/bindings/Operation'
 | 
			
		||||
import { codeManager, engineCommandManager, kclManager } from './singletons'
 | 
			
		||||
@ -332,9 +333,11 @@ const prepareToEditHelix: PrepareToEditCallback = async ({ operation }) => {
 | 
			
		||||
  let axis: string | undefined
 | 
			
		||||
  let edge: Selections | undefined
 | 
			
		||||
  if (axisValue.type === 'String') {
 | 
			
		||||
    // default axis casee
 | 
			
		||||
    axisOrEdge = 'Axis'
 | 
			
		||||
    axis = axisValue.value
 | 
			
		||||
  } else if (axisValue.type === 'TagIdentifier' && axisValue.artifact_id) {
 | 
			
		||||
    // segment case
 | 
			
		||||
    axisOrEdge = 'Edge'
 | 
			
		||||
    const artifact = getArtifactOfTypes(
 | 
			
		||||
      {
 | 
			
		||||
@ -356,6 +359,37 @@ const prepareToEditHelix: PrepareToEditCallback = async ({ operation }) => {
 | 
			
		||||
      ],
 | 
			
		||||
      otherSelections: [],
 | 
			
		||||
    }
 | 
			
		||||
  } else if (axisValue.type === 'Uuid') {
 | 
			
		||||
    // sweepEdge case
 | 
			
		||||
    axisOrEdge = 'Edge'
 | 
			
		||||
    const artifact = getArtifactOfTypes(
 | 
			
		||||
      {
 | 
			
		||||
        key: axisValue.value,
 | 
			
		||||
        types: ['sweepEdge'],
 | 
			
		||||
      },
 | 
			
		||||
      engineCommandManager.artifactGraph
 | 
			
		||||
    )
 | 
			
		||||
    if (err(artifact)) {
 | 
			
		||||
      return baseCommand
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const codeRef = getSweepEdgeCodeRef(
 | 
			
		||||
      artifact,
 | 
			
		||||
      engineCommandManager.artifactGraph
 | 
			
		||||
    )
 | 
			
		||||
    if (err(codeRef)) {
 | 
			
		||||
      return baseCommand
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    edge = {
 | 
			
		||||
      graphSelections: [
 | 
			
		||||
        {
 | 
			
		||||
          artifact,
 | 
			
		||||
          codeRef,
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
      otherSelections: [],
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  }
 | 
			
		||||
@ -364,8 +398,9 @@ const prepareToEditHelix: PrepareToEditCallback = async ({ operation }) => {
 | 
			
		||||
  if (
 | 
			
		||||
    !('revolutions' in operation.labeledArgs) ||
 | 
			
		||||
    !operation.labeledArgs.revolutions
 | 
			
		||||
  )
 | 
			
		||||
  ) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  }
 | 
			
		||||
  const revolutions = await stringToKclExpression(
 | 
			
		||||
    codeManager.code.slice(
 | 
			
		||||
      operation.labeledArgs.revolutions.sourceRange[0],
 | 
			
		||||
@ -378,22 +413,26 @@ const prepareToEditHelix: PrepareToEditCallback = async ({ operation }) => {
 | 
			
		||||
  if (
 | 
			
		||||
    !('angleStart' in operation.labeledArgs) ||
 | 
			
		||||
    !operation.labeledArgs.angleStart
 | 
			
		||||
  )
 | 
			
		||||
  ) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  }
 | 
			
		||||
  const angleStart = await stringToKclExpression(
 | 
			
		||||
    codeManager.code.slice(
 | 
			
		||||
      operation.labeledArgs.angleStart.sourceRange[0],
 | 
			
		||||
      operation.labeledArgs.angleStart.sourceRange[1]
 | 
			
		||||
    )
 | 
			
		||||
  )
 | 
			
		||||
  if (err(angleStart) || 'errors' in angleStart) return baseCommand
 | 
			
		||||
  if (err(angleStart) || 'errors' in angleStart) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // counterClockWise options boolean arg
 | 
			
		||||
  if (
 | 
			
		||||
    !('counterClockWise' in operation.labeledArgs) ||
 | 
			
		||||
    !operation.labeledArgs.counterClockWise
 | 
			
		||||
  )
 | 
			
		||||
  ) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  }
 | 
			
		||||
  const counterClockWise =
 | 
			
		||||
    codeManager.code.slice(
 | 
			
		||||
      operation.labeledArgs.counterClockWise.sourceRange[0],
 | 
			
		||||
@ -401,26 +440,35 @@ const prepareToEditHelix: PrepareToEditCallback = async ({ operation }) => {
 | 
			
		||||
    ) === 'true'
 | 
			
		||||
 | 
			
		||||
  // radius kcl arg
 | 
			
		||||
  if (!('radius' in operation.labeledArgs) || !operation.labeledArgs.radius)
 | 
			
		||||
  if (!('radius' in operation.labeledArgs) || !operation.labeledArgs.radius) {
 | 
			
		||||
    console.log(
 | 
			
		||||
      "!('radius' in operation.labeledArgs) || !operation.labeledArgs.radius"
 | 
			
		||||
    )
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  }
 | 
			
		||||
  const radius = await stringToKclExpression(
 | 
			
		||||
    codeManager.code.slice(
 | 
			
		||||
      operation.labeledArgs.radius.sourceRange[0],
 | 
			
		||||
      operation.labeledArgs.radius.sourceRange[1]
 | 
			
		||||
    )
 | 
			
		||||
  )
 | 
			
		||||
  if (err(radius) || 'errors' in radius) return baseCommand
 | 
			
		||||
  if (err(radius) || 'errors' in radius) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // length kcl arg
 | 
			
		||||
  if (!('length' in operation.labeledArgs) || !operation.labeledArgs.length)
 | 
			
		||||
  if (!('length' in operation.labeledArgs) || !operation.labeledArgs.length) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  }
 | 
			
		||||
  const length = await stringToKclExpression(
 | 
			
		||||
    codeManager.code.slice(
 | 
			
		||||
      operation.labeledArgs.length.sourceRange[0],
 | 
			
		||||
      operation.labeledArgs.length.sourceRange[1]
 | 
			
		||||
    )
 | 
			
		||||
  )
 | 
			
		||||
  if (err(length) || 'errors' in length) return baseCommand
 | 
			
		||||
  if (err(length) || 'errors' in length) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Assemble the default argument values for the Offset Plane command,
 | 
			
		||||
  // with `nodeToEdit` set, which will let the Offset Plane actor know
 | 
			
		||||
 | 
			
		||||
@ -1940,15 +1940,17 @@ export const modelingMachine = setup({
 | 
			
		||||
          ast
 | 
			
		||||
        )
 | 
			
		||||
        if (err(getAxisResult)) return getAxisResult
 | 
			
		||||
        const { generatedAxis, axisIndexIfAxis } = getAxisResult
 | 
			
		||||
        const { generatedAxis } = getAxisResult
 | 
			
		||||
        if (!generatedAxis) {
 | 
			
		||||
          return new Error('Generated axis selection is missing.')
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: figure out if we want to smart insert after the sketch as below
 | 
			
		||||
        // *or* after the sweep that consumes the sketch, in which case the below code doesn't work
 | 
			
		||||
        // If an axis was selected in KCL, find the max index to insert the revolve command
 | 
			
		||||
        if (axisIndexIfAxis) {
 | 
			
		||||
          opInsertIndex = axisIndexIfAxis + 1
 | 
			
		||||
        }
 | 
			
		||||
        // if (axisIndexIfAxis) {
 | 
			
		||||
        // opInsertIndex = axisIndexIfAxis + 1
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        for (const variable of [revolutions, angleStart, radius, length]) {
 | 
			
		||||
          // Insert the variable if it exists
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user