Make the stream idle option a slider for time
This commit is contained in:
@ -23,7 +23,10 @@ import {
|
|||||||
import { isDesktop } from 'lib/isDesktop'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
|
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
|
||||||
import { EngineConnectionStateType } from 'lang/std/engineConnection'
|
import { EngineConnectionStateType } from 'lang/std/engineConnection'
|
||||||
import useEngineStreamContext, { EngineStreamState, EngineStreamTransition } from 'hooks/useEngineStreamContext'
|
import useEngineStreamContext, {
|
||||||
|
EngineStreamState,
|
||||||
|
EngineStreamTransition,
|
||||||
|
} from 'hooks/useEngineStreamContext'
|
||||||
|
|
||||||
export function Toolbar({
|
export function Toolbar({
|
||||||
className = '',
|
className = '',
|
||||||
|
|||||||
@ -97,10 +97,12 @@ export class CameraControls {
|
|||||||
wasDragging: boolean
|
wasDragging: boolean
|
||||||
mouseDownPosition: Vector2
|
mouseDownPosition: Vector2
|
||||||
mouseNewPosition: Vector2
|
mouseNewPosition: Vector2
|
||||||
old: {
|
old:
|
||||||
camera: PerspectiveCamera,
|
| {
|
||||||
target: Vector3,
|
camera: PerspectiveCamera
|
||||||
} | undefined
|
target: Vector3
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
rotationSpeed = 0.3
|
rotationSpeed = 0.3
|
||||||
enableRotate = true
|
enableRotate = true
|
||||||
enablePan = true
|
enablePan = true
|
||||||
@ -960,7 +962,8 @@ export class CameraControls {
|
|||||||
// camera coordinates after a zoom-to-fit... So this is much easier, and
|
// camera coordinates after a zoom-to-fit... So this is much easier, and
|
||||||
// maps better to screen coordinates.
|
// maps better to screen coordinates.
|
||||||
|
|
||||||
await this.engineCommandManager.sendSceneCommand({
|
await this.engineCommandManager
|
||||||
|
.sendSceneCommand({
|
||||||
type: 'modeling_cmd_batch_req',
|
type: 'modeling_cmd_batch_req',
|
||||||
batch_id: uuidv4(),
|
batch_id: uuidv4(),
|
||||||
responses: true,
|
responses: true,
|
||||||
@ -971,7 +974,7 @@ export class CameraControls {
|
|||||||
cmd: {
|
cmd: {
|
||||||
type: 'zoom_to_fit',
|
type: 'zoom_to_fit',
|
||||||
object_ids: zoomObjectId ? [zoomObjectId] : [], // leave empty to zoom to all objects
|
object_ids: zoomObjectId ? [zoomObjectId] : [], // leave empty to zoom to all objects
|
||||||
padding: panesWidth > 0 ? (window.innerWidth / panesWidth) : 0.2, // padding around the objects
|
padding: panesWidth > 0 ? window.innerWidth / panesWidth : 0.2, // padding around the objects
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -995,11 +998,12 @@ export class CameraControls {
|
|||||||
},
|
},
|
||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
// engineCommandManager can't subscribe to batch responses so we'll send
|
// engineCommandManager can't subscribe to batch responses so we'll send
|
||||||
// this one off by its lonesome after.
|
// this one off by its lonesome after.
|
||||||
.then(() => this.engineCommandManager.sendSceneCommand({
|
.then(() =>
|
||||||
|
this.engineCommandManager.sendSceneCommand({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd: {
|
cmd: {
|
||||||
type: 'camera_drag_end',
|
type: 'camera_drag_end',
|
||||||
@ -1010,7 +1014,8 @@ export class CameraControls {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async tweenCameraToQuaternion(
|
async tweenCameraToQuaternion(
|
||||||
|
|||||||
@ -29,7 +29,9 @@ export const CommandBar = () => {
|
|||||||
}, [pathname])
|
}, [pathname])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (immediateState.type !== EngineConnectionStateType.ConnectionEstablished) {
|
if (
|
||||||
|
immediateState.type !== EngineConnectionStateType.ConnectionEstablished
|
||||||
|
) {
|
||||||
commandBarSend({ type: 'Close' })
|
commandBarSend({ type: 'Close' })
|
||||||
}
|
}
|
||||||
}, [immediateState])
|
}, [immediateState])
|
||||||
|
|||||||
@ -11,7 +11,8 @@ export function CommandBarOpenButton() {
|
|||||||
const { immediateState } = useNetworkContext()
|
const { immediateState } = useNetworkContext()
|
||||||
const platform = usePlatform()
|
const platform = usePlatform()
|
||||||
|
|
||||||
const isDisabled = immediateState.type !== EngineConnectionStateType.ConnectionEstablished
|
const isDisabled =
|
||||||
|
immediateState.type !== EngineConnectionStateType.ConnectionEstablished
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@ -9,13 +9,14 @@ import { btnName } from 'lib/cameraControls'
|
|||||||
import { trap } from 'lib/trap'
|
import { trap } from 'lib/trap'
|
||||||
import { sendSelectEventToEngine } from 'lib/selections'
|
import { sendSelectEventToEngine } from 'lib/selections'
|
||||||
import { kclManager, engineCommandManager } from 'lib/singletons'
|
import { kclManager, engineCommandManager } from 'lib/singletons'
|
||||||
import {
|
import { EngineCommandManagerEvents } from 'lang/std/engineConnection'
|
||||||
EngineCommandManagerEvents,
|
|
||||||
} from 'lang/std/engineConnection'
|
|
||||||
import { useRouteLoaderData } from 'react-router-dom'
|
import { useRouteLoaderData } from 'react-router-dom'
|
||||||
import { PATHS } from 'lib/paths'
|
import { PATHS } from 'lib/paths'
|
||||||
import { IndexLoaderData } from 'lib/types'
|
import { IndexLoaderData } from 'lib/types'
|
||||||
import useEngineStreamContext, { EngineStreamState, EngineStreamTransition } from 'hooks/useEngineStreamContext'
|
import useEngineStreamContext, {
|
||||||
|
EngineStreamState,
|
||||||
|
EngineStreamTransition,
|
||||||
|
} from 'hooks/useEngineStreamContext'
|
||||||
|
|
||||||
export const EngineStream = () => {
|
export const EngineStream = () => {
|
||||||
const { setAppState } = useAppState()
|
const { setAppState } = useAppState()
|
||||||
@ -57,9 +58,9 @@ export const EngineStream = () => {
|
|||||||
onMediaStream(mediaStream: MediaStream) {
|
onMediaStream(mediaStream: MediaStream) {
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
type: EngineStreamTransition.SetMediaStream,
|
type: EngineStreamTransition.SetMediaStream,
|
||||||
mediaStream
|
mediaStream,
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,11 +92,13 @@ export const EngineStream = () => {
|
|||||||
const canvas = engineStreamState.context.canvasRef?.current
|
const canvas = engineStreamState.context.canvasRef?.current
|
||||||
if (!canvas) return
|
if (!canvas) return
|
||||||
|
|
||||||
if (Math.abs(video.width - window.innerWidth) > 4 || Math.abs(video.height - window.innerHeight) > 4) {
|
if (
|
||||||
|
Math.abs(video.width - window.innerWidth) > 4 ||
|
||||||
|
Math.abs(video.height - window.innerHeight) > 4
|
||||||
|
) {
|
||||||
timeoutStart.current = Date.now()
|
timeoutStart.current = Date.now()
|
||||||
configure()
|
configure()
|
||||||
}
|
}
|
||||||
|
|
||||||
}, REASONABLE_TIME_TO_REFRESH_STREAM_SIZE)
|
}, REASONABLE_TIME_TO_REFRESH_STREAM_SIZE)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@ -105,7 +108,10 @@ export const EngineStream = () => {
|
|||||||
|
|
||||||
// When the video and canvas element references are set, start the engine.
|
// When the video and canvas element references are set, start the engine.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (engineStreamState.context.canvasRef.current && engineStreamState.context.videoRef.current) {
|
if (
|
||||||
|
engineStreamState.context.canvasRef.current &&
|
||||||
|
engineStreamState.context.videoRef.current
|
||||||
|
) {
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
type: EngineStreamTransition.StartOrReconfigureEngine,
|
type: EngineStreamTransition.StartOrReconfigureEngine,
|
||||||
modelingMachineActorSend,
|
modelingMachineActorSend,
|
||||||
@ -114,24 +120,30 @@ export const EngineStream = () => {
|
|||||||
onMediaStream(mediaStream: MediaStream) {
|
onMediaStream(mediaStream: MediaStream) {
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
type: EngineStreamTransition.SetMediaStream,
|
type: EngineStreamTransition.SetMediaStream,
|
||||||
mediaStream
|
mediaStream,
|
||||||
|
})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
}, [
|
||||||
}
|
engineStreamState.context.canvasRef.current,
|
||||||
}, [engineStreamState.context.canvasRef.current, engineStreamState.context.videoRef.current])
|
engineStreamState.context.videoRef.current,
|
||||||
|
])
|
||||||
|
|
||||||
// On settings change, reconfigure the engine. When paused this gets really tricky,
|
// On settings change, reconfigure the engine. When paused this gets really tricky,
|
||||||
// and also requires onMediaStream to be set!
|
// and also requires onMediaStream to be set!
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
type: EngineStreamTransition.StartOrReconfigureEngine, modelingMachineActorSend, settings: settingsEngine, setAppState,
|
type: EngineStreamTransition.StartOrReconfigureEngine,
|
||||||
|
modelingMachineActorSend,
|
||||||
|
settings: settingsEngine,
|
||||||
|
setAppState,
|
||||||
onMediaStream(mediaStream: MediaStream) {
|
onMediaStream(mediaStream: MediaStream) {
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
type: EngineStreamTransition.SetMediaStream,
|
type: EngineStreamTransition.SetMediaStream,
|
||||||
mediaStream
|
mediaStream,
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}, [settings.context])
|
}, [settings.context])
|
||||||
|
|
||||||
@ -147,7 +159,7 @@ export const EngineStream = () => {
|
|||||||
}
|
}
|
||||||
}, [file?.path, engineCommandManager.engineConnection])
|
}, [file?.path, engineCommandManager.engineConnection])
|
||||||
|
|
||||||
const IDLE_TIME_MS = 1000 * 6
|
const IDLE_TIME_MS = Number(streamIdleMode) * 1000 * 60
|
||||||
|
|
||||||
// When streamIdleMode is changed, setup or teardown the timeouts
|
// When streamIdleMode is changed, setup or teardown the timeouts
|
||||||
const timeoutStart = useRef<number | null>(null)
|
const timeoutStart = useRef<number | null>(null)
|
||||||
@ -200,9 +212,9 @@ export const EngineStream = () => {
|
|||||||
onMediaStream(mediaStream: MediaStream) {
|
onMediaStream(mediaStream: MediaStream) {
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
type: EngineStreamTransition.SetMediaStream,
|
type: EngineStreamTransition.SetMediaStream,
|
||||||
mediaStream
|
mediaStream,
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,12 +285,15 @@ export const EngineStream = () => {
|
|||||||
/>
|
/>
|
||||||
<canvas
|
<canvas
|
||||||
key={engineStreamActor.id + 'canvas'}
|
key={engineStreamActor.id + 'canvas'}
|
||||||
ref={engineStreamState.context.canvasRef} className="cursor-pointer" id="freeze-frame">No canvas support</canvas>
|
ref={engineStreamState.context.canvasRef}
|
||||||
|
className="cursor-pointer"
|
||||||
|
id="freeze-frame"
|
||||||
|
>
|
||||||
|
No canvas support
|
||||||
|
</canvas>
|
||||||
<ClientSideScene
|
<ClientSideScene
|
||||||
cameraControls={settings.context.modeling.mouseControls.current}
|
cameraControls={settings.context.modeling.mouseControls.current}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import { NetworkMachineIndicator } from './NetworkMachineIndicator'
|
|||||||
import { ModelStateIndicator } from './ModelStateIndicator'
|
import { ModelStateIndicator } from './ModelStateIndicator'
|
||||||
import { reportRejection } from 'lib/trap'
|
import { reportRejection } from 'lib/trap'
|
||||||
|
|
||||||
|
|
||||||
export function LowerRightControls({
|
export function LowerRightControls({
|
||||||
children,
|
children,
|
||||||
coreDumpManager,
|
coreDumpManager,
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useEngineCommands } from './EngineCommands'
|
import { useEngineCommands } from './EngineCommands'
|
||||||
import { CustomIcon } from './CustomIcon'
|
import { CustomIcon } from './CustomIcon'
|
||||||
import useEngineStreamContext, { EngineStreamState } from 'hooks/useEngineStreamContext'
|
import useEngineStreamContext, {
|
||||||
|
EngineStreamState,
|
||||||
|
} from 'hooks/useEngineStreamContext'
|
||||||
|
|
||||||
export const ModelStateIndicator = () => {
|
export const ModelStateIndicator = () => {
|
||||||
const [commands] = useEngineCommands()
|
const [commands] = useEngineCommands()
|
||||||
@ -26,26 +28,13 @@ export const ModelStateIndicator = () => {
|
|||||||
let dataTestId = 'model-state-indicator'
|
let dataTestId = 'model-state-indicator'
|
||||||
|
|
||||||
if (engineStreamState.value === EngineStreamState.Paused) {
|
if (engineStreamState.value === EngineStreamState.Paused) {
|
||||||
className +=
|
className += 'text-secondary'
|
||||||
'text-secondary'
|
icon = <CustomIcon data-testid={dataTestId + '-paused'} name="parallel" />
|
||||||
icon = (
|
|
||||||
<CustomIcon
|
|
||||||
data-testid={dataTestId + '-paused'}
|
|
||||||
name="parallel"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
} else if (engineStreamState.value === EngineStreamState.Resuming) {
|
} else if (engineStreamState.value === EngineStreamState.Resuming) {
|
||||||
className +=
|
className += 'text-secondary'
|
||||||
'text-secondary'
|
icon = <CustomIcon data-testid={dataTestId + '-resuming'} name="parallel" />
|
||||||
icon = (
|
|
||||||
<CustomIcon
|
|
||||||
data-testid={dataTestId + '-resuming'}
|
|
||||||
name="parallel"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
} else if (isDone) {
|
} else if (isDone) {
|
||||||
className +=
|
className += 'text-secondary'
|
||||||
'text-secondary'
|
|
||||||
icon = (
|
icon = (
|
||||||
<CustomIcon
|
<CustomIcon
|
||||||
data-testid={dataTestId + '-execution-done'}
|
data-testid={dataTestId + '-execution-done'}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
useContext,
|
useContext,
|
||||||
MutableRefObject,
|
MutableRefObject,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
} from 'react'm
|
} from 'react'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import { SidebarAction, SidebarType, sidebarPanes } from './ModelingPanes'
|
import { SidebarAction, SidebarType, sidebarPanes } from './ModelingPanes'
|
||||||
import Tooltip from 'components/Tooltip'
|
import Tooltip from 'components/Tooltip'
|
||||||
@ -25,7 +25,7 @@ import { useKclContext } from 'lang/KclProvider'
|
|||||||
import { MachineManagerContext } from 'components/MachineManagerProvider'
|
import { MachineManagerContext } from 'components/MachineManagerProvider'
|
||||||
|
|
||||||
interface ModelingSidebarProps {
|
interface ModelingSidebarProps {
|
||||||
paneOpacity: '' | 'opacity-20' | 'opacity-40',
|
paneOpacity: '' | 'opacity-20' | 'opacity-40'
|
||||||
ref: MutableRefObject<HTMLDivElement>
|
ref: MutableRefObject<HTMLDivElement>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,10 @@ function getPlatformString(): 'web' | 'desktop' {
|
|||||||
return isDesktop() ? 'desktop' : 'web'
|
return isDesktop() ? 'desktop' : 'web'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ModelingSidebar = forwardRef(function ModelingSidebar({ paneOpacity }: ModelingSidebarProps, ref) {
|
export const ModelingSidebar = forwardRef(function ModelingSidebar(
|
||||||
|
{ paneOpacity }: ModelingSidebarProps,
|
||||||
|
ref
|
||||||
|
) {
|
||||||
const machineManager = useContext(MachineManagerContext)
|
const machineManager = useContext(MachineManagerContext)
|
||||||
const { commandBarSend } = useCommandsContext()
|
const { commandBarSend } = useCommandsContext()
|
||||||
const kclContext = useKclContext()
|
const kclContext = useKclContext()
|
||||||
|
|||||||
@ -22,11 +22,11 @@ export enum EngineStreamTransition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface EngineStreamContext {
|
export interface EngineStreamContext {
|
||||||
pool: string | null,
|
pool: string | null
|
||||||
authToken: string | null,
|
authToken: string | null
|
||||||
mediaStream: MediaStream | null,
|
mediaStream: MediaStream | null
|
||||||
videoRef: MutableRefObject<HTMLVideoElement | null>,
|
videoRef: MutableRefObject<HTMLVideoElement | null>
|
||||||
canvasRef: MutableRefObject<HTMLCanvasElement | null>,
|
canvasRef: MutableRefObject<HTMLCanvasElement | null>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDimensions(streamWidth: number, streamHeight: number) {
|
export function getDimensions(streamWidth: number, streamHeight: number) {
|
||||||
@ -57,11 +57,12 @@ const engineStreamMachine = setup({
|
|||||||
const mediaStream = context.mediaStream
|
const mediaStream = context.mediaStream
|
||||||
if (!mediaStream) return false
|
if (!mediaStream) return false
|
||||||
|
|
||||||
video.style.display = "block"
|
video.style.display = 'block'
|
||||||
canvas.style.display = "none"
|
canvas.style.display = 'none'
|
||||||
|
|
||||||
video.srcObject = mediaStream
|
video.srcObject = mediaStream
|
||||||
void sceneInfra.camControls.restoreCameraPosition()
|
void sceneInfra.camControls
|
||||||
|
.restoreCameraPosition()
|
||||||
.then(() => video.play())
|
.then(() => video.play())
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.warn('Video playing was prevented', e, video)
|
console.warn('Video playing was prevented', e, video)
|
||||||
@ -82,9 +83,9 @@ const engineStreamMachine = setup({
|
|||||||
canvas.height = video.videoHeight
|
canvas.height = video.videoHeight
|
||||||
canvas.style.width = video.videoWidth + 'px'
|
canvas.style.width = video.videoWidth + 'px'
|
||||||
canvas.style.height = video.videoHeight + 'px'
|
canvas.style.height = video.videoHeight + 'px'
|
||||||
canvas.style.display = "block"
|
canvas.style.display = 'block'
|
||||||
|
|
||||||
const ctx = canvas.getContext("2d")
|
const ctx = canvas.getContext('2d')
|
||||||
if (!ctx) return
|
if (!ctx) return
|
||||||
|
|
||||||
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
|
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
|
||||||
@ -92,7 +93,7 @@ const engineStreamMachine = setup({
|
|||||||
// 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(() => {
|
||||||
video.style.display = "none"
|
video.style.display = 'none'
|
||||||
|
|
||||||
// Destroy the media stream only. We will re-establish it. We could
|
// Destroy the media stream only. 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
|
||||||
@ -103,13 +104,16 @@ const engineStreamMachine = setup({
|
|||||||
|
|
||||||
sceneInfra.camControls.old = {
|
sceneInfra.camControls.old = {
|
||||||
camera: sceneInfra.camControls.camera.clone(),
|
camera: sceneInfra.camControls.camera.clone(),
|
||||||
target: sceneInfra.camControls.target.clone()
|
target: sceneInfra.camControls.target.clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
engineCommandManager.tearDown({ idleMode: true })
|
engineCommandManager.tearDown({ idleMode: true })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async [EngineStreamTransition.StartOrReconfigureEngine]({ context, event }) {
|
async [EngineStreamTransition.StartOrReconfigureEngine]({
|
||||||
|
context,
|
||||||
|
event,
|
||||||
|
}) {
|
||||||
if (!context.authToken) return
|
if (!context.authToken) return
|
||||||
|
|
||||||
const video = context.videoRef.current
|
const video = context.videoRef.current
|
||||||
@ -117,7 +121,7 @@ const engineStreamMachine = setup({
|
|||||||
|
|
||||||
const { width, height } = getDimensions(
|
const { width, height } = getDimensions(
|
||||||
window.innerWidth,
|
window.innerWidth,
|
||||||
window.innerHeight,
|
window.innerHeight
|
||||||
)
|
)
|
||||||
|
|
||||||
video.width = width
|
video.width = width
|
||||||
@ -134,7 +138,8 @@ const engineStreamMachine = setup({
|
|||||||
|
|
||||||
engineCommandManager.start({
|
engineCommandManager.start({
|
||||||
setMediaStream: event.onMediaStream,
|
setMediaStream: event.onMediaStream,
|
||||||
setIsStreamReady: (isStreamReady) => event.setAppState({ isStreamReady }),
|
setIsStreamReady: (isStreamReady) =>
|
||||||
|
event.setAppState({ isStreamReady }),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
token: context.authToken,
|
token: context.authToken,
|
||||||
@ -160,8 +165,8 @@ const engineStreamMachine = setup({
|
|||||||
async [EngineStreamTransition.Resume]({ context, event }) {
|
async [EngineStreamTransition.Resume]({ context, event }) {
|
||||||
// engineCommandManager.engineConnection?.reattachMediaStream()
|
// engineCommandManager.engineConnection?.reattachMediaStream()
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}).createMachine({
|
}).createMachine({
|
||||||
context: (initial) => initial.input,
|
context: (initial) => initial.input,
|
||||||
initial: EngineStreamState.Off,
|
initial: EngineStreamState.Off,
|
||||||
states: {
|
states: {
|
||||||
@ -169,58 +174,64 @@ const engineStreamMachine = setup({
|
|||||||
on: {
|
on: {
|
||||||
[EngineStreamTransition.StartOrReconfigureEngine]: {
|
[EngineStreamTransition.StartOrReconfigureEngine]: {
|
||||||
target: EngineStreamState.On,
|
target: EngineStreamState.On,
|
||||||
actions: [{ type: EngineStreamTransition.StartOrReconfigureEngine } ]
|
actions: [{ type: EngineStreamTransition.StartOrReconfigureEngine }],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
[EngineStreamState.On]: {
|
[EngineStreamState.On]: {
|
||||||
on: {
|
on: {
|
||||||
[EngineStreamTransition.SetMediaStream]: {
|
[EngineStreamTransition.SetMediaStream]: {
|
||||||
target: EngineStreamState.On,
|
target: EngineStreamState.On,
|
||||||
actions: [ assign({ mediaStream: ({ context, event }) => event.mediaStream }) ]
|
actions: [
|
||||||
|
assign({ mediaStream: ({ context, event }) => event.mediaStream }),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
[EngineStreamTransition.Play]: {
|
[EngineStreamTransition.Play]: {
|
||||||
target: EngineStreamState.Playing,
|
target: EngineStreamState.Playing,
|
||||||
actions: [ { type: EngineStreamTransition.Play, params: { zoomToFit: true }} ]
|
actions: [
|
||||||
}
|
{ type: EngineStreamTransition.Play, params: { zoomToFit: true } },
|
||||||
}
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
[EngineStreamState.Playing]: {
|
[EngineStreamState.Playing]: {
|
||||||
on: {
|
on: {
|
||||||
[EngineStreamTransition.StartOrReconfigureEngine]: {
|
[EngineStreamTransition.StartOrReconfigureEngine]: {
|
||||||
target: EngineStreamState.Playing,
|
target: EngineStreamState.Playing,
|
||||||
reenter: true,
|
reenter: true,
|
||||||
actions: [{ type: EngineStreamTransition.StartOrReconfigureEngine } ]
|
actions: [{ type: EngineStreamTransition.StartOrReconfigureEngine }],
|
||||||
},
|
},
|
||||||
[EngineStreamTransition.Pause]: {
|
[EngineStreamTransition.Pause]: {
|
||||||
target: EngineStreamState.Paused,
|
target: EngineStreamState.Paused,
|
||||||
actions: [ { type: EngineStreamTransition.Pause } ]
|
actions: [{ type: EngineStreamTransition.Pause }],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
[EngineStreamState.Paused]: {
|
[EngineStreamState.Paused]: {
|
||||||
on: {
|
on: {
|
||||||
[EngineStreamTransition.StartOrReconfigureEngine]: {
|
[EngineStreamTransition.StartOrReconfigureEngine]: {
|
||||||
target: EngineStreamState.Resuming,
|
target: EngineStreamState.Resuming,
|
||||||
actions: [{ type: EngineStreamTransition.StartOrReconfigureEngine } ]
|
actions: [{ type: EngineStreamTransition.StartOrReconfigureEngine }],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[EngineStreamState.Resuming]: {
|
[EngineStreamState.Resuming]: {
|
||||||
on: {
|
on: {
|
||||||
[EngineStreamTransition.SetMediaStream]: {
|
[EngineStreamTransition.SetMediaStream]: {
|
||||||
target: EngineStreamState.Resuming,
|
target: EngineStreamState.Resuming,
|
||||||
actions: [ assign({ mediaStream: ({ context, event }) => event.mediaStream }) ]
|
actions: [
|
||||||
|
assign({ mediaStream: ({ context, event }) => event.mediaStream }),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
[EngineStreamTransition.Play]: {
|
[EngineStreamTransition.Play]: {
|
||||||
target: EngineStreamState.Playing,
|
target: EngineStreamState.Playing,
|
||||||
actions: [ { type: EngineStreamTransition.Play, params: { zoomToFit: false }} ]
|
actions: [
|
||||||
}
|
{ type: EngineStreamTransition.Play, params: { zoomToFit: false } },
|
||||||
}
|
],
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
})
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
export default createActorContext(engineStreamMachine)
|
export default createActorContext(engineStreamMachine)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -404,7 +404,8 @@ class EngineConnection extends EventTarget {
|
|||||||
default:
|
default:
|
||||||
if (this.isConnecting()) break
|
if (this.isConnecting()) break
|
||||||
// Means we never could do an initial connection. Reconnect everything.
|
// Means we never could do an initial connection. Reconnect everything.
|
||||||
if (!this.pingPongSpan.ping) this.connect({ reconnect: false }).catch(reportRejection)
|
if (!this.pingPongSpan.ping)
|
||||||
|
this.connect({ reconnect: false }).catch(reportRejection)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}, pingIntervalMs)
|
}, pingIntervalMs)
|
||||||
@ -542,7 +543,6 @@ class EngineConnection extends EventTarget {
|
|||||||
type: DisconnectingType.Quit,
|
type: DisconnectingType.Quit,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -181,13 +181,46 @@ export function createSettings() {
|
|||||||
/**
|
/**
|
||||||
* Stream resource saving behavior toggle
|
* Stream resource saving behavior toggle
|
||||||
*/
|
*/
|
||||||
streamIdleMode: new Setting<boolean>({
|
streamIdleMode: new Setting<number | null>({
|
||||||
defaultValue: false,
|
defaultValue: null,
|
||||||
description: 'Toggle stream idling, saving bandwidth and battery',
|
description: 'Toggle stream idling, saving bandwidth and battery',
|
||||||
validate: (v) => typeof v === 'boolean',
|
validate: (v) =>
|
||||||
commandConfig: {
|
v === null ||
|
||||||
inputType: 'boolean',
|
(typeof v === 'number' &&
|
||||||
},
|
Number(v) >= 0 &&
|
||||||
|
Number(v) <= 60),
|
||||||
|
Component: ({ value, updateValue }) => (
|
||||||
|
<div className="flex item-center gap-4 px-2 m-0 py-0">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={value !== null}
|
||||||
|
onChange={(e) => updateValue(!e.currentTarget.checked ? null : 5)}
|
||||||
|
className="block w-4 h-4"
|
||||||
|
/>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col grow">
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
onChange={(e) =>
|
||||||
|
updateValue(parseInt(e.currentTarget.value))
|
||||||
|
}
|
||||||
|
disabled={value === null}
|
||||||
|
value={value}
|
||||||
|
min={1}
|
||||||
|
max={60}
|
||||||
|
step={1}
|
||||||
|
className="block flex-1"
|
||||||
|
/>
|
||||||
|
{ value !== null &&
|
||||||
|
<div>
|
||||||
|
{value === 60 ? '1 hour' : value === 1 ? '1 minute' : value + ' minutes'}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
onboardingStatus: new Setting<string>({
|
onboardingStatus: new Setting<string>({
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
|
|||||||
@ -121,7 +121,7 @@ pub struct AppSettings {
|
|||||||
pub dismiss_web_banner: bool,
|
pub dismiss_web_banner: bool,
|
||||||
/// When the user is idle, and this is true, the stream will be torn down.
|
/// When the user is idle, and this is true, the stream will be torn down.
|
||||||
#[serde(default, alias = "streamIdleMode", skip_serializing_if = "is_default")]
|
#[serde(default, alias = "streamIdleMode", skip_serializing_if = "is_default")]
|
||||||
stream_idle_mode: bool,
|
stream_idle_mode: Option<FloatOrInt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: When we remove backwards compatibility with the old settings file, we can remove this.
|
// TODO: When we remove backwards compatibility with the old settings file, we can remove this.
|
||||||
@ -582,7 +582,7 @@ textWrapping = true
|
|||||||
theme_color: None,
|
theme_color: None,
|
||||||
dismiss_web_banner: false,
|
dismiss_web_banner: false,
|
||||||
enable_ssao: None,
|
enable_ssao: None,
|
||||||
stream_idle_mode: false,
|
stream_idle_mode: None,
|
||||||
},
|
},
|
||||||
modeling: ModelingSettings {
|
modeling: ModelingSettings {
|
||||||
base_unit: UnitLength::In,
|
base_unit: UnitLength::In,
|
||||||
@ -643,7 +643,7 @@ includeSettings = false
|
|||||||
theme_color: None,
|
theme_color: None,
|
||||||
dismiss_web_banner: false,
|
dismiss_web_banner: false,
|
||||||
enable_ssao: None,
|
enable_ssao: None,
|
||||||
stream_idle_mode: false,
|
stream_idle_mode: None,
|
||||||
},
|
},
|
||||||
modeling: ModelingSettings {
|
modeling: ModelingSettings {
|
||||||
base_unit: UnitLength::Yd,
|
base_unit: UnitLength::Yd,
|
||||||
@ -709,7 +709,7 @@ defaultProjectName = "projects-$nnn"
|
|||||||
theme_color: None,
|
theme_color: None,
|
||||||
dismiss_web_banner: false,
|
dismiss_web_banner: false,
|
||||||
enable_ssao: None,
|
enable_ssao: None,
|
||||||
stream_idle_mode: false,
|
stream_idle_mode: None,
|
||||||
},
|
},
|
||||||
modeling: ModelingSettings {
|
modeling: ModelingSettings {
|
||||||
base_unit: UnitLength::Yd,
|
base_unit: UnitLength::Yd,
|
||||||
@ -787,7 +787,7 @@ projectDirectory = "/Users/macinatormax/Documents/kittycad-modeling-projects""#;
|
|||||||
theme_color: None,
|
theme_color: None,
|
||||||
dismiss_web_banner: false,
|
dismiss_web_banner: false,
|
||||||
enable_ssao: None,
|
enable_ssao: None,
|
||||||
stream_idle_mode: false,
|
stream_idle_mode: None,
|
||||||
},
|
},
|
||||||
modeling: ModelingSettings {
|
modeling: ModelingSettings {
|
||||||
base_unit: UnitLength::Mm,
|
base_unit: UnitLength::Mm,
|
||||||
|
|||||||
@ -123,7 +123,7 @@ includeSettings = false
|
|||||||
theme_color: None,
|
theme_color: None,
|
||||||
dismiss_web_banner: false,
|
dismiss_web_banner: false,
|
||||||
enable_ssao: None,
|
enable_ssao: None,
|
||||||
stream_idle_mode: false,
|
stream_idle_mode: None,
|
||||||
},
|
},
|
||||||
modeling: ModelingSettings {
|
modeling: ModelingSettings {
|
||||||
base_unit: UnitLength::Yd,
|
base_unit: UnitLength::Yd,
|
||||||
|
|||||||
Reference in New Issue
Block a user