world autosave on any edit/change
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
import type { ObjectInstance } from "../types";
|
||||
import { useEffect, useRef, type RefObject } from "react";
|
||||
import { useRef, type RefObject } from "react";
|
||||
import type { Group } from "three";
|
||||
import { TransformControls, useHelper } from "@react-three/drei";
|
||||
import { BoxHelper } from "three";
|
||||
@@ -15,7 +15,6 @@ type ObjectViewProps = {
|
||||
|
||||
export const ObjectView = observer(function ({ object }: ObjectViewProps) {
|
||||
const groupRef = useRef<Group>(null);
|
||||
const controlsRef = useRef<any>(null);
|
||||
|
||||
const isSelected = state.worldEditor.isEnabled &&
|
||||
state.worldEditor.selectedObjectId === object.id;
|
||||
@@ -29,48 +28,33 @@ export const ObjectView = observer(function ({ object }: ObjectViewProps) {
|
||||
? state.worldEditor.selectedObjectMode
|
||||
: undefined;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isSelected)
|
||||
return;
|
||||
const controls = controlsRef.current;
|
||||
if (!controls)
|
||||
return;
|
||||
const onDragChanged = (e: { value: boolean }) => {
|
||||
state.worldEditor.setIsDragging(e.value);
|
||||
if (!e.value) {
|
||||
const group = groupRef.current;
|
||||
if (group)
|
||||
state.worldEditor.setObjectTransform(
|
||||
object.id,
|
||||
group.position.toArray(),
|
||||
group.rotation.toArray().slice(0, 3) as R3,
|
||||
group.scale.toArray(),
|
||||
);
|
||||
}
|
||||
};
|
||||
controls.addEventListener('dragging-changed', onDragChanged);
|
||||
return () => {
|
||||
controls.removeEventListener('dragging-changed', onDragChanged);
|
||||
state.worldEditor.setIsDragging(false);
|
||||
};
|
||||
}, [isSelected]);
|
||||
|
||||
const handleClick = (e: ThreeEvent<MouseEvent>) => {
|
||||
function handleClick(e: ThreeEvent<MouseEvent>) {
|
||||
if (!state.worldEditor.isEnabled)
|
||||
return;
|
||||
if (e.delta > 5)
|
||||
return;
|
||||
e.stopPropagation();
|
||||
|
||||
state.worldEditor.setSelectedObject(object.id, nextSelectionEditMode(selectionMode));
|
||||
};
|
||||
|
||||
function handleTransformEnd() {
|
||||
const group = groupRef.current;
|
||||
if (group)
|
||||
state.worldEditor.setObjectTransform(
|
||||
object.id,
|
||||
group.position.toArray(),
|
||||
group.rotation.toArray().slice(0, 3) as R3,
|
||||
group.scale.toArray(),
|
||||
);
|
||||
};
|
||||
|
||||
return (<>
|
||||
{
|
||||
(isSelected && (selectionMode !== undefined) && groupRef.current) &&
|
||||
<TransformControls
|
||||
object={groupRef as RefObject<Group>}
|
||||
mode={selectionMode}
|
||||
onMouseUp={handleTransformEnd}
|
||||
/>
|
||||
}
|
||||
<group
|
||||
|
||||
@@ -6,6 +6,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import { state } from '../state';
|
||||
import { SceneView } from './SceneView';
|
||||
import type { Pos3 } from '../types/3d';
|
||||
import type { OrthographicCamera, PerspectiveCamera } from 'three';
|
||||
|
||||
const CameraSync = observer(function ({ camera }: { camera: Pos3 }) {
|
||||
const { camera: threeCamera } = useThree();
|
||||
@@ -22,10 +23,29 @@ const CameraSync = observer(function ({ camera }: { camera: Pos3 }) {
|
||||
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(),
|
||||
@@ -36,7 +56,7 @@ export const SceneEditorView = observer(function () {
|
||||
return (<>
|
||||
<OrbitControls
|
||||
ref={controlsRef}
|
||||
enabled={!state.worldEditor.isDragging}
|
||||
onStart={handleStart}
|
||||
onEnd={handleEnd}
|
||||
makeDefault
|
||||
enableDamping={false}
|
||||
|
||||
@@ -8,11 +8,16 @@ export const Toolbar = observer(function () {
|
||||
state.worldEditor.addObjectCloneAtRandomPosition('test1');
|
||||
}
|
||||
|
||||
function handleLoadWorld(): void {
|
||||
state.world.load();
|
||||
}
|
||||
|
||||
function handleLoadMockWorld(): void {
|
||||
state.world.loadMock();
|
||||
}
|
||||
|
||||
return <div className="toolbar">
|
||||
<button onClick={handleLoadWorld}>Load</button>
|
||||
<button onClick={handleLoadMockWorld}>Load mock world</button>
|
||||
<button onClick={handleCloneTest1Object}>Clone test1</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user