workspaces folders
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import { BrowserRouter, Link, Outlet, Route, Routes, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { VoxelEditorPage } from './components/voxelEditor/VoxelEditorPage';
|
||||
import { useEffect, useLayoutEffect, useRef } from 'react';
|
||||
import { reaction } from 'mobx';
|
||||
import { ThreeView } from './components/ThreeView';
|
||||
import { state } from './state';
|
||||
import './App.scss';
|
||||
import { Panels } from './components/Panels';
|
||||
|
||||
function StateToUrlSync() {
|
||||
const navigate = useNavigate();
|
||||
const { pathname } = useLocation();
|
||||
const pathnameRef = useRef(pathname);
|
||||
useLayoutEffect(() => { pathnameRef.current = pathname; });
|
||||
|
||||
useEffect(() => reaction(
|
||||
() => ({
|
||||
isGame: !!state.game,
|
||||
selectedObjectId: state.worldEditor.selection?.type === 'object' && state.worldEditor.selection.id,
|
||||
selectedObjectTypeId: state.worldEditor.selection?.type === 'objectType' && state.worldEditor.selection.id,
|
||||
}),
|
||||
({ isGame, selectedObjectId, selectedObjectTypeId }) => {
|
||||
let target: string;
|
||||
if (isGame)
|
||||
target = '/game';
|
||||
else if (selectedObjectId)
|
||||
target = `/editor/object/${selectedObjectId}`;
|
||||
else if (selectedObjectTypeId)
|
||||
target = `/editor/objectType/${selectedObjectTypeId}`;
|
||||
else
|
||||
target = '/editor';
|
||||
|
||||
const current = pathnameRef.current;
|
||||
if (current === target || current.startsWith(target + '/'))
|
||||
return;
|
||||
navigate(target);
|
||||
},
|
||||
), [navigate]);
|
||||
return null;
|
||||
}
|
||||
|
||||
function EditorRoute() {
|
||||
useEffect(() => {
|
||||
if (state.game)
|
||||
state.stopGame();
|
||||
state.worldEditor.resetSelection();
|
||||
}, []);
|
||||
return null;
|
||||
}
|
||||
|
||||
function EditorObjectRoute() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
useEffect(() => {
|
||||
if (!id)
|
||||
return;
|
||||
if (state.game)
|
||||
state.stopGame();
|
||||
const editMode = state.worldEditor.selection?.type === 'object' && state.worldEditor.selection.id === id
|
||||
? state.worldEditor.selection.editMode ?? 'translate'
|
||||
: 'translate';
|
||||
state.worldEditor.setSelectedObject({ id, editMode });
|
||||
}, [id]);
|
||||
return null;
|
||||
}
|
||||
|
||||
function EditorObjectTypeRoute() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
useEffect(() => {
|
||||
if (!id)
|
||||
return;
|
||||
if (state.game)
|
||||
state.stopGame();
|
||||
const editMode = state.worldEditor.selection?.type === 'objectType' && state.worldEditor.selection.id === id
|
||||
? state.worldEditor.selection.editMode ?? 'scripts'
|
||||
: 'scripts';
|
||||
state.worldEditor.setSelectedObjectType({ id, editMode });
|
||||
}, [id]);
|
||||
return null;
|
||||
}
|
||||
|
||||
function GameRoute() {
|
||||
useEffect(() => {
|
||||
if (!state.game)
|
||||
state.startGame();
|
||||
}, []);
|
||||
return null;
|
||||
}
|
||||
|
||||
function HomePage() {
|
||||
return <Link to="/editor">Open Editor</Link>;
|
||||
}
|
||||
|
||||
function EditorLayout() {
|
||||
return (
|
||||
<>
|
||||
<Outlet />
|
||||
<ThreeView />
|
||||
<Panels />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const App = function () {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<StateToUrlSync />
|
||||
<Routes>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
<Route path="/editor/objectType/:id/voxels" element={<VoxelEditorPage />} />
|
||||
<Route element={<EditorLayout />}>
|
||||
<Route path="/editor" element={<EditorRoute />} />
|
||||
<Route path="/editor/object/:id" element={<EditorObjectRoute />} />
|
||||
<Route path="/editor/objectType/:id" element={<EditorObjectTypeRoute />} />
|
||||
<Route path="/game" element={<GameRoute />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user