2024-02-14 08:03:20 +11:00
|
|
|
import { useRef, useEffect, useState } from 'react'
|
|
|
|
import { useModelingContext } from 'hooks/useModelingContext'
|
|
|
|
|
|
|
|
import { cameraMouseDragGuards } from 'lib/cameraControls'
|
2024-03-11 20:26:13 -04:00
|
|
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
2024-02-14 08:03:20 +11:00
|
|
|
import { useStore } from 'useStore'
|
2024-03-22 16:55:30 +11:00
|
|
|
import { DEBUG_SHOW_BOTH_SCENES } from './sceneInfra'
|
2024-02-26 19:53:44 +11:00
|
|
|
import { ReactCameraProperties } from './CameraControls'
|
2024-02-14 08:03:20 +11:00
|
|
|
import { throttle } from 'lib/utils'
|
2024-03-22 16:55:30 +11:00
|
|
|
import { sceneInfra } from 'lib/singletons'
|
2024-02-14 08:03:20 +11:00
|
|
|
|
|
|
|
function useShouldHideScene(): { hideClient: boolean; hideServer: boolean } {
|
|
|
|
const [isCamMoving, setIsCamMoving] = useState(false)
|
|
|
|
const [isTween, setIsTween] = useState(false)
|
|
|
|
|
|
|
|
const { state } = useModelingContext()
|
|
|
|
|
|
|
|
useEffect(() => {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.setIsCamMovingCallback((isMoving, isTween) => {
|
2024-02-14 08:03:20 +11:00
|
|
|
setIsCamMoving(isMoving)
|
|
|
|
setIsTween(isTween)
|
|
|
|
})
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
if (DEBUG_SHOW_BOTH_SCENES || !isCamMoving)
|
|
|
|
return { hideClient: false, hideServer: false }
|
2024-02-17 07:04:24 +11:00
|
|
|
let hideServer = state.matches('Sketch')
|
2024-02-14 08:03:20 +11:00
|
|
|
if (isTween) {
|
|
|
|
hideServer = false
|
|
|
|
}
|
|
|
|
|
|
|
|
return { hideClient: !hideServer, hideServer }
|
|
|
|
}
|
|
|
|
|
|
|
|
export const ClientSideScene = ({
|
|
|
|
cameraControls,
|
|
|
|
}: {
|
|
|
|
cameraControls: ReturnType<
|
2024-03-11 20:26:13 -04:00
|
|
|
typeof useSettingsAuthContext
|
2024-02-14 08:03:20 +11:00
|
|
|
>['settings']['context']['cameraControls']
|
|
|
|
}) => {
|
|
|
|
const canvasRef = useRef<HTMLDivElement>(null)
|
|
|
|
const { state, send } = useModelingContext()
|
|
|
|
const { hideClient, hideServer } = useShouldHideScene()
|
|
|
|
const { setHighlightRange } = useStore((s) => ({
|
|
|
|
setHighlightRange: s.setHighlightRange,
|
|
|
|
highlightRange: s.highlightRange,
|
|
|
|
}))
|
|
|
|
|
|
|
|
// Listen for changes to the camera controls setting
|
|
|
|
// and update the client-side scene's controls accordingly.
|
|
|
|
useEffect(() => {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.interactionGuards =
|
|
|
|
cameraMouseDragGuards[cameraControls]
|
2024-02-14 08:03:20 +11:00
|
|
|
}, [cameraControls])
|
|
|
|
useEffect(() => {
|
|
|
|
sceneInfra.updateOtherSelectionColors(
|
|
|
|
state?.context?.selectionRanges?.otherSelections || []
|
|
|
|
)
|
|
|
|
}, [state?.context?.selectionRanges?.otherSelections])
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (!canvasRef.current) return
|
|
|
|
const canvas = canvasRef.current
|
|
|
|
canvas.appendChild(sceneInfra.renderer.domElement)
|
|
|
|
sceneInfra.animate()
|
|
|
|
sceneInfra.setHighlightCallback(setHighlightRange)
|
|
|
|
canvas.addEventListener('mousemove', sceneInfra.onMouseMove, false)
|
|
|
|
canvas.addEventListener('mousedown', sceneInfra.onMouseDown, false)
|
|
|
|
canvas.addEventListener('mouseup', sceneInfra.onMouseUp, false)
|
|
|
|
sceneInfra.setSend(send)
|
|
|
|
return () => {
|
|
|
|
canvas?.removeEventListener('mousemove', sceneInfra.onMouseMove)
|
|
|
|
canvas?.removeEventListener('mousedown', sceneInfra.onMouseDown)
|
|
|
|
canvas?.removeEventListener('mouseup', sceneInfra.onMouseUp)
|
|
|
|
}
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
ref={canvasRef}
|
|
|
|
className={`absolute inset-0 h-full w-full transition-all duration-300 ${
|
|
|
|
hideClient ? 'opacity-0' : 'opacity-100'
|
|
|
|
} ${hideServer ? 'bg-black' : ''} ${
|
|
|
|
!hideClient && !hideServer && state.matches('Sketch')
|
|
|
|
? 'bg-black/80'
|
|
|
|
: ''
|
|
|
|
}`}
|
|
|
|
></div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
const throttled = throttle((a: ReactCameraProperties) => {
|
|
|
|
if (a.type === 'perspective' && a.fov) {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.dollyZoom(a.fov)
|
2024-02-14 08:03:20 +11:00
|
|
|
}
|
|
|
|
}, 1000 / 15)
|
|
|
|
|
|
|
|
export const CamDebugSettings = () => {
|
|
|
|
const [camSettings, setCamSettings] = useState<ReactCameraProperties>({
|
|
|
|
type: 'perspective',
|
|
|
|
fov: 12,
|
|
|
|
position: [0, 0, 0],
|
|
|
|
quaternion: [0, 0, 0, 1],
|
|
|
|
})
|
|
|
|
const [fov, setFov] = useState(12)
|
|
|
|
|
|
|
|
useEffect(() => {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.setReactCameraPropertiesCallback(setCamSettings)
|
2024-02-14 08:03:20 +11:00
|
|
|
}, [sceneInfra])
|
|
|
|
useEffect(() => {
|
|
|
|
if (camSettings.type === 'perspective' && camSettings.fov) {
|
|
|
|
setFov(camSettings.fov)
|
|
|
|
}
|
|
|
|
}, [(camSettings as any)?.fov])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
<h3>cam settings</h3>
|
|
|
|
perspective cam
|
|
|
|
<input
|
|
|
|
type="checkbox"
|
|
|
|
checked={camSettings.type === 'perspective'}
|
|
|
|
onChange={(e) => {
|
|
|
|
if (camSettings.type === 'perspective') {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.useOrthographicCamera()
|
2024-02-14 08:03:20 +11:00
|
|
|
} else {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.usePerspectiveCamera()
|
2024-02-14 08:03:20 +11:00
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
{camSettings.type === 'perspective' && (
|
|
|
|
<input
|
|
|
|
type="range"
|
|
|
|
min="4"
|
|
|
|
max="90"
|
|
|
|
step={0.5}
|
|
|
|
value={fov}
|
|
|
|
onChange={(e) => {
|
|
|
|
setFov(parseFloat(e.target.value))
|
|
|
|
|
|
|
|
throttled({
|
|
|
|
...camSettings,
|
|
|
|
fov: parseFloat(e.target.value),
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
className="w-full cursor-pointer pointer-events-auto"
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
{camSettings.type === 'perspective' && (
|
|
|
|
<div>
|
|
|
|
<span>fov</span>
|
|
|
|
<input
|
|
|
|
type="number"
|
|
|
|
value={camSettings.fov}
|
|
|
|
className="text-black w-16"
|
|
|
|
onChange={(e) => {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.setCam({
|
2024-02-14 08:03:20 +11:00
|
|
|
...camSettings,
|
|
|
|
fov: parseFloat(e.target.value),
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
{camSettings.type === 'orthographic' && (
|
|
|
|
<>
|
|
|
|
<div>
|
|
|
|
<span>fov</span>
|
|
|
|
<input
|
|
|
|
type="number"
|
|
|
|
value={camSettings.zoom}
|
|
|
|
className="text-black w-16"
|
|
|
|
onChange={(e) => {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.setCam({
|
2024-02-14 08:03:20 +11:00
|
|
|
...camSettings,
|
|
|
|
zoom: parseFloat(e.target.value),
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
<div>
|
|
|
|
Position
|
|
|
|
<ul className="flex">
|
|
|
|
<li>
|
|
|
|
<span className="pl-2 pr-1">x:</span>
|
|
|
|
<input
|
|
|
|
type="number"
|
|
|
|
step={5}
|
|
|
|
data-testid="cam-x-position"
|
|
|
|
value={camSettings.position[0]}
|
|
|
|
className="text-black w-16"
|
|
|
|
onChange={(e) => {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.setCam({
|
2024-02-14 08:03:20 +11:00
|
|
|
...camSettings,
|
|
|
|
position: [
|
|
|
|
parseFloat(e.target.value),
|
|
|
|
camSettings.position[1],
|
|
|
|
camSettings.position[2],
|
|
|
|
],
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<span className="pl-2 pr-1">y:</span>
|
|
|
|
<input
|
|
|
|
type="number"
|
|
|
|
step={5}
|
|
|
|
data-testid="cam-y-position"
|
|
|
|
value={camSettings.position[1]}
|
|
|
|
className="text-black w-16"
|
|
|
|
onChange={(e) => {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.setCam({
|
2024-02-14 08:03:20 +11:00
|
|
|
...camSettings,
|
|
|
|
position: [
|
|
|
|
camSettings.position[0],
|
|
|
|
parseFloat(e.target.value),
|
|
|
|
camSettings.position[2],
|
|
|
|
],
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<span className="pl-2 pr-1">z:</span>
|
|
|
|
<input
|
|
|
|
type="number"
|
|
|
|
step={5}
|
|
|
|
data-testid="cam-z-position"
|
|
|
|
value={camSettings.position[2]}
|
|
|
|
className="text-black w-16"
|
|
|
|
onChange={(e) => {
|
2024-02-26 19:53:44 +11:00
|
|
|
sceneInfra.camControls.setCam({
|
2024-02-14 08:03:20 +11:00
|
|
|
...camSettings,
|
|
|
|
position: [
|
|
|
|
camSettings.position[0],
|
|
|
|
camSettings.position[1],
|
|
|
|
parseFloat(e.target.value),
|
|
|
|
],
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|