tune(debug): refine fog and debug controls

This commit is contained in:
Tom Boullay
2026-05-25 01:00:31 +02:00
parent a4383a7cec
commit f175ad6240
4 changed files with 69 additions and 8 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ import { TERRAIN_COLORS } from "@/data/world/terrainConfig";
export const FOG_CONFIG = { export const FOG_CONFIG = {
enabled: true, enabled: true,
color: "#eef3f5", color: "#dce8df",
near: 38, near: 38,
far: 45, far: 45,
}; };
+61 -5
View File
@@ -1,6 +1,7 @@
import GUI from "lil-gui"; import GUI from "lil-gui";
import type { CameraMode, SceneMode } from "@/types/debug/debug"; import type { CameraMode, SceneMode } from "@/types/debug/debug";
import type { HandTrackingSource } from "@/types/handTracking/handTracking"; import type { HandTrackingSource } from "@/types/handTracking/handTracking";
import { FOG_CONFIG } from "@/data/world/fogConfig";
import { EventEmitter } from "@/utils/core/EventEmitter"; import { EventEmitter } from "@/utils/core/EventEmitter";
import { isDebugEnabled } from "@/utils/debug/isDebugEnabled"; import { isDebugEnabled } from "@/utils/debug/isDebugEnabled";
@@ -15,6 +16,15 @@ interface DebugEvents {
change: void; change: void;
} }
const DEBUG_FOLDER_ORDER = [
"La Fabrik",
"Lighting",
"Game",
"Interaction",
"Hand Tracking",
"Performance / Map",
] as const;
function isRecord(value: unknown): value is Record<string, unknown> { function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null; return typeof value === "object" && value !== null;
} }
@@ -58,6 +68,7 @@ export class Debug {
private readonly folderRefCounts = new Map<string, number>(); private readonly folderRefCounts = new Map<string, number>();
private readonly controls: { private readonly controls: {
cameraMode: CameraMode; cameraMode: CameraMode;
fogEnabled: boolean;
handTrackingSource: HandTrackingSource; handTrackingSource: HandTrackingSource;
showDebugOverlay: boolean; showDebugOverlay: boolean;
showHandTrackingSvg: boolean; showHandTrackingSvg: boolean;
@@ -80,7 +91,8 @@ export class Debug {
this.controls = { this.controls = {
cameraMode: storedControls.cameraMode ?? "player", cameraMode: storedControls.cameraMode ?? "player",
handTrackingSource: "backend", fogEnabled: FOG_CONFIG.enabled,
handTrackingSource: "browser",
showDebugOverlay: true, showDebugOverlay: true,
showHandTrackingSvg: false, showHandTrackingSvg: false,
showInteractionSpheres: false, showInteractionSpheres: false,
@@ -88,10 +100,10 @@ export class Debug {
sceneMode: storedControls.sceneMode ?? "game", sceneMode: storedControls.sceneMode ?? "game",
}; };
this.gui = this.active ? new GUI({ title: "La-Fabrik Debug" }) : null; this.gui = this.active ? new GUI({ title: "Debug" }) : null;
if (this.gui) { if (this.gui) {
const folder = this.createFolder("Debug"); const folder = this.createFolder("La Fabrik", { open: true });
if (!folder) return; if (!folder) return;
@@ -127,6 +139,14 @@ 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
@@ -139,8 +159,8 @@ export class Debug {
handTrackingFolder handTrackingFolder
?.add(this.controls, "handTrackingSource", { ?.add(this.controls, "handTrackingSource", {
Backend: "backend",
"Browser JS": "browser", "Browser JS": "browser",
Backend: "backend",
}) })
.name("Source") .name("Source")
.onChange((value: HandTrackingSource) => { .onChange((value: HandTrackingSource) => {
@@ -154,7 +174,7 @@ export class Debug {
* Acquires a named GUI folder. Returns the folder on first acquisition and null * Acquires a named GUI folder. Returns the folder on first acquisition and null
* on subsequent acquisitions so callers only register controls once. * on subsequent acquisitions so callers only register controls once.
*/ */
createFolder(name: string): GUI | null { createFolder(name: string, options?: { open?: boolean }): GUI | null {
if (!this.gui) return null; if (!this.gui) return null;
const existing = this.folders.get(name); const existing = this.folders.get(name);
@@ -167,6 +187,13 @@ export class Debug {
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);
this.sortFolders();
if (options?.open) {
folder.open();
} else {
folder.close();
}
return folder; return folder;
} }
@@ -206,6 +233,10 @@ export class Debug {
return this.controls.handTrackingSource; return this.controls.handTrackingSource;
} }
getFogEnabled(): boolean {
return this.controls.fogEnabled;
}
getShowInteractionSpheres(): boolean { getShowInteractionSpheres(): boolean {
return this.controls.showInteractionSpheres; return this.controls.showInteractionSpheres;
} }
@@ -247,4 +278,29 @@ export class Debug {
this.emit(); this.emit();
} }
private sortFolders(): void {
if (!this.gui) return;
const rootElement = this.gui.domElement.querySelector(".children");
if (!rootElement) return;
const orderedFolders = [...this.folders.entries()].sort(([a], [b]) => {
const aIndex = DEBUG_FOLDER_ORDER.indexOf(
a as (typeof DEBUG_FOLDER_ORDER)[number],
);
const bIndex = DEBUG_FOLDER_ORDER.indexOf(
b as (typeof DEBUG_FOLDER_ORDER)[number],
);
const safeAIndex = aIndex === -1 ? DEBUG_FOLDER_ORDER.length : aIndex;
const safeBIndex = bIndex === -1 ? DEBUG_FOLDER_ORDER.length : bIndex;
if (safeAIndex !== safeBIndex) return safeAIndex - safeBIndex;
return a.localeCompare(b);
});
for (const [, folder] of orderedFolders) {
rootElement.appendChild(folder.domElement);
}
}
} }
+6 -1
View File
@@ -14,10 +14,12 @@ import {
useMapPerformanceStore, useMapPerformanceStore,
} from "@/managers/stores/useMapPerformanceStore"; } from "@/managers/stores/useMapPerformanceStore";
import { SkyModel } from "@/components/three/world/SkyModel"; import { SkyModel } from "@/components/three/world/SkyModel";
import { useDebugStore } from "@/hooks/debug/useDebugStore";
export function Environment(): React.JSX.Element { export function Environment(): React.JSX.Element {
const cameraMode = useCameraMode(); const cameraMode = useCameraMode();
const sceneMode = useSceneMode(); const sceneMode = useSceneMode();
const fogEnabled = useDebugStore((debug) => debug.getFogEnabled());
const groups = useMapPerformanceStore((state) => state.groups); const groups = useMapPerformanceStore((state) => state.groups);
const models = useMapPerformanceStore((state) => state.models); const models = useMapPerformanceStore((state) => state.models);
const showSky = isMapModelVisible("sky", { groups, models }); const showSky = isMapModelVisible("sky", { groups, models });
@@ -30,7 +32,10 @@ export function Environment(): React.JSX.Element {
return ( return (
<> <>
{FOG_CONFIG.enabled && sceneMode === "game" && cameraMode === "player" ? ( {FOG_CONFIG.enabled &&
fogEnabled &&
sceneMode === "game" &&
cameraMode === "player" ? (
<fog <fog
attach="fog" attach="fog"
args={[FOG_CONFIG.color, FOG_CONFIG.near, FOG_CONFIG.far]} args={[FOG_CONFIG.color, FOG_CONFIG.near, FOG_CONFIG.far]}
+1 -1
View File
@@ -16,7 +16,7 @@ export const VEGETATION_TYPES = {
sapin: { sapin: {
mapName: "sapin", mapName: "sapin",
modelPath: "/models/sapin/model.gltf", modelPath: "/models/sapin/model.gltf",
scaleMultiplier: 2, scaleMultiplier: 5,
castShadow: true, castShadow: true,
receiveShadow: true, receiveShadow: true,
enabled: true, enabled: true,