2024-07-05 13:40:16 +10:00
|
|
|
import {
|
|
|
|
PathToNode,
|
|
|
|
VariableDeclaration,
|
|
|
|
VariableDeclarator,
|
|
|
|
parse,
|
|
|
|
recast,
|
Remove KclValue::SketchGroup variant (#3446)
We can store Rust types like `SketchGroup` as their own variant of `KclValue`, or as `KclValue::UserVal`. Sometimes we store in one and try to read from the other, which fails. This causes bugs, like #3338.
Instead, we should use either ::SketchGroup or ::UserVal, and stop using the other. If we stopped using ::UserVal, we'd need a new variant for every Rust type we wanted to build, including user-defined types. So I don't think that's practical.
Instead, we should store every KCL value by de/serializing it into UserVal. This is a first step along that path, removing just the SketchGroup variants. If it goes well, we can remove the other specialized variants too.
My only concern is there might be performance implications from how frequently we convert between serde_json::Value and Rust types via Serde. But I'm not too worried -- there's no parsing JSON strings, just traversing serde_json::Value trees. This isn't great for performance but I think it'll probably be miniscule in comparison to doing all the API calls.
2024-08-21 11:06:48 -05:00
|
|
|
sketchGroupFromKclValue,
|
2024-07-05 13:40:16 +10:00
|
|
|
} from 'lang/wasm'
|
2024-05-30 13:28:29 +10:00
|
|
|
import { Axis, Selection, Selections, updateSelections } from 'lib/selections'
|
2023-10-11 13:36:54 +11:00
|
|
|
import { assign, createMachine } from 'xstate'
|
2024-07-02 17:16:27 +10:00
|
|
|
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
2024-05-24 20:54:42 +10:00
|
|
|
import {
|
|
|
|
isNodeSafeToReplacePath,
|
|
|
|
getNodePathFromSourceRange,
|
|
|
|
} from 'lang/queryAst'
|
2024-03-28 17:22:11 +11:00
|
|
|
import {
|
|
|
|
kclManager,
|
|
|
|
sceneInfra,
|
|
|
|
sceneEntitiesManager,
|
|
|
|
engineCommandManager,
|
2024-04-19 14:24:40 -07:00
|
|
|
editorManager,
|
2024-03-28 17:22:11 +11:00
|
|
|
} from 'lib/singletons'
|
2023-10-11 13:36:54 +11:00
|
|
|
import {
|
|
|
|
horzVertInfo,
|
|
|
|
applyConstraintHorzVert,
|
|
|
|
} from 'components/Toolbar/HorzVert'
|
|
|
|
import {
|
|
|
|
applyConstraintHorzVertAlign,
|
|
|
|
horzVertDistanceInfo,
|
|
|
|
} from 'components/Toolbar/SetHorzVertDistance'
|
|
|
|
import { angleBetweenInfo } from 'components/Toolbar/SetAngleBetween'
|
2023-12-01 20:18:51 +11:00
|
|
|
import { angleLengthInfo } from 'components/Toolbar/setAngleLength'
|
2023-10-11 13:36:54 +11:00
|
|
|
import {
|
|
|
|
applyConstraintEqualLength,
|
|
|
|
setEqualLengthInfo,
|
|
|
|
} from 'components/Toolbar/EqualLength'
|
2024-08-03 07:05:35 +10:00
|
|
|
import { deleteFromSelection, extrudeSketch } from 'lang/modifyAst'
|
2024-07-15 19:20:32 +10:00
|
|
|
import { addFillet } from 'lang/modifyAst/addFillet'
|
2023-10-11 13:36:54 +11:00
|
|
|
import { getNodeFromPath } from '../lang/queryAst'
|
2023-10-16 08:54:38 +11:00
|
|
|
import {
|
|
|
|
applyConstraintEqualAngle,
|
|
|
|
equalAngleInfo,
|
|
|
|
} from 'components/Toolbar/EqualAngle'
|
|
|
|
import {
|
|
|
|
applyRemoveConstrainingValues,
|
|
|
|
removeConstrainingValuesInfo,
|
|
|
|
} from 'components/Toolbar/RemoveConstrainingValues'
|
|
|
|
import { intersectInfo } from 'components/Toolbar/Intersect'
|
2023-12-01 20:18:51 +11:00
|
|
|
import {
|
|
|
|
absDistanceInfo,
|
|
|
|
applyConstraintAxisAlign,
|
|
|
|
} from 'components/Toolbar/SetAbsDistance'
|
2024-02-11 12:59:00 +11:00
|
|
|
import { Models } from '@kittycad/lib/dist/types/src'
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
import { ModelingCommandSchema } from 'lib/commandBarConfigs/modelingCommandConfig'
|
2024-06-24 11:45:40 -04:00
|
|
|
import { err, trap } from 'lib/trap'
|
2024-06-29 10:36:04 -07:00
|
|
|
import { DefaultPlaneStr, getFaceDetails } from 'clientSideScene/sceneEntities'
|
2024-04-03 19:38:16 +11:00
|
|
|
import { uuidv4 } from 'lib/utils'
|
2024-05-24 20:54:42 +10:00
|
|
|
import { Coords2d } from 'lang/std/sketch'
|
|
|
|
import { deleteSegment } from 'clientSideScene/ClientSideSceneComp'
|
2024-07-02 17:16:27 +10:00
|
|
|
import { executeAst } from 'lang/langHelpers'
|
2024-06-29 10:36:04 -07:00
|
|
|
import toast from 'react-hot-toast'
|
2024-08-03 18:08:51 +10:00
|
|
|
import { getExtrusionFromSuspectedPath } from 'lang/std/artifactGraph'
|
2023-10-11 13:36:54 +11:00
|
|
|
|
|
|
|
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
|
|
|
|
|
|
|
|
export type SetSelections =
|
|
|
|
| {
|
|
|
|
selectionType: 'singleCodeCursor'
|
|
|
|
selection?: Selection
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
selectionType: 'otherSelection'
|
|
|
|
selection: Axis
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
selectionType: 'completeSelection'
|
|
|
|
selection: Selections
|
2024-05-31 11:36:08 +10:00
|
|
|
updatedPathToNode?: PathToNode
|
2023-10-11 13:36:54 +11:00
|
|
|
}
|
|
|
|
| {
|
|
|
|
selectionType: 'mirrorCodeMirrorSelections'
|
|
|
|
selection: Selections
|
|
|
|
}
|
|
|
|
|
2024-04-04 11:07:51 +11:00
|
|
|
export type MouseState =
|
|
|
|
| {
|
|
|
|
type: 'idle'
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: 'isHovering'
|
|
|
|
on: any
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: 'isDragging'
|
|
|
|
on: any
|
|
|
|
}
|
2024-05-24 20:54:42 +10:00
|
|
|
| {
|
|
|
|
type: 'timeoutEnd'
|
|
|
|
pathToNodeString: string
|
|
|
|
}
|
2024-04-04 11:07:51 +11:00
|
|
|
|
2024-03-22 10:23:04 +11:00
|
|
|
export interface SketchDetails {
|
|
|
|
sketchPathToNode: PathToNode
|
|
|
|
zAxis: [number, number, number]
|
|
|
|
yAxis: [number, number, number]
|
|
|
|
origin: [number, number, number]
|
|
|
|
}
|
|
|
|
|
2024-05-24 20:54:42 +10:00
|
|
|
export interface SegmentOverlay {
|
|
|
|
windowCoords: Coords2d
|
|
|
|
angle: number
|
|
|
|
group: any
|
|
|
|
pathToNode: PathToNode
|
|
|
|
visible: boolean
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface SegmentOverlays {
|
|
|
|
[pathToNodeString: string]: SegmentOverlay
|
|
|
|
}
|
|
|
|
|
|
|
|
export type SegmentOverlayPayload =
|
|
|
|
| {
|
|
|
|
type: 'set-one'
|
|
|
|
pathToNodeString: string
|
|
|
|
seg: SegmentOverlay
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: 'delete-one'
|
|
|
|
pathToNodeString: string
|
|
|
|
}
|
|
|
|
| { type: 'clear' }
|
|
|
|
| {
|
|
|
|
type: 'set-many'
|
|
|
|
overlays: SegmentOverlays
|
|
|
|
}
|
|
|
|
|
2024-08-14 14:26:44 -04:00
|
|
|
export interface Store {
|
2024-07-04 01:55:06 -04:00
|
|
|
videoElement?: HTMLVideoElement
|
2024-07-02 17:16:27 +10:00
|
|
|
buttonDownInStream: number | undefined
|
|
|
|
didDragInStream: boolean
|
|
|
|
streamDimensions: { streamWidth: number; streamHeight: number }
|
|
|
|
openPanes: SidebarType[]
|
|
|
|
}
|
|
|
|
|
2024-07-12 16:16:26 -04:00
|
|
|
export type SketchTool = 'line' | 'tangentialArc' | 'rectangle' | 'none'
|
|
|
|
|
2023-10-16 21:20:05 +11:00
|
|
|
export type ModelingMachineEvent =
|
2024-02-19 17:23:03 +11:00
|
|
|
| {
|
|
|
|
type: 'Enter sketch'
|
|
|
|
data?: {
|
|
|
|
forceNewSketch?: boolean
|
|
|
|
}
|
|
|
|
}
|
2024-03-22 10:23:04 +11:00
|
|
|
| { type: 'Sketch On Face' }
|
2023-10-16 21:20:05 +11:00
|
|
|
| {
|
2024-02-11 12:59:00 +11:00
|
|
|
type: 'Select default plane'
|
2024-03-22 10:23:04 +11:00
|
|
|
data: {
|
|
|
|
zAxis: [number, number, number]
|
|
|
|
yAxis: [number, number, number]
|
|
|
|
} & (
|
|
|
|
| {
|
|
|
|
type: 'defaultPlane'
|
|
|
|
plane: DefaultPlaneStr
|
2024-04-22 20:14:06 +10:00
|
|
|
planeId: string
|
2024-03-22 10:23:04 +11:00
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: 'extrudeFace'
|
|
|
|
position: [number, number, number]
|
2024-06-04 13:57:01 -04:00
|
|
|
sketchPathToNode: PathToNode
|
|
|
|
extrudePathToNode: PathToNode
|
2024-03-22 10:23:04 +11:00
|
|
|
cap: 'start' | 'end' | 'none'
|
2024-04-22 20:14:06 +10:00
|
|
|
faceId: string
|
2024-03-22 10:23:04 +11:00
|
|
|
}
|
|
|
|
)
|
2023-10-16 21:20:05 +11:00
|
|
|
}
|
2024-05-30 13:28:29 +10:00
|
|
|
| {
|
|
|
|
type: 'Set selection'
|
|
|
|
data: SetSelections
|
|
|
|
}
|
2024-06-29 10:36:04 -07:00
|
|
|
| {
|
|
|
|
type: 'Delete selection'
|
|
|
|
}
|
2023-10-16 21:20:05 +11:00
|
|
|
| { type: 'Sketch no face' }
|
|
|
|
| { type: 'Toggle gui mode' }
|
|
|
|
| { type: 'Cancel' }
|
|
|
|
| { type: 'CancelSketch' }
|
2024-02-11 12:59:00 +11:00
|
|
|
| { type: 'Add start point' }
|
2023-10-16 21:20:05 +11:00
|
|
|
| { type: 'Make segment horizontal' }
|
|
|
|
| { type: 'Make segment vertical' }
|
|
|
|
| { type: 'Constrain horizontal distance' }
|
2023-12-01 20:18:51 +11:00
|
|
|
| { type: 'Constrain ABS X' }
|
|
|
|
| { type: 'Constrain ABS Y' }
|
2023-10-16 21:20:05 +11:00
|
|
|
| { type: 'Constrain vertical distance' }
|
|
|
|
| { type: 'Constrain angle' }
|
|
|
|
| { type: 'Constrain perpendicular distance' }
|
|
|
|
| { type: 'Constrain horizontally align' }
|
|
|
|
| { type: 'Constrain vertically align' }
|
2023-12-01 20:18:51 +11:00
|
|
|
| { type: 'Constrain snap to X' }
|
|
|
|
| { type: 'Constrain snap to Y' }
|
2023-10-16 21:20:05 +11:00
|
|
|
| { type: 'Constrain length' }
|
|
|
|
| { type: 'Constrain equal length' }
|
|
|
|
| { type: 'Constrain parallel' }
|
2024-06-04 16:29:20 +10:00
|
|
|
| { type: 'Constrain remove constraints'; data?: PathToNode }
|
2023-10-18 08:03:02 +11:00
|
|
|
| { type: 'Re-execute' }
|
2024-03-04 16:06:43 -05:00
|
|
|
| { type: 'Export'; data: ModelingCommandSchema['Export'] }
|
2024-08-04 00:51:30 -04:00
|
|
|
| { type: 'Make'; data: ModelingCommandSchema['Make'] }
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
| { type: 'Extrude'; data?: ModelingCommandSchema['Extrude'] }
|
2024-07-15 19:20:32 +10:00
|
|
|
| { type: 'Fillet'; data?: ModelingCommandSchema['Fillet'] }
|
2024-08-14 14:26:44 -04:00
|
|
|
| { type: 'Text-to-CAD'; data: ModelingCommandSchema['Text-to-CAD'] }
|
2024-04-19 11:56:21 -04:00
|
|
|
| {
|
|
|
|
type: 'Add rectangle origin'
|
|
|
|
data: [x: number, y: number]
|
|
|
|
}
|
2024-02-11 12:59:00 +11:00
|
|
|
| {
|
2024-03-22 10:23:04 +11:00
|
|
|
type: 'done.invoke.animate-to-face' | 'done.invoke.animate-to-sketch'
|
|
|
|
data: SketchDetails
|
2024-02-11 12:59:00 +11:00
|
|
|
}
|
2024-04-04 11:07:51 +11:00
|
|
|
| { type: 'Set mouse state'; data: MouseState }
|
2024-07-02 17:16:27 +10:00
|
|
|
| { type: 'Set context'; data: Partial<Store> }
|
2024-05-24 20:54:42 +10:00
|
|
|
| {
|
|
|
|
type: 'Set Segment Overlays'
|
|
|
|
data: SegmentOverlayPayload
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: 'Delete segment'
|
|
|
|
data: PathToNode
|
|
|
|
}
|
2024-05-06 19:28:30 +10:00
|
|
|
| {
|
|
|
|
type: 'code edit during sketch'
|
|
|
|
}
|
2024-05-24 20:54:42 +10:00
|
|
|
| {
|
|
|
|
type: 'Convert to variable'
|
|
|
|
data: {
|
|
|
|
pathToNode: PathToNode
|
|
|
|
variableName: string
|
|
|
|
}
|
|
|
|
}
|
2024-07-05 13:40:16 +10:00
|
|
|
| {
|
|
|
|
type: 'change tool'
|
2024-07-12 16:16:26 -04:00
|
|
|
data: {
|
|
|
|
tool: SketchTool
|
|
|
|
}
|
2024-07-05 13:40:16 +10:00
|
|
|
}
|
|
|
|
| { type: 'Finish rectangle' }
|
2024-08-03 07:05:35 +10:00
|
|
|
| { type: 'Artifact graph populated' }
|
|
|
|
| { type: 'Artifact graph emptied' }
|
2024-02-11 12:59:00 +11:00
|
|
|
|
|
|
|
export type MoveDesc = { line: number; snippet: string }
|
2023-10-16 21:20:05 +11:00
|
|
|
|
2024-07-02 17:16:27 +10:00
|
|
|
export const PERSIST_MODELING_CONTEXT = 'persistModelingContext'
|
|
|
|
interface PersistedModelingContext {
|
|
|
|
openPanes: Store['openPanes']
|
|
|
|
}
|
|
|
|
|
|
|
|
type PersistedKeys = keyof PersistedModelingContext
|
|
|
|
export const PersistedValues: PersistedKeys[] = ['openPanes']
|
|
|
|
|
2024-08-02 15:39:05 -04:00
|
|
|
export const getPersistedContext = (): Partial<PersistedModelingContext> => {
|
|
|
|
const c = (typeof window !== 'undefined' &&
|
|
|
|
JSON.parse(localStorage.getItem(PERSIST_MODELING_CONTEXT) || '{}')) || {
|
|
|
|
openPanes: ['code'],
|
|
|
|
}
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
export const modelingMachineDefaultContext = {
|
|
|
|
tool: null as Models['SceneToolType_type'] | null,
|
|
|
|
selection: [] as string[],
|
|
|
|
selectionRanges: {
|
|
|
|
otherSelections: [],
|
|
|
|
codeBasedSelections: [],
|
|
|
|
} as Selections,
|
|
|
|
sketchDetails: {
|
|
|
|
sketchPathToNode: [],
|
|
|
|
zAxis: [0, 0, 1],
|
|
|
|
yAxis: [0, 1, 0],
|
|
|
|
origin: [0, 0, 0],
|
|
|
|
} as null | SketchDetails,
|
|
|
|
sketchPlaneId: '' as string,
|
|
|
|
sketchEnginePathId: '' as string,
|
|
|
|
moveDescs: [] as MoveDesc[],
|
|
|
|
mouseState: { type: 'idle' } as MouseState,
|
|
|
|
segmentOverlays: {} as SegmentOverlays,
|
|
|
|
segmentHoverMap: {} as { [pathToNodeString: string]: number },
|
|
|
|
store: {
|
|
|
|
buttonDownInStream: undefined,
|
|
|
|
didDragInStream: false,
|
|
|
|
streamDimensions: { streamWidth: 1280, streamHeight: 720 },
|
|
|
|
openPanes: getPersistedContext().openPanes || ['code'],
|
|
|
|
} as Store,
|
2024-07-02 17:16:27 +10:00
|
|
|
}
|
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
export const modelingMachine = createMachine(
|
|
|
|
{
|
2024-08-14 14:26:44 -04:00
|
|
|
/** @xstate-layout N4IgpgJg5mDOIC5QFkD2EwBsCWA7KAxAMICGuAxlgNoAMAuoqAA6qzYAu2qujIAHogC0ANhoBWAHQAOAMwB2KQEY5AFgCcGqWqkAaEAE9Ew0RLEqa64TIBMKmTUXCAvk71oMOfAQDKYdgAJYLDByTm5aBiQQFjYwniiBBEEpYSkJOUUaOWsxeylrWzk9QwQClQkrVOsZNWExFItnVxB3LDxCXwCAW1QAVyDA9hJ2MAjeGI4ueNBE5KkaCWspZfMM+XE1YsQZMQWxNQtxao0ZeRc3dDavTv9ybhG+djGoibjeRJothBpzlsvPDp+fy+KBdMC4AIAeQAbmAAE6YEj6WDPZisSbcd6IT4GbG-VoAiTYCCYMAEACiEPhgQA1n5yAALVHRdFvBJCazCOQSRSctQyKS5RRqFTWL6nNTSfnSsS5FRiZT4-7tIkksmUkZw2n0pmKSJo2JTLFJWwLFSOBy7WQ0eZFXEIczWCRqaxyOq81KKAWOJUeFXE0kUx5w3oYZmvI3spJiOQyZ1mZQyeUyRSC4RfXmndKOKRyWUpmqKX1XKCqwMAMWwmFJT3o41ZkZmQnzEjsgoVXPE2TtJS9KmEPNjuZsKbkDmLhID6r4LDhtf1LMNmKjgjEdXSrtENuEihUcjUigz-cUEhqeaUwmsqavE-9aoIyBIdPDDeXTYdTtSIusalj5qy+xfFyaSxvUKh7rKdgqFIt74GWZIACLBCMgTBKEUwvku0z8EIO7lNoCZjqm5qKGIGYxuUNSXj+iiOLR+6waWU4EAAKmAjyCOwqCCEQACCCGYRi2GzAqTpmCkspqLKf7pvayj9hU8gFPs+TCOaciMfBEgMsSYAAAqIrgcAELxc7YAAZiQoT+FAcIkEwDL+CwTC9IiIwQIJbLvoI-aSuIia-loQUyLJJS-nGlrQbmXq0VIKiaVOEiwAyqAAO4GWQxmmZwlnWbZ9mOWAXRMJwkCeY2OFJHu3IKDGYicsB4F5hmvJOqmB5ejQNBWAe1iad4dLsIyxBkJQmADTq5VvpVmZxrYSacmuHq2C1BwSN1-Y7DG+40DI-WDcNSE1mAqGguC871lhxpyHmzo-vVcW-jashfPK3IaOY+a7Gp3X7TqBB3Bg-iQBw-gQL0cLtNqQ1MnWLyvsJiBei6ph7oFWhqWYPaINK61rsstRZLRIp-TDEgTTDACS96PnSp1ghC-iwmZ5AkJgU2IwgXoCqeqaqY40G1EeBSLPKj3zMsSx7c0BIqhTjLkwdDLU4GtMnUEZ2MylkMAF73GzHPGl6V7pOB9Q7PylQqBmNhmge9X7ETXVFjLypwfLDKKzqKtkkQ3CwOwdl4P42vYHrEJs2D2AB6NoxwwaQlG-YJ7KPkywpjGyxfKakjOzYe47KRbqkwrHs+8Q-uByQwfM5wrOYFHMcUHHC4RtNiQxQOz3WrywpytnSxOnuXU0AcuQpiXntl-efu4AHQe4P4vEAELeP4AAahtRtzYl-vy5pXjuZH2j+VjOjQnIWPY1gODBrt+u7Ste1TM+VwvS+r-4ACaW-vjvp4KF3KPWoDtrb2nsL+CoaxzxxQUCkSez9GTl1nvPaui8yBQFJL-GaNQ9jCltBsCw+Rs4dkWBYR0u0ljgXivfEsiCp5K2QW-NB-hST4HYLDVuCMk5xVMJaXMO4UxxRkNnS8NVSK2AKDfZYpEEHT0DCgquwcmDwhUbgCA2ByCuRIFqDRTdKDYI7q6SQVh6oHEltkbQ2d8hxmMDGAoI91B9VoYSD29CmFzyUYvUO4chjVn0P4Nm2AoC4EMUjCBzoRSbVUsY4+vYHai0cNkLqIUbTSwuA-Usbj5G+2YTXeEdc2aYACUEkJYSuY2AHPjQU+5fycjsBmKw5RchrgKFJA4I45GMNfp49+sBcD2X8FxDe5SvQmBqIFVQ+xMjEJPv5Qcu5zFKAPBpFxcsn45Irr0lh-TBnDJ-vHRcidt6pMWK1WoV59yxhESfUiA51Dyl2MKHYo8unex6ag4OYAACOvRI5sKgBw0ZSYFh1AAkoFI5yMyxklPIHc81Km7jeS-BReTF5MB0UU6ghy26cy9KoHkl59hckyLuL0GYpJVNlHFBwak+zIqQR8rx-g4RFVQLCW4aL2Aohxdw7e91TbCL3GC4xGZZCSguaoYeB4UwuwyXQ7J3TAwACUwCCHYiEXoIxRk7jSNoc0dQNCiF-BmcQZpZDgUpcIE4zj5WuI2UqskgMTogwCODSG+BoaMmBSjHcHUFBjjsMKU1u11pulMWufkso5V-EyfQ9xPTa5DNQEzHR2ASAACMsG8quicjQ0gsiqRFMKKwYpwGH1PGuPCN99g0LtesnUCbAyMgwSdLiqB2Y5uOe+HIF9pA-lHjkA44Uy29gkWGrcbTZBWDvvWx+jbeKpWrgEHx+sG56KGM3fweBzKoAIBAbgYAiS4GhKgOkEgYDsEEKuiOmBBA7tQOU6oCpTA2MltI-scTECSJAtoNSUrcgODrbGhVT9F3LpDqgXWa7G6bsoNu3Au6CDwjhFBiQTA3K7rhF0C9fhr1QbDmu+9iHH1dq8pVZ9Tpe0Cm0JyUimwT64OdCkUU-YljzBjAg8DoNa6aMjhu2OCGkMHqMse0957L2CF4-XYju6n0W0WLGOBcV5iXgHijfImQ3TmBdIqNZ86ybcYCNJ-j0c4MnQfchuEqG4Tocw1BnDkmTN3offJ-Yzp1JwrXGOEUA8X20V3A1NSpx0kgftQupdoMV5r3XkJvdImj14HE0eyTmbYCCD4LJ0jXDc09pCnGLQ+5bRJktdnX8J5tymjHCkbIXHIsBGixvOLVmbN2eGFhxzeG0sZay-JtSphrUpBvhkdSZWcinnITdAUWR+SrLnVksD9WP5ry-s1hLYmz0pa6xm9L+hetkYqokaoZ91CJnApkea2MED2DdK2JqqhBTDtzHViDjXVuWZQ2hjD7WHO4avd1vbrmDvt2-SFcojgQpFz3FeG04pEzrVItBOoroDVzbCw2wzS2MGkjW4ejbEmuv4FJPtnL3aKNg9bPIWi8hzCzJKDkdcAibBmBTL1YDssDMKyM4EonFmSMta+-Z7Df3BDY7VUD0n5GjshUkDSzIxgHBukPCfeqXd9g1HlItEbL3QYAo4bj0TSXNsi71wyEnl0yfS8vAN2Q2Q6i7GyKIkU61R5kqsDdTj+mFsRYg6b5rn3bPffYB1k34JAVm4lxbqXoOz7HdOMYdQSZdyiJfaIWQ+KFT5F2jrgIKi4RqI0VoxEuizOCcs+to3BOr154L5o7RcJBACebub+GuXyeZHWiKewKZdrRqu1LSiygB25mkjnpyqjwSF-r7Bsv-OA9teD79yTNfJ91+L430vzfI+t8t6Djvo87C7UyFtZQ2cFADlHMPvMnv5vxoADJ4DbagDtAMGStuTR2p9ogqlixuqmUtXwLoaQquuwtQogro44Xu9+j+H+mAEglMuAHABAT6UszoUqICeYvIL09o1qCwxEbopwXotutq6OnOnsD+RksB8BiB7AyBeoUeh236NEaBWB-Y4ESkoUiA+4A4v41qEOV4AoCgCCFBT+HaEgAAcimnpKgHgNyiZBABAIMDornjIRCF-mtNfDUCONoFJEBNkK2EfNtNkPsAxFAW4iIVQZIf4NIbIbACNM3J2pLowVzBjIStOl2PYroPaBkGaKKIrvUFoDaAgggUgaMt1LYofFng0OfhmJIq2H2LsPHhAsETQXQU4SDlzMAutJyOnLREsGOJwRUl1OkLKoGhfLkIKAgixK2hCOmg3DouQMmq-u-u2o4QwRkesBfvKOINasNqIFdueBUMPAQTNjaGIAgr0OoimjHHOB7JCLgPunjpXkerxN4CxIIJMQeoIDMewHMaEsDnipDq+jdFeGLPsL5t4f5pjNBJnGjOzm7N7mTKqqEGLrAc0fgKIW0TvtHtdpkHgeJCjryOfldhdpKLqvkHmGMWuAgs8Zupgp8RIEZlDEEHcOopynCEZHCAQJWIgclCyiEHCdmukZzAtJ+EKI0P5AqGAiULmE6PnN+DuJkHuPcXGm4rCa8a0YifVlDARlAHgPIYoayi8bzv4LyX
|
2023-10-11 13:36:54 +11:00
|
|
|
id: 'Modeling',
|
|
|
|
|
|
|
|
tsTypes: {} as import('./modelingMachine.typegen').Typegen0,
|
|
|
|
predictableActionArguments: true,
|
|
|
|
preserveActionOrder: true,
|
|
|
|
|
2024-08-02 15:39:05 -04:00
|
|
|
context: modelingMachineDefaultContext,
|
2023-10-11 13:36:54 +11:00
|
|
|
|
|
|
|
schema: {
|
2023-10-16 21:20:05 +11:00
|
|
|
events: {} as ModelingMachineEvent,
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
states: {
|
|
|
|
idle: {
|
|
|
|
on: {
|
|
|
|
'Enter sketch': [
|
|
|
|
{
|
2024-02-11 12:59:00 +11:00
|
|
|
target: 'animating to existing sketch',
|
2024-02-19 17:23:03 +11:00
|
|
|
cond: 'Selection is on face',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
'Sketch no face',
|
|
|
|
],
|
|
|
|
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
Extrude: {
|
|
|
|
target: 'idle',
|
|
|
|
cond: 'has valid extrude selection',
|
|
|
|
actions: ['AST extrude'],
|
|
|
|
internal: true,
|
|
|
|
},
|
2024-03-04 16:06:43 -05:00
|
|
|
|
2024-07-15 19:20:32 +10:00
|
|
|
Fillet: {
|
|
|
|
target: 'idle',
|
|
|
|
cond: 'has valid fillet selection', // TODO: fix selections
|
|
|
|
actions: ['AST fillet'],
|
|
|
|
internal: true,
|
|
|
|
},
|
|
|
|
|
2024-03-04 16:06:43 -05:00
|
|
|
Export: {
|
|
|
|
target: 'idle',
|
|
|
|
internal: true,
|
|
|
|
cond: 'Has exportable geometry',
|
|
|
|
actions: 'Engine export',
|
|
|
|
},
|
2024-06-29 10:36:04 -07:00
|
|
|
|
2024-08-04 00:51:30 -04:00
|
|
|
Make: {
|
|
|
|
target: 'idle',
|
|
|
|
internal: true,
|
|
|
|
cond: 'Has exportable geometry',
|
|
|
|
actions: 'Make',
|
|
|
|
},
|
|
|
|
|
2024-06-29 10:36:04 -07:00
|
|
|
'Delete selection': {
|
|
|
|
target: 'idle',
|
|
|
|
cond: 'has valid selection for deletion',
|
|
|
|
actions: ['AST delete selection'],
|
|
|
|
internal: true,
|
|
|
|
},
|
2024-08-14 14:26:44 -04:00
|
|
|
|
|
|
|
'Text-to-CAD': {
|
|
|
|
target: 'idle',
|
|
|
|
internal: true,
|
2024-08-14 23:08:37 -07:00
|
|
|
actions: ['Submit to Text-to-CAD API'],
|
2024-08-14 14:26:44 -04:00
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
2024-02-19 12:41:36 +11:00
|
|
|
|
|
|
|
entry: 'reset client scene mouse handlers',
|
2024-08-03 07:05:35 +10:00
|
|
|
|
|
|
|
states: {
|
|
|
|
hidePlanes: {
|
|
|
|
on: {
|
|
|
|
'Artifact graph populated': 'showPlanes',
|
|
|
|
},
|
|
|
|
|
|
|
|
entry: 'hide default planes',
|
|
|
|
},
|
|
|
|
|
|
|
|
showPlanes: {
|
|
|
|
on: {
|
|
|
|
'Artifact graph emptied': 'hidePlanes',
|
|
|
|
},
|
|
|
|
|
2024-08-06 17:05:46 +10:00
|
|
|
entry: ['show default planes', 'reset camera position'],
|
2024-08-03 07:05:35 +10:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
initial: 'hidePlanes',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
Sketch: {
|
|
|
|
states: {
|
|
|
|
SketchIdle: {
|
|
|
|
on: {
|
|
|
|
'Make segment vertical': {
|
|
|
|
cond: 'Can make selection vertical',
|
2024-05-30 19:43:35 +10:00
|
|
|
target: 'Await constrain vertically',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
'Make segment horizontal': {
|
|
|
|
cond: 'Can make selection horizontal',
|
2024-05-30 19:43:35 +10:00
|
|
|
target: 'Await constrain horizontally',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
'Constrain horizontal distance': {
|
|
|
|
target: 'Await horizontal distance info',
|
|
|
|
cond: 'Can constrain horizontal distance',
|
|
|
|
},
|
|
|
|
|
|
|
|
'Constrain vertical distance': {
|
|
|
|
target: 'Await vertical distance info',
|
|
|
|
cond: 'Can constrain vertical distance',
|
|
|
|
},
|
|
|
|
|
2023-12-01 20:18:51 +11:00
|
|
|
'Constrain ABS X': {
|
|
|
|
target: 'Await ABS X info',
|
|
|
|
cond: 'Can constrain ABS X',
|
|
|
|
},
|
|
|
|
|
|
|
|
'Constrain ABS Y': {
|
|
|
|
target: 'Await ABS Y info',
|
|
|
|
cond: 'Can constrain ABS Y',
|
|
|
|
},
|
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
'Constrain angle': {
|
|
|
|
target: 'Await angle info',
|
|
|
|
cond: 'Can constrain angle',
|
|
|
|
},
|
|
|
|
|
|
|
|
'Constrain length': {
|
|
|
|
target: 'Await length info',
|
|
|
|
cond: 'Can constrain length',
|
|
|
|
},
|
|
|
|
|
2023-10-16 08:54:38 +11:00
|
|
|
'Constrain perpendicular distance': {
|
|
|
|
target: 'Await perpendicular distance info',
|
|
|
|
cond: 'Can constrain perpendicular distance',
|
|
|
|
},
|
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
'Constrain horizontally align': {
|
|
|
|
cond: 'Can constrain horizontally align',
|
2024-05-30 13:28:29 +10:00
|
|
|
target: 'Await constrain horizontally align',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
'Constrain vertically align': {
|
|
|
|
cond: 'Can constrain vertically align',
|
2024-05-30 13:28:29 +10:00
|
|
|
target: 'Await constrain vertically align',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
2023-12-01 20:18:51 +11:00
|
|
|
'Constrain snap to X': {
|
|
|
|
cond: 'Can constrain snap to X',
|
2024-05-30 13:28:29 +10:00
|
|
|
target: 'Await constrain snap to X',
|
2023-12-01 20:18:51 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
'Constrain snap to Y': {
|
|
|
|
cond: 'Can constrain snap to Y',
|
2024-05-30 13:28:29 +10:00
|
|
|
target: 'Await constrain snap to Y',
|
2023-12-01 20:18:51 +11:00
|
|
|
},
|
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
'Constrain equal length': {
|
|
|
|
cond: 'Can constrain equal length',
|
2024-05-30 13:28:29 +10:00
|
|
|
target: 'Await constrain equal length',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
2023-10-16 08:54:38 +11:00
|
|
|
|
|
|
|
'Constrain parallel': {
|
2024-05-30 13:28:29 +10:00
|
|
|
target: 'Await constrain parallel',
|
2023-10-16 08:54:38 +11:00
|
|
|
cond: 'Can canstrain parallel',
|
|
|
|
},
|
|
|
|
|
|
|
|
'Constrain remove constraints': {
|
|
|
|
cond: 'Can constrain remove constraints',
|
2024-06-03 22:40:59 +10:00
|
|
|
target: 'Await constrain remove constraints',
|
2023-10-16 08:54:38 +11:00
|
|
|
},
|
2023-10-18 08:03:02 +11:00
|
|
|
|
|
|
|
'Re-execute': {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
internal: true,
|
2024-02-13 07:41:37 +11:00
|
|
|
actions: ['set sketchMetadata from pathToNode'],
|
2023-10-18 08:03:02 +11:00
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
|
2024-05-06 19:28:30 +10:00
|
|
|
'code edit during sketch': 'clean slate',
|
2024-05-24 20:54:42 +10:00
|
|
|
|
|
|
|
'Convert to variable': {
|
|
|
|
target: 'Await convert to variable',
|
|
|
|
cond: 'Can convert to variable',
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
|
|
|
'change tool': {
|
|
|
|
target: 'Change Tool',
|
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
2024-02-14 05:35:05 +11:00
|
|
|
entry: 'setup client side sketch segments',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
'Await horizontal distance info': {
|
|
|
|
invoke: {
|
|
|
|
src: 'Get horizontal info',
|
|
|
|
id: 'get-horizontal-info',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
onError: 'SketchIdle',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
'Await vertical distance info': {
|
|
|
|
invoke: {
|
|
|
|
src: 'Get vertical info',
|
|
|
|
id: 'get-vertical-info',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
onError: 'SketchIdle',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
2023-12-01 20:18:51 +11:00
|
|
|
'Await ABS X info': {
|
|
|
|
invoke: {
|
|
|
|
src: 'Get ABS X info',
|
|
|
|
id: 'get-abs-x-info',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
onError: 'SketchIdle',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
'Await ABS Y info': {
|
|
|
|
invoke: {
|
|
|
|
src: 'Get ABS Y info',
|
|
|
|
id: 'get-abs-y-info',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
onError: 'SketchIdle',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
'Await angle info': {
|
|
|
|
invoke: {
|
|
|
|
src: 'Get angle info',
|
|
|
|
id: 'get-angle-info',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
onError: 'SketchIdle',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
'Await length info': {
|
|
|
|
invoke: {
|
|
|
|
src: 'Get length info',
|
|
|
|
id: 'get-length-info',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
onError: 'SketchIdle',
|
|
|
|
},
|
|
|
|
},
|
2023-10-16 08:54:38 +11:00
|
|
|
|
|
|
|
'Await perpendicular distance info': {
|
|
|
|
invoke: {
|
|
|
|
src: 'Get perpendicular distance info',
|
|
|
|
id: 'get-perpendicular-distance-info',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
onError: 'SketchIdle',
|
|
|
|
},
|
|
|
|
},
|
2024-02-11 12:59:00 +11:00
|
|
|
|
|
|
|
'Line tool': {
|
2024-02-20 11:04:42 +11:00
|
|
|
exit: [],
|
2024-02-11 12:59:00 +11:00
|
|
|
|
|
|
|
states: {
|
|
|
|
Init: {
|
|
|
|
always: [
|
|
|
|
{
|
|
|
|
target: 'normal',
|
2024-07-10 07:01:49 +10:00
|
|
|
cond: 'has made first point',
|
2024-02-11 12:59:00 +11:00
|
|
|
actions: 'set up draft line',
|
|
|
|
},
|
|
|
|
'No Points',
|
|
|
|
],
|
|
|
|
},
|
|
|
|
|
2024-04-02 20:20:42 +11:00
|
|
|
normal: {},
|
2024-02-11 12:59:00 +11:00
|
|
|
|
|
|
|
'No Points': {
|
|
|
|
entry: 'setup noPoints onClick listener',
|
|
|
|
|
|
|
|
on: {
|
|
|
|
'Add start point': {
|
|
|
|
target: 'normal',
|
|
|
|
actions: 'set up draft line without teardown',
|
|
|
|
},
|
2024-02-14 05:35:05 +11:00
|
|
|
|
|
|
|
Cancel: '#Modeling.Sketch.undo startSketchOn',
|
2024-02-11 12:59:00 +11:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
initial: 'Init',
|
2024-07-05 13:40:16 +10:00
|
|
|
|
|
|
|
on: {
|
|
|
|
'change tool': {
|
|
|
|
target: 'Change Tool',
|
|
|
|
},
|
|
|
|
},
|
2024-02-11 12:59:00 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
Init: {
|
|
|
|
always: [
|
|
|
|
{
|
|
|
|
target: 'SketchIdle',
|
|
|
|
cond: 'is editing existing sketch',
|
|
|
|
},
|
|
|
|
'Line tool',
|
|
|
|
],
|
|
|
|
},
|
|
|
|
|
|
|
|
'Tangential arc to': {
|
|
|
|
entry: 'set up draft arc',
|
|
|
|
|
|
|
|
on: {
|
2024-07-05 13:40:16 +10:00
|
|
|
'change tool': {
|
|
|
|
target: 'Change Tool',
|
|
|
|
},
|
2024-02-11 12:59:00 +11:00
|
|
|
},
|
|
|
|
},
|
2024-02-14 05:35:05 +11:00
|
|
|
|
|
|
|
'undo startSketchOn': {
|
|
|
|
invoke: {
|
|
|
|
src: 'AST-undo-startSketchOn',
|
|
|
|
id: 'AST-undo-startSketchOn',
|
|
|
|
onDone: '#Modeling.idle',
|
|
|
|
},
|
|
|
|
},
|
2024-04-19 11:56:21 -04:00
|
|
|
|
|
|
|
'Rectangle tool': {
|
|
|
|
entry: ['listen for rectangle origin'],
|
2024-05-06 19:28:30 +10:00
|
|
|
|
2024-04-19 11:56:21 -04:00
|
|
|
states: {
|
2024-07-05 13:40:16 +10:00
|
|
|
'Awaiting second corner': {
|
|
|
|
on: {
|
|
|
|
'Finish rectangle': 'Finished Rectangle',
|
|
|
|
},
|
|
|
|
},
|
2024-04-19 11:56:21 -04:00
|
|
|
|
|
|
|
'Awaiting origin': {
|
|
|
|
on: {
|
|
|
|
'Add rectangle origin': {
|
|
|
|
target: 'Awaiting second corner',
|
|
|
|
actions: 'set up draft rectangle',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
|
|
|
'Finished Rectangle': {
|
|
|
|
always: '#Modeling.Sketch.SketchIdle',
|
|
|
|
},
|
2024-04-19 11:56:21 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
initial: 'Awaiting origin',
|
2024-07-05 13:40:16 +10:00
|
|
|
|
|
|
|
on: {
|
|
|
|
'change tool': {
|
|
|
|
target: 'Change Tool',
|
|
|
|
},
|
|
|
|
},
|
2024-04-19 11:56:21 -04:00
|
|
|
},
|
2024-05-06 19:28:30 +10:00
|
|
|
|
|
|
|
'clean slate': {
|
|
|
|
always: 'SketchIdle',
|
|
|
|
},
|
2024-05-24 20:54:42 +10:00
|
|
|
|
|
|
|
'Await convert to variable': {
|
|
|
|
invoke: {
|
|
|
|
src: 'Get convert to variable info',
|
|
|
|
id: 'get-convert-to-variable-info',
|
|
|
|
onError: 'SketchIdle',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
2024-06-24 11:45:40 -04:00
|
|
|
actions: ['Set selection'],
|
2024-05-24 20:54:42 +10:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-05-30 13:28:29 +10:00
|
|
|
|
2024-06-03 22:40:59 +10:00
|
|
|
'Await constrain remove constraints': {
|
|
|
|
invoke: {
|
|
|
|
src: 'do-constrain-remove-constraint',
|
|
|
|
id: 'do-constrain-remove-constraint',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
2024-05-30 19:43:35 +10:00
|
|
|
'Await constrain horizontally': {
|
|
|
|
invoke: {
|
|
|
|
src: 'do-constrain-horizontally',
|
|
|
|
id: 'do-constrain-horizontally',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
2024-05-30 19:43:35 +10:00
|
|
|
'Await constrain vertically': {
|
|
|
|
invoke: {
|
|
|
|
src: 'do-constrain-vertically',
|
|
|
|
id: 'do-constrain-vertically',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
2024-05-30 13:28:29 +10:00
|
|
|
'Await constrain horizontally align': {
|
|
|
|
invoke: {
|
|
|
|
src: 'do-constrain-horizontally-align',
|
|
|
|
id: 'do-constrain-horizontally-align',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
2024-05-30 13:28:29 +10:00
|
|
|
'Await constrain vertically align': {
|
|
|
|
invoke: {
|
|
|
|
src: 'do-constrain-vertically-align',
|
|
|
|
id: 'do-constrain-vertically-align',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
2024-05-30 13:28:29 +10:00
|
|
|
'Await constrain snap to X': {
|
|
|
|
invoke: {
|
|
|
|
src: 'do-constrain-snap-to-x',
|
|
|
|
id: 'do-constrain-snap-to-x',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
2024-05-30 13:28:29 +10:00
|
|
|
'Await constrain snap to Y': {
|
|
|
|
invoke: {
|
|
|
|
src: 'do-constrain-snap-to-y',
|
|
|
|
id: 'do-constrain-snap-to-y',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
'Await constrain equal length': {
|
|
|
|
invoke: {
|
|
|
|
src: 'do-constrain-equal-length',
|
|
|
|
id: 'do-constrain-equal-length',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
2024-05-30 13:28:29 +10:00
|
|
|
'Await constrain parallel': {
|
|
|
|
invoke: {
|
|
|
|
src: 'do-constrain-parallel',
|
|
|
|
id: 'do-constrain-parallel',
|
|
|
|
onDone: {
|
|
|
|
target: 'SketchIdle',
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
|
|
|
|
'Change Tool': {
|
|
|
|
always: [
|
|
|
|
{
|
|
|
|
target: 'SketchIdle',
|
|
|
|
cond: 'next is none',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
target: 'Line tool',
|
|
|
|
cond: 'next is line',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
target: 'Rectangle tool',
|
|
|
|
cond: 'next is rectangle',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
target: 'Tangential arc to',
|
|
|
|
cond: 'next is tangential arc',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
2024-02-11 12:59:00 +11:00
|
|
|
initial: 'Init',
|
2023-10-11 13:36:54 +11:00
|
|
|
|
|
|
|
on: {
|
|
|
|
CancelSketch: '.SketchIdle',
|
2024-05-24 20:54:42 +10:00
|
|
|
|
|
|
|
'Delete segment': {
|
|
|
|
internal: true,
|
2024-06-24 11:45:40 -04:00
|
|
|
actions: ['Delete segment', 'Set sketchDetails'],
|
2024-05-24 20:54:42 +10:00
|
|
|
},
|
2024-05-06 19:28:30 +10:00
|
|
|
'code edit during sketch': '.clean slate',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
2024-02-11 12:59:00 +11:00
|
|
|
exit: [
|
|
|
|
'sketch exit execute',
|
|
|
|
'tear down client sketch',
|
|
|
|
'remove sketch grid',
|
2024-03-02 08:20:50 +11:00
|
|
|
'engineToClient cam sync direction',
|
2024-05-24 20:54:42 +10:00
|
|
|
'Reset Segment Overlays',
|
2024-07-01 21:05:31 -07:00
|
|
|
'enable copilot',
|
2024-02-11 12:59:00 +11:00
|
|
|
],
|
|
|
|
|
2024-04-22 20:14:06 +10:00
|
|
|
entry: [
|
|
|
|
'add axis n grid',
|
|
|
|
'conditionally equip line tool',
|
|
|
|
'clientToEngine cam sync direction',
|
|
|
|
],
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
'Sketch no face': {
|
2024-07-01 21:05:31 -07:00
|
|
|
entry: [
|
|
|
|
'disable copilot',
|
|
|
|
'show default planes',
|
|
|
|
'set selection filter to faces only',
|
|
|
|
],
|
2023-10-11 13:36:54 +11:00
|
|
|
|
2024-03-28 17:22:11 +11:00
|
|
|
exit: ['hide default planes', 'set selection filter to defaults'],
|
2023-10-11 13:36:54 +11:00
|
|
|
on: {
|
|
|
|
'Select default plane': {
|
2024-02-11 12:59:00 +11:00
|
|
|
target: 'animating to plane',
|
|
|
|
actions: ['reset sketch metadata'],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
'animating to plane': {
|
|
|
|
invoke: {
|
|
|
|
src: 'animate-to-face',
|
|
|
|
id: 'animate-to-face',
|
|
|
|
onDone: {
|
2023-10-11 13:36:54 +11:00
|
|
|
target: 'Sketch',
|
2024-02-11 12:59:00 +11:00
|
|
|
actions: 'set new sketch metadata',
|
|
|
|
},
|
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
2024-02-11 12:59:00 +11:00
|
|
|
|
|
|
|
'animating to existing sketch': {
|
|
|
|
invoke: [
|
|
|
|
{
|
|
|
|
src: 'animate-to-sketch',
|
|
|
|
id: 'animate-to-sketch',
|
2024-03-22 10:23:04 +11:00
|
|
|
onDone: {
|
|
|
|
target: 'Sketch',
|
2024-07-01 21:05:31 -07:00
|
|
|
actions: ['disable copilot', 'set new sketch metadata'],
|
2024-03-22 10:23:04 +11:00
|
|
|
},
|
2024-02-11 12:59:00 +11:00
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
|
|
|
|
initial: 'idle',
|
|
|
|
|
|
|
|
on: {
|
|
|
|
Cancel: {
|
|
|
|
target: 'idle',
|
2023-11-01 17:34:54 -05:00
|
|
|
// TODO what if we're existing extrude equipped, should these actions still be fired?
|
|
|
|
// maybe cancel needs to have a guard for if else logic?
|
2024-07-03 01:50:40 +10:00
|
|
|
actions: ['reset sketch metadata', 'enable copilot'],
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
|
|
|
|
'Set selection': {
|
|
|
|
internal: true,
|
|
|
|
actions: 'Set selection',
|
|
|
|
},
|
2024-05-06 19:28:30 +10:00
|
|
|
|
2024-04-04 11:07:51 +11:00
|
|
|
'Set mouse state': {
|
|
|
|
internal: true,
|
|
|
|
actions: 'Set mouse state',
|
|
|
|
},
|
2024-07-02 17:16:27 +10:00
|
|
|
'Set context': {
|
|
|
|
internal: true,
|
|
|
|
actions: 'Set context',
|
|
|
|
},
|
2024-05-24 20:54:42 +10:00
|
|
|
'Set Segment Overlays': {
|
|
|
|
internal: true,
|
|
|
|
actions: 'Set Segment Overlays',
|
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
guards: {
|
2024-07-10 07:01:49 +10:00
|
|
|
'has made first point': ({ sketchDetails }) => {
|
|
|
|
if (!sketchDetails?.sketchPathToNode) return false
|
|
|
|
const variableDeclaration = getNodeFromPath<VariableDeclarator>(
|
|
|
|
kclManager.ast,
|
|
|
|
sketchDetails.sketchPathToNode,
|
|
|
|
'VariableDeclarator'
|
|
|
|
)
|
|
|
|
if (err(variableDeclaration)) return false
|
|
|
|
if (variableDeclaration.node.type !== 'VariableDeclarator') return false
|
|
|
|
const pipeExpression = variableDeclaration.node.init
|
|
|
|
if (pipeExpression.type !== 'PipeExpression') return false
|
|
|
|
const hasStartSketchOn = pipeExpression.body.some(
|
|
|
|
(item) =>
|
|
|
|
item.type === 'CallExpression' &&
|
|
|
|
item.callee.name === 'startSketchOn'
|
|
|
|
)
|
|
|
|
return hasStartSketchOn && pipeExpression.body.length > 1
|
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
'is editing existing sketch': ({ sketchDetails }) =>
|
|
|
|
isEditingExistingSketch({ sketchDetails }),
|
2024-06-24 11:45:40 -04:00
|
|
|
'Can make selection horizontal': ({ selectionRanges }) => {
|
|
|
|
const info = horzVertInfo(selectionRanges, 'horizontal')
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can make selection vertical': ({ selectionRanges }) => {
|
|
|
|
const info = horzVertInfo(selectionRanges, 'vertical')
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain horizontal distance': ({ selectionRanges }) => {
|
|
|
|
const info = horzVertDistanceInfo({
|
|
|
|
selectionRanges,
|
|
|
|
constraint: 'setHorzDistance',
|
|
|
|
})
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain vertical distance': ({ selectionRanges }) => {
|
|
|
|
const info = horzVertDistanceInfo({
|
|
|
|
selectionRanges,
|
|
|
|
constraint: 'setVertDistance',
|
|
|
|
})
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain ABS X': ({ selectionRanges }) => {
|
|
|
|
const info = absDistanceInfo({ selectionRanges, constraint: 'xAbs' })
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain ABS Y': ({ selectionRanges }) => {
|
|
|
|
const info = absDistanceInfo({ selectionRanges, constraint: 'yAbs' })
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain angle': ({ selectionRanges }) => {
|
|
|
|
const angleBetween = angleBetweenInfo({ selectionRanges })
|
|
|
|
if (trap(angleBetween)) return false
|
|
|
|
const angleLength = angleLengthInfo({
|
|
|
|
selectionRanges,
|
|
|
|
angleOrLength: 'setAngle',
|
|
|
|
})
|
|
|
|
if (trap(angleLength)) return false
|
|
|
|
return angleBetween.enabled || angleLength.enabled
|
|
|
|
},
|
|
|
|
'Can constrain length': ({ selectionRanges }) => {
|
|
|
|
const angleLength = angleLengthInfo({ selectionRanges })
|
|
|
|
if (trap(angleLength)) return false
|
|
|
|
return angleLength.enabled
|
|
|
|
},
|
|
|
|
'Can constrain perpendicular distance': ({ selectionRanges }) => {
|
|
|
|
const info = intersectInfo({ selectionRanges })
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain horizontally align': ({ selectionRanges }) => {
|
|
|
|
const info = horzVertDistanceInfo({
|
|
|
|
selectionRanges,
|
|
|
|
constraint: 'setHorzDistance',
|
|
|
|
})
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain vertically align': ({ selectionRanges }) => {
|
|
|
|
const info = horzVertDistanceInfo({
|
|
|
|
selectionRanges,
|
|
|
|
constraint: 'setHorzDistance',
|
|
|
|
})
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain snap to X': ({ selectionRanges }) => {
|
|
|
|
const info = absDistanceInfo({
|
|
|
|
selectionRanges,
|
|
|
|
constraint: 'snapToXAxis',
|
|
|
|
})
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain snap to Y': ({ selectionRanges }) => {
|
|
|
|
const info = absDistanceInfo({
|
|
|
|
selectionRanges,
|
|
|
|
constraint: 'snapToYAxis',
|
|
|
|
})
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain equal length': ({ selectionRanges }) => {
|
|
|
|
const info = setEqualLengthInfo({ selectionRanges })
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can canstrain parallel': ({ selectionRanges }) => {
|
|
|
|
const info = equalAngleInfo({ selectionRanges })
|
|
|
|
if (err(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
|
|
|
'Can constrain remove constraints': ({ selectionRanges }, { data }) => {
|
|
|
|
const info = removeConstrainingValuesInfo({
|
2024-06-04 16:29:20 +10:00
|
|
|
selectionRanges,
|
|
|
|
pathToNodes: data && [data],
|
2024-06-24 11:45:40 -04:00
|
|
|
})
|
|
|
|
if (trap(info)) return false
|
|
|
|
return info.enabled
|
|
|
|
},
|
2024-05-24 20:54:42 +10:00
|
|
|
'Can convert to variable': (_, { data }) => {
|
|
|
|
if (!data) return false
|
2024-06-24 11:45:40 -04:00
|
|
|
const ast = parse(recast(kclManager.ast))
|
|
|
|
if (err(ast)) return false
|
|
|
|
const isSafeRetVal = isNodeSafeToReplacePath(ast, data.pathToNode)
|
|
|
|
if (err(isSafeRetVal)) return false
|
|
|
|
return isSafeRetVal.isSafe
|
2024-05-24 20:54:42 +10:00
|
|
|
},
|
2024-07-05 13:40:16 +10:00
|
|
|
'next is tangential arc': ({ sketchDetails }, _, { state }) =>
|
2024-07-12 16:16:26 -04:00
|
|
|
(state?.event as any).data.tool === 'tangentialArc' &&
|
2024-07-05 13:40:16 +10:00
|
|
|
isEditingExistingSketch({ sketchDetails }),
|
|
|
|
'next is rectangle': ({ sketchDetails }, _, { state }) => {
|
2024-07-12 16:16:26 -04:00
|
|
|
if ((state?.event as any).data.tool !== 'rectangle') return false
|
2024-07-05 13:40:16 +10:00
|
|
|
return canRectangleTool({ sketchDetails })
|
|
|
|
},
|
|
|
|
'next is line': (_, __, { state }) =>
|
2024-07-12 16:16:26 -04:00
|
|
|
(state?.event as any).data.tool === 'line',
|
2024-07-05 13:40:16 +10:00
|
|
|
'next is none': (_, __, { state }) =>
|
2024-07-12 16:16:26 -04:00
|
|
|
(state?.event as any).data.tool === 'none',
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
2024-02-11 12:59:00 +11:00
|
|
|
// end guards
|
2023-10-11 13:36:54 +11:00
|
|
|
actions: {
|
2024-03-22 10:23:04 +11:00
|
|
|
'set sketchMetadata from pathToNode': assign(({ sketchDetails }) => {
|
|
|
|
if (!sketchDetails?.sketchPathToNode || !sketchDetails) return {}
|
|
|
|
return {
|
|
|
|
sketchDetails: {
|
|
|
|
...sketchDetails,
|
|
|
|
sketchPathToNode: sketchDetails.sketchPathToNode,
|
|
|
|
},
|
|
|
|
}
|
2023-10-18 08:03:02 +11:00
|
|
|
}),
|
2024-08-03 07:05:35 +10:00
|
|
|
'hide default planes': () => kclManager.hidePlanes(),
|
2023-10-11 13:36:54 +11:00
|
|
|
'reset sketch metadata': assign({
|
2024-03-22 10:23:04 +11:00
|
|
|
sketchDetails: null,
|
2023-10-11 13:36:54 +11:00
|
|
|
sketchEnginePathId: '',
|
|
|
|
sketchPlaneId: '',
|
|
|
|
}),
|
2024-08-06 17:05:46 +10:00
|
|
|
'reset camera position': () =>
|
|
|
|
engineCommandManager.sendSceneCommand({
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
cmd: {
|
|
|
|
type: 'default_camera_look_at',
|
|
|
|
center: { x: 0, y: 0, z: 0 },
|
|
|
|
vantage: { x: 0, y: -1250, z: 580 },
|
|
|
|
up: { x: 0, y: 0, z: 1 },
|
|
|
|
},
|
|
|
|
}),
|
2024-03-22 10:23:04 +11:00
|
|
|
'set new sketch metadata': assign((_, { data }) => ({
|
|
|
|
sketchDetails: data,
|
|
|
|
})),
|
2024-07-04 01:55:06 -04:00
|
|
|
'AST extrude': async ({ store }, event) => {
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
if (!event.data) return
|
|
|
|
const { selection, distance } = event.data
|
2024-02-23 11:24:22 -05:00
|
|
|
let ast = kclManager.ast
|
|
|
|
if (
|
|
|
|
'variableName' in distance &&
|
|
|
|
distance.variableName &&
|
|
|
|
distance.insertIndex !== undefined
|
|
|
|
) {
|
|
|
|
const newBody = [...ast.body]
|
|
|
|
newBody.splice(
|
|
|
|
distance.insertIndex,
|
|
|
|
0,
|
|
|
|
distance.variableDeclarationAst
|
|
|
|
)
|
|
|
|
ast.body = newBody
|
|
|
|
}
|
2023-10-11 13:36:54 +11:00
|
|
|
const pathToNode = getNodePathFromSourceRange(
|
2024-02-23 11:24:22 -05:00
|
|
|
ast,
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
selection.codeBasedSelections[0].range
|
2023-10-11 13:36:54 +11:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
const extrudeSketchRes = extrudeSketch(
|
2024-02-23 11:24:22 -05:00
|
|
|
ast,
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
pathToNode,
|
2024-06-04 13:57:01 -04:00
|
|
|
false,
|
2024-02-23 11:24:22 -05:00
|
|
|
'variableName' in distance
|
|
|
|
? distance.variableIdentifierAst
|
|
|
|
: distance.valueAst
|
2023-10-11 13:36:54 +11:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(extrudeSketchRes)) return
|
|
|
|
const { modifiedAst, pathToExtrudeArg } = extrudeSketchRes
|
|
|
|
|
2024-07-04 01:55:06 -04:00
|
|
|
store.videoElement?.pause()
|
2024-06-24 11:45:40 -04:00
|
|
|
const updatedAst = await kclManager.updateAst(modifiedAst, true, {
|
2023-10-11 13:36:54 +11:00
|
|
|
focusPath: pathToExtrudeArg,
|
2024-08-05 16:08:30 +10:00
|
|
|
// commented out as a part of https://github.com/KittyCAD/modeling-app/issues/3270
|
|
|
|
// looking to add back in the future
|
|
|
|
// zoomToFit: true,
|
|
|
|
// zoomOnRangeAndType: {
|
|
|
|
// range: selection.codeBasedSelections[0].range,
|
|
|
|
// type: 'path',
|
|
|
|
// },
|
2023-10-11 13:36:54 +11:00
|
|
|
})
|
2024-07-16 22:45:11 -04:00
|
|
|
if (!engineCommandManager.engineConnection?.idleMode) {
|
2024-08-01 01:40:14 -04:00
|
|
|
store.videoElement?.play().catch((e) => {
|
|
|
|
console.warn('Video playing was prevented', e)
|
|
|
|
})
|
2024-07-07 13:10:52 -04:00
|
|
|
}
|
2024-06-24 11:45:40 -04:00
|
|
|
if (updatedAst?.selections) {
|
|
|
|
editorManager.selectRange(updatedAst?.selections)
|
2024-04-19 14:24:40 -07:00
|
|
|
}
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
2024-08-03 18:08:51 +10:00
|
|
|
'AST delete selection': async ({ selectionRanges }) => {
|
2024-06-29 10:36:04 -07:00
|
|
|
let ast = kclManager.ast
|
|
|
|
|
|
|
|
const modifiedAst = await deleteFromSelection(
|
|
|
|
ast,
|
|
|
|
selectionRanges.codeBasedSelections[0],
|
|
|
|
kclManager.programMemory,
|
2024-07-04 11:05:27 +10:00
|
|
|
getFaceDetails
|
2024-06-29 10:36:04 -07:00
|
|
|
)
|
|
|
|
if (err(modifiedAst)) return
|
|
|
|
|
|
|
|
const testExecute = await executeAst({
|
|
|
|
ast: modifiedAst,
|
|
|
|
useFakeExecutor: true,
|
|
|
|
engineCommandManager,
|
|
|
|
})
|
|
|
|
if (testExecute.errors.length) {
|
|
|
|
toast.error('Unable to delete part')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
await kclManager.updateAst(modifiedAst, true)
|
|
|
|
},
|
2024-07-15 19:20:32 +10:00
|
|
|
'AST fillet': async (_, event) => {
|
|
|
|
if (!event.data) return
|
|
|
|
|
|
|
|
const { selection, radius } = event.data
|
|
|
|
let ast = kclManager.ast
|
|
|
|
|
|
|
|
if (
|
|
|
|
'variableName' in radius &&
|
|
|
|
radius.variableName &&
|
|
|
|
radius.insertIndex !== undefined
|
|
|
|
) {
|
|
|
|
const newBody = [...ast.body]
|
|
|
|
newBody.splice(radius.insertIndex, 0, radius.variableDeclarationAst)
|
|
|
|
ast.body = newBody
|
|
|
|
}
|
|
|
|
|
|
|
|
const pathToSegmentNode = getNodePathFromSourceRange(
|
|
|
|
ast,
|
|
|
|
selection.codeBasedSelections[0].range
|
|
|
|
)
|
|
|
|
|
|
|
|
const varDecNode = getNodeFromPath<VariableDeclaration>(
|
|
|
|
ast,
|
|
|
|
pathToSegmentNode,
|
|
|
|
'VariableDeclaration'
|
|
|
|
)
|
|
|
|
if (err(varDecNode)) return
|
|
|
|
const sketchVar = varDecNode.node.declarations[0].id.name
|
Remove KclValue::SketchGroup variant (#3446)
We can store Rust types like `SketchGroup` as their own variant of `KclValue`, or as `KclValue::UserVal`. Sometimes we store in one and try to read from the other, which fails. This causes bugs, like #3338.
Instead, we should use either ::SketchGroup or ::UserVal, and stop using the other. If we stopped using ::UserVal, we'd need a new variant for every Rust type we wanted to build, including user-defined types. So I don't think that's practical.
Instead, we should store every KCL value by de/serializing it into UserVal. This is a first step along that path, removing just the SketchGroup variants. If it goes well, we can remove the other specialized variants too.
My only concern is there might be performance implications from how frequently we convert between serde_json::Value and Rust types via Serde. But I'm not too worried -- there's no parsing JSON strings, just traversing serde_json::Value trees. This isn't great for performance but I think it'll probably be miniscule in comparison to doing all the API calls.
2024-08-21 11:06:48 -05:00
|
|
|
const sketchGroup = sketchGroupFromKclValue(
|
|
|
|
kclManager.programMemory.get(sketchVar),
|
|
|
|
sketchVar
|
|
|
|
)
|
|
|
|
if (trap(sketchGroup)) return
|
2024-08-03 18:08:51 +10:00
|
|
|
const extrusion = getExtrusionFromSuspectedPath(
|
|
|
|
sketchGroup.id,
|
|
|
|
engineCommandManager.artifactGraph
|
2024-07-15 19:20:32 +10:00
|
|
|
)
|
2024-08-03 18:08:51 +10:00
|
|
|
const pathToExtrudeNode = err(extrusion)
|
|
|
|
? []
|
|
|
|
: getNodePathFromSourceRange(ast, extrusion.codeRef.range)
|
2024-07-15 19:20:32 +10:00
|
|
|
|
|
|
|
// we assume that there is only one body related to the sketch
|
|
|
|
// and apply the fillet to it
|
|
|
|
|
|
|
|
const addFilletResult = addFillet(
|
|
|
|
ast,
|
|
|
|
pathToSegmentNode,
|
|
|
|
pathToExtrudeNode,
|
|
|
|
'variableName' in radius
|
|
|
|
? radius.variableIdentifierAst
|
|
|
|
: radius.valueAst
|
|
|
|
)
|
|
|
|
|
|
|
|
if (trap(addFilletResult)) return
|
|
|
|
const { modifiedAst, pathToFilletNode } = addFilletResult
|
|
|
|
|
|
|
|
const updatedAst = await kclManager.updateAst(modifiedAst, true, {
|
|
|
|
focusPath: pathToFilletNode,
|
|
|
|
})
|
|
|
|
if (updatedAst?.selections) {
|
|
|
|
editorManager.selectRange(updatedAst?.selections)
|
|
|
|
}
|
|
|
|
},
|
2024-02-14 05:35:05 +11:00
|
|
|
'conditionally equip line tool': (_, { type }) => {
|
|
|
|
if (type === 'done.invoke.animate-to-face') {
|
2024-07-05 13:40:16 +10:00
|
|
|
sceneInfra.modelingSend({
|
|
|
|
type: 'change tool',
|
2024-07-12 16:16:26 -04:00
|
|
|
data: { tool: 'line' },
|
2024-07-05 13:40:16 +10:00
|
|
|
})
|
2024-02-14 05:35:05 +11:00
|
|
|
}
|
|
|
|
},
|
2024-06-22 04:49:31 -04:00
|
|
|
'setup client side sketch segments': ({
|
|
|
|
sketchDetails,
|
|
|
|
selectionRanges,
|
|
|
|
}) => {
|
2024-03-22 10:23:04 +11:00
|
|
|
if (!sketchDetails) return
|
2024-03-25 15:20:43 +11:00
|
|
|
;(async () => {
|
|
|
|
if (Object.keys(sceneEntitiesManager.activeSegments).length > 0) {
|
|
|
|
await sceneEntitiesManager.tearDownSketch({ removeAxis: false })
|
|
|
|
}
|
2024-04-03 13:22:56 +11:00
|
|
|
sceneInfra.resetMouseListeners()
|
2024-03-25 15:20:43 +11:00
|
|
|
await sceneEntitiesManager.setupSketch({
|
2024-03-22 10:23:04 +11:00
|
|
|
sketchPathToNode: sketchDetails?.sketchPathToNode || [],
|
|
|
|
forward: sketchDetails.zAxis,
|
|
|
|
up: sketchDetails.yAxis,
|
|
|
|
position: sketchDetails.origin,
|
2024-03-25 15:20:43 +11:00
|
|
|
maybeModdedAst: kclManager.ast,
|
2024-06-22 04:49:31 -04:00
|
|
|
selectionRanges,
|
2024-02-11 12:59:00 +11:00
|
|
|
})
|
2024-04-03 13:22:56 +11:00
|
|
|
sceneInfra.resetMouseListeners()
|
|
|
|
sceneEntitiesManager.setupSketchIdleCallbacks({
|
|
|
|
pathToNode: sketchDetails?.sketchPathToNode || [],
|
|
|
|
forward: sketchDetails.zAxis,
|
|
|
|
up: sketchDetails.yAxis,
|
|
|
|
position: sketchDetails.origin,
|
|
|
|
})
|
2024-03-25 15:20:43 +11:00
|
|
|
})()
|
2024-02-11 12:59:00 +11:00
|
|
|
},
|
2024-02-14 05:35:05 +11:00
|
|
|
'tear down client sketch': () => {
|
2024-02-14 08:03:20 +11:00
|
|
|
if (sceneEntitiesManager.activeSegments) {
|
|
|
|
sceneEntitiesManager.tearDownSketch({ removeAxis: false })
|
2024-02-14 05:35:05 +11:00
|
|
|
}
|
|
|
|
},
|
2024-02-14 08:03:20 +11:00
|
|
|
'remove sketch grid': () => sceneEntitiesManager.removeSketchGrid(),
|
2024-03-22 10:23:04 +11:00
|
|
|
'set up draft line': ({ sketchDetails }) => {
|
|
|
|
if (!sketchDetails) return
|
2024-03-25 15:20:43 +11:00
|
|
|
sceneEntitiesManager.setUpDraftSegment(
|
2024-03-22 10:23:04 +11:00
|
|
|
sketchDetails.sketchPathToNode,
|
|
|
|
sketchDetails.zAxis,
|
2024-03-25 15:20:43 +11:00
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin,
|
|
|
|
'line'
|
2024-03-22 10:23:04 +11:00
|
|
|
)
|
2024-02-11 12:59:00 +11:00
|
|
|
},
|
2024-03-22 10:23:04 +11:00
|
|
|
'set up draft arc': ({ sketchDetails }) => {
|
|
|
|
if (!sketchDetails) return
|
2024-03-25 15:20:43 +11:00
|
|
|
sceneEntitiesManager.setUpDraftSegment(
|
2024-03-22 10:23:04 +11:00
|
|
|
sketchDetails.sketchPathToNode,
|
|
|
|
sketchDetails.zAxis,
|
2024-03-25 15:20:43 +11:00
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin,
|
|
|
|
'tangentialArcTo'
|
|
|
|
)
|
|
|
|
},
|
2024-04-19 11:56:21 -04:00
|
|
|
'listen for rectangle origin': ({ sketchDetails }) => {
|
|
|
|
if (!sketchDetails) return
|
2024-07-30 14:16:53 -04:00
|
|
|
sceneEntitiesManager.setupNoPointsListener({
|
|
|
|
sketchDetails,
|
|
|
|
afterClick: (args) => {
|
|
|
|
const twoD = args.intersectionPoint?.twoD
|
|
|
|
if (twoD) {
|
|
|
|
sceneInfra.modelingSend({
|
|
|
|
type: 'Add rectangle origin',
|
|
|
|
data: [twoD.x, twoD.y],
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
console.error('No intersection point found')
|
|
|
|
}
|
|
|
|
},
|
|
|
|
})
|
2024-04-19 11:56:21 -04:00
|
|
|
},
|
|
|
|
'set up draft rectangle': ({ sketchDetails }, { data }) => {
|
|
|
|
if (!sketchDetails || !data) return
|
|
|
|
sceneEntitiesManager.setupDraftRectangle(
|
|
|
|
sketchDetails.sketchPathToNode,
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin,
|
|
|
|
data
|
|
|
|
)
|
|
|
|
},
|
2024-03-25 15:20:43 +11:00
|
|
|
'set up draft line without teardown': ({ sketchDetails }) => {
|
|
|
|
if (!sketchDetails) return
|
|
|
|
sceneEntitiesManager.setUpDraftSegment(
|
|
|
|
sketchDetails.sketchPathToNode,
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin,
|
|
|
|
'line',
|
|
|
|
false
|
2024-03-22 10:23:04 +11:00
|
|
|
)
|
2024-02-11 12:59:00 +11:00
|
|
|
},
|
2024-08-03 07:05:35 +10:00
|
|
|
'show default planes': () => kclManager.showPlanes(),
|
2024-03-22 10:23:04 +11:00
|
|
|
'setup noPoints onClick listener': ({ sketchDetails }) => {
|
|
|
|
if (!sketchDetails) return
|
2024-07-30 14:16:53 -04:00
|
|
|
|
|
|
|
sceneEntitiesManager.setupNoPointsListener({
|
|
|
|
sketchDetails,
|
|
|
|
afterClick: () => sceneInfra.modelingSend('Add start point'),
|
2024-02-11 12:59:00 +11:00
|
|
|
})
|
|
|
|
},
|
2024-03-22 10:23:04 +11:00
|
|
|
'add axis n grid': ({ sketchDetails }) => {
|
|
|
|
if (!sketchDetails) return
|
2024-06-24 11:45:40 -04:00
|
|
|
if (localStorage.getItem('disableAxis')) return
|
2024-03-22 10:23:04 +11:00
|
|
|
sceneEntitiesManager.createSketchAxis(
|
|
|
|
sketchDetails.sketchPathToNode || [],
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
|
|
|
},
|
2024-02-19 12:41:36 +11:00
|
|
|
'reset client scene mouse handlers': () => {
|
|
|
|
// when not in sketch mode we don't need any mouse listeners
|
|
|
|
// (note the orbit controls are always active though)
|
2024-02-20 11:04:42 +11:00
|
|
|
sceneInfra.resetMouseListeners()
|
2024-02-19 12:41:36 +11:00
|
|
|
},
|
2024-03-02 08:20:50 +11:00
|
|
|
'clientToEngine cam sync direction': () => {
|
|
|
|
sceneInfra.camControls.syncDirection = 'clientToEngine'
|
|
|
|
},
|
|
|
|
'engineToClient cam sync direction': () => {
|
|
|
|
sceneInfra.camControls.syncDirection = 'engineToClient'
|
|
|
|
},
|
2024-03-28 17:22:11 +11:00
|
|
|
'set selection filter to faces only': () =>
|
|
|
|
engineCommandManager.sendSceneCommand({
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
cmd: {
|
|
|
|
type: 'set_selection_filter',
|
2024-06-18 16:08:41 +10:00
|
|
|
filter: ['face', 'object'],
|
2024-03-28 17:22:11 +11:00
|
|
|
},
|
|
|
|
}),
|
2024-05-21 05:55:34 +10:00
|
|
|
'set selection filter to defaults': () =>
|
|
|
|
kclManager.defaultSelectionFilter(),
|
2024-05-24 20:54:42 +10:00
|
|
|
'Delete segment': ({ sketchDetails }, { data: pathToNode }) =>
|
|
|
|
deleteSegment({ pathToNode, sketchDetails }),
|
|
|
|
'Reset Segment Overlays': () => sceneEntitiesManager.resetOverlays(),
|
2024-07-02 17:16:27 +10:00
|
|
|
'Set context': assign({
|
|
|
|
store: ({ store }, { data }) => {
|
|
|
|
if (data.streamDimensions) {
|
|
|
|
sceneInfra._streamDimensions = data.streamDimensions
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = {
|
|
|
|
...store,
|
|
|
|
...data,
|
|
|
|
}
|
|
|
|
const persistedContext: Partial<PersistedModelingContext> = {}
|
|
|
|
for (const key of PersistedValues) {
|
|
|
|
persistedContext[key] = result[key]
|
|
|
|
}
|
|
|
|
if (typeof window !== 'undefined') {
|
|
|
|
window.localStorage.setItem(
|
|
|
|
PERSIST_MODELING_CONTEXT,
|
|
|
|
JSON.stringify(persistedContext)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
},
|
|
|
|
}),
|
2023-10-11 13:36:54 +11:00
|
|
|
},
|
2024-02-11 12:59:00 +11:00
|
|
|
// end actions
|
2024-05-30 13:28:29 +10:00
|
|
|
services: {
|
2024-06-04 16:29:20 +10:00
|
|
|
'do-constrain-remove-constraint': async (
|
|
|
|
{ selectionRanges, sketchDetails },
|
|
|
|
{ data }
|
|
|
|
) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const constraint = applyRemoveConstrainingValues({
|
2024-06-03 22:40:59 +10:00
|
|
|
selectionRanges,
|
2024-06-04 16:29:20 +10:00
|
|
|
pathToNodes: data && [data],
|
2024-06-03 22:40:59 +10:00
|
|
|
})
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(constraint)) return
|
|
|
|
const { pathToNodeMap } = constraint
|
2024-06-03 22:40:59 +10:00
|
|
|
if (!sketchDetails) return
|
2024-06-24 11:45:40 -04:00
|
|
|
let updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
|
|
|
pathToNodeMap[0],
|
|
|
|
constraint.modifiedAst,
|
2024-06-03 22:40:59 +10:00
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(updatedAst, { suppress: true })) return
|
|
|
|
if (!updatedAst) return
|
2024-06-03 22:40:59 +10:00
|
|
|
return {
|
|
|
|
selectionType: 'completeSelection',
|
|
|
|
selection: updateSelections(
|
|
|
|
pathToNodeMap,
|
|
|
|
selectionRanges,
|
2024-06-24 11:45:40 -04:00
|
|
|
updatedAst.newAst
|
2024-06-03 22:40:59 +10:00
|
|
|
),
|
|
|
|
}
|
|
|
|
},
|
2024-05-30 19:43:35 +10:00
|
|
|
'do-constrain-horizontally': async ({
|
|
|
|
selectionRanges,
|
|
|
|
sketchDetails,
|
|
|
|
}) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const constraint = applyConstraintHorzVert(
|
2024-05-30 19:43:35 +10:00
|
|
|
selectionRanges,
|
|
|
|
'horizontal',
|
|
|
|
kclManager.ast,
|
|
|
|
kclManager.programMemory
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(constraint)) return false
|
|
|
|
const { modifiedAst, pathToNodeMap } = constraint
|
2024-05-30 19:43:35 +10:00
|
|
|
if (!sketchDetails) return
|
2024-06-24 11:45:40 -04:00
|
|
|
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
2024-05-30 19:43:35 +10:00
|
|
|
sketchDetails.sketchPathToNode,
|
|
|
|
modifiedAst,
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(updatedAst, { suppress: true })) return
|
|
|
|
if (!updatedAst) return
|
2024-05-30 19:43:35 +10:00
|
|
|
return {
|
|
|
|
selectionType: 'completeSelection',
|
|
|
|
selection: updateSelections(
|
|
|
|
pathToNodeMap,
|
|
|
|
selectionRanges,
|
2024-06-24 11:45:40 -04:00
|
|
|
updatedAst.newAst
|
2024-05-30 19:43:35 +10:00
|
|
|
),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'do-constrain-vertically': async ({ selectionRanges, sketchDetails }) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const constraint = applyConstraintHorzVert(
|
2024-05-30 19:43:35 +10:00
|
|
|
selectionRanges,
|
|
|
|
'vertical',
|
|
|
|
kclManager.ast,
|
|
|
|
kclManager.programMemory
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(constraint)) return false
|
|
|
|
const { modifiedAst, pathToNodeMap } = constraint
|
2024-05-30 19:43:35 +10:00
|
|
|
if (!sketchDetails) return
|
2024-06-24 11:45:40 -04:00
|
|
|
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
2024-05-30 19:43:35 +10:00
|
|
|
sketchDetails.sketchPathToNode || [],
|
|
|
|
modifiedAst,
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(updatedAst, { suppress: true })) return
|
|
|
|
if (!updatedAst) return
|
2024-05-30 19:43:35 +10:00
|
|
|
return {
|
|
|
|
selectionType: 'completeSelection',
|
|
|
|
selection: updateSelections(
|
|
|
|
pathToNodeMap,
|
|
|
|
selectionRanges,
|
2024-06-24 11:45:40 -04:00
|
|
|
updatedAst.newAst
|
2024-05-30 19:43:35 +10:00
|
|
|
),
|
|
|
|
}
|
|
|
|
},
|
2024-05-30 13:28:29 +10:00
|
|
|
'do-constrain-horizontally-align': async ({
|
|
|
|
selectionRanges,
|
|
|
|
sketchDetails,
|
|
|
|
}) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const constraint = applyConstraintHorzVertAlign({
|
2024-05-30 13:28:29 +10:00
|
|
|
selectionRanges,
|
|
|
|
constraint: 'setVertDistance',
|
|
|
|
})
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(constraint)) return
|
|
|
|
const { modifiedAst, pathToNodeMap } = constraint
|
2024-05-30 13:28:29 +10:00
|
|
|
if (!sketchDetails) return
|
2024-06-24 11:45:40 -04:00
|
|
|
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
2024-05-30 13:28:29 +10:00
|
|
|
sketchDetails?.sketchPathToNode || [],
|
|
|
|
modifiedAst,
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(updatedAst, { suppress: true })) return
|
|
|
|
if (!updatedAst) return
|
2024-05-30 13:28:29 +10:00
|
|
|
const updatedSelectionRanges = updateSelections(
|
|
|
|
pathToNodeMap,
|
|
|
|
selectionRanges,
|
2024-06-24 11:45:40 -04:00
|
|
|
updatedAst.newAst
|
2024-05-30 13:28:29 +10:00
|
|
|
)
|
|
|
|
return {
|
|
|
|
selectionType: 'completeSelection',
|
|
|
|
selection: updatedSelectionRanges,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'do-constrain-vertically-align': async ({
|
|
|
|
selectionRanges,
|
|
|
|
sketchDetails,
|
|
|
|
}) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const constraint = applyConstraintHorzVertAlign({
|
2024-05-30 13:28:29 +10:00
|
|
|
selectionRanges,
|
|
|
|
constraint: 'setHorzDistance',
|
|
|
|
})
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(constraint)) return
|
|
|
|
const { modifiedAst, pathToNodeMap } = constraint
|
2024-05-30 13:28:29 +10:00
|
|
|
if (!sketchDetails) return
|
2024-06-24 11:45:40 -04:00
|
|
|
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
2024-05-30 13:28:29 +10:00
|
|
|
sketchDetails?.sketchPathToNode || [],
|
|
|
|
modifiedAst,
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(updatedAst, { suppress: true })) return
|
|
|
|
if (!updatedAst) return
|
2024-05-30 13:28:29 +10:00
|
|
|
const updatedSelectionRanges = updateSelections(
|
|
|
|
pathToNodeMap,
|
|
|
|
selectionRanges,
|
2024-06-24 11:45:40 -04:00
|
|
|
updatedAst.newAst
|
2024-05-30 13:28:29 +10:00
|
|
|
)
|
|
|
|
return {
|
|
|
|
selectionType: 'completeSelection',
|
|
|
|
selection: updatedSelectionRanges,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'do-constrain-snap-to-x': async ({ selectionRanges, sketchDetails }) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const constraint = applyConstraintAxisAlign({
|
2024-05-30 13:28:29 +10:00
|
|
|
selectionRanges,
|
|
|
|
constraint: 'snapToXAxis',
|
|
|
|
})
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(constraint)) return false
|
|
|
|
const { modifiedAst, pathToNodeMap } = constraint
|
2024-05-30 13:28:29 +10:00
|
|
|
if (!sketchDetails) return
|
2024-06-24 11:45:40 -04:00
|
|
|
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
2024-05-30 13:28:29 +10:00
|
|
|
sketchDetails?.sketchPathToNode || [],
|
|
|
|
modifiedAst,
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(updatedAst, { suppress: true })) return
|
|
|
|
if (!updatedAst) return
|
2024-05-30 13:28:29 +10:00
|
|
|
const updatedSelectionRanges = updateSelections(
|
|
|
|
pathToNodeMap,
|
|
|
|
selectionRanges,
|
2024-06-24 11:45:40 -04:00
|
|
|
updatedAst.newAst
|
2024-05-30 13:28:29 +10:00
|
|
|
)
|
|
|
|
return {
|
|
|
|
selectionType: 'completeSelection',
|
|
|
|
selection: updatedSelectionRanges,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'do-constrain-snap-to-y': async ({ selectionRanges, sketchDetails }) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const constraint = applyConstraintAxisAlign({
|
2024-05-30 13:28:29 +10:00
|
|
|
selectionRanges,
|
|
|
|
constraint: 'snapToYAxis',
|
|
|
|
})
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(constraint)) return false
|
|
|
|
const { modifiedAst, pathToNodeMap } = constraint
|
2024-05-30 13:28:29 +10:00
|
|
|
if (!sketchDetails) return
|
2024-06-24 11:45:40 -04:00
|
|
|
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
2024-05-30 13:28:29 +10:00
|
|
|
sketchDetails?.sketchPathToNode || [],
|
|
|
|
modifiedAst,
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(updatedAst, { suppress: true })) return
|
|
|
|
if (!updatedAst) return
|
2024-05-30 13:28:29 +10:00
|
|
|
const updatedSelectionRanges = updateSelections(
|
|
|
|
pathToNodeMap,
|
|
|
|
selectionRanges,
|
2024-06-24 11:45:40 -04:00
|
|
|
updatedAst.newAst
|
2024-05-30 13:28:29 +10:00
|
|
|
)
|
|
|
|
return {
|
|
|
|
selectionType: 'completeSelection',
|
|
|
|
selection: updatedSelectionRanges,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'do-constrain-parallel': async ({ selectionRanges, sketchDetails }) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const constraint = applyConstraintEqualAngle({
|
2024-05-30 13:28:29 +10:00
|
|
|
selectionRanges,
|
|
|
|
})
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(constraint)) return false
|
|
|
|
const { modifiedAst, pathToNodeMap } = constraint
|
|
|
|
|
|
|
|
if (!sketchDetails) {
|
|
|
|
trap(new Error('No sketch details'))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
2024-05-30 13:28:29 +10:00
|
|
|
sketchDetails?.sketchPathToNode || [],
|
|
|
|
parse(recast(modifiedAst)),
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(updatedAst, { suppress: true })) return
|
|
|
|
if (!updatedAst) return
|
2024-05-30 13:28:29 +10:00
|
|
|
const updatedSelectionRanges = updateSelections(
|
|
|
|
pathToNodeMap,
|
|
|
|
selectionRanges,
|
2024-06-24 11:45:40 -04:00
|
|
|
updatedAst.newAst
|
2024-05-30 13:28:29 +10:00
|
|
|
)
|
|
|
|
return {
|
|
|
|
selectionType: 'completeSelection',
|
|
|
|
selection: updatedSelectionRanges,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'do-constrain-equal-length': async ({
|
|
|
|
selectionRanges,
|
|
|
|
sketchDetails,
|
|
|
|
}) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const constraint = applyConstraintEqualLength({
|
2024-05-30 13:28:29 +10:00
|
|
|
selectionRanges,
|
|
|
|
})
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(constraint)) return false
|
|
|
|
const { modifiedAst, pathToNodeMap } = constraint
|
2024-05-30 13:28:29 +10:00
|
|
|
if (!sketchDetails) return
|
2024-06-24 11:45:40 -04:00
|
|
|
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
2024-05-30 13:28:29 +10:00
|
|
|
sketchDetails?.sketchPathToNode || [],
|
|
|
|
modifiedAst,
|
|
|
|
sketchDetails.zAxis,
|
|
|
|
sketchDetails.yAxis,
|
|
|
|
sketchDetails.origin
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (trap(updatedAst, { suppress: true })) return
|
|
|
|
if (!updatedAst) return
|
2024-05-30 13:28:29 +10:00
|
|
|
const updatedSelectionRanges = updateSelections(
|
|
|
|
pathToNodeMap,
|
|
|
|
selectionRanges,
|
2024-06-24 11:45:40 -04:00
|
|
|
updatedAst.newAst
|
2024-05-30 13:28:29 +10:00
|
|
|
)
|
|
|
|
return {
|
|
|
|
selectionType: 'completeSelection',
|
|
|
|
selection: updatedSelectionRanges,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
// end services
|
2023-10-11 13:36:54 +11:00
|
|
|
}
|
|
|
|
)
|
2024-07-05 13:40:16 +10:00
|
|
|
|
|
|
|
export function isEditingExistingSketch({
|
|
|
|
sketchDetails,
|
|
|
|
}: {
|
|
|
|
sketchDetails: SketchDetails | null
|
|
|
|
}): boolean {
|
|
|
|
// should check that the variable declaration is a pipeExpression
|
|
|
|
// and that the pipeExpression contains a "startProfileAt" callExpression
|
|
|
|
if (!sketchDetails?.sketchPathToNode) return false
|
|
|
|
const variableDeclaration = getNodeFromPath<VariableDeclarator>(
|
|
|
|
kclManager.ast,
|
|
|
|
sketchDetails.sketchPathToNode,
|
|
|
|
'VariableDeclarator'
|
|
|
|
)
|
|
|
|
if (err(variableDeclaration)) return false
|
|
|
|
if (variableDeclaration.node.type !== 'VariableDeclarator') return false
|
|
|
|
const pipeExpression = variableDeclaration.node.init
|
|
|
|
if (pipeExpression.type !== 'PipeExpression') return false
|
|
|
|
const hasStartProfileAt = pipeExpression.body.some(
|
|
|
|
(item) =>
|
|
|
|
item.type === 'CallExpression' && item.callee.name === 'startProfileAt'
|
|
|
|
)
|
|
|
|
return hasStartProfileAt && pipeExpression.body.length > 2
|
|
|
|
}
|
|
|
|
|
|
|
|
export function canRectangleTool({
|
|
|
|
sketchDetails,
|
|
|
|
}: {
|
|
|
|
sketchDetails: SketchDetails | null
|
|
|
|
}): boolean {
|
|
|
|
const node = getNodeFromPath<VariableDeclaration>(
|
|
|
|
kclManager.ast,
|
|
|
|
sketchDetails?.sketchPathToNode || [],
|
|
|
|
'VariableDeclaration'
|
|
|
|
)
|
|
|
|
// This should not be returning false, and it should be caught
|
|
|
|
// but we need to simulate old behavior to move on.
|
|
|
|
if (err(node)) return false
|
|
|
|
return node.node?.declarations?.[0]?.init.type !== 'PipeExpression'
|
|
|
|
}
|