2023-08-08 18:30:26 -04:00
|
|
|
import {
|
|
|
|
MouseEventHandler,
|
|
|
|
WheelEventHandler,
|
|
|
|
useEffect,
|
|
|
|
useRef,
|
|
|
|
useState,
|
|
|
|
} from 'react'
|
2023-06-21 09:15:02 +10:00
|
|
|
import { v4 as uuidv4 } from 'uuid'
|
2023-06-22 16:43:33 +10:00
|
|
|
import { useStore } from '../useStore'
|
2023-08-09 20:49:10 +10:00
|
|
|
import { getNormalisedCoordinates } from '../lib/utils'
|
2023-08-10 16:22:45 -04:00
|
|
|
import Loading from './Loading'
|
2023-03-06 20:13:34 +11:00
|
|
|
|
2023-08-06 21:29:26 -04:00
|
|
|
export const Stream = ({ className = '' }) => {
|
2023-08-10 16:22:45 -04:00
|
|
|
const [isLoading, setIsLoading] = useState(true)
|
2023-03-06 20:13:34 +11:00
|
|
|
const videoRef = useRef<HTMLVideoElement>(null)
|
2023-08-06 21:29:26 -04:00
|
|
|
const {
|
|
|
|
mediaStream,
|
|
|
|
engineCommandManager,
|
|
|
|
setIsMouseDownInStream,
|
2023-08-09 20:49:10 +10:00
|
|
|
didDragInStream,
|
|
|
|
setDidDragInStream,
|
|
|
|
streamDimensions,
|
2023-08-06 21:29:26 -04:00
|
|
|
} = useStore((s) => ({
|
2023-06-22 16:43:33 +10:00
|
|
|
mediaStream: s.mediaStream,
|
|
|
|
engineCommandManager: s.engineCommandManager,
|
2023-08-06 21:29:26 -04:00
|
|
|
isMouseDownInStream: s.isMouseDownInStream,
|
|
|
|
setIsMouseDownInStream: s.setIsMouseDownInStream,
|
|
|
|
fileId: s.fileId,
|
2023-08-09 20:49:10 +10:00
|
|
|
didDragInStream: s.didDragInStream,
|
|
|
|
setDidDragInStream: s.setDidDragInStream,
|
|
|
|
streamDimensions: s.streamDimensions,
|
2023-06-22 16:43:33 +10:00
|
|
|
}))
|
2023-03-06 20:13:34 +11:00
|
|
|
|
|
|
|
useEffect(() => {
|
2023-03-07 15:45:59 +11:00
|
|
|
if (
|
|
|
|
typeof window === 'undefined' ||
|
|
|
|
typeof RTCPeerConnection === 'undefined'
|
|
|
|
)
|
|
|
|
return
|
2023-06-22 16:43:33 +10:00
|
|
|
if (!videoRef.current) return
|
|
|
|
if (!mediaStream) return
|
|
|
|
videoRef.current.srcObject = mediaStream
|
2023-08-18 17:14:35 -05:00
|
|
|
}, [mediaStream, engineCommandManager])
|
2023-03-06 20:13:34 +11:00
|
|
|
|
2023-06-22 16:43:33 +10:00
|
|
|
const handleMouseDown: MouseEventHandler<HTMLVideoElement> = ({
|
|
|
|
clientX,
|
|
|
|
clientY,
|
2023-07-20 14:08:32 -04:00
|
|
|
ctrlKey,
|
2023-06-22 16:43:33 +10:00
|
|
|
}) => {
|
|
|
|
if (!videoRef.current) return
|
2023-08-09 20:49:10 +10:00
|
|
|
const { x, y } = getNormalisedCoordinates({
|
|
|
|
clientX,
|
|
|
|
clientY,
|
|
|
|
el: videoRef.current,
|
|
|
|
...streamDimensions,
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
console.log('click', x, y)
|
|
|
|
|
|
|
|
const newId = uuidv4()
|
|
|
|
|
2023-07-20 14:08:32 -04:00
|
|
|
const interaction = ctrlKey ? 'pan' : 'rotate'
|
|
|
|
|
2023-06-22 16:43:33 +10:00
|
|
|
engineCommandManager?.sendSceneCommand({
|
2023-08-02 15:41:59 +10:00
|
|
|
type: 'modeling_cmd_req',
|
2023-06-22 16:43:33 +10:00
|
|
|
cmd: {
|
2023-08-02 15:41:59 +10:00
|
|
|
type: 'camera_drag_start',
|
|
|
|
interaction,
|
2023-08-03 07:28:06 +10:00
|
|
|
window: { x, y },
|
2023-06-22 16:43:33 +10:00
|
|
|
},
|
|
|
|
cmd_id: newId,
|
|
|
|
})
|
2023-08-06 21:29:26 -04:00
|
|
|
|
|
|
|
setIsMouseDownInStream(true)
|
2023-06-22 16:43:33 +10:00
|
|
|
}
|
2023-08-06 21:29:26 -04:00
|
|
|
|
2023-08-08 18:30:26 -04:00
|
|
|
const handleScroll: WheelEventHandler<HTMLVideoElement> = (e) => {
|
|
|
|
e.preventDefault()
|
2023-08-21 10:52:41 -04:00
|
|
|
engineCommandManager?.sendSceneCommand({
|
2023-08-08 18:30:26 -04:00
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd: {
|
2023-08-21 10:52:41 -04:00
|
|
|
type: 'default_camera_zoom',
|
|
|
|
magnitude: e.deltaY * 0.4,
|
2023-08-08 18:30:26 -04:00
|
|
|
},
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-06-22 16:43:33 +10:00
|
|
|
const handleMouseUp: MouseEventHandler<HTMLVideoElement> = ({
|
|
|
|
clientX,
|
|
|
|
clientY,
|
2023-07-20 14:08:32 -04:00
|
|
|
ctrlKey,
|
2023-06-22 16:43:33 +10:00
|
|
|
}) => {
|
|
|
|
if (!videoRef.current) return
|
2023-08-09 20:49:10 +10:00
|
|
|
const { x, y } = getNormalisedCoordinates({
|
|
|
|
clientX,
|
|
|
|
clientY,
|
|
|
|
el: videoRef.current,
|
|
|
|
...streamDimensions,
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
|
2023-08-06 21:29:26 -04:00
|
|
|
const newCmdId = uuidv4()
|
2023-07-20 14:08:32 -04:00
|
|
|
const interaction = ctrlKey ? 'pan' : 'rotate'
|
|
|
|
|
2023-06-22 16:43:33 +10:00
|
|
|
engineCommandManager?.sendSceneCommand({
|
2023-08-02 15:41:59 +10:00
|
|
|
type: 'modeling_cmd_req',
|
2023-06-22 16:43:33 +10:00
|
|
|
cmd: {
|
2023-08-02 15:41:59 +10:00
|
|
|
type: 'camera_drag_end',
|
|
|
|
interaction,
|
2023-08-03 07:28:06 +10:00
|
|
|
window: { x, y },
|
2023-06-22 16:43:33 +10:00
|
|
|
},
|
2023-08-06 21:29:26 -04:00
|
|
|
cmd_id: newCmdId,
|
2023-06-22 16:43:33 +10:00
|
|
|
})
|
2023-08-06 21:29:26 -04:00
|
|
|
|
|
|
|
setIsMouseDownInStream(false)
|
2023-08-09 20:49:10 +10:00
|
|
|
if (!didDragInStream) {
|
|
|
|
engineCommandManager?.sendSceneCommand({
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd: {
|
|
|
|
type: 'select_with_point',
|
|
|
|
selection_type: 'add',
|
|
|
|
selected_at_window: { x, y },
|
|
|
|
},
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
setDidDragInStream(false)
|
2023-06-22 16:43:33 +10:00
|
|
|
}
|
2023-03-06 20:13:34 +11:00
|
|
|
|
|
|
|
return (
|
2023-08-06 21:29:26 -04:00
|
|
|
<div id="stream" className={className}>
|
2023-06-22 16:43:33 +10:00
|
|
|
<video
|
|
|
|
ref={videoRef}
|
|
|
|
muted
|
|
|
|
autoPlay
|
|
|
|
controls={false}
|
|
|
|
onMouseDown={handleMouseDown}
|
|
|
|
onMouseUp={handleMouseUp}
|
2023-07-20 14:08:32 -04:00
|
|
|
onContextMenu={(e) => e.preventDefault()}
|
|
|
|
onContextMenuCapture={(e) => e.preventDefault()}
|
2023-08-21 10:52:41 -04:00
|
|
|
onWheel={handleScroll}
|
2023-08-10 16:22:45 -04:00
|
|
|
onPlay={() => setIsLoading(false)}
|
2023-08-06 21:29:26 -04:00
|
|
|
className="w-full h-full"
|
2023-06-22 16:43:33 +10:00
|
|
|
/>
|
2023-08-10 16:22:45 -04:00
|
|
|
{isLoading && (
|
|
|
|
<div className="text-center absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
|
|
|
<Loading>Loading stream...</Loading>
|
|
|
|
</div>
|
|
|
|
)}
|
2023-03-06 20:13:34 +11:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|