73
src/App.tsx
73
src/App.tsx
@ -73,7 +73,9 @@ export function App() {
|
|||||||
streamDimensions,
|
streamDimensions,
|
||||||
setIsExecuting,
|
setIsExecuting,
|
||||||
defferedCode,
|
defferedCode,
|
||||||
|
guiMode,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
|
guiMode: s.guiMode,
|
||||||
addLog: s.addLog,
|
addLog: s.addLog,
|
||||||
defferedCode: s.defferedCode,
|
defferedCode: s.defferedCode,
|
||||||
setCode: s.setCode,
|
setCode: s.setCode,
|
||||||
@ -181,7 +183,18 @@ export function App() {
|
|||||||
const asyncWrap = async () => {
|
const asyncWrap = async () => {
|
||||||
try {
|
try {
|
||||||
if (!defferedCode) {
|
if (!defferedCode) {
|
||||||
setAst(null)
|
setAst({
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
body: [],
|
||||||
|
nonCodeMeta: {
|
||||||
|
noneCodeNodes: {},
|
||||||
|
start: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
setProgramMemory({ root: {} })
|
||||||
|
engineCommandManager.endSession()
|
||||||
|
engineCommandManager.startNewSession()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const _ast = await asyncParser(defferedCode)
|
const _ast = await asyncParser(defferedCode)
|
||||||
@ -223,6 +236,9 @@ export function App() {
|
|||||||
const { artifactMap, sourceRangeMap } =
|
const { artifactMap, sourceRangeMap } =
|
||||||
await engineCommandManager.waitForAllCommands()
|
await engineCommandManager.waitForAllCommands()
|
||||||
setIsExecuting(false)
|
setIsExecuting(false)
|
||||||
|
if (programMemory !== undefined) {
|
||||||
|
setProgramMemory(programMemory)
|
||||||
|
}
|
||||||
|
|
||||||
setArtifactMap({ artifactMap, sourceRangeMap })
|
setArtifactMap({ artifactMap, sourceRangeMap })
|
||||||
const unSubHover = engineCommandManager.subscribeToUnreliable({
|
const unSubHover = engineCommandManager.subscribeToUnreliable({
|
||||||
@ -251,9 +267,6 @@ export function App() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
unsubFn.push(unSubHover, unSubClick)
|
unsubFn.push(unSubHover, unSubClick)
|
||||||
if (programMemory !== undefined) {
|
|
||||||
setProgramMemory(programMemory)
|
|
||||||
}
|
|
||||||
|
|
||||||
setError()
|
setError()
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@ -287,8 +300,42 @@ export function App() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const newCmdId = uuidv4()
|
const newCmdId = uuidv4()
|
||||||
|
if (buttonDownInStream === undefined) {
|
||||||
if (buttonDownInStream !== undefined) {
|
if (
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('sketch_line' as any)
|
||||||
|
) {
|
||||||
|
debounceSocketSend({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: newCmdId,
|
||||||
|
cmd: {
|
||||||
|
type: 'mouse_move',
|
||||||
|
window: { x, y },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else if (
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('move' as any)
|
||||||
|
) {
|
||||||
|
debounceSocketSend({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: newCmdId,
|
||||||
|
cmd: {
|
||||||
|
type: 'handle_mouse_drag_move',
|
||||||
|
window: { x, y },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
debounceSocketSend({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd: {
|
||||||
|
type: 'highlight_set_entity',
|
||||||
|
selected_at_window: { x, y },
|
||||||
|
},
|
||||||
|
cmd_id: newCmdId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
const interactionGuards = cameraMouseDragGuards[cameraControls]
|
const interactionGuards = cameraMouseDragGuards[cameraControls]
|
||||||
let interaction: CameraDragInteractionType_type
|
let interaction: CameraDragInteractionType_type
|
||||||
|
|
||||||
@ -301,6 +348,7 @@ export function App() {
|
|||||||
} else if (interactionGuards.zoom.dragCallback(eWithButton)) {
|
} else if (interactionGuards.zoom.dragCallback(eWithButton)) {
|
||||||
interaction = 'zoom'
|
interaction = 'zoom'
|
||||||
} else {
|
} else {
|
||||||
|
console.log('none')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,15 +361,6 @@ export function App() {
|
|||||||
},
|
},
|
||||||
cmd_id: newCmdId,
|
cmd_id: newCmdId,
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
debounceSocketSend({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd: {
|
|
||||||
type: 'highlight_set_entity',
|
|
||||||
selected_at_window: { x, y },
|
|
||||||
},
|
|
||||||
cmd_id: newCmdId,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,11 +389,11 @@ export function App() {
|
|||||||
paneOpacity
|
paneOpacity
|
||||||
}
|
}
|
||||||
defaultSize={{
|
defaultSize={{
|
||||||
width: '400px',
|
width: '550px',
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
}}
|
}}
|
||||||
minWidth={200}
|
minWidth={200}
|
||||||
maxWidth={600}
|
maxWidth={800}
|
||||||
minHeight={'auto'}
|
minHeight={'auto'}
|
||||||
maxHeight={'auto'}
|
maxHeight={'auto'}
|
||||||
handleClasses={{
|
handleClasses={{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useStore, toolTips } from './useStore'
|
import { useStore, toolTips, Selections } from './useStore'
|
||||||
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
|
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
|
||||||
import { getNodePathFromSourceRange } from './lang/queryAst'
|
import { getNodePathFromSourceRange } from './lang/queryAst'
|
||||||
import { HorzVert } from './components/Toolbar/HorzVert'
|
import { HorzVert } from './components/Toolbar/HorzVert'
|
||||||
@ -15,6 +15,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|||||||
import { faSearch, faX } from '@fortawesome/free-solid-svg-icons'
|
import { faSearch, faX } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { Popover, Transition } from '@headlessui/react'
|
import { Popover, Transition } from '@headlessui/react'
|
||||||
import styles from './Toolbar.module.css'
|
import styles from './Toolbar.module.css'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { useAppMode } from 'hooks/useAppMode'
|
||||||
|
|
||||||
export const Toolbar = () => {
|
export const Toolbar = () => {
|
||||||
const {
|
const {
|
||||||
@ -24,6 +26,7 @@ export const Toolbar = () => {
|
|||||||
ast,
|
ast,
|
||||||
updateAst,
|
updateAst,
|
||||||
programMemory,
|
programMemory,
|
||||||
|
engineCommandManager,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
guiMode: s.guiMode,
|
guiMode: s.guiMode,
|
||||||
setGuiMode: s.setGuiMode,
|
setGuiMode: s.setGuiMode,
|
||||||
@ -31,7 +34,9 @@ export const Toolbar = () => {
|
|||||||
ast: s.ast,
|
ast: s.ast,
|
||||||
updateAst: s.updateAst,
|
updateAst: s.updateAst,
|
||||||
programMemory: s.programMemory,
|
programMemory: s.programMemory,
|
||||||
|
engineCommandManager: s.engineCommandManager,
|
||||||
}))
|
}))
|
||||||
|
useAppMode()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('guiMode', guiMode)
|
console.log('guiMode', guiMode)
|
||||||
@ -39,7 +44,7 @@ export const Toolbar = () => {
|
|||||||
|
|
||||||
function ToolbarButtons() {
|
function ToolbarButtons() {
|
||||||
return (
|
return (
|
||||||
<>
|
<span className="overflow-x-auto">
|
||||||
{guiMode.mode === 'default' && (
|
{guiMode.mode === 'default' && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -71,9 +76,18 @@ export const Toolbar = () => {
|
|||||||
SketchOnFace
|
SketchOnFace
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{(guiMode.mode === 'canEditSketch' || false) && (
|
{guiMode.mode === 'canEditSketch' && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
console.log('guiMode.pathId', guiMode.pathId)
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'edit_mode_enter',
|
||||||
|
target: guiMode.pathId,
|
||||||
|
},
|
||||||
|
})
|
||||||
setGuiMode({
|
setGuiMode({
|
||||||
mode: 'sketch',
|
mode: 'sketch',
|
||||||
sketchMode: 'sketchEdit',
|
sketchMode: 'sketchEdit',
|
||||||
@ -125,14 +139,23 @@ export const Toolbar = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{guiMode.mode === 'sketch' && (
|
{guiMode.mode === 'sketch' && (
|
||||||
<button onClick={() => setGuiMode({ mode: 'default' })}>
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: { type: 'edit_mode_exit' },
|
||||||
|
})
|
||||||
|
setGuiMode({ mode: 'default' })
|
||||||
|
}}
|
||||||
|
>
|
||||||
Exit sketch
|
Exit sketch
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{toolTips
|
{toolTips
|
||||||
.filter(
|
.filter(
|
||||||
// (sketchFnName) => !['angledLineThatIntersects'].includes(sketchFnName)
|
// (sketchFnName) => !['angledLineThatIntersects'].includes(sketchFnName)
|
||||||
(sketchFnName) => ['line'].includes(sketchFnName)
|
(sketchFnName) => ['sketch_line', 'move'].includes(sketchFnName)
|
||||||
)
|
)
|
||||||
.map((sketchFnName) => {
|
.map((sketchFnName) => {
|
||||||
if (
|
if (
|
||||||
@ -143,7 +166,18 @@ export const Toolbar = () => {
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={sketchFnName}
|
key={sketchFnName}
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'set_tool',
|
||||||
|
tool:
|
||||||
|
guiMode.sketchMode === sketchFnName
|
||||||
|
? 'select'
|
||||||
|
: (sketchFnName as any),
|
||||||
|
},
|
||||||
|
})
|
||||||
setGuiMode({
|
setGuiMode({
|
||||||
...guiMode,
|
...guiMode,
|
||||||
...(guiMode.sketchMode === sketchFnName
|
...(guiMode.sketchMode === sketchFnName
|
||||||
@ -153,10 +187,11 @@ export const Toolbar = () => {
|
|||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
sketchMode: sketchFnName,
|
sketchMode: sketchFnName,
|
||||||
|
waitingFirstClick: true,
|
||||||
isTooltip: true,
|
isTooltip: true,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
{sketchFnName}
|
{sketchFnName}
|
||||||
{guiMode.sketchMode === sketchFnName && '✅'}
|
{guiMode.sketchMode === sketchFnName && '✅'}
|
||||||
@ -180,7 +215,7 @@ export const Toolbar = () => {
|
|||||||
<Intersect />
|
<Intersect />
|
||||||
<RemoveConstrainingValues />
|
<RemoveConstrainingValues />
|
||||||
<SetAngleBetween />
|
<SetAngleBetween />
|
||||||
</>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,11 +7,14 @@ import {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { useStore } from '../useStore'
|
import { useStore } from '../useStore'
|
||||||
import { getNormalisedCoordinates } from '../lib/utils'
|
import { getNormalisedCoordinates, roundOff } from '../lib/utils'
|
||||||
import Loading from './Loading'
|
import Loading from './Loading'
|
||||||
import { cameraMouseDragGuards } from 'lib/cameraControls'
|
import { cameraMouseDragGuards } from 'lib/cameraControls'
|
||||||
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
||||||
import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
|
import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
|
||||||
|
import { Models } from '@kittycad/lib'
|
||||||
|
import { addStartSketch } from 'lang/modifyAst'
|
||||||
|
import { addNewSketchLn } from 'lang/std/sketch'
|
||||||
|
|
||||||
export const Stream = ({ className = '' }) => {
|
export const Stream = ({ className = '' }) => {
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
@ -25,6 +28,11 @@ export const Stream = ({ className = '' }) => {
|
|||||||
setDidDragInStream,
|
setDidDragInStream,
|
||||||
streamDimensions,
|
streamDimensions,
|
||||||
isExecuting,
|
isExecuting,
|
||||||
|
guiMode,
|
||||||
|
ast,
|
||||||
|
updateAst,
|
||||||
|
setGuiMode,
|
||||||
|
programMemory,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
mediaStream: s.mediaStream,
|
mediaStream: s.mediaStream,
|
||||||
engineCommandManager: s.engineCommandManager,
|
engineCommandManager: s.engineCommandManager,
|
||||||
@ -34,6 +42,11 @@ export const Stream = ({ className = '' }) => {
|
|||||||
setDidDragInStream: s.setDidDragInStream,
|
setDidDragInStream: s.setDidDragInStream,
|
||||||
streamDimensions: s.streamDimensions,
|
streamDimensions: s.streamDimensions,
|
||||||
isExecuting: s.isExecuting,
|
isExecuting: s.isExecuting,
|
||||||
|
guiMode: s.guiMode,
|
||||||
|
ast: s.ast,
|
||||||
|
updateAst: s.updateAst,
|
||||||
|
setGuiMode: s.setGuiMode,
|
||||||
|
programMemory: s.programMemory,
|
||||||
}))
|
}))
|
||||||
const {
|
const {
|
||||||
settings: {
|
settings: {
|
||||||
@ -64,7 +77,7 @@ export const Stream = ({ className = '' }) => {
|
|||||||
const newId = uuidv4()
|
const newId = uuidv4()
|
||||||
|
|
||||||
const interactionGuards = cameraMouseDragGuards[cameraControls]
|
const interactionGuards = cameraMouseDragGuards[cameraControls]
|
||||||
let interaction: CameraDragInteractionType_type
|
let interaction: CameraDragInteractionType_type = 'rotate'
|
||||||
|
|
||||||
if (
|
if (
|
||||||
interactionGuards.pan.callback(e) ||
|
interactionGuards.pan.callback(e) ||
|
||||||
@ -81,19 +94,33 @@ export const Stream = ({ className = '' }) => {
|
|||||||
interactionGuards.zoom.lenientDragStartButton === e.button
|
interactionGuards.zoom.lenientDragStartButton === e.button
|
||||||
) {
|
) {
|
||||||
interaction = 'zoom'
|
interaction = 'zoom'
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
engineCommandManager?.sendSceneCommand({
|
if (guiMode.mode === 'sketch' && guiMode.sketchMode === ('move' as any)) {
|
||||||
type: 'modeling_cmd_req',
|
engineCommandManager?.sendSceneCommand({
|
||||||
cmd: {
|
type: 'modeling_cmd_req',
|
||||||
type: 'camera_drag_start',
|
cmd: {
|
||||||
interaction,
|
type: 'handle_mouse_drag_start',
|
||||||
window: { x, y },
|
window: { x, y },
|
||||||
},
|
},
|
||||||
cmd_id: newId,
|
cmd_id: newId,
|
||||||
})
|
})
|
||||||
|
} else if (
|
||||||
|
!(
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('sketch_line' as any)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd: {
|
||||||
|
type: 'camera_drag_start',
|
||||||
|
interaction,
|
||||||
|
window: { x, y },
|
||||||
|
},
|
||||||
|
cmd_id: newId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
setButtonDownInStream(e.button)
|
setButtonDownInStream(e.button)
|
||||||
setClickCoords({ x, y })
|
setClickCoords({ x, y })
|
||||||
@ -118,6 +145,7 @@ export const Stream = ({ className = '' }) => {
|
|||||||
ctrlKey,
|
ctrlKey,
|
||||||
}) => {
|
}) => {
|
||||||
if (!videoRef.current) return
|
if (!videoRef.current) return
|
||||||
|
setButtonDownInStream(undefined)
|
||||||
const { x, y } = getNormalisedCoordinates({
|
const { x, y } = getNormalisedCoordinates({
|
||||||
clientX,
|
clientX,
|
||||||
clientY,
|
clientY,
|
||||||
@ -128,7 +156,7 @@ export const Stream = ({ className = '' }) => {
|
|||||||
const newCmdId = uuidv4()
|
const newCmdId = uuidv4()
|
||||||
const interaction = ctrlKey ? 'pan' : 'rotate'
|
const interaction = ctrlKey ? 'pan' : 'rotate'
|
||||||
|
|
||||||
engineCommandManager?.sendSceneCommand({
|
const command: Models['WebSocketRequest_type'] = {
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd: {
|
cmd: {
|
||||||
type: 'camera_drag_end',
|
type: 'camera_drag_end',
|
||||||
@ -136,9 +164,8 @@ export const Stream = ({ className = '' }) => {
|
|||||||
window: { x, y },
|
window: { x, y },
|
||||||
},
|
},
|
||||||
cmd_id: newCmdId,
|
cmd_id: newCmdId,
|
||||||
})
|
}
|
||||||
|
|
||||||
setButtonDownInStream(undefined)
|
|
||||||
if (!didDragInStream) {
|
if (!didDragInStream) {
|
||||||
engineCommandManager?.sendSceneCommand({
|
engineCommandManager?.sendSceneCommand({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
@ -150,6 +177,95 @@ export const Stream = ({ className = '' }) => {
|
|||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!didDragInStream && guiMode.mode === 'default') {
|
||||||
|
command.cmd = {
|
||||||
|
type: 'select_with_point',
|
||||||
|
selection_type: 'add',
|
||||||
|
selected_at_window: { x, y },
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
(!didDragInStream &&
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
['move', 'select'].includes(guiMode.sketchMode)) ||
|
||||||
|
(guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('sketch_line' as any))
|
||||||
|
) {
|
||||||
|
command.cmd = {
|
||||||
|
type: 'mouse_click',
|
||||||
|
window: { x, y },
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('move' as any)
|
||||||
|
) {
|
||||||
|
command.cmd = {
|
||||||
|
type: 'handle_mouse_drag_end',
|
||||||
|
window: { x, y },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
engineCommandManager?.sendSceneCommand(command).then(async ({ data }) => {
|
||||||
|
if (command.cmd.type !== 'mouse_click' || !ast) return
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('sketch_line' as any as 'line')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (data?.data?.entities_modified?.length && guiMode.waitingFirstClick) {
|
||||||
|
const curve = await engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'curve_get_control_points',
|
||||||
|
curve_id: data?.data?.entities_modified[0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const coords: { x: number; y: number }[] =
|
||||||
|
curve.data.data.control_points
|
||||||
|
const _addStartSketch = addStartSketch(
|
||||||
|
ast,
|
||||||
|
[roundOff(coords[0].x), roundOff(coords[0].y)],
|
||||||
|
[
|
||||||
|
roundOff(coords[1].x - coords[0].x),
|
||||||
|
roundOff(coords[1].y - coords[0].y),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
const _modifiedAst = _addStartSketch.modifiedAst
|
||||||
|
const _pathToNode = _addStartSketch.pathToNode
|
||||||
|
|
||||||
|
setGuiMode({
|
||||||
|
...guiMode,
|
||||||
|
pathToNode: _pathToNode,
|
||||||
|
waitingFirstClick: false,
|
||||||
|
})
|
||||||
|
updateAst(_modifiedAst)
|
||||||
|
} else if (
|
||||||
|
data?.data?.entities_modified?.length &&
|
||||||
|
!guiMode.waitingFirstClick
|
||||||
|
) {
|
||||||
|
const curve = await engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'curve_get_control_points',
|
||||||
|
curve_id: data?.data?.entities_modified[0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const coords: { x: number; y: number }[] =
|
||||||
|
curve.data.data.control_points
|
||||||
|
const _modifiedAst = addNewSketchLn({
|
||||||
|
node: ast,
|
||||||
|
programMemory,
|
||||||
|
to: [coords[1].x, coords[1].y],
|
||||||
|
fnName: 'line',
|
||||||
|
pathToNode: guiMode.pathToNode,
|
||||||
|
}).modifiedAst
|
||||||
|
updateAst(_modifiedAst)
|
||||||
|
}
|
||||||
|
})
|
||||||
setDidDragInStream(false)
|
setDidDragInStream(false)
|
||||||
setClickCoords(undefined)
|
setClickCoords(undefined)
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,6 @@ export const TextEditor = ({
|
|||||||
sourceRangeMap,
|
sourceRangeMap,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
code: s.code,
|
code: s.code,
|
||||||
defferedCode: s.defferedCode,
|
|
||||||
defferedSetCode: s.defferedSetCode,
|
defferedSetCode: s.defferedSetCode,
|
||||||
editorView: s.editorView,
|
editorView: s.editorView,
|
||||||
engineCommandManager: s.engineCommandManager,
|
engineCommandManager: s.engineCommandManager,
|
||||||
@ -70,7 +69,6 @@ export const TextEditor = ({
|
|||||||
isLSPServerReady: s.isLSPServerReady,
|
isLSPServerReady: s.isLSPServerReady,
|
||||||
selectionRanges: s.selectionRanges,
|
selectionRanges: s.selectionRanges,
|
||||||
selectionRangeTypeMap: s.selectionRangeTypeMap,
|
selectionRangeTypeMap: s.selectionRangeTypeMap,
|
||||||
setCode: s.setCode,
|
|
||||||
setEditorView: s.setEditorView,
|
setEditorView: s.setEditorView,
|
||||||
setIsLSPServerReady: s.setIsLSPServerReady,
|
setIsLSPServerReady: s.setIsLSPServerReady,
|
||||||
setSelectionRanges: s.setSelectionRanges,
|
setSelectionRanges: s.setSelectionRanges,
|
||||||
|
243
src/hooks/useAppMode.ts
Normal file
243
src/hooks/useAppMode.ts
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
// needed somewhere to dump this logic,
|
||||||
|
// Once we have xState this should be removed
|
||||||
|
|
||||||
|
import { useStore, Selections } from 'useStore'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { ArtifactMap, EngineCommandManager } from 'lang/std/engineConnection'
|
||||||
|
import { Models } from '@kittycad/lib/dist/types/src'
|
||||||
|
import { isReducedMotion } from 'lang/util'
|
||||||
|
import { isOverlap } from 'lib/utils'
|
||||||
|
|
||||||
|
interface DefaultPlanes {
|
||||||
|
xy: string
|
||||||
|
yz: string
|
||||||
|
xz: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAppMode() {
|
||||||
|
const {
|
||||||
|
guiMode,
|
||||||
|
setGuiMode,
|
||||||
|
selectionRanges,
|
||||||
|
engineCommandManager,
|
||||||
|
selectionRangeTypeMap,
|
||||||
|
} = useStore((s) => ({
|
||||||
|
guiMode: s.guiMode,
|
||||||
|
setGuiMode: s.setGuiMode,
|
||||||
|
selectionRanges: s.selectionRanges,
|
||||||
|
engineCommandManager: s.engineCommandManager,
|
||||||
|
selectionRangeTypeMap: s.selectionRangeTypeMap,
|
||||||
|
}))
|
||||||
|
const [defaultPlanes, setDefaultPlanes] = useState<DefaultPlanes | null>(null)
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === 'selectFace' &&
|
||||||
|
engineCommandManager
|
||||||
|
) {
|
||||||
|
if (!defaultPlanes) {
|
||||||
|
const xy = createPlane(engineCommandManager, {
|
||||||
|
x_axis: { x: 1, y: 0, z: 0 },
|
||||||
|
y_axis: { x: 0, y: 1, z: 0 },
|
||||||
|
color: { r: 0.7, g: 0.28, b: 0.28, a: 0.4 },
|
||||||
|
})
|
||||||
|
const yz = createPlane(engineCommandManager, {
|
||||||
|
x_axis: { x: 0, y: 1, z: 0 },
|
||||||
|
y_axis: { x: 0, y: 0, z: 1 },
|
||||||
|
color: { r: 0.28, g: 0.7, b: 0.28, a: 0.4 },
|
||||||
|
})
|
||||||
|
const xz = createPlane(engineCommandManager, {
|
||||||
|
x_axis: { x: 1, y: 0, z: 0 },
|
||||||
|
y_axis: { x: 0, y: 0, z: 1 },
|
||||||
|
color: { r: 0.28, g: 0.28, b: 0.7, a: 0.4 },
|
||||||
|
})
|
||||||
|
setDefaultPlanes({ xy, yz, xz })
|
||||||
|
} else {
|
||||||
|
hideDefaultPlanes(engineCommandManager, defaultPlanes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (guiMode.mode !== 'sketch' && defaultPlanes) {
|
||||||
|
Object.values(defaultPlanes).forEach((planeId) => {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'object_visible',
|
||||||
|
object_id: planeId,
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else if (guiMode.mode === 'default') {
|
||||||
|
const pathId =
|
||||||
|
engineCommandManager &&
|
||||||
|
isCursorInSketchCommandRange(
|
||||||
|
engineCommandManager.artifactMap,
|
||||||
|
selectionRanges
|
||||||
|
)
|
||||||
|
if (pathId) {
|
||||||
|
setGuiMode({
|
||||||
|
mode: 'canEditSketch',
|
||||||
|
rotation: [0, 0, 0, 1],
|
||||||
|
position: [0, 0, 0],
|
||||||
|
pathToNode: [],
|
||||||
|
pathId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if (guiMode.mode === 'canEditSketch') {
|
||||||
|
if (
|
||||||
|
!engineCommandManager ||
|
||||||
|
!isCursorInSketchCommandRange(
|
||||||
|
engineCommandManager.artifactMap,
|
||||||
|
selectionRanges
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
setGuiMode({
|
||||||
|
mode: 'default',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
guiMode,
|
||||||
|
guiMode.mode,
|
||||||
|
engineCommandManager,
|
||||||
|
selectionRanges,
|
||||||
|
selectionRangeTypeMap,
|
||||||
|
])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const unSub = engineCommandManager?.subscribeTo({
|
||||||
|
event: 'select_with_point',
|
||||||
|
callback: async ({ data }) => {
|
||||||
|
if (!data.entity_id) return
|
||||||
|
if (!defaultPlanes) return
|
||||||
|
if (!Object.values(defaultPlanes || {}).includes(data.entity_id)) {
|
||||||
|
// user clicked something else in the scene
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const sketchModeResponse = await engineCommandManager?.sendSceneCommand(
|
||||||
|
{
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'sketch_mode_enable',
|
||||||
|
plane_id: data.entity_id,
|
||||||
|
ortho: true,
|
||||||
|
animated: !isReducedMotion(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
hideDefaultPlanes(engineCommandManager, defaultPlanes)
|
||||||
|
const sketchUuid = uuidv4()
|
||||||
|
const proms: any[] = []
|
||||||
|
proms.push(
|
||||||
|
engineCommandManager.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: sketchUuid,
|
||||||
|
cmd: {
|
||||||
|
type: 'start_path',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
proms.push(
|
||||||
|
engineCommandManager.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'edit_mode_enter',
|
||||||
|
target: sketchUuid,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
const res = await Promise.all(proms)
|
||||||
|
console.log('res', res)
|
||||||
|
setGuiMode({
|
||||||
|
mode: 'sketch',
|
||||||
|
sketchMode: 'sketchEdit',
|
||||||
|
rotation: [0, 0, 0, 1],
|
||||||
|
position: [0, 0, 0],
|
||||||
|
pathToNode: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('sketchModeResponse', sketchModeResponse)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return unSub
|
||||||
|
}, [engineCommandManager, defaultPlanes])
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPlane(
|
||||||
|
engineCommandManager: EngineCommandManager,
|
||||||
|
{
|
||||||
|
x_axis,
|
||||||
|
y_axis,
|
||||||
|
color,
|
||||||
|
}: {
|
||||||
|
x_axis: Models['Point3d_type']
|
||||||
|
y_axis: Models['Point3d_type']
|
||||||
|
color: Models['Color_type']
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const planeId = uuidv4()
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd: {
|
||||||
|
type: 'make_plane',
|
||||||
|
size: 60,
|
||||||
|
origin: { x: 0, y: 0, z: 0 },
|
||||||
|
x_axis,
|
||||||
|
y_axis,
|
||||||
|
clobber: false,
|
||||||
|
},
|
||||||
|
cmd_id: planeId,
|
||||||
|
})
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd: {
|
||||||
|
type: 'plane_set_color',
|
||||||
|
plane_id: planeId,
|
||||||
|
color,
|
||||||
|
},
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
})
|
||||||
|
return planeId
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideDefaultPlanes(
|
||||||
|
engineCommandManager: EngineCommandManager,
|
||||||
|
defaultPlanes: DefaultPlanes
|
||||||
|
) {
|
||||||
|
Object.values(defaultPlanes).forEach((planeId) => {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'object_visible',
|
||||||
|
object_id: planeId,
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCursorInSketchCommandRange(
|
||||||
|
artifactMap: ArtifactMap,
|
||||||
|
selectionRanges: Selections
|
||||||
|
): string | false {
|
||||||
|
const overlapingEntries = Object.entries(artifactMap || {}).filter(
|
||||||
|
([id, artifact]) =>
|
||||||
|
selectionRanges.codeBasedSelections.some(
|
||||||
|
(selection) =>
|
||||||
|
Array.isArray(selection.range) &&
|
||||||
|
Array.isArray(artifact.range) &&
|
||||||
|
isOverlap(selection.range, artifact.range) &&
|
||||||
|
(artifact.commandType === 'start_path' ||
|
||||||
|
artifact.commandType === 'extend_path' ||
|
||||||
|
'close_path')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return overlapingEntries.length === 1 && overlapingEntries[0][1].parentId
|
||||||
|
? overlapingEntries[0][1].parentId
|
||||||
|
: false
|
||||||
|
}
|
@ -28,6 +28,46 @@ import {
|
|||||||
createFirstArg,
|
createFirstArg,
|
||||||
} from './std/sketch'
|
} from './std/sketch'
|
||||||
|
|
||||||
|
export function addStartSketch(
|
||||||
|
node: Program,
|
||||||
|
start: [number, number],
|
||||||
|
end: [number, number]
|
||||||
|
): { modifiedAst: Program; id: string; pathToNode: PathToNode } {
|
||||||
|
const _node = { ...node }
|
||||||
|
const _name = findUniqueName(node, 'part')
|
||||||
|
|
||||||
|
const startSketchAt = createCallExpression('startSketchAt', [
|
||||||
|
createArrayExpression([createLiteral(start[0]), createLiteral(start[1])]),
|
||||||
|
])
|
||||||
|
const initialLineTo = createCallExpression('line', [
|
||||||
|
createArrayExpression([createLiteral(end[0]), createLiteral(end[1])]),
|
||||||
|
createPipeSubstitution(),
|
||||||
|
])
|
||||||
|
|
||||||
|
const pipeBody = [startSketchAt, initialLineTo]
|
||||||
|
|
||||||
|
const variableDeclaration = createVariableDeclaration(
|
||||||
|
_name,
|
||||||
|
createPipeExpression(pipeBody)
|
||||||
|
)
|
||||||
|
|
||||||
|
_node.body = [...node.body, variableDeclaration]
|
||||||
|
|
||||||
|
let pathToNode: PathToNode = [
|
||||||
|
['body', ''],
|
||||||
|
['0', 'index'],
|
||||||
|
['declarations', 'VariableDeclaration'],
|
||||||
|
['0', 'index'],
|
||||||
|
['init', 'VariableDeclarator'],
|
||||||
|
]
|
||||||
|
|
||||||
|
return {
|
||||||
|
modifiedAst: _node,
|
||||||
|
id: _name,
|
||||||
|
pathToNode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function addSketchTo(
|
export function addSketchTo(
|
||||||
node: Program,
|
node: Program,
|
||||||
axis: 'xy' | 'xz' | 'yz',
|
axis: 'xy' | 'xz' | 'yz',
|
||||||
|
@ -6,6 +6,8 @@ import { exportSave } from 'lib/exportSave'
|
|||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import * as Sentry from '@sentry/react'
|
import * as Sentry from '@sentry/react'
|
||||||
|
|
||||||
|
let lastMessage = ''
|
||||||
|
|
||||||
interface CommandInfo {
|
interface CommandInfo {
|
||||||
commandType: CommandTypes
|
commandType: CommandTypes
|
||||||
range: SourceRange
|
range: SourceRange
|
||||||
@ -754,6 +756,13 @@ export class EngineCommandManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
sendSceneCommand(command: EngineCommand): Promise<any> {
|
sendSceneCommand(command: EngineCommand): Promise<any> {
|
||||||
|
if (
|
||||||
|
command.type === 'modeling_cmd_req' &&
|
||||||
|
command.cmd.type !== lastMessage
|
||||||
|
) {
|
||||||
|
console.log('sending command', command.cmd.type)
|
||||||
|
lastMessage = command.cmd.type
|
||||||
|
}
|
||||||
if (!this.engineConnection?.isReady()) {
|
if (!this.engineConnection?.isReady()) {
|
||||||
console.log('socket not ready')
|
console.log('socket not ready')
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
|
@ -20,7 +20,7 @@ import {
|
|||||||
getNodePathFromSourceRange,
|
getNodePathFromSourceRange,
|
||||||
} from '../queryAst'
|
} from '../queryAst'
|
||||||
import { GuiModes, toolTips, TooTip } from '../../useStore'
|
import { GuiModes, toolTips, TooTip } from '../../useStore'
|
||||||
import { splitPathAtPipeExpression } from '../modifyAst'
|
import { createPipeExpression, splitPathAtPipeExpression } from '../modifyAst'
|
||||||
import { generateUuidFromHashSeed } from '../../lib/uuid'
|
import { generateUuidFromHashSeed } from '../../lib/uuid'
|
||||||
|
|
||||||
import { SketchLineHelper, ModifyAstBase, TransformCallback } from './stdTypes'
|
import { SketchLineHelper, ModifyAstBase, TransformCallback } from './stdTypes'
|
||||||
@ -185,7 +185,7 @@ export const line: SketchLineHelper = {
|
|||||||
createCallback,
|
createCallback,
|
||||||
}) => {
|
}) => {
|
||||||
const _node = { ...node }
|
const _node = { ...node }
|
||||||
const { node: pipe } = getNodeFromPath<PipeExpression>(
|
const { node: pipe } = getNodeFromPath<PipeExpression | CallExpression>(
|
||||||
_node,
|
_node,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
'PipeExpression'
|
'PipeExpression'
|
||||||
@ -202,7 +202,7 @@ export const line: SketchLineHelper = {
|
|||||||
const newXVal = createLiteral(roundOff(to[0] - from[0], 2))
|
const newXVal = createLiteral(roundOff(to[0] - from[0], 2))
|
||||||
const newYVal = createLiteral(roundOff(to[1] - from[1], 2))
|
const newYVal = createLiteral(roundOff(to[1] - from[1], 2))
|
||||||
|
|
||||||
if (replaceExisting && createCallback) {
|
if (replaceExisting && createCallback && pipe.type !== 'CallExpression') {
|
||||||
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
|
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
|
||||||
const { callExp, valueUsedInTransform } = createCallback(
|
const { callExp, valueUsedInTransform } = createCallback(
|
||||||
[newXVal, newYVal],
|
[newXVal, newYVal],
|
||||||
@ -220,7 +220,11 @@ export const line: SketchLineHelper = {
|
|||||||
createArrayExpression([newXVal, newYVal]),
|
createArrayExpression([newXVal, newYVal]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
])
|
])
|
||||||
pipe.body = [...pipe.body, callExp]
|
if (pipe.type === 'PipeExpression') {
|
||||||
|
pipe.body = [...pipe.body, callExp]
|
||||||
|
} else {
|
||||||
|
varDec.init = createPipeExpression([varDec.init, callExp])
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
modifiedAst: _node,
|
modifiedAst: _node,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
@ -238,22 +242,10 @@ export const line: SketchLineHelper = {
|
|||||||
createLiteral(roundOff(to[1] - from[1], 2)),
|
createLiteral(roundOff(to[1] - from[1], 2)),
|
||||||
])
|
])
|
||||||
|
|
||||||
if (
|
if (callExpression.arguments?.[0].type === 'ObjectExpression') {
|
||||||
callExpression.arguments?.[0].type === 'Literal' &&
|
|
||||||
callExpression.arguments?.[0].value === 'default'
|
|
||||||
) {
|
|
||||||
callExpression.arguments[0] = toArrExp
|
|
||||||
} else if (callExpression.arguments?.[0].type === 'ObjectExpression') {
|
|
||||||
const toProp = callExpression.arguments?.[0].properties?.find(
|
const toProp = callExpression.arguments?.[0].properties?.find(
|
||||||
({ key }) => key.name === 'to'
|
({ key }) => key.name === 'to'
|
||||||
)
|
)
|
||||||
if (
|
|
||||||
toProp &&
|
|
||||||
toProp.value.type === 'Literal' &&
|
|
||||||
toProp.value.value === 'default'
|
|
||||||
) {
|
|
||||||
toProp.value = toArrExp
|
|
||||||
}
|
|
||||||
mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to')
|
mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to')
|
||||||
} else {
|
} else {
|
||||||
mutateArrExp(callExpression.arguments?.[0], toArrExp)
|
mutateArrExp(callExpression.arguments?.[0], toArrExp)
|
||||||
@ -968,60 +960,14 @@ export function addNewSketchLn({
|
|||||||
pathToNode,
|
pathToNode,
|
||||||
'VariableDeclarator'
|
'VariableDeclarator'
|
||||||
)
|
)
|
||||||
const { node: pipeExp, shallowPath: pipePath } =
|
const { node: pipeExp, shallowPath: pipePath } = getNodeFromPath<
|
||||||
getNodeFromPath<PipeExpression>(node, pathToNode, 'PipeExpression')
|
PipeExpression | CallExpression
|
||||||
const maybeStartSketchAt = pipeExp.body.find(
|
>(node, pathToNode, 'PipeExpression')
|
||||||
(exp) =>
|
|
||||||
exp.type === 'CallExpression' &&
|
|
||||||
exp.callee.name === 'startSketchAt' &&
|
|
||||||
exp.arguments[0].type === 'Literal' &&
|
|
||||||
exp.arguments[0].value === 'default'
|
|
||||||
)
|
|
||||||
const maybeDefaultLine = pipeExp.body.findIndex(
|
|
||||||
(exp) =>
|
|
||||||
exp.type === 'CallExpression' &&
|
|
||||||
exp.callee.name === 'line' &&
|
|
||||||
exp.arguments[0].type === 'Literal' &&
|
|
||||||
exp.arguments[0].value === 'default'
|
|
||||||
)
|
|
||||||
const defaultLinePath: PathToNode = [
|
|
||||||
...pipePath,
|
|
||||||
['body', ''],
|
|
||||||
[maybeDefaultLine, ''],
|
|
||||||
]
|
|
||||||
const variableName = varDec.id.name
|
const variableName = varDec.id.name
|
||||||
const sketch = previousProgramMemory?.root?.[variableName]
|
const sketch = previousProgramMemory?.root?.[variableName]
|
||||||
if (sketch.type !== 'sketchGroup') throw new Error('not a sketchGroup')
|
if (sketch.type !== 'sketchGroup') throw new Error('not a sketchGroup')
|
||||||
|
|
||||||
if (maybeStartSketchAt) {
|
const last = sketch.value[sketch.value.length - 1] || sketch.start
|
||||||
const startSketchAt = maybeStartSketchAt as any
|
|
||||||
startSketchAt.arguments[0] = createArrayExpression([
|
|
||||||
createLiteral(to[0]),
|
|
||||||
createLiteral(to[1]),
|
|
||||||
])
|
|
||||||
return {
|
|
||||||
modifiedAst: node,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (maybeDefaultLine !== -1) {
|
|
||||||
const defaultLine = getNodeFromPath<CallExpression>(
|
|
||||||
node,
|
|
||||||
defaultLinePath
|
|
||||||
).node
|
|
||||||
const { from } = getSketchSegmentFromSourceRange(sketch, [
|
|
||||||
defaultLine.start,
|
|
||||||
defaultLine.end,
|
|
||||||
]).segment
|
|
||||||
return updateArgs({
|
|
||||||
node,
|
|
||||||
previousProgramMemory,
|
|
||||||
pathToNode: defaultLinePath,
|
|
||||||
to,
|
|
||||||
from,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const last = sketch.value[sketch.value.length - 1]
|
|
||||||
const from = last.to
|
const from = last.to
|
||||||
|
|
||||||
return add({
|
return add({
|
||||||
@ -1198,14 +1144,6 @@ function getFirstArgValuesForXYFns(callExpression: CallExpression): {
|
|||||||
} {
|
} {
|
||||||
// used for lineTo, line
|
// used for lineTo, line
|
||||||
const firstArg = callExpression.arguments[0]
|
const firstArg = callExpression.arguments[0]
|
||||||
if (firstArg.type === 'Literal' && firstArg.value === 'default') {
|
|
||||||
return {
|
|
||||||
val:
|
|
||||||
callExpression.callee.name === 'startSketchAt'
|
|
||||||
? [createLiteral(0), createLiteral(0)]
|
|
||||||
: [createLiteral(1), createLiteral(1)],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (firstArg.type === 'ArrayExpression') {
|
if (firstArg.type === 'ArrayExpression') {
|
||||||
return { val: [firstArg.elements[0], firstArg.elements[1]] }
|
return { val: [firstArg.elements[0], firstArg.elements[1]] }
|
||||||
}
|
}
|
||||||
@ -1215,8 +1153,6 @@ function getFirstArgValuesForXYFns(callExpression: CallExpression): {
|
|||||||
if (to?.type === 'ArrayExpression') {
|
if (to?.type === 'ArrayExpression') {
|
||||||
const [x, y] = to.elements
|
const [x, y] = to.elements
|
||||||
return { val: [x, y], tag }
|
return { val: [x, y], tag }
|
||||||
} else if (to?.type === 'Literal' && to.value === 'default') {
|
|
||||||
return { val: [createLiteral(0), createLiteral(0)], tag }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error('expected ArrayExpression or ObjectExpression')
|
throw new Error('expected ArrayExpression or ObjectExpression')
|
||||||
|
@ -43,9 +43,12 @@ export type TooTip =
|
|||||||
| 'yLineTo'
|
| 'yLineTo'
|
||||||
| 'angledLineThatIntersects'
|
| 'angledLineThatIntersects'
|
||||||
|
|
||||||
export const toolTips: TooTip[] = [
|
export const toolTips = [
|
||||||
'lineTo',
|
'sketch_line',
|
||||||
|
'move',
|
||||||
|
// original tooltips
|
||||||
'line',
|
'line',
|
||||||
|
'lineTo',
|
||||||
'angledLine',
|
'angledLine',
|
||||||
'angledLineOfXLength',
|
'angledLineOfXLength',
|
||||||
'angledLineOfYLength',
|
'angledLineOfYLength',
|
||||||
@ -56,7 +59,7 @@ export const toolTips: TooTip[] = [
|
|||||||
'xLineTo',
|
'xLineTo',
|
||||||
'yLineTo',
|
'yLineTo',
|
||||||
'angledLineThatIntersects',
|
'angledLineThatIntersects',
|
||||||
]
|
] as any as TooTip[]
|
||||||
|
|
||||||
export type GuiModes =
|
export type GuiModes =
|
||||||
| {
|
| {
|
||||||
@ -66,6 +69,7 @@ export type GuiModes =
|
|||||||
mode: 'sketch'
|
mode: 'sketch'
|
||||||
sketchMode: TooTip
|
sketchMode: TooTip
|
||||||
isTooltip: true
|
isTooltip: true
|
||||||
|
waitingFirstClick: boolean
|
||||||
rotation: Rotation
|
rotation: Rotation
|
||||||
position: Position
|
position: Position
|
||||||
id?: string
|
id?: string
|
||||||
@ -84,6 +88,7 @@ export type GuiModes =
|
|||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
mode: 'canEditSketch'
|
mode: 'canEditSketch'
|
||||||
|
pathId: string
|
||||||
pathToNode: PathToNode
|
pathToNode: PathToNode
|
||||||
rotation: Rotation
|
rotation: Rotation
|
||||||
position: Position
|
position: Position
|
||||||
@ -122,8 +127,8 @@ export interface StoreState {
|
|||||||
kclErrors: KCLError[]
|
kclErrors: KCLError[]
|
||||||
addKCLError: (err: KCLError) => void
|
addKCLError: (err: KCLError) => void
|
||||||
resetKCLErrors: () => void
|
resetKCLErrors: () => void
|
||||||
ast: Program | null
|
ast: Program
|
||||||
setAst: (ast: Program | null) => void
|
setAst: (ast: Program) => void
|
||||||
updateAst: (
|
updateAst: (
|
||||||
ast: Program,
|
ast: Program,
|
||||||
optionalParams?: {
|
optionalParams?: {
|
||||||
@ -222,12 +227,13 @@ export const useStore = create<StoreState>()(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
editorView.dispatch({
|
ranges.length &&
|
||||||
selection: EditorSelection.create(
|
editorView.dispatch({
|
||||||
ranges,
|
selection: EditorSelection.create(
|
||||||
selections.codeBasedSelections.length - 1
|
ranges,
|
||||||
),
|
selections.codeBasedSelections.length - 1
|
||||||
})
|
),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setCursor2: (codeSelections) => {
|
setCursor2: (codeSelections) => {
|
||||||
@ -281,7 +287,15 @@ export const useStore = create<StoreState>()(
|
|||||||
resetKCLErrors: () => {
|
resetKCLErrors: () => {
|
||||||
set({ kclErrors: [] })
|
set({ kclErrors: [] })
|
||||||
},
|
},
|
||||||
ast: null,
|
ast: {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
body: [],
|
||||||
|
nonCodeMeta: {
|
||||||
|
noneCodeNodes: {},
|
||||||
|
start: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
setAst: (ast) => {
|
setAst: (ast) => {
|
||||||
set({ ast })
|
set({ ast })
|
||||||
},
|
},
|
||||||
@ -290,7 +304,11 @@ export const useStore = create<StoreState>()(
|
|||||||
const astWithUpdatedSource = parser_wasm(newCode)
|
const astWithUpdatedSource = parser_wasm(newCode)
|
||||||
callBack(astWithUpdatedSource)
|
callBack(astWithUpdatedSource)
|
||||||
|
|
||||||
set({ ast: astWithUpdatedSource, code: newCode })
|
set({
|
||||||
|
ast: astWithUpdatedSource,
|
||||||
|
code: newCode,
|
||||||
|
defferedCode: newCode,
|
||||||
|
})
|
||||||
if (focusPath) {
|
if (focusPath) {
|
||||||
const { node } = getNodeFromPath<any>(
|
const { node } = getNodeFromPath<any>(
|
||||||
astWithUpdatedSource,
|
astWithUpdatedSource,
|
||||||
|
Reference in New Issue
Block a user