blockly3d/src/components/ThreeView.tsx

72 lines
3.0 KiB
TypeScript

import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { KeyboardControls, Stats } from '@react-three/drei';
import { action } from 'mobx';
import { chartRef } from './chartRef';
function RenderInfoUpdater() {
const { gl } = useThree();
useFrame(action(() => {
const { calls, triangles } = gl.info.render;
const shaders = gl.info.programs?.length ?? 0;
const { geometries, textures } = gl.info.memory;
state.setRenderInfo({
calls,
triangles,
shaders,
geometries,
textures,
});
}));
return null;
}
import { observer } from 'mobx-react-lite';
import { state } from '../state';
import { GameView } from './GameView';
import { SceneEditorView } from './SceneEditorView';
import { JoystickView } from './JoystickView';
import type { RefObject } from 'react';
const IconStop = () => <svg viewBox="0 0 14 14"><rect x="2" y="2" width="10" height="10" fill="currentColor" /></svg>;
const IconPause = () => <svg viewBox="0 0 14 14"><rect x="2" y="2" width="4" height="10" fill="currentColor" /><rect x="8" y="2" width="4" height="10" fill="currentColor" /></svg >;
const IconPlay = () => <svg viewBox="0 0 14 14"><polygon points="3,1 13,7 3,13" fill="currentColor" /></svg>;
export const ThreeView = observer(function () {
const isGame = state.isGamePlaying;
return (
<KeyboardControls map={[
{ name: 'forward', keys: ['ArrowUp', 'w', 'W'] },
{ name: 'backward', keys: ['ArrowDown', 's', 'S'] },
{ name: 'left', keys: ['ArrowLeft', 'a', 'A'] },
{ name: 'right', keys: ['ArrowRight', 'd', 'D'] },
{ name: 'jump', keys: ['Space'] },
]}>
<div style={{ position: 'fixed', inset: 0, overflow: 'hidden' }}>
<Canvas
// camera={state.world.character.camera}
onPointerMissed={() => state.worldEditor.resetSelection()}
>
<Stats parent={chartRef as RefObject<HTMLElement>} />
<RenderInfoUpdater />
{isGame ? <GameView /> : <SceneEditorView />}
</Canvas>
{isGame && <JoystickView />}
<div style={{ position: 'absolute', top: 8, right: 8, display: 'flex', gap: 4 }}>
{
state.game
? <>
<button onClick={() => state.stopGame()}><IconStop /></button>
{
state.game!.isPaused
? <button onClick={() => state.game!.resume()}><IconPlay /></button>
: <button onClick={() => state.game!.pause()}><IconPause /></button>
}
</>
: <button onClick={() => state.startGame()}><IconPlay /></button>
}
</div>
</div>
</KeyboardControls>
)
});