inprogress conversion, lots of type error still, but think this is a dead end because artifact ids are not stable across executions

This commit is contained in:
Kurt Hutten Irev-Dev
2024-09-30 10:42:51 +10:00
parent 70694d9dd3
commit dc9000f6c7
13 changed files with 528 additions and 235 deletions

View File

@ -22,6 +22,7 @@ import {
} from 'lib/toolbar'
import { isDesktop } from 'lib/isDesktop'
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
import { convertSelectionsToOld } from 'lib/selections'
export function Toolbar({
className = '',
@ -38,12 +39,17 @@ export function Toolbar({
'!border-transparent hover:!border-chalkboard-20 dark:enabled:hover:!border-primary pressed:!border-primary ui-open:!border-primary'
const sketchPathId = useMemo(() => {
if (!isSingleCursorInPipe(context.selectionRanges, kclManager.ast)) {
if (
!isSingleCursorInPipe(
convertSelectionsToOld(context.selectionRanges),
kclManager.ast
)
) {
return false
}
return isCursorInSketchCommandRange(
engineCommandManager.artifactGraph,
context.selectionRanges
convertSelectionsToOld(context.selectionRanges)
)
}, [engineCommandManager.artifactGraph, context.selectionRanges])

View File

@ -1171,6 +1171,7 @@ export class SceneEntities {
},
onMove: () => {},
onClick: (args) => {
console.log('onClick', args)
if (args?.mouseEvent.which !== 1) return
if (!args || !args.selected) {
sceneInfra.modelingSend({
@ -1183,6 +1184,7 @@ export class SceneEntities {
}
const { selected } = args
const event = getEventForSegmentSelection(selected)
console.log('event', event)
if (!event) return
sceneInfra.modelingSend(event)
},

View File

@ -12,6 +12,7 @@ import { useKclContext } from 'lang/KclProvider'
import { useModelingContext } from 'hooks/useModelingContext'
import { executeAst } from 'lang/langHelpers'
import { trap } from 'lib/trap'
import { convertSelectionsToOld } from 'lib/selections'
export const AvailableVars = ({
onVarClick,
@ -96,7 +97,8 @@ export function useCalc({
} {
const { programMemory } = useKclContext()
const { context } = useModelingContext()
const selectionRange = context.selectionRanges.codeBasedSelections[0].range
const selectionRange = convertSelectionsToOld(context.selectionRanges)
.codeBasedSelections[0].range
const inputRef = useRef<HTMLInputElement>(null)
const [availableVarInfo, setAvailableVarInfo] = useState<
ReturnType<typeof findAllPreviousVariables>

View File

@ -5,6 +5,8 @@ import { CommandArgument } from 'lib/commandTypes'
import {
Selection__old,
canSubmitSelectionArg,
convertSelectionToOld,
convertSelectionsToOld,
getSelectionType,
getSelectionTypeDisplayText,
} from 'lib/selections'
@ -51,10 +53,14 @@ function CommandBarSelectionInput({
const [hasSubmitted, setHasSubmitted] = useState(false)
const selection = useSelector(arg.machineActor, selectionSelector)
const selectionsByType = useMemo(() => {
const selectionRangeEnd = selection?.codeBasedSelections[0]?.range[1]
return !selectionRangeEnd || selectionRangeEnd === code.length
const selectionRangeEnd = !selection
? null
: convertSelectionsToOld(selection)?.codeBasedSelections[0]?.range[1]
return !selectionRangeEnd || selectionRangeEnd === code.length || !selection
? 'none'
: getSelectionType(selection)
: !selection
? 'none'
: getSelectionType(convertSelectionsToOld(selection))
}, [selection, code])
const canSubmitSelection = useMemo<boolean>(
() => canSubmitSelectionArg(selectionsByType, arg),
@ -89,6 +95,8 @@ function CommandBarSelectionInput({
onSubmit(selection)
}
const selectionOld = selection && convertSelectionsToOld(selection)
return (
<form id="arg-form" onSubmit={handleSubmit}>
<label
@ -98,7 +106,7 @@ function CommandBarSelectionInput({
}
>
{canSubmitSelection
? getSelectionTypeDisplayText(selection) + ' selected'
? getSelectionTypeDisplayText(selectionOld) + ' selected'
: `Please select ${
arg.multiple ? 'one or more ' : 'one '
}${getSemanticSelectionType(arg.selectionTypes).join(' or ')}`}

View File

@ -44,6 +44,10 @@ import {
isRangeBetweenCharacters,
isSketchPipe,
updateSelections,
convertSelectionsToOld,
convertSelectionToOld,
Selections,
updateSelections2,
} from 'lib/selections'
import { applyConstraintIntersect } from './Toolbar/Intersect'
import { applyConstraintAbsDistance } from './Toolbar/SetAbsDistance'
@ -249,6 +253,7 @@ export const ModelingMachineProvider = ({
'Set selection': assign(
({ context: { selectionRanges, sketchDetails }, event }) => {
// this was needed for ts after adding 'Set selection' action to on done modal events
// const oldSelections = convertSelectionsToOld(selectionRanges)
const setSelections =
('data' in event &&
event.data &&
@ -275,8 +280,12 @@ export const ModelingMachineProvider = ({
})
})
}
let selections: Selections__old = {
codeBasedSelections: [],
// let selections: Selections__old = {
// codeBasedSelections: [],
// otherSelections: [],
// }
let selections: Selections = {
graphSelections: [],
otherSelections: [],
}
if (setSelections.selectionType === 'singleCodeCursor') {
@ -286,21 +295,28 @@ export const ModelingMachineProvider = ({
!editorManager.isShiftDown
) {
selections = {
codeBasedSelections: [],
graphSelections: [],
otherSelections: [],
}
} else if (
setSelections.selection &&
!editorManager.isShiftDown
) {
// const oldSelection = convertSelectionToOld(setSelections.selection)
// if (oldSelection) {
// }
selections = {
codeBasedSelections: [setSelections.selection],
graphSelections: [setSelections.selection],
otherSelections: [],
}
} else if (setSelections.selection && editorManager.isShiftDown) {
// const oldSelection = convertSelectionToOld(setSelections.selection)
// if (oldSelection) {
// }
selections = {
codeBasedSelections: [
...selectionRanges.codeBasedSelections,
graphSelections: [
...selectionRanges.graphSelections,
setSelections.selection,
],
otherSelections: selectionRanges.otherSelections,
@ -312,7 +328,7 @@ export const ModelingMachineProvider = ({
codeMirrorSelection,
updateSceneObjectColors,
} = handleSelectionBatch({
selections,
selections: convertSelectionsToOld(selections),
})
codeMirrorSelection && dispatchSelection(codeMirrorSelection)
engineEvents &&
@ -336,18 +352,18 @@ export const ModelingMachineProvider = ({
if (setSelections.selectionType === 'otherSelection') {
if (editorManager.isShiftDown) {
selections = {
codeBasedSelections: selectionRanges.codeBasedSelections,
graphSelections: selectionRanges.graphSelections,
otherSelections: [setSelections.selection],
}
} else {
selections = {
codeBasedSelections: [],
graphSelections: [],
otherSelections: [setSelections.selection],
}
}
const { engineEvents, updateSceneObjectColors } =
handleSelectionBatch({
selections,
selections: convertSelectionsToOld(selections),
})
engineEvents &&
engineEvents.forEach((event) => {
@ -360,7 +376,9 @@ export const ModelingMachineProvider = ({
}
}
if (setSelections.selectionType === 'completeSelection') {
editorManager.selectRange(setSelections.selection)
editorManager.selectRange(
convertSelectionsToOld(setSelections.selection)
)
if (!sketchDetails)
return {
selectionRanges: setSelections.selection,
@ -494,10 +512,11 @@ export const ModelingMachineProvider = ({
'has valid sweep selection': ({ context: { selectionRanges } }) => {
// A user can begin extruding if they either have 1+ faces selected or nothing selected
// TODO: I believe this guard only allows for extruding a single face at a time
const _selections = convertSelectionsToOld(selectionRanges)
const hasNoSelection =
selectionRanges.codeBasedSelections.length === 0 ||
isRangeBetweenCharacters(selectionRanges) ||
isSelectionLastLine(selectionRanges, codeManager.code)
_selections.codeBasedSelections.length === 0 ||
isRangeBetweenCharacters(_selections) ||
isSelectionLastLine(_selections, codeManager.code)
if (hasNoSelection) {
// they have no selection, we should enable the button
@ -505,31 +524,34 @@ export const ModelingMachineProvider = ({
// BUT only if there's extrudable geometry
return doesSceneHaveSweepableSketch(kclManager.ast)
}
if (!isSketchPipe(selectionRanges)) return false
if (!isSketchPipe(_selections)) return false
return canSweepSelection(selectionRanges)
return canSweepSelection(_selections)
},
'has valid selection for deletion': ({
context: { selectionRanges },
}) => {
const _selections = convertSelectionsToOld(selectionRanges)
if (!commandBarState.matches('Closed')) return false
if (selectionRanges.codeBasedSelections.length <= 0) return false
if (_selections.codeBasedSelections.length <= 0) return false
return true
},
'has valid fillet selection': ({ context: { selectionRanges } }) =>
hasValidFilletSelection({
selectionRanges,
'has valid fillet selection': ({ context: { selectionRanges } }) => {
const _selections = convertSelectionsToOld(selectionRanges)
return hasValidFilletSelection({
selectionRanges: _selections,
ast: kclManager.ast,
code: codeManager.code,
}),
})
},
'Selection is on face': ({ context: { selectionRanges }, event }) => {
if (event.type !== 'Enter sketch') return false
if (event.data?.forceNewSketch) return false
if (!isSingleCursorInPipe(selectionRanges, kclManager.ast))
return false
const _selections = convertSelectionsToOld(selectionRanges)
if (!isSingleCursorInPipe(_selections, kclManager.ast)) return false
return !!isCursorInSketchCommandRange(
engineCommandManager.artifactGraph,
selectionRanges
_selections
)
},
'Has exportable geometry': () => {
@ -619,7 +641,8 @@ export const ModelingMachineProvider = ({
}),
'animate-to-sketch': fromPromise(
async ({ input: { selectionRanges } }) => {
const sourceRange = selectionRanges.codeBasedSelections[0].range
const _selections = convertSelectionsToOld(selectionRanges)
const sourceRange = _selections.codeBasedSelections[0].range
const sketchPathToNode = getNodePathFromSourceRange(
kclManager.ast,
sourceRange
@ -643,10 +666,11 @@ export const ModelingMachineProvider = ({
),
'Get horizontal info': fromPromise(
async ({ input: { selectionRanges, sketchDetails } }) => {
const _selections = convertSelectionsToOld(selectionRanges)
const { modifiedAst, pathToNodeMap } =
await applyConstraintHorzVertDistance({
constraint: 'setHorzDistance',
selectionRanges,
selectionRanges: _selections,
})
const _modifiedAst = parse(recast(modifiedAst))
if (!sketchDetails)
@ -664,7 +688,8 @@ export const ModelingMachineProvider = ({
sketchDetails.origin
)
if (err(updatedAst)) return Promise.reject(updatedAst)
const selection = updateSelections(
// const selection = updateSelections(
const selection = updateSelections2(
pathToNodeMap,
selectionRanges,
updatedAst.newAst
@ -682,7 +707,7 @@ export const ModelingMachineProvider = ({
const { modifiedAst, pathToNodeMap } =
await applyConstraintHorzVertDistance({
constraint: 'setVertDistance',
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
})
const _modifiedAst = parse(recast(modifiedAst))
if (!sketchDetails)
@ -702,7 +727,7 @@ export const ModelingMachineProvider = ({
if (err(updatedAst)) return Promise.reject(updatedAst)
const selection = updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
)
if (err(selection)) return Promise.reject(selection)
@ -716,15 +741,15 @@ export const ModelingMachineProvider = ({
'Get angle info': fromPromise(
async ({ input: { selectionRanges, sketchDetails } }) => {
const info = angleBetweenInfo({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
})
if (err(info)) return Promise.reject(info)
const { modifiedAst, pathToNodeMap } = await (info.enabled
? applyConstraintAngleBetween({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
})
: applyConstraintAngleLength({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
angleOrLength: 'setAngle',
}))
const _modifiedAst = parse(recast(modifiedAst))
@ -747,7 +772,7 @@ export const ModelingMachineProvider = ({
if (err(updatedAst)) return Promise.reject(updatedAst)
const selection = updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
)
if (err(selection)) return Promise.reject(selection)

View File

@ -9,10 +9,9 @@ import { useModelingContext } from './useModelingContext'
import { getEventForSelectWithPoint } from 'lib/selections'
import {
getCapCodeRef,
getSweepEdgeCodeRef,
getSweepFromSuspectedSweepSurface,
getSolid2dCodeRef,
getWallCodeRef,
getCodeRefsByArtifactId,
} from 'lang/std/artifactGraph'
import { err, reportRejection } from 'lib/trap'
import { DefaultPlaneStr, getFaceDetails } from 'clientSideScene/sceneEntities'
@ -29,52 +28,14 @@ export function useEngineConnectionSubscriptions() {
event: 'highlight_set_entity',
callback: ({ data }) => {
if (data?.entity_id) {
const artifact = engineCommandManager.artifactGraph.get(
data.entity_id
)
if (artifact?.type === 'solid2D') {
const codeRef = getSolid2dCodeRef(
artifact,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return
editorManager.setHighlightRange([codeRef.range])
} else if (artifact?.type === 'cap') {
const codeRef = getCapCodeRef(
artifact,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return
editorManager.setHighlightRange([codeRef.range])
} else if (artifact?.type === 'wall') {
const extrusion = getSweepFromSuspectedSweepSurface(
const codeRefs = getCodeRefsByArtifactId(
data.entity_id,
engineCommandManager.artifactGraph
)
const codeRef = getWallCodeRef(
artifact,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return
editorManager.setHighlightRange(
err(extrusion)
? [codeRef.range]
: [codeRef.range, extrusion.codeRef.range]
)
} else if (artifact?.type === 'sweepEdge') {
const codeRef = getSweepEdgeCodeRef(
artifact,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return
editorManager.setHighlightRange([codeRef.range])
} else if (artifact?.type === 'segment') {
editorManager.setHighlightRange([
artifact?.codeRef?.range || [0, 0],
])
} else {
editorManager.setHighlightRange([[0, 0]])
if (codeRefs) {
editorManager.setHighlightRange(codeRefs.map(({ range }) => range))
}
editorManager.setHighlightRange([[0, 0]])
} else if (
!editorManager.highlightRange ||
(editorManager.highlightRange[0][0] !== 0 &&

View File

@ -11,6 +11,7 @@ import { useModelingContext } from './useModelingContext'
import { PathToNode, SourceRange } from 'lang/wasm'
import { useKclContext } from 'lang/KclProvider'
import { toSync } from 'lib/utils'
import { convertSelectionsToOld } from 'lib/selections'
export const getVarNameModal = createSetVarNameModal(SetVarNameModal)
@ -28,14 +29,19 @@ export function useConvertToVariable(range?: SourceRange) {
const meta = isNodeSafeToReplace(
parsed,
range || context.selectionRanges.codeBasedSelections?.[0]?.range || []
range ||
convertSelectionsToOld(context.selectionRanges).codeBasedSelections?.[0]
?.range ||
[]
)
if (trap(meta)) return
const { isSafe, value } = meta
const canReplace = isSafe && value.type !== 'Identifier'
const isOnlyOneSelection =
!!range || context.selectionRanges.codeBasedSelections.length === 1
!!range ||
convertSelectionsToOld(context.selectionRanges).codeBasedSelections
.length === 1
setEnabled(canReplace && isOnlyOneSelection)
}, [context.selectionRanges])
@ -52,7 +58,9 @@ export function useConvertToVariable(range?: SourceRange) {
moveValueIntoNewVariable(
ast,
kclManager.programMemory,
range || context.selectionRanges.codeBasedSelections[0].range,
range ||
convertSelectionsToOld(context.selectionRanges)
.codeBasedSelections[0].range,
variableName
)

View File

@ -9,7 +9,7 @@ interface BaseArtifact {
id: ArtifactId
}
interface CodeRef {
export interface CodeRef {
range: SourceRange
pathToNode: PathToNode
}
@ -775,3 +775,33 @@ export function getSweepFromSuspectedPath(
artifactGraph
)
}
export function getCodeRefsByArtifactId(
id: string,
artifactGraph: ArtifactGraph
): Array<CodeRef> | null {
const artifact = artifactGraph.get(id)
if (artifact?.type === 'solid2D') {
const codeRef = getSolid2dCodeRef(artifact, artifactGraph)
if (err(codeRef)) return null
return [codeRef]
// editorManager.setHighlightRange([codeRef.range])
} else if (artifact?.type === 'cap') {
const codeRef = getCapCodeRef(artifact, artifactGraph)
if (err(codeRef)) return null
return [codeRef]
} else if (artifact?.type === 'wall') {
const extrusion = getSweepFromSuspectedSweepSurface(id, artifactGraph)
const codeRef = getWallCodeRef(artifact, artifactGraph)
if (err(codeRef)) return null
return err(extrusion) ? [codeRef] : [codeRef, extrusion.codeRef]
} else if (artifact?.type === 'sweepEdge') {
const codeRef = getSweepEdgeCodeRef(artifact, artifactGraph)
if (err(codeRef)) return null
return [codeRef]
} else if (artifact?.type === 'segment') {
return [artifact.codeRef]
} else {
return null
}
}

View File

@ -1917,7 +1917,7 @@ export function getConstraintInfo(
code,
pathToNode
)
console.log('result path', result[0].pathToNode)
// console.log('result path', result[0].pathToNode)
return result
}

View File

@ -35,6 +35,8 @@ import {
getSweepEdgeCodeRef,
getSolid2dCodeRef,
getWallCodeRef,
CodeRef,
getCodeRefsByArtifactId,
} from 'lang/std/artifactGraph'
export const X_AXIS_UUID = 'ad792545-7fd3-482a-a602-a93924e3055b'
@ -65,24 +67,124 @@ export type Selections__old = {
otherSelections: Axis[]
codeBasedSelections: Selection__old[]
}
export interface Selection {
artifact: Artifact
codeRef: CodeRef
}
export type Selections = {
otherSelections: Axis[]
graphSelections: Artifact[]
otherSelections: Array<Axis>
graphSelections: Array<Selection>
}
/** @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 convertSelectionToOld(selection: Selection__old): Artifact {
return {} as Artifact
export function convertSelectionToOld(
selection: Selection
): Selection__old | null {
// return {} as Selection__old
// TODO implementation
const _artifact = selection.artifact
if (_artifact.type === 'solid2D') {
const codeRef = getSolid2dCodeRef(
_artifact,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return null
return { range: codeRef.range, type: 'solid2D' }
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range: codeRef.range, type: 'solid2D' },
// },
// }
}
if (_artifact.type === 'cap') {
const codeRef = getCapCodeRef(_artifact, engineCommandManager.artifactGraph)
if (err(codeRef)) return null
return {
range: codeRef.range,
type: _artifact?.subType === 'end' ? 'end-cap' : 'start-cap',
}
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: {
// range: codeRef.range,
// type: _artifact?.subType === 'end' ? 'end-cap' : 'start-cap',
// },
// },
// }
}
if (_artifact.type === 'wall') {
const codeRef = getWallCodeRef(
_artifact,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return null
return { range: codeRef.range, type: 'extrude-wall' }
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range: codeRef.range, type: 'extrude-wall' },
// },
// }
}
if (_artifact.type === 'segment' || _artifact.type === 'path') {
return { range: _artifact.codeRef.range, type: 'default' }
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range: _artifact.codeRef.range, type: 'default' },
// },
// }
}
if (_artifact.type === 'sweepEdge') {
const codeRef = getSweepEdgeCodeRef(
_artifact,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return null
if (_artifact?.subType === 'adjacent') {
return { range: codeRef.range, type: 'adjacent-edge' }
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range: codeRef.range, type: 'adjacent-edge' },
// },
// }
}
return { range: codeRef.range, type: 'edge' }
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range: codeRef.range, type: 'edge' },
// },
// }
}
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__old): Selections {
// TODO implementation
return { otherSelections: [], graphSelections: [] }
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({
@ -107,85 +209,102 @@ export async function getEventForSelectWithPoint({
}
}
let _artifact = engineCommandManager.artifactGraph.get(data.entity_id)
if (!_artifact)
return {
type: 'Set selection',
data: { selectionType: 'singleCodeCursor' },
}
if (_artifact.type === 'solid2D') {
const codeRef = getSolid2dCodeRef(
_artifact,
const codeRefs = getCodeRefsByArtifactId(
data.entity_id,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return null
return {
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: { range: codeRef.range, type: 'solid2D' },
},
}
}
if (_artifact.type === 'cap') {
const codeRef = getCapCodeRef(_artifact, engineCommandManager.artifactGraph)
if (err(codeRef)) return null
if (_artifact && codeRefs) {
return {
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: {
range: codeRef.range,
type: _artifact?.subType === 'end' ? 'end-cap' : 'start-cap',
artifact: _artifact,
codeRef: codeRefs[0],
},
},
}
}
if (_artifact.type === 'wall') {
const codeRef = getWallCodeRef(
_artifact,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return null
return {
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: { range: codeRef.range, type: 'extrude-wall' },
},
}
}
if (_artifact.type === 'segment' || _artifact.type === 'path') {
return {
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: { range: _artifact.codeRef.range, type: 'default' },
},
}
}
if (_artifact.type === 'sweepEdge') {
const codeRef = getSweepEdgeCodeRef(
_artifact,
engineCommandManager.artifactGraph
)
if (err(codeRef)) return null
if (_artifact?.subType === 'adjacent') {
return {
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: { range: codeRef.range, type: 'adjacent-edge' },
},
}
}
return {
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: { range: codeRef.range, type: 'edge' },
},
}
}
// if (!_artifact)
// return {
// type: 'Set selection',
// data: { selectionType: 'singleCodeCursor' },
// }
// if (_artifact.type === 'solid2D') {
// const codeRef = getSolid2dCodeRef(
// _artifact,
// engineCommandManager.artifactGraph
// )
// if (err(codeRef)) return null
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// // selection: { range: codeRef.range, type: 'solid2D' },
// },
// }
// }
// if (_artifact.type === 'cap') {
// const codeRef = getCapCodeRef(_artifact, engineCommandManager.artifactGraph)
// if (err(codeRef)) return null
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: {
// range: codeRef.range,
// type: _artifact?.subType === 'end' ? 'end-cap' : 'start-cap',
// },
// },
// }
// }
// if (_artifact.type === 'wall') {
// const codeRef = getWallCodeRef(
// _artifact,
// engineCommandManager.artifactGraph
// )
// if (err(codeRef)) return null
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range: codeRef.range, type: 'extrude-wall' },
// },
// }
// }
// if (_artifact.type === 'segment' || _artifact.type === 'path') {
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range: _artifact.codeRef.range, type: 'default' },
// },
// }
// }
// if (_artifact.type === 'sweepEdge') {
// const codeRef = getSweepEdgeCodeRef(
// _artifact,
// engineCommandManager.artifactGraph
// )
// if (err(codeRef)) return null
// if (_artifact?.subType === 'adjacent') {
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range: codeRef.range, type: 'adjacent-edge' },
// },
// }
// }
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range: codeRef.range, type: 'edge' },
// },
// }
// }
return null
}
@ -204,30 +323,50 @@ export function getEventForSegmentSelection(
},
}
}
const pathToNode = group?.userData?.pathToNode
if (!pathToNode) return null
// previous drags don't update ast for efficiency reasons
// So we want to make sure we have and updated ast with
// accurate source ranges
const updatedAst = parse(codeManager.code)
if (err(updatedAst)) return null
const nodeMeta = getNodeFromPath<CallExpression>(
updatedAst,
pathToNode,
'CallExpression'
// console.log('group', group?.userData.)
const id = group?.userData?.id
if (!id) return null
const artifact = engineCommandManager.artifactGraph.get(id)
const codeRefs = getCodeRefsByArtifactId(
id,
engineCommandManager.artifactGraph
)
if (err(nodeMeta)) return null
const node = nodeMeta.node
const range: SourceRange = [node.start, node.end]
console.log('artifact', artifact, group.userData)
if (!artifact || !codeRefs) return null
return {
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
selection: { range, type: 'default' },
selection: {
artifact,
codeRef: codeRefs[0],
},
},
}
// const pathToNode = group?.userData?.pathToNode
// if (!pathToNode) return null
// // previous drags don't update ast for efficiency reasons
// // So we want to make sure we have and updated ast with
// // accurate source ranges
// const updatedAst = parse(codeManager.code)
// if (err(updatedAst)) return null
// const nodeMeta = getNodeFromPath<CallExpression>(
// updatedAst,
// pathToNode,
// 'CallExpression'
// )
// if (err(nodeMeta)) return null
// const node = nodeMeta.node
// const range: SourceRange = [node.start, node.end]
// return {
// type: 'Set selection',
// data: {
// selectionType: 'singleCodeCursor',
// selection: { range, type: 'default' },
// },
// }
}
export function handleSelectionBatch({
@ -289,7 +428,8 @@ export function processCodeMirrorRanges({
engineEvents: Models['WebSocketRequest_type'][]
} {
const isChange =
codeMirrorRanges.length !== selectionRanges.codeBasedSelections.length ||
// todo should this take old or new selections?
codeMirrorRanges.length !== selectionRanges?.codeBasedSelections?.length ||
codeMirrorRanges.some(({ from, to }, i) => {
return (
from !== selectionRanges.codeBasedSelections[i].range[0] ||
@ -307,6 +447,15 @@ export function processCodeMirrorRanges({
})
const idBasedSelections: SelectionToEngine[] =
codeToIdSelections(codeBasedSelections)
const artifacts: Selection[] = []
for (const { id } of idBasedSelections) {
const artifact = engineCommandManager.artifactGraph.get(id)
const codeRefs = getCodeRefsByArtifactId(
id,
engineCommandManager.artifactGraph
)
if (artifact && codeRefs) artifacts.push({ artifact, codeRef: codeRefs[0] })
}
if (!selectionRanges) return null
updateSceneObjectColors(codeBasedSelections)
@ -317,7 +466,7 @@ export function processCodeMirrorRanges({
selectionType: 'mirrorCodeMirrorSelections',
selection: {
otherSelections: isShiftDown ? selectionRanges.otherSelections : [],
codeBasedSelections,
graphSelections: artifacts,
},
},
},
@ -734,3 +883,74 @@ export function updateSelections(
otherSelections: prevSelectionRanges.otherSelections,
}
}
// using artifact as the selection is maybe not such a good idea.
// is the artifact stable, once you add a constrain, there will a new artifact graph
// then the ids will not match up
export function updateSelections2(
pathToNodeMap: PathToNodeMap,
prevSelectionRanges: Selections,
ast: Program | Error
): Selections | Error {
if (err(ast)) return ast
const newSelections = Object.entries(pathToNodeMap)
.map(([index, pathToNode]): Selection | undefined => {
const previousSelection =
prevSelectionRanges.graphSelections[Number(index)]
const nodeMeta = getNodeFromPath<Expr>(ast, pathToNode)
if (err(nodeMeta)) return undefined
const node = nodeMeta.node
let artifact: Artifact | null = null
for (const [id, a] of engineCommandManager.artifactGraph) {
if (previousSelection.artifact.type === a.type) {
const codeRefs = getCodeRefsByArtifactId(
id,
engineCommandManager.artifactGraph
)
console.log('codeRef', codeRefs)
if (!codeRefs) continue
if (
JSON.stringify(codeRefs[0].pathToNode) ===
JSON.stringify(pathToNode)
) {
artifact = a
console.log('found artifact', a)
break
}
}
// if (
// a.codeRef.range[0] === node.start &&
// a.codeRef.range[1] === node.end
// ) {
// artifact = a
// break
// }
}
if (!artifact) return undefined
return {
artifact: artifact,
codeRef: {
range: [node.start, node.end],
pathToNode: pathToNode,
},
// codeRef: {
// range: [node.start, node.end],
// pathToNode: pathToNode,
// },
}
// return {
// range: [node.start, node.end],
// type: prevSelectionRanges.codeBasedSelections[Number(index)]?.type,
// }
})
.filter((x?: Selection) => x !== undefined) as Selection[]
return {
graphSelections:
newSelections.length > 0
? newSelections
: prevSelectionRanges.graphSelections,
otherSelections: prevSelectionRanges.otherSelections,
}
}

View File

@ -7,6 +7,7 @@ import { ProgramMemory, Expr, parse } from 'lang/wasm'
import { useEffect, useRef, useState } from 'react'
import { executeAst } from 'lang/langHelpers'
import { err, trap } from 'lib/trap'
import { convertSelectionsToOld } from './selections'
const isValidVariableName = (name: string) =>
/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)
@ -34,9 +35,10 @@ export function useCalculateKclExpression({
} {
const { programMemory, code } = useKclContext()
const { context } = useModelingContext()
const selectionOld = convertSelectionsToOld(context.selectionRanges)
const selectionRange:
| (typeof context.selectionRanges.codeBasedSelections)[number]['range']
| undefined = context.selectionRanges.codeBasedSelections[0]?.range
| (typeof selectionOld.codeBasedSelections)[number]['range']
| undefined = selectionOld.codeBasedSelections[0]?.range
const inputRef = useRef<HTMLInputElement>(null)
const [availableVarInfo, setAvailableVarInfo] = useState<
ReturnType<typeof findAllPreviousVariables>

View File

@ -3,12 +3,13 @@ import { kclManager } from 'lib/singletons'
import { useKclContext } from 'lang/KclProvider'
import { findAllPreviousVariables } from 'lang/queryAst'
import { useEffect, useState } from 'react'
import { convertSelectionsToOld } from './selections'
export function usePreviousVariables() {
const { programMemory, code } = useKclContext()
const { context } = useModelingContext()
const selectionRange = context.selectionRanges.codeBasedSelections[0]
?.range || [code.length, code.length]
const selectionRange = convertSelectionsToOld(context.selectionRanges)
.codeBasedSelections[0]?.range || [code.length, code.length]
const [previousVariablesInfo, setPreviousVariablesInfo] = useState<
ReturnType<typeof findAllPreviousVariables>
>({

View File

@ -7,8 +7,10 @@ import {
} from 'lang/wasm'
import {
Axis,
Selection__old,
Selections__old,
convertSelectionsToOld,
convertSelectionToOld,
Selections,
Selection,
updateSelections,
} from 'lib/selections'
import { assign, fromPromise, setup } from 'xstate'
@ -75,7 +77,7 @@ export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
export type SetSelections =
| {
selectionType: 'singleCodeCursor'
selection?: Selection__old
selection?: Selection
}
| {
selectionType: 'otherSelection'
@ -83,12 +85,12 @@ export type SetSelections =
}
| {
selectionType: 'completeSelection'
selection: Selections__old
selection: Selections
updatedPathToNode?: PathToNode
}
| {
selectionType: 'mirrorCodeMirrorSelections'
selection: Selections__old
selection: Selections
}
export type MouseState =
@ -288,7 +290,7 @@ export interface ModelingMachineContext {
currentMode: ToolbarModeName
currentTool: SketchTool
selection: string[]
selectionRanges: Selections__old
selectionRanges: Selections
sketchDetails: SketchDetails | null
sketchPlaneId: string
sketchEnginePathId: string
@ -304,7 +306,7 @@ export const modelingMachineDefaultContext: ModelingMachineContext = {
selection: [],
selectionRanges: {
otherSelections: [],
codeBasedSelections: [],
graphSelections: [],
},
sketchDetails: {
sketchPathToNode: [],
@ -355,18 +357,24 @@ export const modelingMachine = setup({
'is editing existing sketch': ({ context: { sketchDetails } }) =>
isEditingExistingSketch({ sketchDetails }),
'Can make selection horizontal': ({ context: { selectionRanges } }) => {
const info = horzVertInfo(selectionRanges, 'horizontal')
const info = horzVertInfo(
convertSelectionsToOld(selectionRanges),
'horizontal'
)
if (trap(info)) return false
return info.enabled
},
'Can make selection vertical': ({ context: { selectionRanges } }) => {
const info = horzVertInfo(selectionRanges, 'vertical')
const info = horzVertInfo(
convertSelectionsToOld(selectionRanges),
'vertical'
)
if (trap(info)) return false
return info.enabled
},
'Can constrain horizontal distance': ({ context: { selectionRanges } }) => {
const info = horzVertDistanceInfo({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'setHorzDistance',
})
if (trap(info)) return false
@ -374,47 +382,59 @@ export const modelingMachine = setup({
},
'Can constrain vertical distance': ({ context: { selectionRanges } }) => {
const info = horzVertDistanceInfo({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'setVertDistance',
})
if (trap(info)) return false
return info.enabled
},
'Can constrain ABS X': ({ context: { selectionRanges } }) => {
const info = absDistanceInfo({ selectionRanges, constraint: 'xAbs' })
const info = absDistanceInfo({
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'xAbs',
})
if (trap(info)) return false
return info.enabled
},
'Can constrain ABS Y': ({ context: { selectionRanges } }) => {
const info = absDistanceInfo({ selectionRanges, constraint: 'yAbs' })
const info = absDistanceInfo({
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'yAbs',
})
if (trap(info)) return false
return info.enabled
},
'Can constrain angle': ({ context: { selectionRanges } }) => {
const angleBetween = angleBetweenInfo({ selectionRanges })
const angleBetween = angleBetweenInfo({
selectionRanges: convertSelectionsToOld(selectionRanges),
})
if (trap(angleBetween)) return false
const angleLength = angleLengthInfo({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
angleOrLength: 'setAngle',
})
if (trap(angleLength)) return false
return angleBetween.enabled || angleLength.enabled
},
'Can constrain length': ({ context: { selectionRanges } }) => {
const angleLength = angleLengthInfo({ selectionRanges })
const angleLength = angleLengthInfo({
selectionRanges: convertSelectionsToOld(selectionRanges),
})
if (trap(angleLength)) return false
return angleLength.enabled
},
'Can constrain perpendicular distance': ({
context: { selectionRanges },
}) => {
const info = intersectInfo({ selectionRanges })
const info = intersectInfo({
selectionRanges: convertSelectionsToOld(selectionRanges),
})
if (trap(info)) return false
return info.enabled
},
'Can constrain horizontally align': ({ context: { selectionRanges } }) => {
const info = horzVertDistanceInfo({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'setHorzDistance',
})
if (trap(info)) return false
@ -422,7 +442,7 @@ export const modelingMachine = setup({
},
'Can constrain vertically align': ({ context: { selectionRanges } }) => {
const info = horzVertDistanceInfo({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'setHorzDistance',
})
if (trap(info)) return false
@ -430,7 +450,7 @@ export const modelingMachine = setup({
},
'Can constrain snap to X': ({ context: { selectionRanges } }) => {
const info = absDistanceInfo({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'snapToXAxis',
})
if (trap(info)) return false
@ -438,19 +458,23 @@ export const modelingMachine = setup({
},
'Can constrain snap to Y': ({ context: { selectionRanges } }) => {
const info = absDistanceInfo({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'snapToYAxis',
})
if (trap(info)) return false
return info.enabled
},
'Can constrain equal length': ({ context: { selectionRanges } }) => {
const info = setEqualLengthInfo({ selectionRanges })
const info = setEqualLengthInfo({
selectionRanges: convertSelectionsToOld(selectionRanges),
})
if (trap(info)) return false
return info.enabled
},
'Can canstrain parallel': ({ context: { selectionRanges } }) => {
const info = equalAngleInfo({ selectionRanges })
const info = equalAngleInfo({
selectionRanges: convertSelectionsToOld(selectionRanges),
})
if (err(info)) return false
return info.enabled
},
@ -460,7 +484,7 @@ export const modelingMachine = setup({
}) => {
if (event.type !== 'Constrain remove constraints') return false
const info = removeConstrainingValuesInfo({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
pathToNodes: event.data && [event.data],
})
if (trap(info)) return false
@ -641,10 +665,14 @@ export const modelingMachine = setup({
'AST delete selection': ({ context: { selectionRanges } }) => {
;(async () => {
let ast = kclManager.ast
const oldSelection = convertSelectionToOld(
selectionRanges.graphSelections[0]
)
if (!oldSelection) return
const modifiedAst = await deleteFromSelection(
ast,
selectionRanges.codeBasedSelections[0],
oldSelection,
kclManager.programMemory,
getFaceDetails
)
@ -714,7 +742,7 @@ export const modelingMachine = setup({
up: sketchDetails.yAxis,
position: sketchDetails.origin,
maybeModdedAst: kclManager.ast,
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
})
sceneInfra.resetMouseListeners()
sceneEntitiesManager.setupSketchIdleCallbacks({
@ -944,7 +972,7 @@ export const modelingMachine = setup({
> & { data?: PathToNode }
}) => {
const constraint = applyRemoveConstrainingValues({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
pathToNodes: data && [data],
})
if (trap(constraint)) return
@ -963,7 +991,7 @@ export const modelingMachine = setup({
selectionType: 'completeSelection',
selection: updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
),
}
@ -976,7 +1004,7 @@ export const modelingMachine = setup({
input: Pick<ModelingMachineContext, 'selectionRanges' | 'sketchDetails'>
}) => {
const constraint = applyConstraintHorzVert(
selectionRanges,
convertSelectionsToOld(selectionRanges),
'horizontal',
kclManager.ast,
kclManager.programMemory
@ -997,7 +1025,7 @@ export const modelingMachine = setup({
selectionType: 'completeSelection',
selection: updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
),
}
@ -1010,7 +1038,7 @@ export const modelingMachine = setup({
input: Pick<ModelingMachineContext, 'selectionRanges' | 'sketchDetails'>
}) => {
const constraint = applyConstraintHorzVert(
selectionRanges,
convertSelectionsToOld(selectionRanges),
'vertical',
kclManager.ast,
kclManager.programMemory
@ -1031,7 +1059,7 @@ export const modelingMachine = setup({
selectionType: 'completeSelection',
selection: updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
),
}
@ -1044,7 +1072,7 @@ export const modelingMachine = setup({
input: Pick<ModelingMachineContext, 'selectionRanges' | 'sketchDetails'>
}) => {
const constraint = applyConstraintHorzVertAlign({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'setVertDistance',
})
if (trap(constraint)) return
@ -1061,7 +1089,7 @@ export const modelingMachine = setup({
if (!updatedAst) return
const updatedSelectionRanges = updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
)
return {
@ -1077,7 +1105,7 @@ export const modelingMachine = setup({
input: Pick<ModelingMachineContext, 'selectionRanges' | 'sketchDetails'>
}) => {
const constraint = applyConstraintHorzVertAlign({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'setHorzDistance',
})
if (trap(constraint)) return
@ -1094,7 +1122,7 @@ export const modelingMachine = setup({
if (!updatedAst) return
const updatedSelectionRanges = updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
)
return {
@ -1110,7 +1138,7 @@ export const modelingMachine = setup({
input: Pick<ModelingMachineContext, 'selectionRanges' | 'sketchDetails'>
}) => {
const constraint = applyConstraintAxisAlign({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'snapToXAxis',
})
if (err(constraint)) return false
@ -1127,7 +1155,7 @@ export const modelingMachine = setup({
if (!updatedAst) return
const updatedSelectionRanges = updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
)
return {
@ -1143,7 +1171,7 @@ export const modelingMachine = setup({
input: Pick<ModelingMachineContext, 'selectionRanges' | 'sketchDetails'>
}) => {
const constraint = applyConstraintAxisAlign({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
constraint: 'snapToYAxis',
})
if (trap(constraint)) return false
@ -1160,7 +1188,7 @@ export const modelingMachine = setup({
if (!updatedAst) return
const updatedSelectionRanges = updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
)
return {
@ -1176,7 +1204,7 @@ export const modelingMachine = setup({
input: Pick<ModelingMachineContext, 'selectionRanges' | 'sketchDetails'>
}) => {
const constraint = applyConstraintEqualAngle({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
})
if (trap(constraint)) return false
const { modifiedAst, pathToNodeMap } = constraint
@ -1197,7 +1225,7 @@ export const modelingMachine = setup({
if (!updatedAst) return
const updatedSelectionRanges = updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
)
return {
@ -1213,7 +1241,7 @@ export const modelingMachine = setup({
input: Pick<ModelingMachineContext, 'selectionRanges' | 'sketchDetails'>
}) => {
const constraint = applyConstraintEqualLength({
selectionRanges,
selectionRanges: convertSelectionsToOld(selectionRanges),
})
if (trap(constraint)) return false
const { modifiedAst, pathToNodeMap } = constraint
@ -1229,7 +1257,7 @@ export const modelingMachine = setup({
if (!updatedAst) return
const updatedSelectionRanges = updateSelections(
pathToNodeMap,
selectionRanges,
convertSelectionsToOld(selectionRanges),
updatedAst.newAst
)
return {