import { useEffect, useId, useMemo } from "react"; import { Quaternion, Vector3 } from "three"; import { useCameras } from "./CamerasProvider"; import type { CameraEntity } from "../state/gameEntityTypes"; export function Camera({ entity }: { entity: CameraEntity }) { const { registerCamera, unregisterCamera } = useCameras(); const id = useId(); const dataBlock = entity.cameraDataBlock; const position = useMemo( () => (entity.position ? new Vector3(...entity.position) : new Vector3()), [entity.position], ); const rotation = useMemo( () => entity.rotation ? new Quaternion(...entity.rotation) : new Quaternion(), [entity.rotation], ); useEffect(() => { if (dataBlock === "Observer") { const camera = { id, position, rotation }; registerCamera(camera); return () => { unregisterCamera(camera); }; } }, [id, dataBlock, registerCamera, unregisterCamera, position, rotation]); // Maps can define preset observer camera locations. You should be able to jump // to an observer camera position and then fly around from that starting point // But, we wouldn't want the user to take control of the actual camera's // position, because then if you want to cycle back through them again, the // "fixed" camera location has moved. There are multiple approaches to fixing // this: make Camera render an actual PerspectiveCamera, switch it when cycling, // but clone a new "flying" camera when the user moves. The other is to not // have multiple cameras at all, but rather update the default camera with // new position information when cycling. This uses the latter approach. return null; }