add gizmo (#738)
* add gizmo Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix force ast execution Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -3,6 +3,7 @@ import { _executor } from '../lang/wasm'
|
|||||||
import { useStore } from '../useStore'
|
import { useStore } from '../useStore'
|
||||||
import { engineCommandManager } from '../lang/std/engineConnection'
|
import { engineCommandManager } from '../lang/std/engineConnection'
|
||||||
import { deferExecution } from 'lib/utils'
|
import { deferExecution } from 'lib/utils'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
export function useSetupEngineManager(
|
export function useSetupEngineManager(
|
||||||
streamRef: React.RefObject<HTMLDivElement>,
|
streamRef: React.RefObject<HTMLDivElement>,
|
||||||
@ -12,14 +13,14 @@ export function useSetupEngineManager(
|
|||||||
setMediaStream,
|
setMediaStream,
|
||||||
setIsStreamReady,
|
setIsStreamReady,
|
||||||
setStreamDimensions,
|
setStreamDimensions,
|
||||||
executeCode,
|
|
||||||
streamDimensions,
|
streamDimensions,
|
||||||
|
executeCode,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
setMediaStream: s.setMediaStream,
|
setMediaStream: s.setMediaStream,
|
||||||
setIsStreamReady: s.setIsStreamReady,
|
setIsStreamReady: s.setIsStreamReady,
|
||||||
setStreamDimensions: s.setStreamDimensions,
|
setStreamDimensions: s.setStreamDimensions,
|
||||||
executeCode: s.executeCode,
|
|
||||||
streamDimensions: s.streamDimensions,
|
streamDimensions: s.streamDimensions,
|
||||||
|
executeCode: s.executeCode,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const streamWidth = streamRef?.current?.offsetWidth
|
const streamWidth = streamRef?.current?.offsetWidth
|
||||||
@ -40,11 +41,9 @@ export function useSetupEngineManager(
|
|||||||
setIsStreamReady,
|
setIsStreamReady,
|
||||||
width: quadWidth,
|
width: quadWidth,
|
||||||
height: quadHeight,
|
height: quadHeight,
|
||||||
|
executeCode,
|
||||||
token,
|
token,
|
||||||
})
|
})
|
||||||
engineCommandManager.waitForReady.then(() => {
|
|
||||||
executeCode()
|
|
||||||
})
|
|
||||||
setStreamDimensions({
|
setStreamDimensions({
|
||||||
streamWidth: quadWidth,
|
streamWidth: quadWidth,
|
||||||
streamHeight: quadHeight,
|
streamHeight: quadHeight,
|
||||||
|
@ -491,9 +491,11 @@ export class EngineConnection {
|
|||||||
|
|
||||||
this.onDataChannelOpen(this)
|
this.onDataChannelOpen(this)
|
||||||
|
|
||||||
this.onEngineConnectionOpen(this)
|
|
||||||
this.ready = true
|
this.ready = true
|
||||||
this.connecting = false
|
this.connecting = false
|
||||||
|
// Do this after we set the connection is ready to avoid errors when
|
||||||
|
// we try to send messages before the connection is ready.
|
||||||
|
this.onEngineConnectionOpen(this)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.unreliableDataChannel.addEventListener('close', (event) => {
|
this.unreliableDataChannel.addEventListener('close', (event) => {
|
||||||
@ -586,6 +588,9 @@ export class EngineCommandManager {
|
|||||||
outSequence = 1
|
outSequence = 1
|
||||||
inSequence = 1
|
inSequence = 1
|
||||||
engineConnection?: EngineConnection
|
engineConnection?: EngineConnection
|
||||||
|
// Folks should realize that wait for ready does not get called _everytime_
|
||||||
|
// the connection resets and restarts, it only gets called the first time.
|
||||||
|
// Be careful what you put here.
|
||||||
waitForReady: Promise<void> = new Promise(() => {})
|
waitForReady: Promise<void> = new Promise(() => {})
|
||||||
private resolveReady = () => {}
|
private resolveReady = () => {}
|
||||||
|
|
||||||
@ -609,12 +614,14 @@ export class EngineCommandManager {
|
|||||||
setIsStreamReady,
|
setIsStreamReady,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
executeCode,
|
||||||
token,
|
token,
|
||||||
}: {
|
}: {
|
||||||
setMediaStream: (stream: MediaStream) => void
|
setMediaStream: (stream: MediaStream) => void
|
||||||
setIsStreamReady: (isStreamReady: boolean) => void
|
setIsStreamReady: (isStreamReady: boolean) => void
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
|
executeCode: (code?: string, force?: boolean) => void
|
||||||
token?: string
|
token?: string
|
||||||
}) {
|
}) {
|
||||||
if (width === 0 || height === 0) {
|
if (width === 0 || height === 0) {
|
||||||
@ -637,6 +644,32 @@ export class EngineCommandManager {
|
|||||||
onEngineConnectionOpen: () => {
|
onEngineConnectionOpen: () => {
|
||||||
this.resolveReady()
|
this.resolveReady()
|
||||||
setIsStreamReady(true)
|
setIsStreamReady(true)
|
||||||
|
|
||||||
|
// Make the axis gizmo.
|
||||||
|
// We do this after the connection opened to avoid a race condition.
|
||||||
|
// Connected opened is the last thing that happens when the stream
|
||||||
|
// is ready.
|
||||||
|
// We also do this here because we want to ensure we create the gizmo
|
||||||
|
// and execute the code everytime the stream is restarted.
|
||||||
|
const gizmoId = uuidv4()
|
||||||
|
this.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: gizmoId,
|
||||||
|
cmd: {
|
||||||
|
type: 'make_axes_gizmo',
|
||||||
|
clobber: false,
|
||||||
|
// If true, axes gizmo will be placed in the corner of the screen.
|
||||||
|
// If false, it will be placed at the origin of the scene.
|
||||||
|
gizmo_mode: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// We execute the code here to make sure if the stream was to
|
||||||
|
// restart in a session, we want to make sure to execute the code.
|
||||||
|
// We force it to re-execute the code because we want to make sure
|
||||||
|
// the code is executed everytime the stream is restarted.
|
||||||
|
// We pass undefined for the code so it reads from the current state.
|
||||||
|
executeCode(undefined, true)
|
||||||
},
|
},
|
||||||
onClose: () => {
|
onClose: () => {
|
||||||
setIsStreamReady(false)
|
setIsStreamReady(false)
|
||||||
@ -733,10 +766,6 @@ export class EngineCommandManager {
|
|||||||
this.engineConnection?.send(resizeCmd)
|
this.engineConnection?.send(resizeCmd)
|
||||||
}
|
}
|
||||||
handleModelingCommand(message: WebSocketResponse, id: string) {
|
handleModelingCommand(message: WebSocketResponse, id: string) {
|
||||||
if (this.engineConnection === undefined) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.type !== 'modeling') {
|
if (message.type !== 'modeling') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -904,6 +933,11 @@ export class EngineCommandManager {
|
|||||||
if (this.engineConnection === undefined) {
|
if (this.engineConnection === undefined) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.engineConnection?.isReady()) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
command.type === 'modeling_cmd_req' &&
|
command.type === 'modeling_cmd_req' &&
|
||||||
command.cmd.type !== lastMessage
|
command.cmd.type !== lastMessage
|
||||||
@ -911,9 +945,6 @@ export class EngineCommandManager {
|
|||||||
console.log('sending command', command.cmd.type)
|
console.log('sending command', command.cmd.type)
|
||||||
lastMessage = command.cmd.type
|
lastMessage = command.cmd.type
|
||||||
}
|
}
|
||||||
if (!this.engineConnection?.isReady()) {
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
if (command.type !== 'modeling_cmd_req') return Promise.resolve()
|
if (command.type !== 'modeling_cmd_req') return Promise.resolve()
|
||||||
const cmd = command.cmd
|
const cmd = command.cmd
|
||||||
if (
|
if (
|
||||||
|
@ -79,6 +79,7 @@ export async function executor(
|
|||||||
setMediaStream: () => {},
|
setMediaStream: () => {},
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
|
executeCode: () => {},
|
||||||
})
|
})
|
||||||
await engineCommandManager.waitForReady
|
await engineCommandManager.waitForReady
|
||||||
engineCommandManager.startNewSession()
|
engineCommandManager.startNewSession()
|
||||||
|
@ -157,7 +157,7 @@ export interface StoreState {
|
|||||||
code: string
|
code: string
|
||||||
setCode: (code: string) => void
|
setCode: (code: string) => void
|
||||||
deferredSetCode: (code: string) => void
|
deferredSetCode: (code: string) => void
|
||||||
executeCode: (code?: string) => void
|
executeCode: (code?: string, force?: boolean) => void
|
||||||
formatCode: () => void
|
formatCode: () => void
|
||||||
programMemory: ProgramMemory
|
programMemory: ProgramMemory
|
||||||
setProgramMemory: (programMemory: ProgramMemory) => void
|
setProgramMemory: (programMemory: ProgramMemory) => void
|
||||||
@ -221,11 +221,12 @@ export const useStore = create<StoreState>()(
|
|||||||
editorView.dispatch({ effects: addLineHighlight.of(selection) })
|
editorView.dispatch({ effects: addLineHighlight.of(selection) })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
executeCode: async (code) => {
|
executeCode: async (code, force) => {
|
||||||
const result = await executeCode({
|
const result = await executeCode({
|
||||||
code: code || get().code,
|
code: code || get().code,
|
||||||
lastAst: get().ast,
|
lastAst: get().ast,
|
||||||
engineCommandManager: engineCommandManager,
|
engineCommandManager: engineCommandManager,
|
||||||
|
force,
|
||||||
})
|
})
|
||||||
if (!result.isChange) {
|
if (!result.isChange) {
|
||||||
return
|
return
|
||||||
@ -511,10 +512,12 @@ async function executeCode({
|
|||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
code,
|
code,
|
||||||
lastAst,
|
lastAst,
|
||||||
|
force,
|
||||||
}: {
|
}: {
|
||||||
code: string
|
code: string
|
||||||
lastAst: Program
|
lastAst: Program
|
||||||
engineCommandManager: EngineCommandManager
|
engineCommandManager: EngineCommandManager
|
||||||
|
force?: boolean
|
||||||
}): Promise<
|
}): Promise<
|
||||||
| {
|
| {
|
||||||
logs: string[]
|
logs: string[]
|
||||||
@ -557,7 +560,7 @@ async function executeCode({
|
|||||||
}
|
}
|
||||||
// Check if the ast we have is equal to the ast in the storage.
|
// Check if the ast we have is equal to the ast in the storage.
|
||||||
// If it is, we don't need to update the ast.
|
// If it is, we don't need to update the ast.
|
||||||
if (JSON.stringify(ast) === JSON.stringify(lastAst))
|
if (JSON.stringify(ast) === JSON.stringify(lastAst) && !force)
|
||||||
return { isChange: false }
|
return { isChange: false }
|
||||||
|
|
||||||
const { logs, errors, programMemory } = await executeAst({
|
const { logs, errors, programMemory } = await executeAst({
|
||||||
|
Reference in New Issue
Block a user