Feat/polish-mission1 #12
@@ -1,4 +1,5 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { createJSONStorage, persist } from "zustand/middleware";
|
||||||
import { AudioManager } from "@/managers/AudioManager";
|
import { AudioManager } from "@/managers/AudioManager";
|
||||||
import type { AudioCategory } from "@/managers/AudioManager";
|
import type { AudioCategory } from "@/managers/AudioManager";
|
||||||
import type { SubtitleLanguage } from "@/types/settings/settings";
|
import type { SubtitleLanguage } from "@/types/settings/settings";
|
||||||
@@ -33,6 +34,8 @@ const DEFAULT_SETTINGS: SettingsState = {
|
|||||||
subtitleLanguage: "fr",
|
subtitleLanguage: "fr",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SETTINGS_STORAGE_KEY = "la-fabrik-settings";
|
||||||
|
|
||||||
function clampVolume(volume: number): number {
|
function clampVolume(volume: number): number {
|
||||||
return Math.max(0, Math.min(1, volume));
|
return Math.max(0, Math.min(1, volume));
|
||||||
}
|
}
|
||||||
@@ -46,24 +49,22 @@ function setAudioCategoryVolume(
|
|||||||
return nextVolume;
|
return nextVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyDefaultAudioSettings(): void {
|
function applyAudioSettings(
|
||||||
AudioManager.getInstance().setCategoryVolume(
|
settings: Pick<SettingsState, "musicVolume" | "sfxVolume" | "dialogueVolume">,
|
||||||
"music",
|
): void {
|
||||||
DEFAULT_SETTINGS.musicVolume,
|
AudioManager.getInstance().setCategoryVolume("music", settings.musicVolume);
|
||||||
);
|
AudioManager.getInstance().setCategoryVolume("sfx", settings.sfxVolume);
|
||||||
AudioManager.getInstance().setCategoryVolume(
|
|
||||||
"sfx",
|
|
||||||
DEFAULT_SETTINGS.sfxVolume,
|
|
||||||
);
|
|
||||||
AudioManager.getInstance().setCategoryVolume(
|
AudioManager.getInstance().setCategoryVolume(
|
||||||
"dialogue",
|
"dialogue",
|
||||||
DEFAULT_SETTINGS.dialogueVolume,
|
settings.dialogueVolume,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyDefaultAudioSettings();
|
applyAudioSettings(DEFAULT_SETTINGS);
|
||||||
|
|
||||||
export const useSettingsStore = create<SettingsStore>()((set) => ({
|
export const useSettingsStore = create<SettingsStore>()(
|
||||||
|
persist(
|
||||||
|
(set) => ({
|
||||||
...DEFAULT_SETTINGS,
|
...DEFAULT_SETTINGS,
|
||||||
setSettingsMenuOpen: (isSettingsMenuOpen) => set({ isSettingsMenuOpen }),
|
setSettingsMenuOpen: (isSettingsMenuOpen) => set({ isSettingsMenuOpen }),
|
||||||
setMusicVolume: (volume) =>
|
setMusicVolume: (volume) =>
|
||||||
@@ -75,7 +76,23 @@ export const useSettingsStore = create<SettingsStore>()((set) => ({
|
|||||||
setSubtitlesEnabled: (subtitlesEnabled) => set({ subtitlesEnabled }),
|
setSubtitlesEnabled: (subtitlesEnabled) => set({ subtitlesEnabled }),
|
||||||
setSubtitleLanguage: (subtitleLanguage) => set({ subtitleLanguage }),
|
setSubtitleLanguage: (subtitleLanguage) => set({ subtitleLanguage }),
|
||||||
resetSettings: () => {
|
resetSettings: () => {
|
||||||
applyDefaultAudioSettings();
|
applyAudioSettings(DEFAULT_SETTINGS);
|
||||||
set(DEFAULT_SETTINGS);
|
set(DEFAULT_SETTINGS);
|
||||||
},
|
},
|
||||||
}));
|
}),
|
||||||
|
{
|
||||||
|
name: SETTINGS_STORAGE_KEY,
|
||||||
|
storage: createJSONStorage(() => window.localStorage),
|
||||||
|
partialize: (state) => ({
|
||||||
|
dialogueVolume: state.dialogueVolume,
|
||||||
|
musicVolume: state.musicVolume,
|
||||||
|
sfxVolume: state.sfxVolume,
|
||||||
|
subtitleLanguage: state.subtitleLanguage,
|
||||||
|
subtitlesEnabled: state.subtitlesEnabled,
|
||||||
|
}),
|
||||||
|
onRehydrateStorage: () => (state) => {
|
||||||
|
if (state) applyAudioSettings(state);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { createJSONStorage, persist } from "zustand/middleware";
|
||||||
import { CLOUD_DEFAULTS, type CloudState } from "@/data/world/cloudConfig";
|
import { CLOUD_DEFAULTS, type CloudState } from "@/data/world/cloudConfig";
|
||||||
import { FOG_CONFIG, type FogState } from "@/data/world/fogConfig";
|
import { FOG_CONFIG, type FogState } from "@/data/world/fogConfig";
|
||||||
import { WIND_DEFAULTS, type WindState } from "@/data/world/windConfig";
|
import { WIND_DEFAULTS, type WindState } from "@/data/world/windConfig";
|
||||||
@@ -46,7 +47,11 @@ const DEFAULT_STATE: WorldSettingsState = {
|
|||||||
graphics: { ...GRAPHICS_DEFAULTS },
|
graphics: { ...GRAPHICS_DEFAULTS },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useWorldSettingsStore = create<WorldSettingsStore>()((set) => ({
|
const WORLD_SETTINGS_STORAGE_KEY = "la-fabrik-world-settings";
|
||||||
|
|
||||||
|
export const useWorldSettingsStore = create<WorldSettingsStore>()(
|
||||||
|
persist(
|
||||||
|
(set) => ({
|
||||||
...DEFAULT_STATE,
|
...DEFAULT_STATE,
|
||||||
|
|
||||||
setClouds: (cloudsUpdate) =>
|
setClouds: (cloudsUpdate) =>
|
||||||
@@ -115,4 +120,16 @@ export const useWorldSettingsStore = create<WorldSettingsStore>()((set) => ({
|
|||||||
})),
|
})),
|
||||||
|
|
||||||
resetToDefaults: () => set(DEFAULT_STATE),
|
resetToDefaults: () => set(DEFAULT_STATE),
|
||||||
}));
|
}),
|
||||||
|
{
|
||||||
|
name: WORLD_SETTINGS_STORAGE_KEY,
|
||||||
|
storage: createJSONStorage(() => window.localStorage),
|
||||||
|
partialize: (state) => ({
|
||||||
|
clouds: state.clouds,
|
||||||
|
fog: state.fog,
|
||||||
|
graphics: state.graphics,
|
||||||
|
wind: state.wind,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const DEBUG_CONTROLS_STORAGE_KEY = "la-fabrik-debug-controls";
|
|||||||
|
|
||||||
interface StoredDebugControls {
|
interface StoredDebugControls {
|
||||||
cameraMode: CameraMode;
|
cameraMode: CameraMode;
|
||||||
|
handTrackingSource: HandTrackingSource;
|
||||||
sceneMode: SceneMode;
|
sceneMode: SceneMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +40,10 @@ function isSceneMode(value: unknown): value is SceneMode {
|
|||||||
return value === "game" || value === "physics";
|
return value === "game" || value === "physics";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isHandTrackingSource(value: unknown): value is HandTrackingSource {
|
||||||
|
return value === "browser" || value === "backend";
|
||||||
|
}
|
||||||
|
|
||||||
function getStoredDebugControls(): Partial<StoredDebugControls> {
|
function getStoredDebugControls(): Partial<StoredDebugControls> {
|
||||||
try {
|
try {
|
||||||
const rawValue = window.localStorage.getItem(DEBUG_CONTROLS_STORAGE_KEY);
|
const rawValue = window.localStorage.getItem(DEBUG_CONTROLS_STORAGE_KEY);
|
||||||
@@ -51,6 +56,9 @@ function getStoredDebugControls(): Partial<StoredDebugControls> {
|
|||||||
...(isCameraMode(parsedValue.cameraMode)
|
...(isCameraMode(parsedValue.cameraMode)
|
||||||
? { cameraMode: parsedValue.cameraMode }
|
? { cameraMode: parsedValue.cameraMode }
|
||||||
: {}),
|
: {}),
|
||||||
|
...(isHandTrackingSource(parsedValue.handTrackingSource)
|
||||||
|
? { handTrackingSource: parsedValue.handTrackingSource }
|
||||||
|
: {}),
|
||||||
...(isSceneMode(parsedValue.sceneMode)
|
...(isSceneMode(parsedValue.sceneMode)
|
||||||
? { sceneMode: parsedValue.sceneMode }
|
? { sceneMode: parsedValue.sceneMode }
|
||||||
: {}),
|
: {}),
|
||||||
@@ -94,7 +102,7 @@ export class Debug {
|
|||||||
this.controls = {
|
this.controls = {
|
||||||
cameraMode: storedControls.cameraMode ?? "player",
|
cameraMode: storedControls.cameraMode ?? "player",
|
||||||
fogEnabled: FOG_CONFIG.enabled,
|
fogEnabled: FOG_CONFIG.enabled,
|
||||||
handTrackingSource: "browser",
|
handTrackingSource: storedControls.handTrackingSource ?? "browser",
|
||||||
showDebugOverlay: true,
|
showDebugOverlay: true,
|
||||||
showHandTrackingSvg: false,
|
showHandTrackingSvg: false,
|
||||||
showInteractionSpheres: false,
|
showInteractionSpheres: false,
|
||||||
@@ -159,7 +167,7 @@ export class Debug {
|
|||||||
.name("Source")
|
.name("Source")
|
||||||
.onChange((value: HandTrackingSource) => {
|
.onChange((value: HandTrackingSource) => {
|
||||||
this.controls.handTrackingSource = value;
|
this.controls.handTrackingSource = value;
|
||||||
this.emit();
|
this.saveAndEmit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +254,7 @@ export class Debug {
|
|||||||
|
|
||||||
setHandTrackingSource(value: HandTrackingSource): void {
|
setHandTrackingSource(value: HandTrackingSource): void {
|
||||||
this.controls.handTrackingSource = value;
|
this.controls.handTrackingSource = value;
|
||||||
this.emit();
|
this.saveAndEmit();
|
||||||
}
|
}
|
||||||
|
|
||||||
getFogEnabled(): boolean {
|
getFogEnabled(): boolean {
|
||||||
@@ -285,6 +293,7 @@ export class Debug {
|
|||||||
DEBUG_CONTROLS_STORAGE_KEY,
|
DEBUG_CONTROLS_STORAGE_KEY,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
cameraMode: this.controls.cameraMode,
|
cameraMode: this.controls.cameraMode,
|
||||||
|
handTrackingSource: this.controls.handTrackingSource,
|
||||||
sceneMode: this.controls.sceneMode,
|
sceneMode: this.controls.sceneMode,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user