67 lines
2.1 KiB
TypeScript
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>
|
|
</>);
|
|
});
|