blockly3d/src/components/SceneEditorView.tsx

67 lines
2.1 KiB
TypeScript

import { Suspense, useRef } from 'react';
import type React from 'react';
import { Grid, OrbitControls } from '@react-three/drei';
import { observer } from 'mobx-react-lite';
import { state } from '../state';
import { SceneView } from './SceneView';
import { type OrthographicCamera, type PerspectiveCamera } from 'three';
import { CameraSync } from './tools/CameraSync';
import { Physics } from '@react-three/rapier';
export const SceneEditorView = observer(function () {
const controlsRef = useRef<React.ComponentRef<typeof OrbitControls>>(null);
const cameraAtStart = useRef<string>('');
function cameraSnapshot(camera: OrthographicCamera | PerspectiveCamera): string {
return JSON.stringify({
position: camera.position,
rotation: camera.rotation,
});
}
const handleStart = () => {
const controls = controlsRef.current;
if (!controls)
return;
cameraAtStart.current = cameraSnapshot(controls.object);
};
const handleEnd = () => {
const controls = controlsRef.current;
if (!controls)
return;
const snapshot = cameraSnapshot(controls.object);
if (snapshot === cameraAtStart.current)
return;
const [x, y, z] = controls.object.rotation.toArray();
state.worldEditor.setCamera({
position: controls.object.position.toArray(),
look: [x, y, z],
});
};
return (<>
<Suspense>
<OrbitControls
ref={controlsRef}
onStart={handleStart}
onEnd={handleEnd}
makeDefault
enableDamping={false}
/>
<CameraSync camera={state.worldEditor.camera} />
<Grid
sectionThickness={0.5}
cellThickness={0}
sectionColor="white"
infiniteGrid
/>
<Physics colliders={false} paused={true}>
<SceneView scene={state.worldEditor.scene} editMode />
</Physics>
</Suspense>
</>);
});