From 29070a9b043c74adf5328b18b70b5b9c4af723a8 Mon Sep 17 00:00:00 2001 From: Frank Noirot Date: Tue, 23 Apr 2024 14:54:56 -0400 Subject: [PATCH] Hook up circle tool to client side scene, still missing displaying circle in sketch mode --- src/Toolbar.tsx | 29 +++++ src/clientSideScene/sceneEntities.ts | 153 ++++++++++++++++++++++++++- src/components/CustomIcon.tsx | 10 ++ src/lib/circleTool.ts | 59 +++++++++++ src/machines/modelingMachine.ts | 10 +- 5 files changed, 254 insertions(+), 7 deletions(-) create mode 100644 src/lib/circleTool.ts diff --git a/src/Toolbar.tsx b/src/Toolbar.tsx index 37185bcbc..c31b23bb8 100644 --- a/src/Toolbar.tsx +++ b/src/Toolbar.tsx @@ -193,6 +193,35 @@ export const Toolbar = () => { Rectangle +
  • + + state.matches('Sketch.Circle tool') + ? send('CancelSketch') + : send('Equip circle tool') + } + aria-pressed={state.matches('Sketch.Circle tool')} + icon={{ + icon: 'circle', + iconClassName, + bgClassName, + }} + disabled={ + (!state.can('Equip circle tool') && + !state.matches('Sketch.Circle tool')) || + disableAllButtons + } + title={ + state.can('Equip circle tool') + ? 'Circle' + : 'Can only be used when a sketch is empty currently' + } + > + Circle + +
  • )} {state.matches('Sketch.SketchIdle') && diff --git a/src/clientSideScene/sceneEntities.ts b/src/clientSideScene/sceneEntities.ts index 103e2d79a..440533584 100644 --- a/src/clientSideScene/sceneEntities.ts +++ b/src/clientSideScene/sceneEntities.ts @@ -97,6 +97,7 @@ import { getRectangleCallExpressions, updateRectangleSketch, } from 'lib/rectangleTool' +import { circleAsCallExpressions, updateCircleSketch } from 'lib/circleTool' type DraftSegment = 'line' | 'tangentialArcTo' @@ -580,7 +581,7 @@ export class SceneEntities { ...this.mouseEnterLeaveCallbacks(), }) } - setupRectangleOriginListener = () => { + setupOriginListener = (type: 'circle' | 'rectangle') => { sceneInfra.setCallbacks({ onClick: (args) => { const twoD = args.intersectionPoint?.twoD @@ -589,7 +590,7 @@ export class SceneEntities { return } sceneInfra.modelingSend({ - type: 'Add rectangle origin', + type: `Add ${type} origin`, data: [twoD.x, twoD.y], }) }, @@ -747,6 +748,154 @@ export class SceneEntities { }, }) } + setupDraftCircle = async ( + sketchPathToNode: PathToNode, + forward: [number, number, number], + up: [number, number, number], + sketchOrigin: [number, number, number], + circleOrigin: [x: number, y: number] + ) => { + let _ast = JSON.parse(JSON.stringify(kclManager.ast)) + + const variableDeclarationName = + getNodeFromPath( + _ast, + sketchPathToNode || [], + 'VariableDeclaration' + )?.node?.declarations?.[0]?.id?.name || '' + + const tags: [string] = [findUniqueName(_ast, 'circle')] + + const startSketchOn = getNodeFromPath( + _ast, + sketchPathToNode || [], + 'VariableDeclaration' + )?.node?.declarations + + const startSketchOnInit = startSketchOn?.[0]?.init + startSketchOn[0].init = createPipeExpression([ + startSketchOnInit, + ...circleAsCallExpressions(circleOrigin, tags), + ]) + + _ast = parse(recast(_ast)) + + const { programMemoryOverride, truncatedAst } = await this.setupSketch({ + sketchPathToNode, + forward, + up, + position: sketchOrigin, + maybeModdedAst: _ast, + draftExpressionsIndices: { start: 0, end: 1 }, + }) + + sceneInfra.setCallbacks({ + onMove: async (args) => { + // Update the radius of the draft rectangle + const pathToNodeTwo = JSON.parse(JSON.stringify(sketchPathToNode)) + pathToNodeTwo[1][0] = 0 + + const sketchInit = getNodeFromPath( + truncatedAst, + pathToNodeTwo || [], + 'VariableDeclaration' + )?.node?.declarations?.[0]?.init + + const x = (args.intersectionPoint.twoD.x || 0) - circleOrigin[0] + const y = (args.intersectionPoint.twoD.y || 0) - circleOrigin[1] + + if (sketchInit.type === 'PipeExpression') { + updateCircleSketch(sketchInit, x, y, tags[0]) + } + + const { programMemory } = await executeAst({ + ast: truncatedAst, + useFakeExecutor: true, + engineCommandManager: this.engineCommandManager, + programMemoryOverride, + }) + this.sceneProgramMemory = programMemory + const sketchGroup = programMemory.root[ + variableDeclarationName + ] as SketchGroup + const sgPaths = sketchGroup.value + const orthoFactor = orthoScale(sceneInfra.camControls.camera) + + this.updateSegment( + sketchGroup.start, + 0, + 0, + _ast, + orthoFactor, + sketchGroup + ) + sgPaths.forEach((seg, index) => + this.updateSegment(seg, index, 0, _ast, orthoFactor, sketchGroup) + ) + }, + onClick: async (args) => { + // Commit the circle to the full AST/code and return to sketch.idle + const radiusPoint = args.intersectionPoint?.twoD + if (!radiusPoint || args.mouseEvent.button !== 0) return + + const x = roundOff((radiusPoint.x || 0) - circleOrigin[0]) + const y = roundOff((radiusPoint.y || 0) - circleOrigin[1]) + + const sketchInit = getNodeFromPath( + _ast, + sketchPathToNode || [], + 'VariableDeclaration' + )?.node?.declarations?.[0]?.init + + if (sketchInit.type === 'PipeExpression') { + updateCircleSketch(sketchInit, x, y, tags[0]) + + _ast = parse(recast(_ast)) + + console.log('onClick', { + sketchInit: sketchInit, + _ast, + x, + y, + truncatedAst, + }) + + // Update the primary AST and unequip the rectangle tool + await kclManager.executeAstMock(_ast) + sceneInfra.modelingSend({ type: 'CancelSketch' }) + + const { programMemory } = await executeAst({ + ast: _ast, + useFakeExecutor: true, + engineCommandManager: this.engineCommandManager, + programMemoryOverride, + }) + + // Prepare to update the THREEjs scene + this.sceneProgramMemory = programMemory + const sketchGroup = programMemory.root[ + variableDeclarationName + ] as SketchGroup + const sgPaths = sketchGroup.value + const orthoFactor = orthoScale(sceneInfra.camControls.camera) + + // Update the starting segment of the THREEjs scene + this.updateSegment( + sketchGroup.start, + 0, + 0, + _ast, + orthoFactor, + sketchGroup + ) + // Update the rest of the segments of the THREEjs scene + sgPaths.forEach((seg, index) => + this.updateSegment(seg, index, 0, _ast, orthoFactor, sketchGroup) + ) + } + }, + }) + } setupSketchIdleCallbacks = ({ pathToNode, up, diff --git a/src/components/CustomIcon.tsx b/src/components/CustomIcon.tsx index 4e0a8b84f..722498e56 100644 --- a/src/components/CustomIcon.tsx +++ b/src/components/CustomIcon.tsx @@ -61,6 +61,16 @@ const CustomIconMap = { /> ), + circle: ( + + + + ), clipboardCheckmark: ( circle([0, 0], 0, %) + */ +export const circleAsCallExpressions = ( + circleOrigin: [number, number], + tags: [string] +) => [ + createCallExpressionStdLib('circle', [ + createArrayExpression([ + createLiteral(roundOff(circleOrigin[0])), + createLiteral(roundOff(circleOrigin[1])), + ]), + createLiteral(10), + createPipeSubstitution(), + createLiteral(tags[0]), + ]), +] + +/** + * Mutates the pipeExpression to update the circle sketch + * @param pipeExpression + * @param x + * @param y + * @param tag + */ +export function updateCircleSketch( + pipeExpression: PipeExpression, + x: number, + y: number, + tag: string +) { + const circle = pipeExpression.body[1] as CallExpression + const origin = circle.arguments[0] as ArrayExpression + const originX = (origin.elements[0] as Literal).value + const originY = (origin.elements[1] as Literal).value + + const radius = roundOff( + Math.sqrt((x - Number(originX)) ** 2 + (y - Number(originY)) ** 2) + ) + + ;(circle.arguments[1] as Literal) = createLiteral(radius) +} diff --git a/src/machines/modelingMachine.ts b/src/machines/modelingMachine.ts index de91fbc7c..bd56b5e56 100644 --- a/src/machines/modelingMachine.ts +++ b/src/machines/modelingMachine.ts @@ -160,7 +160,7 @@ export type MoveDesc = { line: number; snippet: string } export const modelingMachine = createMachine( { - /** @xstate-layout N4IgpgJg5mDOIC5QFkD2EwBsCWA7KAxAMICGuAxlgNoAMAuoqAA6qzYAu2qujIAHogC0AdgCsAZgB04gEyjhADnEA2GgoUAWJQBoQAT0QBGGuICckmoZkbTM42YWKAvk91oMOfAQDKYdgAJYLDByTm5aBiQQFjYwniiBBEFTU2VJYWFxDUNDbPFxCQ1dAwQZO0lDW3EcuQzlBRoNFzd0LDxCXwCAW1QAVyDA9hJ2MAjeGI4ueNBE5JTJVUNNBUNlLQ05YsQsjQWNLVE5Yw0aZXFmkHc2-ElsCEwwAgBRXBGAJ0CAaz9yAAsxqITOK8WYyZTCCpg1JaKw5cFFfSIGSmXYaLKyPI0UwKZSmC5XTxQW73R4vd5fH7-QyRZisSbcEFCaw0STZRaiNTiNQ0YRbBAnGSSWzCZSiKz1QziFbKfGtQnEh7PPjsN69DAA2mxKaMpKieSSZE0US40QaUQrPk5DkGnEKFIcmz7QyyjztBWkvgsN7sDXROnAhJM9Q25llXIo818jKGBZiLKihoyYRml3XIneb7sP7EMiUTAZym+oHawMIHI4io8-YNBpmWSWpYx8srSWWBTm1PygtZ36Sbt-ACSJIIyBI30CYCgXTAr38ADcwN7sOQSJgi-6SzMjMimwoZJoRZoaEnLXlpDQL3IJEmlE1XJc5W7+73n0PFaPx0EpzOAr9UG9sAAL24IY13ocYNwZUsrGTBY1FUMUYPBGRLWqGNTXkSwzmMPUZE7J9Mz+PtCN+N9HiIbhYBVEg8H8P8AOA15V38CBsCo3NRnAwFIOmfht1NCwNi5bEslMJYFD5GQzDSI09QvM0xMlfCbmfYjKTI4hKOo2iFyXFdMBYtihgoTiaT9LUoK3MswQUIVDnbVZsjUDZJKTKRDmyA8MjBU1lPTEi1J7DSKNwKi3ho3B-AAQQAIW8fwAA11ws3jEisdtWXEMRw2qZEpMk0wBMK8EGmPURTEyc57wJAjKUCwdhxCsKIuiuL-AATWS+lUu3DLrDsZQjmNY0UMRBAuWDYQrzFVRHH2Pz6pfEjgq08LaLIKAHi6gMrMlNFpCUPd20UQxhFMSSOQhORjoyY0zoqhbVNfRrVpah58HYf4uM1bqdUlLLpFFVQxNkapREk5QlnSXFsjO6sVGER6AuexUmu0yKmEXTHcFY8hekwEgPlY9iTO2zc+Os-dWRSXKTiWVRlEklZdmESo7W8-YNDEJG6pR8jXto+igJA1dMD0fxV2wKBcDJyyKfFQV22WQpTVOcRLRmg1Cq8pNjXyHme0WlbQvR+dF04fSxYlnBpdlnrrLOzL9zOmazDFS1BtESRzQq7F6mRRwqpaV0VOR5aXpNtbItgXASCYfx2FQRK7b+6opDBKU1AqvczEkxpBTKY1lGLo1HDKA2iL5zTI5amO44TpPOu+8zfugtOLBFaoMiy45JNyCFTTL8rTo0NYg4fEP-N58PUYFyKwAAR16Zj3qgT6U+g5F3P7s7hCNOQsstTIWTREwLyNIG8Wqx9Q+n9SI+a2imEJ0XqGb4s5bS2QIWPDPDHKrII9LSmABiYaokMUg8jUKICuS176zxrrRN4YAegLn8OQOe7BYAb12tYWykNrAjU0P-HQY0ljVAsKsWwjR8jwTwtfSei0jbDgAEpgEEGAPgIRegjBwfLAoUhJSLGmmIRmY1UhpHKt3c0VgxKNFgcwxUTwl7YHjgAGTwGABuqAwJmQ-vbJYqRvb5DWPaLI6g+RKC9pdfqchR6IQUVXZRvRVEJw2j+bAzFCbkAbnwxIdg5CsixEaQq+RR7qzIVnA0eoVCnD9kaceNVb6GycSo+OyDQgbQeNo3REEUo6jKGIA0xhNDIn2ByCJJQrCWFZAHRMW9MiOJnqSNJ6DsBvHINkxOOi-FImRGkUwJgzQtmPpkI+2RikoilKkMS7YFFRQAO40V-P+YWTEDLE2MpQfweAABmqACAQG4GAW4uA5yoG+JIGA7BBBC0YqBQQezUC9NKFyVEo8TgVTMBVMZY1rCVEkO2fcUkqFyHBPMpZHA6KrPucxTZHEdm4H2QQRcbx-ySCYATdg+y3hdCuX4W5MKRaYEeUi5578eIFK5F7HITo9r2QqpJKUgpGinAvAUJMkMIXLLNnpOFRkEVPMOcc055zLnXMELpC2q5SX7JeSCwUkoTomHBJUE8fz9xSEcIcQ4-1Tr0ODmmJhiyeVSuXPykm2yhWovRZi4YOK8USrNfpWV5K9GUtLAqwFRoxBiTEJoVyGwKhA2PFKI6ShuVQtivFBKiLkVHNwCcvAYqTkSpIAAI1gIIPgrr5XgOhjIS8B9Ix-NSIqk4bI0RgjcpGgI0bEpxoOTat4GKsUOvxTcjNWac1PLzadTKYaCiDMHgVVY0hzSimqI0ZMV9DVdgCiaqNbV2qNuFYm0VFzU0Eq7YIPQuaKX5M9fmgo8g9S2BAcmcGY0uTgmpnaDk5pqV3jnbVQ2i663LtXc21t9r-yOu3Zm3d+73WHqsiCn+nKspgjOGyPk4DdhxOLoXJVBqJ5GtUu+iW+BslCoTUms5m6O2CCyew3tB7W5ga7ueHIHLyqFUMBdY0QpqWWH-hOjItasObS0dat4aKW12uxX+ojJHgN5IoxTEFtk97ZH3NUu0p0Lr9po5hOQ+9wUMPQwuyFARV6fVXXhjd4qCV6d+GJ7ioHJNgydmYWGGxjy8j+fUL2asu4qFOlYTjpmv18dtW24TErTPmZ+jtKzY7jAmBkfULmo0ShgiDUhrQKIxC3RlJp+ddVMOYzeNjXG+NCaGUtTxsla78MpqI9l3Ly58tvEEPCkywWW6hf8dWuyShrCDRspsP5e4vY91HqKe0B9OOVZnHlgmRMBUmR8-xn9QncUVaxmN6rE26tTcoI1-RBTWvawxJ1-2V64sZAhP14udGdWJJvlPQ2GjE05OeK04yMBXieIMt43x5HmtIjOgM5mMm6xnUqYgbOQTqhaFFFNSGCgFG3a0d0zAD2XHpJCE9rpqAemffJi1opdhnJlLNCYBseoFgRdUA51mqwYeaPu841x5B2mdLh+j3JFmJOJC7rsCRYpdVSRmkfVmQTLAgKWI0ESVO7vw8kAOXAHACDyqkmkQ6YoGgojkOdMaEoDTTLMCYDIVRxdM50VLmX7A5fUnE190oSZBQcjk2sapuIoyO3CRIWwxpBlGgNzkyQAA5JOAAFVAeAsEECihACAgxCYBBYMH+VxdOcX3KhsBoaw+TF3MGiX2e9FCHS95Lv3-hA-B9gDmEyLOQtY6MJocwJgpJ7ixAcCxY094xhsBA-I6UzgKOl7Ll5xgx0HD3rEw4DfLRSSkKPEUYI2XxedOl19REe+m6oOb1nlucIxjtME8JhbLAIiqTudI7Z4zihsCoBRAAVdxL2vEdIboj1xsOclx-2JlHk7ZCqnFi8D0e6Qpq873lOEnwUV6BxiTnYm9GfAAHlcBSsjMTkopvAL9BBQCjlBAID2BoCZZMdP4jB8hbJDhMhFJ9gCg1A+RzQWRUhKhnJMglAsoFE2FMlsNDcEdad456cOk0cMcQM2dtgR4hRi41hWNCp5BHMqlAChRp89wppR59wYF59kkiJGDUcWDJB312h-BVkoA8BQ9w9-AMkVDNCAJtDsCeDLdnZJE3l3cKpDFTx-5AUVgVhNUIsHoFDrsiIiAGcuDMA1CdMNCtCdCw8I8ODGcjCpY8B5UURFckxZMO91A0RgELwDRZDhRGglhYF-BcAk5dkSBKAfBghQgWIwAcj8Zo8CZE0XlBA7BdwpkMhwcZ1DtEBBpFcrB0R7oRQbAFoyBsAuhhgNDE5-A7VE04Dk1CNujeiRhBBE5BAcjKAXk9Rdx39WVf4eQ08qZcpaF9wKotBoc3DJBxi+j8AG5-BOEjINDYASIRiCNLkDjJjpiLjCwcD7ZPYLBq0zoVhTQoM4MoZi5aDUh1BktdiX1FDexPDOCWCH9kcmDuNn8niqUzQHDd5FAJA9xFMyFaFpBsQ7Ap8LxjQ7x7wsiMB4AogkkoALdK8kgGgYxZB5AlBZplggcyx7DdYz5kwlVf4Fo7gHhyTcCkg1gCDwQvlNBzQuZLEVhjE1B-4NihdYEeT7Z-jWRjoVV95R8-ljxvZsR9495HC7Q0tgT3C4EgoSQ5S-oTh05tizp9wzR3iGwUQKhYjXMh9LtGEMMdNoUGJiVCstlit9kTToJbRWRPlFBWYkw95v9XlbBpAzQuRThcQkw599TjU3TnULVvTG0-Tdp1BFUydJQJBBoxJXJrRjxPJcgzsxRON61Y0nkMz5Y7QpBORZEVBccsQCoKEzQSpFgEI9wKzP1qy18KTDEbcrTqgGgXJr1TgvZC49RfUszZ00MMs303SSN0z+zeTDEvYzh5J8hsRDgQELo1BAU689RVAp8CgvMZw15fgVyK81yt9QdhoVgQFBCIYVB0gxJsQRQ4Y9YRslscYVsCt6srUyUay0p2w0gfsOQjw298hJITp0g2Zh5pzUg89mcQKkR7AO58DTRsRbRyCoYpouRKhDFbNn15yF9ewn9Jcl80LSh-4YweQsKbB1B6g09IzVgYNwlBlR45zSSmFKLmdJAsjcVVwaLrAKpWRu5DRawygowak29KgO99wzhUNeLVJ+KjcC8i9XhiSbz7ZCF04lBcgVha8VBGSp8bQchJQlgOiVhu8TcaKcJzA1hTRmQpQzBcgGxxTmwaM2wOw9jVIr98APFb8fFE5RLzQf5mUNhZDIZR5LQJy9gKpypHAeQUgVKrsmFUDwChhICSIYCHL6hzAJBB49ZH1kRyDf9R41UzQ7owKGCUdlz4dwrXznLL04wRcxED9xSpoIwJATEeKMrVJlDGqBL1CjiggMEcZ0F-xE03hwrNA9h5BrSJAOqNZBlMo1hsorKlABqXSAphrmDvcxqoAwiTDRLIY0g8goQbBWY7Q7CvZ1BGxnCLxXDEzVIwTQimrVy9Lkr0gJ17Eh5OqjAiCKgSFBop8RD0q9q6oPrvDfDlkNDwpWJ+hBig9Xhzrf9-U1gEwppjQ84uZDz9xetorOj-KApYbVDjrTq8BzrFBvYwRTowFT998q9MgDR-ZC1p8YigSyKQTMjsjciwAaKqj8gFhzROaNg1hOa+QuZ04Roy06g6wuiZcJj+ik4hihbvq-ozghQRQuLCoQzTg1iZIw0RRB4JpEY9jbi1aTi+AzjxqSIHLxLREIdjxchqhbAmYWQS4t9mQcR9wUKjdE0FlI8Rh-BDBRKcQINnJCKzRVhwyGZBIAE8zlLrAXAXAgA */ + /** @xstate-layout N4IgpgJg5mDOIC5QFkD2EwBsCWA7KAxAMICGuAxlgNoAMAuoqAA6qzYAu2qujIAHogC0AdgCsAZgB04gEyjhADnEA2GgoUAWJQBoQAT0QBGGuICckmoZkbTM42YWKAvk91oMOfAQDKYdgAJYLDByTm5aBiQQFjYwniiBBEFTU2VJYWFxDUNDbPFxCQ1dAwQZO0lDW3EcuQzlBRoNFzd0LDxCXwCAW1QAVyDA9hJ2MAjeGI4ueNBE5JTJVUNNBUNlLQ05YsQsjQWNLVE5Yw0aZXFmkHc2-ElsCEwwAgBRXBGAJ0CAaz9yAAsxqITOK8WYyZTCCpg1JaKw5cFFfSIGSmXYaLKyPI0UwKZSmC5XTxQW73R4vd5fH7-QyRZisSbcEFCaw0STZRaiNTiNQ0YRbBAnGSSWzCZSiKz1QziFbKfGtQnEh7PPjsN69DAA2mxKaMpKieSSZE0US40QaUQrPk5DkGnEKFIcmz7QyyjztBWkvgsN7sDXROnAhJM9Q25llXIo818jKGBZiLKihoyYRml3XIneb7sP7EMiUTAZym+oHawMIHI4io8-YNBpmWSWpYx8srSWWBTm1PygtZ36Sbt-ACSJIIyBI30CYCgXTAr38ADcwN7sOQSJgi-6SzMjMimwoZJoRZoaEnLXlpDQL3IJEmlE1XJc5W7+73n0PFaPx0EpzOAr9UG9sAAL24IY13ocYNwZUsrGTBY1FUMUYPBGRLWqGNTXkSwzmMPUZE7J9Mz+PtCN+N9HiIbhYBVEg8H8P8AOA15V38CBsCo3NRnAwFIOmfht1NCwNi5bEslMJYFD5GQzDSI09QvM0xMlfCbmfYjKTI4hKOo2iFyXFdMBYtihgoTiaT9LUoK3MswQUIVDnbVZsjUDZJKTKRDmyA8MjBU1lPTEi1J7DSKNwKi3ho3B-AAQQAIW8fwAA11ws3jEisdtWXEMRw2qZEpMk0wBMK8EGmPURTEyc57wJAjKUCwdhxCsKIuiuL-AATWS+lUu3DLrDsZQjmNY0UMRBAuWDYQrzFVRHH2Pz6pfEjgq08LaLIKAHi6gMrMlNFpCUPd20UQxhFMSSOQhORjoyY0zoqhbVNfRrVpah58HYf4uM1bqdUlLLpFFVQxNkapREk5QlnSXFsjO6sVGER6AuexUmu0yKmEXTHcFY8hekwEgPlY9iTO2zc+Os-dWRSXKTiWVRlEklZdmESo7W8-YNDEJG6pR8jXto+igJA1dMD0fxV2wKBcDJyyKfFQV22WQpTVOcRLRmg1Cq8pNjXyHme0WlbQvR+dF04fSxYlnBpdlnrrLOzL9zOmazDFS1BtESRzQq7F6mRRwqpaV0VOR5aXpNtbItgXASCYfx2FQRK7b+6opDBKU1AqvczEkxpBTKY1lGLo1HDKA2iL5zTI5amO44TpPOu+8zfugtOLBFaoMiy45JNyCFTTL8rTo0NYg4fEP-N58PUYFyKwAAR16Zj3qgT6U+g5F3P7s7hCNOQsstTIWTREwLyNIG8Wqx9Q+n9SI+a2imEJ0XqGb4s5bS2QIWPDPDHKrII9LSmABiYaokMUg8jUKICuS176zxrrRN4YAegLn8OQOe7BYAb12tYWykNrAjU0P-HQY0ljVAsKsWwjR8jwTwtfSei0jbDgAEpgEEGAPgIRegjBwfLAoUhJSLGmmIRmY1UhpHKt3c0VgxKNFgcwxUTwl7YHjgAGTwGABuqAwJmQ-vbJYqRvb5DWPaLI6g+RKC9pdfqchR6IQUVXZRvRVEJw2j+bAzFCbkAbnwxIdg5CsixEaQq+RR7qzIVnA0eoVCnD9kaceNVb6GycSo+OyDQgbQeNo3REEUo6jKGIA0xhNDIn2ByCJJQrCWFZAHRMW9MiOJnqSNJ6DsBvHINkxOOi-FImRGkUwJgzQtmPpkI+2RikoilKkMS7YFFRQAO40V-P+YWTEDLE2MpQfweAABmqACAQG4GAW4uA5yoG+JIGA7BBBC0YqBQQezUC9NKFyVEo8TgVTMBVMZY1rCVEkO2fcUkqFyHBPMpZHA6KrPucxTZHEdm4H2QQRcbx-ySCYATdg+y3hdCuX4W5MKRaYEeUi5578eIFK5F7HITo9r2QqpJKUgpGinAvAUJMkMIXLLNnpOFRkEVPMOcc055zLnXMELpC2q5SX7JeSCwUkoTomHBJUE8fz9xSEcIcQ4-1Tr0ODmmJhiyeVSuXPykm2yhWovRZi4YOK8USrNfpWV5K9GUtLAqwFRoxBiTEJoVyGwKhA2PFKI6ShuVQtivFBKiLkVHNwCcvAYqTkSpIAAI1gIIPgrr5XgOhjIS8B9Ix-NSIqk4bI0RgjcpGgI0bEpxoOTat4GKsUOvxTcjNWac1PLzadTKYaCiDMHgVVY0hzSimqI0ZMV9DVdgCiaqNbV2qNuFYm0VFzU0Eq7YIPQuaKX5M9fmgo8g9S2BAcmcGY0uTgmpnaDk5pqV3jnbVQ2i663LtXc21t9r-yOu3Zm3d+73WHqsiCn+nKspgjOGyPk4DdhxOLoXJVBqJ5GtUu+iW+BslCoTUms5m6O2CCyew3tB7W5ga7ueHIHLyqFUMBdY0QpqWWH-hOjItasObS0dat4aKW12uxX+ojJHgN5IoxTEFtk97ZH3NUu0p0Lr9po5hOQ+9wUMPQwuyFARV6fVXXhjd4qCV6d+GJ7ioHJNgydmYWGGxjy8j+fUL2asu4qFOlYTjpmv18dtW24TErTPmZ+jtKzY7jAmBkfULmo0ShgiDUhrQKIxC3RlJp+ddVMOYzeNjXG+NCaGUtTxsla78MpqI9l3Ly58tvEEPCkywWW6hf8dWuyShrCDRspsP5e4vY91HqKe0B9OOVZnHlgmRMBUmR8-xn9QncUVaxmN6rE26tTcoI1-RBTWvawxJ1-2V64sZAhP14udGdWJJvlPQ2GjE05OeK04yMBXieIMt43x5HmtIjOgM5mMm6xnUqYgbOQTqhaFFFNSGCgFG3a0d0zAD2XHpJCE9rpqAemffJi1opdhnJlLNCYBseoFgRdUA51mqwYeaPu841x5B2mdLh+j3JFmJOJC7rsCRYpdVSRmkfVmQTLAgKWI0ESVO7vw8kAOXAHACDyqkmkQ6YoGgojkOdMaEoDTTLMCYDIVRxdM50VLmX7A5fUnE190oSZBQcjk2sapuIoyO3CRIWwxpBlGgNzkyQAA5JOAAFVAeAsEECihACAgxCYBBYMH+VxdOcX3KhsBoaw+TF3MGiX2e9FCHS95Lv3-hA-B9gDmEyLOQtY6MJocwJgpJ7ixAcCxY094xhsBA-I6UzgKOl7Ll5xgx0HD3rEw4DfLRSSkKPEUYI2XxedOl19REe+m6oOb1nlucIxjtME8JhbLAIiqTudI7Z4zihsCoBRAAVdxL2vEdIboj1xsOclx-2JlHk7ZCqnFi8D0e6Qpq873lOEnwUV6BxiTnYm9GfAAHlcBSsjMTkopvAL9BBQCjlBAID2BoCZZMdP4jB8hbJDhMhFJ9gCg1A+RzQWRUhKhnJMglAsoFE2FMlsNDcEdad456cOk0cMcQM2dtgR4hRi41hWNCp5BHMqlAChRp89wppR59wYF59kkiJGDUcWDJB312h-BVkoA8BQ9w9-AMkVDNCAJtDsCeDLcykYwUgA5ZBwRi4GMyFbM-8SFzRkw9wuYFEiAGcuDWDWkDCSNn8cD7ZCkvZcdSkUQCcgcyxaFvYpIAl9g-V9YFDrsiJPDODVD1D8AjCpYdCw8I8ODGcsiTD5UURFckxZMO91A0RgELwDRZDhRGglhYF-BcAk5dkSBKAfBghQgWIwA2j8Zo8CZE0XlBA7BdwpkMhwcZ1DtEBBpFcrB0R7oRQbAFoyBsAuhhgNDE5-A7VE04Dk1CNVj1iRhBBE5BA2jKAXk9Rdx39WVf4eQ08qZcpaF9wKotBockjJBDiNjMitjOEjINDYASI9iCNLkvjjjTjATCxAidRPYLBq0zoVhTQoM4MoZi5aDUh1Bkt3j7wWiMB4AogkkoALdK8kgGgYxZB5AlBZplhIirQDRspOQOtYZUNCT3RiTcCkg1gCDwQvlNBzQuZLEVhjE1B-4nihdYF2T7YMTWRjoVV95R8-ljxvZsQyp2wzRk8ml4EwBJS-oTh05Xizp9wzQESGwUQKhyjXMh9LtGEMMdNoUGJiVCstlit9kdToJbRWRPlFBWYkw95v9XlbBpAzQuRThcQkw58X1FDexMNnULVnTG03Tdp1BFUydJQJBBoxJXJrRjxPJcgzsxRON61Y0nlEz5Y7QpBORZEVBccsQCoKEzQSpFgEI9xCzP0Sy18STDEbcjTqgGgXJr1TgQiRFypkzZ00MMs307T-D2yK8OTDEvYzh5J8hsRDgQELo1BAU689RVAp8CgvMZw15fgEyOy5yt9QdhoVgQFBCIYVB0gxJsQRQ4Y9YRslscYVsCt6srUyVSy0p2w0gfsOQjw298hJITp0g2Zh49Qfs89mcfykR7AO58DTRsRbRyCoYpouRToqSNglIPjVIn9Jcl84LSh-4YweQkKbB1B6g09AzVgYNwlBlR4xzWT8LqdJcWjcVVxiLrAKpWRu5DRawygowak29KgO99wzgWSrsmECLmdfcA8g9Xh8TZygjgybQwcVha8VBIip8bQchJQlgliVgYKjdE0FlI8Rh-BDBuKcQINnJMKzRVh-SGZBIAF0zJLrBu8TdiKcJzA1hTRmQpQzBcgGwhTmwaM2wOw8KAor98APFb8fFE5uKXCLBmUNhZDIZR5LRBy9gKoRzs8rCQCwDI9ICSIYCfL6hzAJBB49ZH1kRyDf9R41UzQ7o-yGCUd-D4duLVBFU1BrdQ1RR1UD9VASdbA7FJRNVmLpLVJlDOq5KMioAJwMEcZ0F-xE03hurrQSl+qFdCCNZcRpBq0YR3dsQpqbSApZrmDvcFrCi8BuqhTtUXZHy7DUIzToxzQXCtBrBEZoq6pUiCiuqTygiRz0gJ17Eh4xFxCzAKh-4vlIdaYPCvD0idMNDwpWJ+htjFL2Burf9-U1gEwppjQ84uZNz9xet0rljfrDZ-rvC1CUbMitC7qgaCkSoYjIYrTT998q9MgDR-ZC1p8yj3jIzkijyWj-BzjtTmbSwRj8gFhzR+aNg1h+a+QuZ04Roy06g6wViZcjjNik4djJaVK-ozghQRRGLCofTTgHiZIw0RRB4JofrhbPidbvjFrfi+B-jMjISewfLeLREIdjxchqhbAmYWQS4t9mQcR9wXAXAgA */ id: 'Modeling', tsTypes: {} as import('./modelingMachine.typegen').Typegen0, @@ -558,7 +558,7 @@ export const modelingMachine = createMachine( on: { 'Equip rectangle tool': { target: 'Rectangle tool', - actions: 'Sketch is empty', + cond: 'Sketch is empty', }, }, }, @@ -993,7 +993,7 @@ export const modelingMachine = createMachine( }, 'listen for rectangle origin': ({ sketchDetails }) => { if (!sketchDetails) return - sceneEntitiesManager.setupRectangleOriginListener() + sceneEntitiesManager.setupOriginListener('rectangle') }, 'set up draft rectangle': ({ sketchDetails }, { data }) => { if (!sketchDetails || !data) return @@ -1007,11 +1007,11 @@ export const modelingMachine = createMachine( }, 'listen for circle origin': ({ sketchDetails }) => { if (!sketchDetails) return - sceneEntitiesManager.setupRectangleOriginListener() + sceneEntitiesManager.setupOriginListener('circle') }, 'set up draft circle': ({ sketchDetails }, { data }) => { if (!sketchDetails || !data) return - sceneEntitiesManager.setupDraftRectangle( + sceneEntitiesManager.setupDraftCircle( sketchDetails.sketchPathToNode, sketchDetails.zAxis, sketchDetails.yAxis,