2023-10-16 21:20:05 +11:00
|
|
|
import { Models } from '@kittycad/lib'
|
2024-03-22 16:55:30 +11:00
|
|
|
import {
|
2024-04-17 20:18:07 -07:00
|
|
|
codeManager,
|
2024-03-22 16:55:30 +11:00
|
|
|
engineCommandManager,
|
|
|
|
kclManager,
|
|
|
|
sceneEntitiesManager,
|
|
|
|
} from 'lib/singletons'
|
2024-12-06 13:57:31 +13:00
|
|
|
import {
|
|
|
|
CallExpression,
|
|
|
|
SourceRange,
|
|
|
|
Expr,
|
|
|
|
defaultSourceRange,
|
2025-01-17 14:34:36 -05:00
|
|
|
topLevelRange,
|
2024-12-06 13:57:31 +13:00
|
|
|
} from 'lang/wasm'
|
2023-10-16 21:20:05 +11:00
|
|
|
import { ModelingMachineEvent } from 'machines/modelingMachine'
|
2024-09-27 09:37:27 -04:00
|
|
|
import { isNonNullable, uuidv4 } from 'lib/utils'
|
2024-07-03 21:28:51 -07:00
|
|
|
import { EditorSelection, SelectionRange } from '@codemirror/state'
|
2024-03-22 10:23:04 +11:00
|
|
|
import { getNormalisedCoordinates, isOverlap } from 'lib/utils'
|
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 { isCursorInSketchCommandRange } from 'lang/util'
|
|
|
|
import { Program } from 'lang/wasm'
|
2025-01-27 14:24:28 +01:00
|
|
|
import { getNodeFromPath, isSingleCursorInPipe } from 'lang/queryAst'
|
|
|
|
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
|
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 { CommandArgument } from './commandTypes'
|
2024-02-11 12:59:00 +11:00
|
|
|
import {
|
|
|
|
getParentGroup,
|
2024-09-13 21:14:14 +10:00
|
|
|
SEGMENT_BODIES_PLUS_PROFILE_START,
|
2024-02-14 08:03:20 +11:00
|
|
|
} from 'clientSideScene/sceneEntities'
|
2024-03-22 10:23:04 +11:00
|
|
|
import { Mesh, Object3D, Object3DEventMap } from 'three'
|
2024-02-14 08:03:20 +11:00
|
|
|
import { AXIS_GROUP, X_AXIS } from 'clientSideScene/sceneInfra'
|
2024-05-30 13:28:29 +10:00
|
|
|
import { PathToNodeMap } from 'lang/std/sketchcombos'
|
2024-06-24 11:45:40 -04:00
|
|
|
import { err } from 'lib/trap'
|
2024-08-03 18:08:51 +10:00
|
|
|
import {
|
2024-11-21 15:04:30 +11:00
|
|
|
Artifact,
|
2024-08-03 18:08:51 +10:00
|
|
|
getArtifactOfTypes,
|
|
|
|
getArtifactsOfTypes,
|
|
|
|
getCapCodeRef,
|
2024-09-17 13:22:53 -05:00
|
|
|
getSweepEdgeCodeRef,
|
2024-08-03 18:08:51 +10:00
|
|
|
getSolid2dCodeRef,
|
|
|
|
getWallCodeRef,
|
2024-11-21 15:04:30 +11:00
|
|
|
CodeRef,
|
|
|
|
getCodeRefsByArtifactId,
|
2024-09-27 09:37:27 -04:00
|
|
|
ArtifactId,
|
2025-02-15 00:57:04 +11:00
|
|
|
getFaceCodeRef,
|
2024-08-03 18:08:51 +10:00
|
|
|
} from 'lang/std/artifactGraph'
|
2024-10-30 16:52:17 -04:00
|
|
|
import { Node } from 'wasm-lib/kcl/bindings/Node'
|
Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b570394f11afbd04d0d126d87305165c73c
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-05 19:33:40 -05:00
|
|
|
import { DefaultPlaneStr } from './planes'
|
2023-10-16 21:20:05 +11:00
|
|
|
|
2023-12-01 20:18:51 +11:00
|
|
|
export const X_AXIS_UUID = 'ad792545-7fd3-482a-a602-a93924e3055b'
|
|
|
|
export const Y_AXIS_UUID = '680fd157-266f-4b8a-984f-cdf46b8bdf01'
|
|
|
|
|
2023-10-16 21:20:05 +11:00
|
|
|
export type Axis = 'y-axis' | 'x-axis' | 'z-axis'
|
2024-11-26 11:36:14 -05:00
|
|
|
export type DefaultPlaneSelection = {
|
|
|
|
name: DefaultPlaneStr
|
|
|
|
id: string
|
|
|
|
}
|
2023-10-16 21:20:05 +11:00
|
|
|
|
2024-11-21 15:04:30 +11:00
|
|
|
/** @deprecated Use {@link Artifact} instead. */
|
|
|
|
type Selection__old =
|
2024-09-26 18:25:05 +10:00
|
|
|
| {
|
|
|
|
type:
|
|
|
|
| 'default'
|
|
|
|
| 'line-end'
|
|
|
|
| 'line-mid'
|
|
|
|
| 'extrude-wall'
|
2025-01-17 14:34:36 -05:00
|
|
|
| 'solid2d'
|
2024-09-26 18:25:05 +10:00
|
|
|
| 'start-cap'
|
|
|
|
| 'end-cap'
|
|
|
|
| 'point'
|
|
|
|
| 'edge'
|
|
|
|
| 'adjacent-edge'
|
|
|
|
| 'line'
|
|
|
|
| 'arc'
|
|
|
|
| 'all'
|
|
|
|
range: SourceRange
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: 'opposite-edgeCut' | 'adjacent-edgeCut' | 'base-edgeCut'
|
|
|
|
range: SourceRange
|
|
|
|
// TODO this is a temporary measure that well be made redundant with: https://github.com/KittyCAD/modeling-app/pull/3836
|
|
|
|
secondaryRange: SourceRange
|
|
|
|
}
|
2024-11-26 11:36:14 -05:00
|
|
|
export type NonCodeSelection = Axis | DefaultPlaneSelection
|
|
|
|
|
2024-11-21 15:04:30 +11:00
|
|
|
/** @deprecated Use {@link Selection} instead. */
|
|
|
|
export type Selections__old = {
|
2024-11-26 11:36:14 -05:00
|
|
|
otherSelections: NonCodeSelection[]
|
2024-11-21 15:04:30 +11:00
|
|
|
codeBasedSelections: Selection__old[]
|
|
|
|
}
|
|
|
|
export interface Selection {
|
|
|
|
artifact?: Artifact
|
|
|
|
codeRef: CodeRef
|
|
|
|
}
|
|
|
|
export type Selections = {
|
2024-11-26 11:36:14 -05:00
|
|
|
otherSelections: Array<NonCodeSelection>
|
2024-11-21 15:04:30 +11:00
|
|
|
graphSelections: Array<Selection>
|
2023-10-16 21:20:05 +11:00
|
|
|
}
|
|
|
|
|
2024-11-21 15:04:30 +11:00
|
|
|
/** @deprecated If you're writing a new function, it should use {@link Selection} and not {@link Selection__old}
|
|
|
|
* this function should only be used for backwards compatibility with old functions.
|
|
|
|
*/
|
|
|
|
function convertSelectionToOld(selection: Selection): Selection__old | null {
|
|
|
|
// return {} as Selection__old
|
|
|
|
// TODO implementation
|
|
|
|
const _artifact = selection.artifact
|
2025-01-17 14:34:36 -05:00
|
|
|
if (_artifact?.type === 'solid2d') {
|
2024-08-03 18:08:51 +10:00
|
|
|
const codeRef = getSolid2dCodeRef(
|
|
|
|
_artifact,
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
if (err(codeRef)) return null
|
2025-01-17 14:34:36 -05:00
|
|
|
return { range: codeRef.range, type: 'solid2d' }
|
2024-05-21 05:55:34 +10:00
|
|
|
}
|
2024-11-21 15:04:30 +11:00
|
|
|
if (_artifact?.type === 'cap') {
|
2024-08-03 18:08:51 +10:00
|
|
|
const codeRef = getCapCodeRef(_artifact, engineCommandManager.artifactGraph)
|
|
|
|
if (err(codeRef)) return null
|
|
|
|
return {
|
2024-11-21 15:04:30 +11:00
|
|
|
range: codeRef.range,
|
|
|
|
type: _artifact?.subType === 'end' ? 'end-cap' : 'start-cap',
|
2024-08-03 18:08:51 +10:00
|
|
|
}
|
|
|
|
}
|
2024-11-21 15:04:30 +11:00
|
|
|
if (_artifact?.type === 'wall') {
|
2024-08-03 18:08:51 +10:00
|
|
|
const codeRef = getWallCodeRef(
|
|
|
|
_artifact,
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
if (err(codeRef)) return null
|
2024-11-21 15:04:30 +11:00
|
|
|
return { range: codeRef.range, type: 'extrude-wall' }
|
2024-08-03 18:08:51 +10:00
|
|
|
}
|
2024-11-21 15:04:30 +11:00
|
|
|
if (_artifact?.type === 'segment' || _artifact?.type === 'path') {
|
|
|
|
return { range: _artifact.codeRef.range, type: 'default' }
|
2023-10-16 21:20:05 +11:00
|
|
|
}
|
2024-11-21 15:04:30 +11:00
|
|
|
if (_artifact?.type === 'sweepEdge') {
|
2024-09-17 13:22:53 -05:00
|
|
|
const codeRef = getSweepEdgeCodeRef(
|
2024-08-30 19:46:48 +10:00
|
|
|
_artifact,
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
if (err(codeRef)) return null
|
2024-09-17 05:38:58 +10:00
|
|
|
if (_artifact?.subType === 'adjacent') {
|
2024-11-21 15:04:30 +11:00
|
|
|
return { range: codeRef.range, type: 'adjacent-edge' }
|
|
|
|
}
|
|
|
|
return { range: codeRef.range, type: 'edge' }
|
|
|
|
}
|
|
|
|
if (_artifact?.type === 'edgeCut') {
|
|
|
|
const codeRef = _artifact.codeRef
|
|
|
|
return { range: codeRef.range, type: 'default' }
|
|
|
|
}
|
|
|
|
if (selection?.codeRef?.range) {
|
|
|
|
return { range: selection.codeRef.range, type: 'default' }
|
|
|
|
}
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
/** @deprecated If you're writing a new function, it should use {@link Selection} and not {@link Selection__old}
|
|
|
|
* this function should only be used for backwards compatibility with old functions.
|
|
|
|
*/
|
|
|
|
export function convertSelectionsToOld(selection: Selections): Selections__old {
|
|
|
|
const selections: Selection__old[] = []
|
|
|
|
for (const artifact of selection.graphSelections) {
|
|
|
|
const converted = convertSelectionToOld(artifact)
|
|
|
|
if (converted) selections.push(converted)
|
|
|
|
}
|
|
|
|
const selectionsOld: Selections__old = {
|
|
|
|
otherSelections: selection.otherSelections,
|
|
|
|
codeBasedSelections: selections,
|
|
|
|
}
|
|
|
|
return selectionsOld
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function getEventForSelectWithPoint({
|
|
|
|
data,
|
|
|
|
}: Extract<
|
|
|
|
Models['OkModelingCmdResponse_type'],
|
|
|
|
{ type: 'select_with_point' }
|
|
|
|
>): Promise<ModelingMachineEvent | null> {
|
|
|
|
if (!data?.entity_id) {
|
|
|
|
return {
|
|
|
|
type: 'Set selection',
|
|
|
|
data: { selectionType: 'singleCodeCursor' },
|
2024-09-17 05:38:58 +10:00
|
|
|
}
|
2024-11-21 15:04:30 +11:00
|
|
|
}
|
|
|
|
if ([X_AXIS_UUID, Y_AXIS_UUID].includes(data.entity_id)) {
|
2024-08-30 19:46:48 +10:00
|
|
|
return {
|
|
|
|
type: 'Set selection',
|
|
|
|
data: {
|
2024-11-26 11:36:14 -05:00
|
|
|
selectionType: 'axisSelection',
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: X_AXIS_UUID === data.entity_id ? 'x-axis' : 'y-axis',
|
2024-08-30 19:46:48 +10:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2024-11-26 11:36:14 -05:00
|
|
|
|
|
|
|
// Check for default plane selection
|
|
|
|
const foundDefaultPlane =
|
|
|
|
engineCommandManager.defaultPlanes !== null &&
|
|
|
|
Object.entries(engineCommandManager.defaultPlanes).find(
|
|
|
|
([, plane]) => plane === data.entity_id
|
|
|
|
)
|
|
|
|
if (foundDefaultPlane) {
|
|
|
|
return {
|
|
|
|
type: 'Set selection',
|
|
|
|
data: {
|
|
|
|
selectionType: 'defaultPlaneSelection',
|
|
|
|
selection: {
|
|
|
|
name: foundDefaultPlane[0] as DefaultPlaneStr,
|
|
|
|
id: data.entity_id,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-21 15:04:30 +11:00
|
|
|
let _artifact = engineCommandManager.artifactGraph.get(data.entity_id)
|
|
|
|
const codeRefs = getCodeRefsByArtifactId(
|
|
|
|
data.entity_id,
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
if (_artifact && codeRefs) {
|
2024-09-26 18:25:05 +10:00
|
|
|
return {
|
|
|
|
type: 'Set selection',
|
|
|
|
data: {
|
|
|
|
selectionType: 'singleCodeCursor',
|
|
|
|
selection: {
|
2024-11-21 15:04:30 +11:00
|
|
|
artifact: _artifact,
|
|
|
|
codeRef: codeRefs[0],
|
2024-09-26 18:25:05 +10:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2024-08-03 18:08:51 +10:00
|
|
|
return null
|
2023-10-16 21:20:05 +11:00
|
|
|
}
|
|
|
|
|
2024-02-11 12:59:00 +11:00
|
|
|
export function getEventForSegmentSelection(
|
2024-03-22 10:23:04 +11:00
|
|
|
obj: Object3D<Object3DEventMap>
|
2024-02-11 12:59:00 +11:00
|
|
|
): ModelingMachineEvent | null {
|
2024-09-13 21:14:14 +10:00
|
|
|
const group = getParentGroup(obj, SEGMENT_BODIES_PLUS_PROFILE_START)
|
2024-02-11 12:59:00 +11:00
|
|
|
const axisGroup = getParentGroup(obj, [AXIS_GROUP])
|
|
|
|
if (!group && !axisGroup) return null
|
|
|
|
if (axisGroup?.userData.type === AXIS_GROUP) {
|
|
|
|
return {
|
|
|
|
type: 'Set selection',
|
|
|
|
data: {
|
2024-11-26 11:36:14 -05:00
|
|
|
selectionType: 'axisSelection',
|
2024-02-11 12:59:00 +11:00
|
|
|
selection: obj?.userData?.type === X_AXIS ? 'x-axis' : 'y-axis',
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2024-11-21 15:04:30 +11:00
|
|
|
// id does not match up with the artifact graph when in sketch mode, because mock executions
|
|
|
|
// do not update the artifact graph, therefore we match up the pathToNode instead
|
|
|
|
// we can reliably use `type === 'segment'` since it's in sketch mode and we're concerned with segments
|
|
|
|
const segWithMatchingPathToNode__Id = [
|
|
|
|
...engineCommandManager.artifactGraph,
|
|
|
|
].find((entry) => {
|
|
|
|
return (
|
|
|
|
entry[1].type === 'segment' &&
|
|
|
|
JSON.stringify(entry[1].codeRef.pathToNode) ===
|
|
|
|
JSON.stringify(group?.userData?.pathToNode)
|
|
|
|
)
|
|
|
|
})?.[0]
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-11-21 15:04:30 +11:00
|
|
|
const id = segWithMatchingPathToNode__Id
|
|
|
|
|
|
|
|
if (!id && group) {
|
|
|
|
const node = getNodeFromPath<Expr>(
|
|
|
|
kclManager.ast,
|
|
|
|
group.userData.pathToNode
|
|
|
|
)
|
|
|
|
if (err(node)) return null
|
|
|
|
return {
|
|
|
|
type: 'Set selection',
|
|
|
|
data: {
|
|
|
|
selectionType: 'singleCodeCursor',
|
|
|
|
selection: {
|
|
|
|
codeRef: {
|
2025-01-17 14:34:36 -05:00
|
|
|
range: topLevelRange(node.node.start, node.node.end),
|
2024-11-21 15:04:30 +11:00
|
|
|
pathToNode: group.userData.pathToNode,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!id || !group) return null
|
|
|
|
const artifact = engineCommandManager.artifactGraph.get(id)
|
2025-02-15 00:57:04 +11:00
|
|
|
if (!artifact) return null
|
|
|
|
const node = getNodeFromPath<Expr>(kclManager.ast, group.userData.pathToNode)
|
|
|
|
if (err(node)) return null
|
2024-02-11 12:59:00 +11:00
|
|
|
return {
|
|
|
|
type: 'Set selection',
|
|
|
|
data: {
|
|
|
|
selectionType: 'singleCodeCursor',
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: {
|
|
|
|
artifact,
|
2025-02-15 00:57:04 +11:00
|
|
|
codeRef: {
|
|
|
|
pathToNode: group?.userData?.pathToNode,
|
|
|
|
range: [node.node.start, node.node.end, 0],
|
|
|
|
},
|
2024-11-21 15:04:30 +11:00
|
|
|
},
|
2024-02-11 12:59:00 +11:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-16 21:20:05 +11:00
|
|
|
export function handleSelectionBatch({
|
|
|
|
selections,
|
|
|
|
}: {
|
|
|
|
selections: Selections
|
|
|
|
}): {
|
2024-03-22 10:23:04 +11:00
|
|
|
engineEvents: Models['WebSocketRequest_type'][]
|
|
|
|
codeMirrorSelection: EditorSelection
|
|
|
|
updateSceneObjectColors: () => void
|
2023-10-16 21:20:05 +11:00
|
|
|
} {
|
|
|
|
const ranges: ReturnType<typeof EditorSelection.cursor>[] = []
|
2024-11-21 15:04:30 +11:00
|
|
|
const selectionToEngine: SelectionToEngine[] = []
|
|
|
|
|
|
|
|
selections.graphSelections.forEach(({ artifact }) => {
|
|
|
|
artifact?.id &&
|
|
|
|
selectionToEngine.push({
|
|
|
|
type: 'default',
|
|
|
|
id: artifact?.id,
|
2024-12-06 13:57:31 +13:00
|
|
|
range:
|
|
|
|
getCodeRefsByArtifactId(
|
|
|
|
artifact.id,
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)?.[0].range || defaultSourceRange(),
|
2024-11-21 15:04:30 +11:00
|
|
|
})
|
|
|
|
})
|
2024-03-22 10:23:04 +11:00
|
|
|
const engineEvents: Models['WebSocketRequest_type'][] =
|
2024-11-21 15:04:30 +11:00
|
|
|
resetAndSetEngineEntitySelectionCmds(selectionToEngine)
|
|
|
|
selections.graphSelections.forEach(({ codeRef }) => {
|
|
|
|
if (codeRef.range?.[1]) {
|
2025-01-06 17:18:58 -08:00
|
|
|
const safeEnd = Math.min(codeRef.range[1], codeManager.code.length)
|
|
|
|
ranges.push(EditorSelection.cursor(safeEnd))
|
2023-10-16 21:20:05 +11:00
|
|
|
}
|
|
|
|
})
|
|
|
|
if (ranges.length)
|
|
|
|
return {
|
2024-03-22 10:23:04 +11:00
|
|
|
engineEvents,
|
2023-10-16 21:20:05 +11:00
|
|
|
codeMirrorSelection: EditorSelection.create(
|
|
|
|
ranges,
|
2024-11-21 15:04:30 +11:00
|
|
|
selections.graphSelections.length - 1
|
2023-10-16 21:20:05 +11:00
|
|
|
),
|
2024-03-22 10:23:04 +11:00
|
|
|
updateSceneObjectColors: () =>
|
2024-11-21 15:04:30 +11:00
|
|
|
updateSceneObjectColors(selections.graphSelections),
|
2023-10-16 21:20:05 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
2024-03-22 10:23:04 +11:00
|
|
|
codeMirrorSelection: EditorSelection.create(
|
2024-04-17 20:18:07 -07:00
|
|
|
[EditorSelection.cursor(codeManager.code.length)],
|
2024-03-22 10:23:04 +11:00
|
|
|
0
|
|
|
|
),
|
|
|
|
engineEvents,
|
|
|
|
updateSceneObjectColors: () =>
|
2024-11-21 15:04:30 +11:00
|
|
|
updateSceneObjectColors(selections.graphSelections),
|
2023-10-16 21:20:05 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-21 15:04:30 +11:00
|
|
|
type SelectionToEngine = {
|
|
|
|
type: Selection__old['type']
|
|
|
|
id?: string
|
|
|
|
range: SourceRange
|
|
|
|
}
|
2023-10-16 21:20:05 +11:00
|
|
|
|
|
|
|
export function processCodeMirrorRanges({
|
|
|
|
codeMirrorRanges,
|
|
|
|
selectionRanges,
|
2023-12-01 20:18:51 +11:00
|
|
|
isShiftDown,
|
2024-11-21 15:04:30 +11:00
|
|
|
ast,
|
2023-10-16 21:20:05 +11:00
|
|
|
}: {
|
|
|
|
codeMirrorRanges: readonly SelectionRange[]
|
|
|
|
selectionRanges: Selections
|
2023-12-01 20:18:51 +11:00
|
|
|
isShiftDown: boolean
|
2024-11-21 15:04:30 +11:00
|
|
|
ast: Program
|
2023-10-16 21:20:05 +11:00
|
|
|
}): null | {
|
|
|
|
modelingEvent: ModelingMachineEvent
|
|
|
|
engineEvents: Models['WebSocketRequest_type'][]
|
|
|
|
} {
|
|
|
|
const isChange =
|
2024-11-21 15:04:30 +11:00
|
|
|
codeMirrorRanges.length !== selectionRanges?.graphSelections?.length ||
|
2023-10-16 21:20:05 +11:00
|
|
|
codeMirrorRanges.some(({ from, to }, i) => {
|
|
|
|
return (
|
2024-11-21 15:04:30 +11:00
|
|
|
from !== selectionRanges.graphSelections[i]?.codeRef?.range[0] ||
|
|
|
|
to !== selectionRanges.graphSelections[i]?.codeRef?.range[1]
|
2023-10-16 21:20:05 +11:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
if (!isChange) return null
|
2024-11-21 15:04:30 +11:00
|
|
|
const codeBasedSelections: Selections['graphSelections'] =
|
2023-10-16 21:20:05 +11:00
|
|
|
codeMirrorRanges.map(({ from, to }) => {
|
2025-01-17 14:34:36 -05:00
|
|
|
const pathToNode = getNodePathFromSourceRange(
|
|
|
|
ast,
|
|
|
|
topLevelRange(from, to)
|
|
|
|
)
|
2023-10-16 21:20:05 +11:00
|
|
|
return {
|
2024-11-21 15:04:30 +11:00
|
|
|
codeRef: {
|
2025-01-17 14:34:36 -05:00
|
|
|
range: topLevelRange(from, to),
|
2024-11-21 15:04:30 +11:00
|
|
|
pathToNode,
|
|
|
|
},
|
2023-10-16 21:20:05 +11:00
|
|
|
}
|
|
|
|
})
|
2024-03-22 10:23:04 +11:00
|
|
|
const idBasedSelections: SelectionToEngine[] =
|
|
|
|
codeToIdSelections(codeBasedSelections)
|
2024-11-21 15:04:30 +11:00
|
|
|
const selections: Selection[] = []
|
|
|
|
for (const { id, range } of idBasedSelections) {
|
|
|
|
if (!id) {
|
|
|
|
const pathToNode = getNodePathFromSourceRange(ast, range)
|
|
|
|
selections.push({
|
|
|
|
codeRef: {
|
|
|
|
range,
|
|
|
|
pathToNode,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
const artifact = engineCommandManager.artifactGraph.get(id)
|
|
|
|
const codeRefs = getCodeRefsByArtifactId(
|
|
|
|
id,
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
if (artifact && codeRefs) {
|
|
|
|
selections.push({ artifact, codeRef: codeRefs[0] })
|
|
|
|
} else if (codeRefs) {
|
|
|
|
selections.push({ codeRef: codeRefs[0] })
|
|
|
|
}
|
|
|
|
}
|
2023-10-16 21:20:05 +11:00
|
|
|
|
|
|
|
if (!selectionRanges) return null
|
2024-02-11 12:59:00 +11:00
|
|
|
updateSceneObjectColors(codeBasedSelections)
|
2023-10-16 21:20:05 +11:00
|
|
|
return {
|
|
|
|
modelingEvent: {
|
|
|
|
type: 'Set selection',
|
|
|
|
data: {
|
|
|
|
selectionType: 'mirrorCodeMirrorSelections',
|
|
|
|
selection: {
|
2023-12-01 20:18:51 +11:00
|
|
|
otherSelections: isShiftDown ? selectionRanges.otherSelections : [],
|
2024-11-21 15:04:30 +11:00
|
|
|
graphSelections: selections,
|
2023-10-16 21:20:05 +11:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-11-21 15:04:30 +11:00
|
|
|
engineEvents: resetAndSetEngineEntitySelectionCmds(
|
|
|
|
idBasedSelections.filter(({ id }) => !!id)
|
|
|
|
),
|
2023-10-16 21:20:05 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-24 11:45:40 -04:00
|
|
|
function updateSceneObjectColors(codeBasedSelections: Selection[]) {
|
2024-09-06 17:52:52 -04:00
|
|
|
const updated = kclManager.ast
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-02-14 08:03:20 +11:00
|
|
|
Object.values(sceneEntitiesManager.activeSegments).forEach((segmentGroup) => {
|
2024-09-13 21:14:14 +10:00
|
|
|
if (!SEGMENT_BODIES_PLUS_PROFILE_START.includes(segmentGroup?.name)) return
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
const nodeMeta = getNodeFromPath<Node<CallExpression | CallExpression>>(
|
2024-02-11 12:59:00 +11:00
|
|
|
updated,
|
|
|
|
segmentGroup.userData.pathToNode,
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
['CallExpression', 'CallExpressionKw']
|
2024-06-24 11:45:40 -04:00
|
|
|
)
|
|
|
|
if (err(nodeMeta)) return
|
|
|
|
const node = nodeMeta.node
|
2024-02-11 12:59:00 +11:00
|
|
|
const groupHasCursor = codeBasedSelections.some((selection) => {
|
2025-01-17 14:34:36 -05:00
|
|
|
return isOverlap(
|
|
|
|
selection?.codeRef?.range,
|
|
|
|
topLevelRange(node.start, node.end)
|
|
|
|
)
|
2024-02-11 12:59:00 +11:00
|
|
|
})
|
2024-06-22 04:49:31 -04:00
|
|
|
|
2024-03-04 14:18:08 +11:00
|
|
|
const color = groupHasCursor
|
|
|
|
? 0x0000ff
|
|
|
|
: segmentGroup?.userData?.baseColor || 0xffffff
|
2024-02-11 12:59:00 +11:00
|
|
|
segmentGroup.traverse(
|
|
|
|
(child) => child instanceof Mesh && child.material.color.set(color)
|
|
|
|
)
|
|
|
|
// TODO if we had access to the xstate context and therefore selections
|
|
|
|
// we wouldn't need to set this here,
|
|
|
|
// it would be better to treat xstate context as the source of truth instead of having
|
|
|
|
// extra redundant state floating around
|
|
|
|
segmentGroup.userData.isSelected = groupHasCursor
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-12-01 20:18:51 +11:00
|
|
|
function resetAndSetEngineEntitySelectionCmds(
|
2023-10-16 21:20:05 +11:00
|
|
|
selections: SelectionToEngine[]
|
|
|
|
): Models['WebSocketRequest_type'][] {
|
|
|
|
if (!engineCommandManager.engineConnection?.isReady()) {
|
|
|
|
return []
|
|
|
|
}
|
|
|
|
return [
|
|
|
|
{
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd: {
|
|
|
|
type: 'select_clear',
|
|
|
|
},
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd: {
|
|
|
|
type: 'select_add',
|
2024-11-21 15:04:30 +11:00
|
|
|
entities: selections.map(({ id }) => id).filter(isNonNullable),
|
2023-10-16 21:20:05 +11:00
|
|
|
},
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
},
|
|
|
|
]
|
|
|
|
}
|
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
|
|
|
|
2024-12-19 18:42:39 -05:00
|
|
|
/**
|
|
|
|
* Is the selection a single cursor in a sketch pipe expression chain?
|
|
|
|
*/
|
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
|
|
|
export function isSketchPipe(selectionRanges: Selections) {
|
2024-02-19 17:23:03 +11:00
|
|
|
if (!isSingleCursorInPipe(selectionRanges, kclManager.ast)) return false
|
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
|
|
|
return isCursorInSketchCommandRange(
|
2024-08-03 18:08:51 +10:00
|
|
|
engineCommandManager.artifactGraph,
|
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
|
|
|
selectionRanges
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// This accounts for non-geometry selections under "other"
|
2024-11-26 11:36:14 -05:00
|
|
|
export type ResolvedSelectionType = Artifact['type'] | 'other'
|
|
|
|
export type SelectionCountsByType = Map<ResolvedSelectionType, number>
|
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
|
|
|
|
|
|
|
/**
|
|
|
|
* In the future, I'd like this function to properly return the type of each selected entity based on
|
|
|
|
* its code source range, so that we can show something like "0 objects" or "1 face" or "1 line, 2 edges",
|
|
|
|
* and then validate the selection in CommandBarSelectionInput.tsx and show the proper label.
|
|
|
|
* @param selection
|
|
|
|
* @returns
|
|
|
|
*/
|
2024-11-26 11:36:14 -05:00
|
|
|
export function getSelectionCountByType(
|
2024-09-23 14:35:38 -04:00
|
|
|
selection?: Selections
|
2024-11-26 11:36:14 -05:00
|
|
|
): SelectionCountsByType | 'none' {
|
|
|
|
const selectionsByType: SelectionCountsByType = new Map()
|
|
|
|
if (
|
|
|
|
!selection ||
|
|
|
|
(!selection.graphSelections.length && !selection.otherSelections.length)
|
2024-11-21 15:04:30 +11:00
|
|
|
)
|
2024-11-26 11:36:14 -05:00
|
|
|
return 'none'
|
|
|
|
|
|
|
|
function incrementOrInitializeSelectionType(type: ResolvedSelectionType) {
|
|
|
|
const count = selectionsByType.get(type) || 0
|
|
|
|
selectionsByType.set(type, count + 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
selection.otherSelections.forEach((selection) => {
|
|
|
|
if (typeof selection === 'string') {
|
|
|
|
incrementOrInitializeSelectionType('other')
|
|
|
|
} else if ('name' in selection) {
|
|
|
|
incrementOrInitializeSelectionType('plane')
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2024-12-09 16:43:58 -05:00
|
|
|
selection.graphSelections.forEach((graphSelection) => {
|
|
|
|
if (!graphSelection.artifact) {
|
|
|
|
/**
|
|
|
|
* TODO: remove this heuristic-based selection type detection.
|
|
|
|
* Currently, if you've created a sketch and have not left sketch mode,
|
|
|
|
* the selection will be a segment selection with no artifact.
|
|
|
|
* This is because the mock execution does not update the artifact graph.
|
|
|
|
* Once we move the artifactGraph creation to WASM, we can remove this,
|
|
|
|
* as the artifactGraph will always be up-to-date.
|
|
|
|
*/
|
|
|
|
if (isSingleCursorInPipe(selection, kclManager.ast)) {
|
|
|
|
incrementOrInitializeSelectionType('segment')
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
console.warn(
|
|
|
|
'Selection is outside of a sketch but has no artifact. Sketch segment selections are the only kind that can have a valid selection with no artifact.',
|
|
|
|
JSON.stringify(graphSelection)
|
|
|
|
)
|
|
|
|
incrementOrInitializeSelectionType('other')
|
|
|
|
return
|
|
|
|
}
|
2024-11-26 11:36:14 -05:00
|
|
|
}
|
2024-12-09 16:43:58 -05:00
|
|
|
incrementOrInitializeSelectionType(graphSelection.artifact.type)
|
2024-11-26 11:36:14 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
return selectionsByType
|
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
|
|
|
}
|
|
|
|
|
|
|
|
export function getSelectionTypeDisplayText(
|
2024-09-23 14:35:38 -04:00
|
|
|
selection?: Selections
|
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
|
|
|
): string | null {
|
2024-11-26 11:36:14 -05:00
|
|
|
const selectionsByType = getSelectionCountByType(selection)
|
|
|
|
if (selectionsByType === 'none') return null
|
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
|
|
|
|
2025-02-15 00:57:04 +11:00
|
|
|
return [...selectionsByType.entries()]
|
2024-04-24 16:34:56 -04:00
|
|
|
.map(
|
|
|
|
// Hack for showing "face" instead of "extrude-wall" in command bar text
|
|
|
|
([type, count]) =>
|
2025-01-31 16:49:57 -05:00
|
|
|
`${count} ${type.replace('wall', 'face').replace('solid2d', 'face')}${
|
|
|
|
count > 1 ? 's' : ''
|
|
|
|
}`
|
2024-04-24 16:34:56 -04: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
|
|
|
.join(', ')
|
|
|
|
}
|
|
|
|
|
|
|
|
export function canSubmitSelectionArg(
|
2024-11-26 11:36:14 -05:00
|
|
|
selectionsByType: 'none' | Map<ResolvedSelectionType, number>,
|
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
|
|
|
argument: CommandArgument<unknown> & { inputType: 'selection' }
|
|
|
|
) {
|
|
|
|
return (
|
|
|
|
selectionsByType !== 'none' &&
|
2025-02-15 00:57:04 +11:00
|
|
|
[...selectionsByType.entries()].every(([type, count]) => {
|
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
|
|
|
const foundIndex = argument.selectionTypes.findIndex((s) => s === type)
|
|
|
|
return (
|
|
|
|
foundIndex !== -1 &&
|
|
|
|
(!argument.multiple ? count < 2 && count > 0 : count > 0)
|
|
|
|
)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-11-21 15:04:30 +11:00
|
|
|
export function codeToIdSelections(
|
|
|
|
selections: Selection[]
|
2024-03-22 10:23:04 +11:00
|
|
|
): SelectionToEngine[] {
|
2024-11-21 15:04:30 +11:00
|
|
|
const selectionsOld = convertSelectionsToOld({
|
|
|
|
graphSelections: selections,
|
|
|
|
otherSelections: [],
|
|
|
|
}).codeBasedSelections
|
|
|
|
return selectionsOld
|
2024-09-27 09:37:27 -04:00
|
|
|
.flatMap((selection): null | SelectionToEngine[] => {
|
|
|
|
const { type } = selection
|
2024-03-22 10:23:04 +11:00
|
|
|
// TODO #868: loops over all artifacts will become inefficient at a large scale
|
2024-08-03 18:08:51 +10:00
|
|
|
const overlappingEntries = Array.from(engineCommandManager.artifactGraph)
|
2024-03-22 10:23:04 +11:00
|
|
|
.map(([id, artifact]) => {
|
2025-02-15 00:57:04 +11:00
|
|
|
const codeRef = getFaceCodeRef(artifact)
|
|
|
|
if (!codeRef) return null
|
|
|
|
return isOverlap(codeRef.range, selection.range)
|
2024-03-22 10:23:04 +11:00
|
|
|
? {
|
|
|
|
artifact,
|
2024-09-27 09:37:27 -04:00
|
|
|
selection,
|
2024-03-22 10:23:04 +11:00
|
|
|
id,
|
|
|
|
}
|
2024-09-27 09:37:27 -04:00
|
|
|
: null
|
2024-03-22 10:23:04 +11:00
|
|
|
})
|
2024-09-27 09:37:27 -04:00
|
|
|
.filter(isNonNullable)
|
2024-08-03 18:08:51 +10:00
|
|
|
|
|
|
|
/** TODO refactor
|
|
|
|
* selections in our app is a sourceRange plus some metadata
|
|
|
|
* The metadata is just a union type string of different types of artifacts or 3d features 'extrude-wall' 'segment' etc
|
|
|
|
* Because the source range is not enough to figure out what the user selected, so here we're using filtering through all the artifacts
|
|
|
|
* to find something that matches both the source range and the metadata.
|
|
|
|
*
|
|
|
|
* What we should migrate to is just storing what the user selected by what it matched in the artifactGraph it will simply the below a lot.
|
|
|
|
*
|
|
|
|
* In the case of a user moving the cursor them, we will still need to figure out what artifact from the graph matches best, but we will just need sane defaults
|
|
|
|
* and most of the time we can expect the user to be clicking in the 3d scene instead.
|
|
|
|
*/
|
2024-09-27 09:37:27 -04:00
|
|
|
let bestCandidate:
|
|
|
|
| {
|
|
|
|
id: ArtifactId
|
|
|
|
artifact: unknown
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: Selection__old
|
2024-09-27 09:37:27 -04:00
|
|
|
}
|
|
|
|
| undefined
|
2024-08-03 18:08:51 +10:00
|
|
|
overlappingEntries.forEach((entry) => {
|
2024-11-21 15:04:30 +11:00
|
|
|
// TODO probably need to remove much of the `type === 'xyz'` below
|
2024-07-25 19:03:56 +10:00
|
|
|
if (type === 'default' && entry.artifact.type === 'segment') {
|
2024-03-22 10:23:04 +11:00
|
|
|
bestCandidate = entry
|
|
|
|
return
|
|
|
|
}
|
2024-11-21 15:04:30 +11:00
|
|
|
if (entry.artifact.type === 'path') {
|
|
|
|
const artifact = engineCommandManager.artifactGraph.get(
|
2024-08-03 18:08:51 +10:00
|
|
|
entry.artifact.solid2dId || ''
|
|
|
|
)
|
2025-01-17 14:34:36 -05:00
|
|
|
if (artifact?.type !== 'solid2d') {
|
2024-11-21 15:04:30 +11:00
|
|
|
bestCandidate = {
|
|
|
|
artifact: entry.artifact,
|
|
|
|
selection,
|
|
|
|
id: entry.id,
|
|
|
|
}
|
|
|
|
}
|
2024-09-27 09:37:27 -04:00
|
|
|
if (!entry.artifact.solid2dId) {
|
|
|
|
console.error(
|
|
|
|
'Expected PathArtifact to have solid2dId, but none found'
|
|
|
|
)
|
|
|
|
return
|
|
|
|
}
|
2024-08-03 18:08:51 +10:00
|
|
|
bestCandidate = {
|
2024-11-21 15:04:30 +11:00
|
|
|
artifact: artifact,
|
2024-09-27 09:37:27 -04:00
|
|
|
selection,
|
2024-08-03 18:08:51 +10:00
|
|
|
id: entry.artifact.solid2dId,
|
|
|
|
}
|
|
|
|
}
|
2025-02-15 00:57:04 +11:00
|
|
|
if (entry.artifact.type === 'plane') {
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: entry.artifact,
|
|
|
|
selection,
|
|
|
|
id: entry.id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (entry.artifact.type === 'cap') {
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: entry.artifact,
|
|
|
|
selection,
|
|
|
|
id: entry.id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (entry.artifact.type === 'wall') {
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: entry.artifact,
|
|
|
|
selection,
|
|
|
|
id: entry.id,
|
|
|
|
}
|
|
|
|
}
|
2024-08-03 18:08:51 +10:00
|
|
|
if (type === 'extrude-wall' && entry.artifact.type === 'segment') {
|
2025-01-13 15:02:55 -05:00
|
|
|
if (!entry.artifact.surfaceId) return
|
2024-08-03 18:08:51 +10:00
|
|
|
const wall = engineCommandManager.artifactGraph.get(
|
|
|
|
entry.artifact.surfaceId
|
|
|
|
)
|
|
|
|
if (wall?.type !== 'wall') return
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: wall,
|
2024-09-27 09:37:27 -04:00
|
|
|
selection,
|
2024-08-03 18:08:51 +10:00
|
|
|
id: entry.artifact.surfaceId,
|
|
|
|
}
|
2024-03-22 10:23:04 +11:00
|
|
|
return
|
|
|
|
}
|
2024-09-17 05:38:58 +10:00
|
|
|
if (type === 'edge' && entry.artifact.type === 'segment') {
|
|
|
|
const edges = getArtifactsOfTypes(
|
2024-09-17 13:22:53 -05:00
|
|
|
{ keys: entry.artifact.edgeIds, types: ['sweepEdge'] },
|
2024-09-17 05:38:58 +10:00
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
2024-09-17 13:22:53 -05:00
|
|
|
const edge = [...edges].find(([_, edge]) => edge.type === 'sweepEdge')
|
2024-09-17 05:38:58 +10:00
|
|
|
if (!edge) return
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: edge[1],
|
2024-09-27 09:37:27 -04:00
|
|
|
selection,
|
2024-09-17 05:38:58 +10:00
|
|
|
id: edge[0],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (type === 'adjacent-edge' && entry.artifact.type === 'segment') {
|
|
|
|
const edges = getArtifactsOfTypes(
|
2024-09-17 13:22:53 -05:00
|
|
|
{ keys: entry.artifact.edgeIds, types: ['sweepEdge'] },
|
2024-09-17 05:38:58 +10:00
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
const edge = [...edges].find(
|
|
|
|
([_, edge]) =>
|
2024-09-17 13:22:53 -05:00
|
|
|
edge.type === 'sweepEdge' && edge.subType === 'adjacent'
|
2024-09-17 05:38:58 +10:00
|
|
|
)
|
|
|
|
if (!edge) return
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: edge[1],
|
2024-09-27 09:37:27 -04:00
|
|
|
selection,
|
2024-09-17 05:38:58 +10:00
|
|
|
id: edge[0],
|
|
|
|
}
|
|
|
|
}
|
2024-03-22 10:23:04 +11:00
|
|
|
if (
|
2024-08-03 18:08:51 +10:00
|
|
|
(type === 'end-cap' || type === 'start-cap') &&
|
|
|
|
entry.artifact.type === 'path'
|
2024-03-22 10:23:04 +11:00
|
|
|
) {
|
2025-01-13 15:02:55 -05:00
|
|
|
if (!entry.artifact.sweepId) return
|
2024-08-03 18:08:51 +10:00
|
|
|
const extrusion = getArtifactOfTypes(
|
|
|
|
{
|
2024-09-17 13:22:53 -05:00
|
|
|
key: entry.artifact.sweepId,
|
|
|
|
types: ['sweep'],
|
2024-08-03 18:08:51 +10:00
|
|
|
},
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
if (err(extrusion)) return
|
|
|
|
const caps = getArtifactsOfTypes(
|
|
|
|
{ keys: extrusion.surfaceIds, types: ['cap'] },
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
const cap = [...caps].find(
|
|
|
|
([_, cap]) => cap.subType === (type === 'end-cap' ? 'end' : 'start')
|
|
|
|
)
|
|
|
|
if (!cap) return
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: entry.artifact,
|
2024-09-27 09:37:27 -04:00
|
|
|
selection,
|
2024-08-03 18:08:51 +10:00
|
|
|
id: cap[0],
|
|
|
|
}
|
2024-03-22 10:23:04 +11:00
|
|
|
return
|
|
|
|
}
|
2024-09-26 18:25:05 +10:00
|
|
|
if (entry.artifact.type === 'edgeCut') {
|
|
|
|
const consumedEdge = getArtifactOfTypes(
|
|
|
|
{
|
|
|
|
key: entry.artifact.consumedEdgeId,
|
|
|
|
types: ['segment', 'sweepEdge'],
|
|
|
|
},
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
if (err(consumedEdge)) return
|
|
|
|
if (
|
|
|
|
consumedEdge.type === 'segment' &&
|
|
|
|
type === 'base-edgeCut' &&
|
|
|
|
isOverlap(
|
|
|
|
consumedEdge.codeRef.range,
|
2024-09-27 09:37:27 -04:00
|
|
|
selection.secondaryRange || [0, 0]
|
2024-09-26 18:25:05 +10:00
|
|
|
)
|
|
|
|
) {
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: entry.artifact,
|
2024-09-27 09:37:27 -04:00
|
|
|
selection,
|
2024-09-26 18:25:05 +10:00
|
|
|
id: entry.id,
|
|
|
|
}
|
|
|
|
} else if (
|
|
|
|
consumedEdge.type === 'sweepEdge' &&
|
|
|
|
((type === 'adjacent-edgeCut' &&
|
|
|
|
consumedEdge.subType === 'adjacent') ||
|
|
|
|
(type === 'opposite-edgeCut' &&
|
|
|
|
consumedEdge.subType === 'opposite'))
|
|
|
|
) {
|
|
|
|
const seg = getArtifactOfTypes(
|
|
|
|
{ key: consumedEdge.segId, types: ['segment'] },
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
if (err(seg)) return
|
|
|
|
if (
|
2024-09-27 09:37:27 -04:00
|
|
|
isOverlap(seg.codeRef.range, selection.secondaryRange || [0, 0])
|
2024-09-26 18:25:05 +10:00
|
|
|
) {
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: entry.artifact,
|
2024-09-27 09:37:27 -04:00
|
|
|
selection,
|
2024-09-26 18:25:05 +10:00
|
|
|
id: entry.id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-12-20 16:19:59 -05:00
|
|
|
|
|
|
|
if (entry.artifact.type === 'sweep') {
|
|
|
|
bestCandidate = {
|
|
|
|
artifact: entry.artifact,
|
|
|
|
selection,
|
|
|
|
id: entry.id,
|
|
|
|
}
|
|
|
|
}
|
2024-03-22 10:23:04 +11:00
|
|
|
})
|
|
|
|
|
|
|
|
if (bestCandidate) {
|
|
|
|
return [
|
|
|
|
{
|
|
|
|
type,
|
2024-09-27 09:37:27 -04:00
|
|
|
id: bestCandidate.id,
|
2024-11-21 15:04:30 +11:00
|
|
|
range: bestCandidate.selection.range,
|
2024-03-22 10:23:04 +11:00
|
|
|
},
|
|
|
|
]
|
|
|
|
}
|
2024-11-21 15:04:30 +11:00
|
|
|
return [selection]
|
2024-03-22 10:23:04 +11:00
|
|
|
})
|
2024-09-27 09:37:27 -04:00
|
|
|
.filter(isNonNullable)
|
2024-03-22 10:23:04 +11:00
|
|
|
}
|
|
|
|
|
2024-06-18 16:08:41 +10:00
|
|
|
export async function sendSelectEventToEngine(
|
2024-03-22 10:23:04 +11:00
|
|
|
e: MouseEvent | React.MouseEvent<HTMLDivElement, MouseEvent>,
|
2024-09-12 22:06:50 -04:00
|
|
|
el: HTMLVideoElement
|
2024-03-22 10:23:04 +11:00
|
|
|
) {
|
|
|
|
const { x, y } = getNormalisedCoordinates({
|
|
|
|
clientX: e.clientX,
|
|
|
|
clientY: e.clientY,
|
|
|
|
el,
|
2025-02-06 12:06:50 -05:00
|
|
|
streamWidth: engineCommandManager.width,
|
|
|
|
streamHeight: engineCommandManager.height,
|
2024-03-22 10:23:04 +11:00
|
|
|
})
|
2024-07-23 17:13:23 +10:00
|
|
|
const res = await engineCommandManager.sendSceneCommand({
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd: {
|
|
|
|
type: 'select_with_point',
|
|
|
|
selected_at_window: { x, y },
|
|
|
|
selection_type: 'add',
|
|
|
|
},
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
})
|
|
|
|
if (
|
|
|
|
res?.success &&
|
|
|
|
res?.resp?.type === 'modeling' &&
|
|
|
|
res?.resp?.data?.modeling_response.type === 'select_with_point'
|
|
|
|
)
|
|
|
|
return res?.resp?.data?.modeling_response?.data
|
|
|
|
return { entity_id: '' }
|
2024-03-22 10:23:04 +11:00
|
|
|
}
|
2024-05-30 13:28:29 +10:00
|
|
|
|
|
|
|
export function updateSelections(
|
|
|
|
pathToNodeMap: PathToNodeMap,
|
|
|
|
prevSelectionRanges: Selections,
|
2024-06-24 11:45:40 -04:00
|
|
|
ast: Program | Error
|
|
|
|
): Selections | Error {
|
|
|
|
if (err(ast)) return ast
|
|
|
|
|
|
|
|
const newSelections = Object.entries(pathToNodeMap)
|
|
|
|
.map(([index, pathToNode]): Selection | undefined => {
|
2024-11-21 15:04:30 +11:00
|
|
|
const previousSelection =
|
|
|
|
prevSelectionRanges.graphSelections[Number(index)]
|
2024-08-12 15:38:42 -05:00
|
|
|
const nodeMeta = getNodeFromPath<Expr>(ast, pathToNode)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(nodeMeta)) return undefined
|
|
|
|
const node = nodeMeta.node
|
2024-11-21 15:04:30 +11:00
|
|
|
let artifact: Artifact | null = null
|
|
|
|
for (const [id, a] of engineCommandManager.artifactGraph) {
|
|
|
|
if (previousSelection?.artifact?.type === a.type) {
|
|
|
|
const codeRefs = getCodeRefsByArtifactId(
|
|
|
|
id,
|
|
|
|
engineCommandManager.artifactGraph
|
|
|
|
)
|
|
|
|
if (!codeRefs) continue
|
|
|
|
if (
|
|
|
|
JSON.stringify(codeRefs[0].pathToNode) ===
|
|
|
|
JSON.stringify(pathToNode)
|
|
|
|
) {
|
|
|
|
artifact = a
|
|
|
|
break
|
|
|
|
}
|
2024-09-26 18:25:05 +10:00
|
|
|
}
|
2024-11-21 15:04:30 +11:00
|
|
|
}
|
|
|
|
if (!artifact) return undefined
|
2024-06-24 11:45:40 -04:00
|
|
|
return {
|
2024-11-21 15:04:30 +11:00
|
|
|
artifact: artifact,
|
|
|
|
codeRef: {
|
2025-01-17 14:34:36 -05:00
|
|
|
range: topLevelRange(node.start, node.end),
|
2024-11-21 15:04:30 +11:00
|
|
|
pathToNode: pathToNode,
|
|
|
|
},
|
2024-05-30 13:28:29 +10:00
|
|
|
}
|
2024-06-24 11:45:40 -04:00
|
|
|
})
|
|
|
|
.filter((x?: Selection) => x !== undefined) as Selection[]
|
|
|
|
|
2024-11-21 15:04:30 +11:00
|
|
|
// for when there is no artifact (sketch mode since mock execute does not update artifactGraph)
|
|
|
|
const pathToNodeBasedSelections: Selections['graphSelections'] = []
|
|
|
|
for (const pathToNode of Object.values(pathToNodeMap)) {
|
|
|
|
const node = getNodeFromPath<Expr>(ast, pathToNode)
|
|
|
|
if (err(node)) return node
|
|
|
|
pathToNodeBasedSelections.push({
|
|
|
|
codeRef: {
|
2025-01-17 14:34:36 -05:00
|
|
|
range: topLevelRange(node.node.start, node.node.end),
|
2024-11-21 15:04:30 +11:00
|
|
|
pathToNode: pathToNode,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-06-24 11:45:40 -04:00
|
|
|
return {
|
2024-11-21 15:04:30 +11:00
|
|
|
graphSelections:
|
|
|
|
newSelections.length >= pathToNodeBasedSelections.length
|
2024-06-24 11:45:40 -04:00
|
|
|
? newSelections
|
2024-11-21 15:04:30 +11:00
|
|
|
: pathToNodeBasedSelections,
|
2024-06-24 11:45:40 -04:00
|
|
|
otherSelections: prevSelectionRanges.otherSelections,
|
2024-05-30 13:28:29 +10:00
|
|
|
}
|
|
|
|
}
|