asyncronise executor (#115)

* Intital async of executor

The execture now sends websocket message instead of calling functions
directly from the engine, When it does so it holds onto the id.
The engine is still returning geo/polys directly but I'm working make it
so that the UI doesn't need to know about that, so that we can switch
over the streaming ui.

Things left to do:
- it is still making both direct function calls and websockets, and the former should be removed.
- It does highlighting of segments and sourceRanges not through websockets and that needs to be fixed.
- Tests have not been adjusted for these changes.
- Selecting the head of a segment is not working correctly again yet.

* Rough engine prep changes (#135)

* rough changes for engine prep

* mouse movements working again

* connect to engine for startsketch, line, close and extrude
This commit is contained in:
Kurt Hutten
2023-06-22 16:43:33 +10:00
committed by GitHub
parent dd3117cf03
commit 2d3c73d46a
39 changed files with 1798 additions and 2443 deletions

View File

@ -1,10 +1,8 @@
import { useRef, useState, useEffect } from 'react'
import { Canvas } from '@react-three/fiber'
import { useRef, useEffect, useMemo } from 'react'
import { Allotment } from 'allotment'
import { OrbitControls, OrthographicCamera } from '@react-three/drei'
import { asyncLexer } from './lang/tokeniser'
import { abstractSyntaxTree } from './lang/abstractSyntaxTree'
import { executor, ExtrudeGroup, SketchGroup } from './lang/executor'
import { _executor, ExtrudeGroup, SketchGroup } from './lang/executor'
import CodeMirror from '@uiw/react-codemirror'
import { javascript } from '@codemirror/lang-javascript'
import { ViewUpdate } from '@codemirror/view'
@ -12,29 +10,25 @@ import {
lineHighlightField,
addLineHighlight,
} from './editor/highlightextension'
import { useStore } from './useStore'
import { Selections, useStore } from './useStore'
import { Toolbar } from './Toolbar'
import { BasePlanes } from './components/BasePlanes'
import { SketchPlane } from './components/SketchPlane'
import { Logs } from './components/Logs'
import { AxisIndicator } from './components/AxisIndicator'
import { RenderViewerArtifacts } from './components/RenderViewerArtifacts'
import { PanelHeader } from './components/PanelHeader'
import { MemoryPanel } from './components/MemoryPanel'
import { useHotKeyListener } from './hooks/useHotKeyListener'
import { Stream } from './components/Stream'
import ModalContainer from 'react-modal-promise'
import { EngineCommandManager } from './lang/std/engineConnection'
import { isOverlap } from './lib/utils'
const OrrthographicCamera = OrthographicCamera as any
function App() {
export function App() {
const cam = useRef()
useHotKeyListener()
const {
editorView,
setEditorView,
setSelectionRanges,
selectionRanges: selectionRange,
selectionRanges,
guiMode,
lastGuiMode,
addLog,
@ -46,6 +40,13 @@ function App() {
setProgramMemory,
resetLogs,
selectionRangeTypeMap,
setArtifactMap,
engineCommandManager: _engineCommandManager,
setEngineCommandManager,
setHighlightRange,
setCursor2,
sourceRangeMap,
setMediaStream,
} = useStore((s) => ({
editorView: s.editorView,
setEditorView: s.setEditorView,
@ -63,6 +64,15 @@ function App() {
setProgramMemory: s.setProgramMemory,
resetLogs: s.resetLogs,
selectionRangeTypeMap: s.selectionRangeTypeMap,
setArtifactMap: s.setArtifactNSourceRangeMaps,
engineCommandManager: s.engineCommandManager,
setEngineCommandManager: s.setEngineCommandManager,
setHighlightRange: s.setHighlightRange,
isShiftDown: s.isShiftDown,
setCursor: s.setCursor,
setCursor2: s.setCursor2,
sourceRangeMap: s.sourceRangeMap,
setMediaStream: s.setMediaStream
}))
// const onChange = React.useCallback((value: string, viewUpdate: ViewUpdate) => {
const onChange = (value: string, viewUpdate: ViewUpdate) => {
@ -78,18 +88,17 @@ function App() {
const ranges = viewUpdate.state.selection.ranges
const isChange =
ranges.length !== selectionRange.codeBasedSelections.length ||
ranges.length !== selectionRanges.codeBasedSelections.length ||
ranges.some(({ from, to }, i) => {
return (
from !== selectionRange.codeBasedSelections[i].range[0] ||
to !== selectionRange.codeBasedSelections[i].range[1]
from !== selectionRanges.codeBasedSelections[i].range[0] ||
to !== selectionRanges.codeBasedSelections[i].range[1]
)
})
if (!isChange) return
setSelectionRanges({
otherSelections: [],
codeBasedSelections: ranges.map(({ from, to }, i) => {
const codeBasedSelections: Selections['codeBasedSelections'] = ranges.map(
({ from, to }) => {
if (selectionRangeTypeMap[to]) {
return {
type: selectionRangeTypeMap[to],
@ -100,15 +109,39 @@ function App() {
type: 'default',
range: [from, to],
}
}),
}
)
const idBasedSelections = codeBasedSelections
.map(({ type, range }) => {
const hasOverlap = Object.entries(sourceRangeMap).filter(
([_, sourceRange]) => {
return isOverlap(sourceRange, range)
}
)
if (hasOverlap.length) {
return {
type,
id: hasOverlap[0][0],
}
}
})
.filter(Boolean) as any
_engineCommandManager?.cusorsSelected({
otherSelections: [],
idBasedSelections,
})
setSelectionRanges({
otherSelections: [],
codeBasedSelections,
})
}
const [geoArray, setGeoArray] = useState<(ExtrudeGroup | SketchGroup)[]>([])
const engineCommandManager = useMemo(() => new EngineCommandManager(setMediaStream), [])
useEffect(() => {
const asyncWrap = async () => {
try {
if (!code) {
setGeoArray([])
setAst(null)
return
}
@ -116,60 +149,86 @@ function App() {
const _ast = abstractSyntaxTree(tokens)
setAst(_ast)
resetLogs()
const programMemory = executor(_ast, {
root: {
log: {
type: 'userVal',
value: (a: any) => {
addLog(a)
},
__meta: [
{
pathToNode: [],
sourceRange: [0, 0],
if (_engineCommandManager) {
_engineCommandManager.endSession()
}
engineCommandManager.startNewSession()
setEngineCommandManager(engineCommandManager)
_executor(
_ast,
{
root: {
log: {
type: 'userVal',
value: (a: any) => {
addLog(a)
},
],
},
_0: {
type: 'userVal',
value: 0,
__meta: [],
},
_90: {
type: 'userVal',
value: 90,
__meta: [],
},
_180: {
type: 'userVal',
value: 180,
__meta: [],
},
_270: {
type: 'userVal',
value: 270,
__meta: [],
__meta: [
{
pathToNode: [],
sourceRange: [0, 0],
},
],
},
_0: {
type: 'userVal',
value: 0,
__meta: [],
},
_90: {
type: 'userVal',
value: 90,
__meta: [],
},
_180: {
type: 'userVal',
value: 180,
__meta: [],
},
_270: {
type: 'userVal',
value: 270,
__meta: [],
},
},
pendingMemory: {},
},
_sketch: [],
})
setProgramMemory(programMemory)
const geos = programMemory?.return
?.map(({ name }: { name: string }) => {
const artifact = programMemory?.root?.[name]
if (
artifact.type === 'extrudeGroup' ||
artifact.type === 'sketchGroup'
) {
return artifact
}
return null
})
.filter((a) => a) as (ExtrudeGroup | SketchGroup)[]
engineCommandManager,
{ bodyType: 'root' },
[]
).then(async (programMemory) => {
const { artifactMap, sourceRangeMap } =
await engineCommandManager.waitForAllCommands()
setGeoArray(geos)
console.log(programMemory)
setError()
setArtifactMap({ artifactMap, sourceRangeMap })
engineCommandManager.onHover((id) => {
if (!id) {
setHighlightRange([0, 0])
} else {
const sourceRange = sourceRangeMap[id]
setHighlightRange(sourceRange)
}
})
engineCommandManager.onClick(({ id, type }) => {
setCursor2({ range: sourceRangeMap[id], type })
})
setProgramMemory(programMemory)
const geos = programMemory?.return
?.map(({ name }: { name: string }) => {
const artifact = programMemory?.root?.[name]
if (
artifact.type === 'extrudeGroup' ||
artifact.type === 'sketchGroup'
) {
return artifact
}
return null
})
.filter((a) => a) as (ExtrudeGroup | SketchGroup)[]
// console.log(programMemory)
setError()
})
} catch (e: any) {
setError('problem')
console.log(e)
@ -209,52 +268,9 @@ function App() {
<MemoryPanel />
<Logs />
</Allotment>
<Allotment vertical defaultSizes={[1, 400]} minSize={20}>
<div className="h-full">
<PanelHeader title="Drafting Board" />
<Allotment vertical defaultSizes={[40, 400]} minSize={20}>
<div>
<Toolbar />
<div className="border h-full border-gray-300 relative">
<div className="absolute inset-0">
<Canvas>
<OrbitControls
enableDamping={false}
enablePan
enableRotate={
!(
guiMode.mode === 'canEditSketch' ||
guiMode.mode === 'sketch'
)
}
enableZoom
reverseOrbit={false}
/>
<OrrthographicCamera
ref={cam}
makeDefault
position={[0, 0, 1000]}
zoom={100}
rotation={[0, 0, 0]}
far={2000}
/>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<RenderViewerArtifacts artifacts={geoArray} />
<BasePlanes />
<SketchPlane />
<AxisIndicator />
</Canvas>
</div>
{errorState.isError && (
<div className="absolute inset-0 bg-gray-700/20">
<pre>
{'last first: \n\n' +
JSON.stringify(lastGuiMode, null, 2) +
'\n\n' +
JSON.stringify(guiMode)}
</pre>
</div>
)}
</div>
</div>
<Stream />
</Allotment>
@ -262,5 +278,3 @@ function App() {
</div>
)
}
export default App