new performance overlay

This commit is contained in:
azykov@mail.ru
2026-06-13 17:25:13 +03:00
parent a61b5f0105
commit 936db7ee0f
11 changed files with 260 additions and 64 deletions
+2 -3
View File
@@ -1,6 +1,5 @@
import { observer } from "mobx-react-lite";
import { SceneView } from "./SceneView";
import { DebugLabelsView } from "./DebugLabelsView";
import { state } from "../state";
import { useFrame } from "@react-three/fiber";
import { Suspense } from "react";
@@ -18,8 +17,8 @@ export const GameView = observer(function () {
return (<>
<Suspense>
<Physics paused={game.isPaused} debug>
<SceneView scene={game.scene} />
<Physics paused={game.isPaused} debug={game.debugOverlay}>
<SceneView scene={game.scene} debugOverlay={game.debugOverlay} />
</Physics>
</Suspense>
</>);
-2
View File
@@ -1,5 +1,4 @@
import { observer } from "mobx-react-lite";
import { RenderInfoView } from "./RenderInfoView";
import { MenuView } from "./MenuView";
import { state } from "../state";
import { Panel } from "./Panel";
@@ -23,6 +22,5 @@ export const LeftPanel = observer(function () {
<div className="gap" />
{/* <button onClick={handleLoadWorld}>Load</button> */}
<button onClick={handleLoadMockWorld}>Load mock world</button>
<div className="debug"><RenderInfoView /></div>
</Panel>;
});
@@ -1,30 +0,0 @@
import { useEffect, useRef } from "react";
import { observer } from "mobx-react-lite";
import { state } from "../state";
import { chartRef } from "./chartRef";
export const RenderInfoView = observer(function () {
const info = state.renderInfo;
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const el = containerRef.current;
if (!el)
return;
el.appendChild(chartRef.current);
return () => { el.removeChild(chartRef.current); };
}, []);
return <>
<div className="chart" ref={containerRef} />
{info != null && (
<div className="metrics">
<span>draw: {info.calls}</span>
<span>tri: {info.triangles}</span>
<span>shaders: {info.shaders}</span>
<span>geometries: {info.geometries}</span>
<span>textures: {info.textures}</span>
</div>
)}
</>;
});
+1 -1
View File
@@ -59,7 +59,7 @@ export const SceneEditorView = observer(function () {
infiniteGrid
/>
<Physics colliders={false} paused={true}>
<SceneView scene={state.worldEditor.scene} editMode />
<SceneView scene={state.worldEditor.scene} editMode debugOverlay />
</Physics>
</Suspense>
</>);
+2 -1
View File
@@ -7,6 +7,7 @@ import { DebugLabelsView } from "./DebugLabelsView";
type SceneViewProps = {
scene: RuntimeScene,
editMode?: boolean;
debugOverlay?: boolean;
}
export const SceneView = observer(function (props: SceneViewProps) {
@@ -20,6 +21,6 @@ export const SceneView = observer(function (props: SceneViewProps) {
: <ObjectEditorView key={obj.id} object={obj} isPlayer={props.scene.playerObjectId === obj.id} />
))
}
<DebugLabelsView scene={props.scene} />
{props.debugOverlay && <DebugLabelsView scene={props.scene} />}
</>);
});
+15 -6
View File
@@ -1,17 +1,27 @@
import { Perf } from 'r3f-perf'
import { Canvas } from '@react-three/fiber';
import { KeyboardControls, Stats } from '@react-three/drei';
import { chartRef } from './chartRef';
import { KeyboardControls } from '@react-three/drei';
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';
import { useEffect } from 'react';
import { runInAction } from 'mobx';
import { IconPlayerPlayFilled, IconPlayerPauseFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled } from '@tabler/icons-react';
import { RenderInfoUpdater } from './renderInfo';
export const ThreeView = observer(function () {
const isGame = !!state.game;
useEffect(() => {
const onKeyDown = (e: KeyboardEvent) => {
if (e.code === 'Backquote' && state.game) {
runInAction(() => { state.game!.debugOverlay = !state.game!.debugOverlay; });
}
};
window.addEventListener('keydown', onKeyDown);
return () => window.removeEventListener('keydown', onKeyDown);
}, []);
return (
<KeyboardControls map={[
{ name: 'forward', keys: ['ArrowUp', 'w', 'W'] },
@@ -25,8 +35,7 @@ export const ThreeView = observer(function () {
// camera={state.world.character.camera}
onPointerMissed={() => state.worldEditor.resetSelection()}
>
<Stats parent={chartRef as RefObject<HTMLElement>} />
<RenderInfoUpdater />
<Perf position="bottom-right" />
{isGame ? <GameView /> : <SceneEditorView />}
</Canvas>
{isGame && <JoystickView />}
-1
View File
@@ -1 +0,0 @@
export const chartRef = { current: document.createElement('span') };
-20
View File
@@ -1,20 +0,0 @@
import { useFrame, useThree } from "@react-three/fiber";
import { state } from "../state";
import { action } from "mobx";
export 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;
}
+1
View File
@@ -10,6 +10,7 @@ export class GameState {
private readonly world: WorldState;
public isPaused: boolean = false;
public debugOverlay: boolean = false;
public time: number = 0;
public isFirstTick: boolean;
public scene: RuntimeGameScene;