Fix up everything after bumping kittycad/lib
This commit is contained in:
@ -105,12 +105,7 @@ export class CameraControls {
|
|||||||
wasDragging: boolean
|
wasDragging: boolean
|
||||||
mouseDownPosition: Vector2
|
mouseDownPosition: Vector2
|
||||||
mouseNewPosition: Vector2
|
mouseNewPosition: Vector2
|
||||||
old:
|
oldCameraState: undefined | CameraViewState_type
|
||||||
| {
|
|
||||||
camera: PerspectiveCamera | OrthographicCamera
|
|
||||||
target: Vector3
|
|
||||||
}
|
|
||||||
| undefined
|
|
||||||
rotationSpeed = 0.3
|
rotationSpeed = 0.3
|
||||||
enableRotate = true
|
enableRotate = true
|
||||||
enablePan = true
|
enablePan = true
|
||||||
@ -281,7 +276,7 @@ export class CameraControls {
|
|||||||
|
|
||||||
const cb = ({ data, type }: CallBackParam) => {
|
const cb = ({ data, type }: CallBackParam) => {
|
||||||
// We're reconnecting, so ignore this init proces.
|
// We're reconnecting, so ignore this init proces.
|
||||||
if (this.old) {
|
if (this.oldCameraState) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,26 +964,40 @@ export class CameraControls {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async restoreCameraPosition(): Promise<void> {
|
async restoreRemoteCameraStateAndTriggerSync() {
|
||||||
if (!this.old) return
|
if (!this.oldCameraState) return
|
||||||
|
|
||||||
this.camera = this.old.camera.clone()
|
await this.engineCommandManager.sendSceneCommand({
|
||||||
this.target = this.old.target.clone()
|
|
||||||
|
|
||||||
void this.engineCommandManager.sendSceneCommand({
|
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
cmd: {
|
cmd: {
|
||||||
type: 'default_camera_look_at',
|
type: 'default_camera_set_view',
|
||||||
...convertThreeCamValuesToEngineCam({
|
view: this.oldCameraState,
|
||||||
isPerspective: true,
|
|
||||||
position: this.camera.position,
|
|
||||||
quaternion: this.camera.quaternion,
|
|
||||||
zoom: this.camera.zoom,
|
|
||||||
target: this.target,
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await this.engineCommandManager.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'default_camera_get_settings',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveRemoteCameraState() {
|
||||||
|
const cameraViewStateResponse = await this.engineCommandManager.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: { type: 'default_camera_get_view' },
|
||||||
|
})
|
||||||
|
if (!cameraViewStateResponse) return
|
||||||
|
if ('resp' in cameraViewStateResponse
|
||||||
|
&& 'modeling_response' in cameraViewStateResponse.resp.data
|
||||||
|
&& 'data' in cameraViewStateResponse.resp.data.modeling_response
|
||||||
|
&& 'view' in cameraViewStateResponse.resp.data.modeling_response.data) {
|
||||||
|
this.oldCameraState = cameraViewStateResponse.resp.data.modeling_response.data.view
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async tweenCameraToQuaternion(
|
async tweenCameraToQuaternion(
|
||||||
|
@ -16,13 +16,16 @@ import { getArtifactOfTypes } from 'lang/std/artifactGraph'
|
|||||||
import { ViewControlContextMenu } from './ViewControlMenu'
|
import { ViewControlContextMenu } from './ViewControlMenu'
|
||||||
import { useSettings, engineStreamActor } from 'machines/appMachine'
|
import { useSettings, engineStreamActor } from 'machines/appMachine'
|
||||||
import { commandBarActor, useCommandBarState } from 'machines/commandBarMachine'
|
import { commandBarActor, useCommandBarState } from 'machines/commandBarMachine'
|
||||||
import { EngineStreamState, EngineStreamTransition } from 'machines/engineStreamMachine'
|
import {
|
||||||
|
EngineStreamState,
|
||||||
|
EngineStreamTransition,
|
||||||
|
} from 'machines/engineStreamMachine'
|
||||||
import { useSelector } from '@xstate/react'
|
import { useSelector } from '@xstate/react'
|
||||||
import { REASONABLE_TIME_TO_REFRESH_STREAM_SIZE } from 'lib/timings'
|
import { REASONABLE_TIME_TO_REFRESH_STREAM_SIZE } from 'lib/timings'
|
||||||
|
|
||||||
export const EngineStream = (props: {
|
export const EngineStream = (props: {
|
||||||
pool: string | null,
|
pool: string | null
|
||||||
authToken: string | undefined,
|
authToken: string | undefined
|
||||||
}) => {
|
}) => {
|
||||||
const { setAppState } = useAppState()
|
const { setAppState } = useAppState()
|
||||||
|
|
||||||
@ -97,6 +100,22 @@ export const EngineStream = (props: {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// In the past we'd try to play immediately, but the proper thing is to way
|
||||||
|
// for the 'canplay' event to tell us data is ready.
|
||||||
|
useEffect(() => {
|
||||||
|
const videoRef = engineStreamState.context.videoRef.current
|
||||||
|
if (!videoRef) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const play = () => {
|
||||||
|
videoRef.play().catch(console.error)
|
||||||
|
}
|
||||||
|
videoRef.addEventListener('canplay', play)
|
||||||
|
return () => {
|
||||||
|
videoRef.removeEventListener('canplay', play)
|
||||||
|
}
|
||||||
|
}, [engineStreamState.context.videoRef.current])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (engineStreamState.value === EngineStreamState.Reconfiguring) return
|
if (engineStreamState.value === EngineStreamState.Reconfiguring) return
|
||||||
const video = engineStreamState.context.videoRef?.current
|
const video = engineStreamState.context.videoRef?.current
|
||||||
@ -105,17 +124,21 @@ export const EngineStream = (props: {
|
|||||||
if (!canvas) return
|
if (!canvas) return
|
||||||
|
|
||||||
new ResizeObserver(() => {
|
new ResizeObserver(() => {
|
||||||
if (Date.now() - last.current < REASONABLE_TIME_TO_REFRESH_STREAM_SIZE)
|
// Prevents:
|
||||||
return
|
// `Uncaught ResizeObserver loop completed with undelivered notifications`
|
||||||
last.current = Date.now()
|
window.requestAnimationFrame(() => {
|
||||||
|
if (Date.now() - last.current < REASONABLE_TIME_TO_REFRESH_STREAM_SIZE)
|
||||||
|
return
|
||||||
|
last.current = Date.now()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
Math.abs(video.width - window.innerWidth) > 4 ||
|
Math.abs(video.width - window.innerWidth) > 4 ||
|
||||||
Math.abs(video.height - window.innerHeight) > 4
|
Math.abs(video.height - window.innerHeight) > 4
|
||||||
) {
|
) {
|
||||||
timeoutStart.current = Date.now()
|
timeoutStart.current = Date.now()
|
||||||
startOrReconfigureEngine()
|
startOrReconfigureEngine()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}).observe(document.body)
|
}).observe(document.body)
|
||||||
}, [engineStreamState.value])
|
}, [engineStreamState.value])
|
||||||
|
|
||||||
@ -262,7 +285,7 @@ export const EngineStream = (props: {
|
|||||||
|
|
||||||
if (btnName(e.nativeEvent).left) {
|
if (btnName(e.nativeEvent).left) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
sendSelectEventToEngine(e, engineStreamState.context.videoRef.current)
|
sendSelectEventToEngine(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +307,7 @@ export const EngineStream = (props: {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sendSelectEventToEngine(e, engineStreamState.context.videoRef.current)
|
sendSelectEventToEngine(e)
|
||||||
.then(({ entity_id }) => {
|
.then(({ entity_id }) => {
|
||||||
if (!entity_id) {
|
if (!entity_id) {
|
||||||
// No entity selected. This is benign
|
// No entity selected. This is benign
|
||||||
|
@ -1,183 +0,0 @@
|
|||||||
import { useAppState, useAppStream } from '@src/AppState'
|
|
||||||
import { useEffect, useLayoutEffect, useRef } from 'react'
|
|
||||||
|
|
||||||
import type { useModelingContext } from '@src/hooks/useModelingContext'
|
|
||||||
import { useNetworkContext } from '@src/hooks/useNetworkContext'
|
|
||||||
import {
|
|
||||||
DisconnectingType,
|
|
||||||
EngineConnectionStateType,
|
|
||||||
} from '@src/lang/std/engineConnection'
|
|
||||||
import type { SettingsViaQueryString } from '@src/lib/settings/settingsTypes'
|
|
||||||
import { engineCommandManager } from '@src/lib/singletons'
|
|
||||||
import { Themes } from '@src/lib/theme'
|
|
||||||
import { deferExecution } from '@src/lib/utils'
|
|
||||||
|
|
||||||
export function useSetupEngineManager(
|
|
||||||
streamRef: React.RefObject<HTMLDivElement>,
|
|
||||||
modelingSend: ReturnType<typeof useModelingContext>['send'],
|
|
||||||
modelingContext: ReturnType<typeof useModelingContext>['context'],
|
|
||||||
settings: SettingsViaQueryString = {
|
|
||||||
pool: null,
|
|
||||||
theme: Themes.System,
|
|
||||||
highlightEdges: true,
|
|
||||||
enableSSAO: true,
|
|
||||||
showScaleGrid: false,
|
|
||||||
cameraProjection: 'perspective',
|
|
||||||
cameraOrbit: 'spherical',
|
|
||||||
},
|
|
||||||
token?: string
|
|
||||||
) {
|
|
||||||
const networkContext = useNetworkContext()
|
|
||||||
const { pingPongHealth, immediateState } = networkContext
|
|
||||||
const { setAppState } = useAppState()
|
|
||||||
const { setMediaStream } = useAppStream()
|
|
||||||
|
|
||||||
const hasSetNonZeroDimensions = useRef<boolean>(false)
|
|
||||||
|
|
||||||
if (settings.pool) {
|
|
||||||
// override the pool param (?pool=) to request a specific engine instance
|
|
||||||
// from a particular pool.
|
|
||||||
engineCommandManager.settings.pool = settings.pool
|
|
||||||
}
|
|
||||||
|
|
||||||
const startEngineInstance = () => {
|
|
||||||
// Load the engine command manager once with the initial width and height,
|
|
||||||
// then we do not want to reload it.
|
|
||||||
const { width: quadWidth, height: quadHeight } = getDimensions(
|
|
||||||
streamRef?.current?.offsetWidth ?? 0,
|
|
||||||
streamRef?.current?.offsetHeight ?? 0
|
|
||||||
)
|
|
||||||
engineCommandManager.start({
|
|
||||||
setMediaStream: (mediaStream) => setMediaStream(mediaStream),
|
|
||||||
setIsStreamReady: (isStreamReady) => setAppState({ isStreamReady }),
|
|
||||||
width: quadWidth,
|
|
||||||
height: quadHeight,
|
|
||||||
token,
|
|
||||||
settings,
|
|
||||||
})
|
|
||||||
hasSetNonZeroDimensions.current = true
|
|
||||||
}
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
const { width: quadWidth, height: quadHeight } = getDimensions(
|
|
||||||
streamRef?.current?.offsetWidth ?? 0,
|
|
||||||
streamRef?.current?.offsetHeight ?? 0
|
|
||||||
)
|
|
||||||
if (!hasSetNonZeroDimensions.current && quadHeight && quadWidth) {
|
|
||||||
startEngineInstance()
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
streamRef?.current?.offsetWidth,
|
|
||||||
streamRef?.current?.offsetHeight,
|
|
||||||
modelingSend,
|
|
||||||
])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (pingPongHealth === 'TIMEOUT') {
|
|
||||||
engineCommandManager.tearDown()
|
|
||||||
}
|
|
||||||
}, [pingPongHealth])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const intervalId = setInterval(() => {
|
|
||||||
if (immediateState.type === EngineConnectionStateType.Disconnected) {
|
|
||||||
engineCommandManager.engineConnection = undefined
|
|
||||||
startEngineInstance()
|
|
||||||
}
|
|
||||||
}, 3000)
|
|
||||||
return () => {
|
|
||||||
clearInterval(intervalId)
|
|
||||||
}
|
|
||||||
}, [immediateState])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
engineCommandManager.settings = settings
|
|
||||||
|
|
||||||
const handleResize = deferExecution(() => {
|
|
||||||
engineCommandManager.handleResize(
|
|
||||||
getDimensions(
|
|
||||||
streamRef?.current?.offsetWidth ?? 0,
|
|
||||||
streamRef?.current?.offsetHeight ?? 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}, 500)
|
|
||||||
|
|
||||||
const onOnline = () => {
|
|
||||||
startEngineInstance()
|
|
||||||
}
|
|
||||||
|
|
||||||
const onVisibilityChange = () => {
|
|
||||||
if (window.document.visibilityState === 'visible') {
|
|
||||||
if (
|
|
||||||
!engineCommandManager.engineConnection?.isReady() &&
|
|
||||||
!engineCommandManager.engineConnection?.isConnecting()
|
|
||||||
) {
|
|
||||||
startEngineInstance()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.document.addEventListener('visibilitychange', onVisibilityChange)
|
|
||||||
|
|
||||||
const onAnyInput = () => {
|
|
||||||
const isEngineNotReadyOrConnecting =
|
|
||||||
!engineCommandManager.engineConnection?.isReady() &&
|
|
||||||
!engineCommandManager.engineConnection?.isConnecting()
|
|
||||||
|
|
||||||
const conn = engineCommandManager.engineConnection
|
|
||||||
|
|
||||||
const isStreamPaused =
|
|
||||||
conn?.state.type === EngineConnectionStateType.Disconnecting &&
|
|
||||||
conn?.state.value.type === DisconnectingType.Pause
|
|
||||||
|
|
||||||
if (isEngineNotReadyOrConnecting || isStreamPaused) {
|
|
||||||
engineCommandManager.engineConnection = undefined
|
|
||||||
startEngineInstance()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.document.addEventListener('keydown', onAnyInput)
|
|
||||||
window.document.addEventListener('mousemove', onAnyInput)
|
|
||||||
window.document.addEventListener('mousedown', onAnyInput)
|
|
||||||
window.document.addEventListener('scroll', onAnyInput)
|
|
||||||
window.document.addEventListener('touchstart', onAnyInput)
|
|
||||||
|
|
||||||
const onOffline = () => {
|
|
||||||
engineCommandManager.tearDown()
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('online', onOnline)
|
|
||||||
window.addEventListener('offline', onOffline)
|
|
||||||
window.addEventListener('resize', handleResize)
|
|
||||||
return () => {
|
|
||||||
window.document.removeEventListener(
|
|
||||||
'visibilitychange',
|
|
||||||
onVisibilityChange
|
|
||||||
)
|
|
||||||
window.document.removeEventListener('keydown', onAnyInput)
|
|
||||||
window.document.removeEventListener('mousemove', onAnyInput)
|
|
||||||
window.document.removeEventListener('mousedown', onAnyInput)
|
|
||||||
window.document.removeEventListener('scroll', onAnyInput)
|
|
||||||
window.document.removeEventListener('touchstart', onAnyInput)
|
|
||||||
window.removeEventListener('online', onOnline)
|
|
||||||
window.removeEventListener('offline', onOffline)
|
|
||||||
window.removeEventListener('resize', handleResize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Engine relies on many settings so we should rebind events when it changes
|
|
||||||
// We have to list out the ones we care about because the settings object holds
|
|
||||||
// non-settings too...
|
|
||||||
}, [...Object.values(settings)])
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDimensions(streamWidth?: number, streamHeight?: number) {
|
|
||||||
const factorOf = 4
|
|
||||||
const maxResolution = 2000
|
|
||||||
const width = streamWidth ? streamWidth : 0
|
|
||||||
const height = streamHeight ? streamHeight : 0
|
|
||||||
const ratio = Math.min(
|
|
||||||
Math.min(maxResolution / width, maxResolution / height),
|
|
||||||
1.0
|
|
||||||
)
|
|
||||||
const quadWidth = Math.round((width * ratio) / factorOf) * factorOf
|
|
||||||
const quadHeight = Math.round((height * ratio) / factorOf) * factorOf
|
|
||||||
return { width: quadWidth, height: quadHeight }
|
|
||||||
}
|
|
@ -839,13 +839,6 @@ class EngineConnection extends EventTarget {
|
|||||||
|
|
||||||
this.engineCommandManager.inSequence = 1
|
this.engineCommandManager.inSequence = 1
|
||||||
|
|
||||||
// Bust the cache before anything
|
|
||||||
;(async () => {
|
|
||||||
await rustContext.clearSceneAndBustCache(
|
|
||||||
kclManager.engineCommandManager.settings
|
|
||||||
)
|
|
||||||
})().catch(reportRejection)
|
|
||||||
|
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CustomEvent(EngineConnectionEvents.Opened, { detail: this })
|
new CustomEvent(EngineConnectionEvents.Opened, { detail: this })
|
||||||
)
|
)
|
||||||
|
@ -43,11 +43,10 @@ describe(`testing settings initialization`, () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const projectConfiguration: DeepPartial<Configuration> = {
|
const projectConfiguration: DeepPartial<ProjectConfiguration> = {
|
||||||
settings: {
|
settings: {
|
||||||
app: {
|
app: {
|
||||||
appearance: {
|
appearance: {
|
||||||
theme: 'light',
|
|
||||||
color: 200,
|
color: 200,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -82,11 +81,10 @@ describe(`testing getAllCurrentSettings`, () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const projectConfiguration: DeepPartial<Configuration> = {
|
const projectConfiguration: DeepPartial<ProjectConfiguration> = {
|
||||||
settings: {
|
settings: {
|
||||||
app: {
|
app: {
|
||||||
appearance: {
|
appearance: {
|
||||||
theme: 'light',
|
|
||||||
color: 200,
|
color: 200,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -68,6 +68,6 @@ export const useSettings = () =>
|
|||||||
return settings
|
return settings
|
||||||
})
|
})
|
||||||
|
|
||||||
export const engineStreamActor = appActor.system.get(ENGINE_STREAM) as ActorRefFrom<
|
export const engineStreamActor = appActor.system.get(
|
||||||
typeof engineStreamMachine
|
ENGINE_STREAM
|
||||||
>
|
) as ActorRefFrom<typeof engineStreamMachine>
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
|
import { jsAppSettings } from 'lang/wasm'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
import { MutableRefObject } from 'react'
|
import { MutableRefObject } from 'react'
|
||||||
import { setup, assign, fromPromise } from 'xstate'
|
import { setup, assign, fromPromise } from 'xstate'
|
||||||
import { rustContext, kclManager, sceneInfra, engineCommandManager } from 'lib/singletons'
|
import {
|
||||||
|
rustContext,
|
||||||
|
kclManager,
|
||||||
|
sceneInfra,
|
||||||
|
engineCommandManager,
|
||||||
|
} from 'lib/singletons'
|
||||||
import { trap } from 'lib/trap'
|
import { trap } from 'lib/trap'
|
||||||
import { Vector3, Vector4 } from 'three'
|
import { Vector3, Vector4 } from 'three'
|
||||||
|
|
||||||
@ -39,7 +45,7 @@ export const engineStreamContextCreate = (): EngineStreamContext => ({
|
|||||||
pool: null,
|
pool: null,
|
||||||
authToken: undefined,
|
authToken: undefined,
|
||||||
mediaStream: null,
|
mediaStream: null,
|
||||||
videoRef: { current: null },
|
videoRef: { current: null },
|
||||||
canvasRef: { current: null },
|
canvasRef: { current: null },
|
||||||
zoomToFit: true,
|
zoomToFit: true,
|
||||||
})
|
})
|
||||||
@ -94,13 +100,28 @@ export const engineStreamMachine = setup({
|
|||||||
const mediaStream = context.mediaStream
|
const mediaStream = context.mediaStream
|
||||||
if (!mediaStream) return false
|
if (!mediaStream) return false
|
||||||
|
|
||||||
|
// If the video is already playing it means we're doing a reconfigure.
|
||||||
|
// We don't want to re-run the KCL or touch the video element at all.
|
||||||
|
if (!video.paused) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await sceneInfra.camControls.restoreRemoteCameraStateAndTriggerSync()
|
||||||
|
|
||||||
video.style.display = 'block'
|
video.style.display = 'block'
|
||||||
canvas.style.display = 'none'
|
canvas.style.display = 'none'
|
||||||
|
|
||||||
// await sceneInfra.camControls.restoreCameraPosition()
|
|
||||||
|
|
||||||
video.srcObject = mediaStream
|
video.srcObject = mediaStream
|
||||||
await video.play()
|
|
||||||
|
// Bust the cache before trying to execute since this may
|
||||||
|
// be a reconnection and if cache is not cleared, it
|
||||||
|
// will not reexecute.
|
||||||
|
// When calling cache before _any_ executions it errors, but non-fatal.
|
||||||
|
await rustContext
|
||||||
|
.clearSceneAndBustCache(
|
||||||
|
{ settings: await jsAppSettings() },
|
||||||
|
)
|
||||||
|
.catch(console.warn)
|
||||||
|
|
||||||
await kclManager.executeCode(params.zoomToFit)
|
await kclManager.executeCode(params.zoomToFit)
|
||||||
}
|
}
|
||||||
@ -120,19 +141,21 @@ export const engineStreamMachine = setup({
|
|||||||
if (!canvas) return
|
if (!canvas) return
|
||||||
|
|
||||||
await holdOntoVideoFrameInCanvas(video, canvas)
|
await holdOntoVideoFrameInCanvas(video, canvas)
|
||||||
|
video.style.display = 'none'
|
||||||
|
|
||||||
|
await sceneInfra.camControls.saveRemoteCameraState()
|
||||||
|
|
||||||
// Make sure we're on the next frame for no flickering between canvas
|
// Make sure we're on the next frame for no flickering between canvas
|
||||||
// and the video elements.
|
// and the video elements.
|
||||||
window.requestAnimationFrame(
|
window.requestAnimationFrame(
|
||||||
() =>
|
() =>
|
||||||
void (async () => {
|
void (async () => {
|
||||||
video.style.display = 'none'
|
|
||||||
|
|
||||||
// Destroy the media stream. We will re-establish it. We could
|
// Destroy the media stream. We will re-establish it. We could
|
||||||
// leave everything at pausing, preventing video decoders from running
|
// leave everything at pausing, preventing video decoders from running
|
||||||
// but we can do even better by significantly reducing network
|
// but we can do even better by significantly reducing network
|
||||||
// cards also.
|
// cards also.
|
||||||
context.mediaStream?.getVideoTracks()[0].stop()
|
context.mediaStream?.getVideoTracks()[0].stop()
|
||||||
|
context.mediaStream = null
|
||||||
video.srcObject = null
|
video.srcObject = null
|
||||||
|
|
||||||
engineCommandManager.tearDown({ idleMode: true })
|
engineCommandManager.tearDown({ idleMode: true })
|
||||||
@ -171,18 +194,10 @@ export const engineStreamMachine = setup({
|
|||||||
|
|
||||||
engineCommandManager.settings = settingsNext
|
engineCommandManager.settings = settingsNext
|
||||||
|
|
||||||
// If we don't pause there could be a really bad flicker
|
|
||||||
// on reconfiguration (resize, for example)
|
|
||||||
await holdOntoVideoFrameInCanvas(video, canvas)
|
|
||||||
canvas.style.display = 'block'
|
|
||||||
|
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
video.style.display = 'none'
|
|
||||||
engineCommandManager.start({
|
engineCommandManager.start({
|
||||||
setMediaStream: event.onMediaStream,
|
setMediaStream: event.onMediaStream,
|
||||||
setIsStreamReady: (isStreamReady) => {
|
setIsStreamReady: (isStreamReady) => {
|
||||||
video.style.display = 'block'
|
|
||||||
canvas.style.display = 'none'
|
|
||||||
event.setAppState({ isStreamReady })
|
event.setAppState({ isStreamReady })
|
||||||
},
|
},
|
||||||
width,
|
width,
|
||||||
@ -212,13 +227,11 @@ export const engineStreamMachine = setup({
|
|||||||
reenter: true,
|
reenter: true,
|
||||||
on: {
|
on: {
|
||||||
[EngineStreamTransition.SetPool]: {
|
[EngineStreamTransition.SetPool]: {
|
||||||
target: EngineStreamState.Setup,
|
target: EngineStreamState.Off,
|
||||||
actions: [
|
actions: [assign({ pool: ({ context, event }) => event.data.pool })],
|
||||||
assign({ pool: ({ context, event }) => event.data.pool }),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
[EngineStreamTransition.SetAuthToken]: {
|
[EngineStreamTransition.SetAuthToken]: {
|
||||||
target: EngineStreamState.Setup,
|
target: EngineStreamState.Off,
|
||||||
actions: [
|
actions: [
|
||||||
assign({ authToken: ({ context, event }) => event.data.authToken }),
|
assign({ authToken: ({ context, event }) => event.data.authToken }),
|
||||||
],
|
],
|
||||||
|
Reference in New Issue
Block a user