fix(debug): stabilize map debug controls
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
|
import { useDebugFolder } from "@/hooks/debug/useDebugFolder";
|
||||||
|
import { Debug } from "@/utils/debug/Debug";
|
||||||
import {
|
import {
|
||||||
MAP_PERFORMANCE_GROUP_NAMES,
|
MAP_PERFORMANCE_GROUP_NAMES,
|
||||||
MAP_PERFORMANCE_MODEL_NAMES,
|
MAP_PERFORMANCE_MODEL_NAMES,
|
||||||
@@ -14,7 +15,9 @@ function toLabel(value: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useMapPerformanceDebug(): void {
|
export function useMapPerformanceDebug(): void {
|
||||||
useDebugFolder("Performance / Map", (folder) => {
|
useDebugFolder("Map", (folder) => {
|
||||||
|
Debug.getInstance().addFogControl(folder);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
groups,
|
groups,
|
||||||
models,
|
models,
|
||||||
|
|||||||
+47
-19
@@ -17,12 +17,11 @@ interface DebugEvents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const DEBUG_FOLDER_ORDER = [
|
const DEBUG_FOLDER_ORDER = [
|
||||||
"La Fabrik",
|
|
||||||
"Lighting",
|
"Lighting",
|
||||||
"Game",
|
"Game",
|
||||||
"Interaction",
|
"Interaction",
|
||||||
"Hand Tracking",
|
"Hand Tracking",
|
||||||
"Performance / Map",
|
"Map",
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
@@ -100,14 +99,13 @@ export class Debug {
|
|||||||
sceneMode: storedControls.sceneMode ?? "game",
|
sceneMode: storedControls.sceneMode ?? "game",
|
||||||
};
|
};
|
||||||
|
|
||||||
this.gui = this.active ? new GUI({ title: "Debug" }) : null;
|
this.gui = this.active ? new GUI({ title: "La Fabrik" }) : null;
|
||||||
|
|
||||||
if (this.gui) {
|
if (this.gui) {
|
||||||
const folder = this.createFolder("La Fabrik", { open: true });
|
this.gui.open();
|
||||||
|
this.createOrderedFolders();
|
||||||
|
|
||||||
if (!folder) return;
|
this.gui
|
||||||
|
|
||||||
folder
|
|
||||||
.add(this.controls, "cameraMode", { Player: "player", Debug: "debug" })
|
.add(this.controls, "cameraMode", { Player: "player", Debug: "debug" })
|
||||||
.name("Camera Mode")
|
.name("Camera Mode")
|
||||||
.onChange((value: CameraMode) => {
|
.onChange((value: CameraMode) => {
|
||||||
@@ -115,7 +113,7 @@ export class Debug {
|
|||||||
this.saveAndEmit();
|
this.saveAndEmit();
|
||||||
});
|
});
|
||||||
|
|
||||||
folder
|
this.gui
|
||||||
.add(this.controls, "sceneMode", { Game: "game", Physics: "physics" })
|
.add(this.controls, "sceneMode", { Game: "game", Physics: "physics" })
|
||||||
.name("Scene")
|
.name("Scene")
|
||||||
.onChange((value: SceneMode) => {
|
.onChange((value: SceneMode) => {
|
||||||
@@ -123,7 +121,7 @@ export class Debug {
|
|||||||
this.saveAndEmit();
|
this.saveAndEmit();
|
||||||
});
|
});
|
||||||
|
|
||||||
folder
|
this.gui
|
||||||
.add(this.controls, "showPerf")
|
.add(this.controls, "showPerf")
|
||||||
.name("R3F Perf")
|
.name("R3F Perf")
|
||||||
.onChange((value: boolean) => {
|
.onChange((value: boolean) => {
|
||||||
@@ -131,7 +129,7 @@ export class Debug {
|
|||||||
this.emit();
|
this.emit();
|
||||||
});
|
});
|
||||||
|
|
||||||
folder
|
this.gui
|
||||||
.add(this.controls, "showDebugOverlay")
|
.add(this.controls, "showDebugOverlay")
|
||||||
.name("Debug Overlay")
|
.name("Debug Overlay")
|
||||||
.onChange((value: boolean) => {
|
.onChange((value: boolean) => {
|
||||||
@@ -139,14 +137,6 @@ export class Debug {
|
|||||||
this.emit();
|
this.emit();
|
||||||
});
|
});
|
||||||
|
|
||||||
folder
|
|
||||||
.add(this.controls, "fogEnabled")
|
|
||||||
.name("Fog")
|
|
||||||
.onChange((value: boolean) => {
|
|
||||||
this.controls.fogEnabled = value;
|
|
||||||
this.emit();
|
|
||||||
});
|
|
||||||
|
|
||||||
const handTrackingFolder = this.createFolder("Hand Tracking");
|
const handTrackingFolder = this.createFolder("Hand Tracking");
|
||||||
|
|
||||||
handTrackingFolder
|
handTrackingFolder
|
||||||
@@ -180,10 +170,17 @@ export class Debug {
|
|||||||
const existing = this.folders.get(name);
|
const existing = this.folders.get(name);
|
||||||
|
|
||||||
if (existing) {
|
if (existing) {
|
||||||
this.folderRefCounts.set(name, (this.folderRefCounts.get(name) ?? 0) + 1);
|
const refCount = this.folderRefCounts.get(name) ?? 0;
|
||||||
|
|
||||||
|
if (refCount > 0) {
|
||||||
|
this.folderRefCounts.set(name, refCount + 1);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.folderRefCounts.set(name, 1);
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
const folder = this.gui.addFolder(name);
|
const folder = this.gui.addFolder(name);
|
||||||
this.folders.set(name, folder);
|
this.folders.set(name, folder);
|
||||||
this.folderRefCounts.set(name, 1);
|
this.folderRefCounts.set(name, 1);
|
||||||
@@ -198,6 +195,16 @@ export class Debug {
|
|||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addFogControl(folder: GUI): void {
|
||||||
|
folder
|
||||||
|
.add(this.controls, "fogEnabled")
|
||||||
|
.name("Fog")
|
||||||
|
.onChange((value: boolean) => {
|
||||||
|
this.controls.fogEnabled = value;
|
||||||
|
this.emit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
destroyFolder(name: string): void {
|
destroyFolder(name: string): void {
|
||||||
const folder = this.folders.get(name);
|
const folder = this.folders.get(name);
|
||||||
const refCount = this.folderRefCounts.get(name);
|
const refCount = this.folderRefCounts.get(name);
|
||||||
@@ -279,6 +286,27 @@ export class Debug {
|
|||||||
this.emit();
|
this.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createOrderedFolders(): void {
|
||||||
|
for (const folderName of DEBUG_FOLDER_ORDER) {
|
||||||
|
this.ensureFolder(folderName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ensureFolder(name: string): GUI | null {
|
||||||
|
if (!this.gui) return null;
|
||||||
|
|
||||||
|
const existing = this.folders.get(name);
|
||||||
|
if (existing) return existing;
|
||||||
|
|
||||||
|
const folder = this.gui.addFolder(name);
|
||||||
|
folder.close();
|
||||||
|
this.folders.set(name, folder);
|
||||||
|
this.folderRefCounts.set(name, 0);
|
||||||
|
this.sortFolders();
|
||||||
|
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
private sortFolders(): void {
|
private sortFolders(): void {
|
||||||
if (!this.gui) return;
|
if (!this.gui) return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Suspense, useMemo, useRef, useState } from "react";
|
import { Suspense, useCallback, useMemo, useRef, useState } from "react";
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { CHUNK_CONFIG } from "@/data/world/fogConfig";
|
import { CHUNK_CONFIG } from "@/data/world/fogConfig";
|
||||||
import { useCameraMode } from "@/hooks/debug/useCameraMode";
|
import { useCameraMode } from "@/hooks/debug/useCameraMode";
|
||||||
@@ -106,16 +106,21 @@ export function VegetationSystem(): React.JSX.Element | null {
|
|||||||
}, [data, groups, models]);
|
}, [data, groups, models]);
|
||||||
|
|
||||||
const visibleChunks = streamingEnabled
|
const visibleChunks = streamingEnabled
|
||||||
? chunks.filter((chunk) => activeChunkKeys.has(chunk.key))
|
? chunks.filter((chunk) => {
|
||||||
|
if (activeChunkKeys.size > 0) {
|
||||||
|
return activeChunkKeys.has(chunk.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
Math.hypot(
|
||||||
|
chunk.centerX - camera.position.x,
|
||||||
|
chunk.centerZ - camera.position.z,
|
||||||
|
) <= CHUNK_CONFIG.loadRadius
|
||||||
|
);
|
||||||
|
})
|
||||||
: chunks;
|
: chunks;
|
||||||
|
|
||||||
useFrame(({ clock }) => {
|
const updateActiveChunks = useCallback(() => {
|
||||||
if (!streamingEnabled) return;
|
|
||||||
|
|
||||||
const now = clock.elapsedTime * 1000;
|
|
||||||
if (now - lastUpdateRef.current < CHUNK_CONFIG.updateInterval) return;
|
|
||||||
lastUpdateRef.current = now;
|
|
||||||
|
|
||||||
const nextKeys = new Set<string>();
|
const nextKeys = new Set<string>();
|
||||||
const cameraX = camera.position.x;
|
const cameraX = camera.position.x;
|
||||||
const cameraZ = camera.position.z;
|
const cameraZ = camera.position.z;
|
||||||
@@ -143,6 +148,16 @@ export function VegetationSystem(): React.JSX.Element | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setActiveChunkKeys(nextKeys);
|
setActiveChunkKeys(nextKeys);
|
||||||
|
}, [activeChunkKeys, camera, chunks]);
|
||||||
|
|
||||||
|
useFrame(({ clock }) => {
|
||||||
|
if (!streamingEnabled) return;
|
||||||
|
|
||||||
|
const now = clock.elapsedTime * 1000;
|
||||||
|
if (now - lastUpdateRef.current < CHUNK_CONFIG.updateInterval) return;
|
||||||
|
lastUpdateRef.current = now;
|
||||||
|
|
||||||
|
updateActiveChunks();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isLoading || !data) {
|
if (isLoading || !data) {
|
||||||
|
|||||||
Reference in New Issue
Block a user