polish(ui): refine pause settings menu
This commit is contained in:
@@ -3,9 +3,11 @@ import type { ReactNode } from "react";
|
|||||||
import {
|
import {
|
||||||
Captions,
|
Captions,
|
||||||
Gauge,
|
Gauge,
|
||||||
LogOut,
|
Hand,
|
||||||
|
Laptop,
|
||||||
Music2,
|
Music2,
|
||||||
RotateCcw,
|
RotateCcw,
|
||||||
|
Server,
|
||||||
Volume2,
|
Volume2,
|
||||||
X,
|
X,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
@@ -14,25 +16,19 @@ import {
|
|||||||
GRAPHICS_PRESETS,
|
GRAPHICS_PRESETS,
|
||||||
type GraphicsPreset,
|
type GraphicsPreset,
|
||||||
} from "@/data/world/graphicsConfig";
|
} from "@/data/world/graphicsConfig";
|
||||||
|
import { useDebugStore } from "@/hooks/debug/useDebugStore";
|
||||||
import { useGameStore } from "@/managers/stores/useGameStore";
|
import { useGameStore } from "@/managers/stores/useGameStore";
|
||||||
import { useSettingsStore } from "@/managers/stores/useSettingsStore";
|
import { useSettingsStore } from "@/managers/stores/useSettingsStore";
|
||||||
import { useWorldSettingsStore } from "@/managers/stores/useWorldSettingsStore";
|
import { useWorldSettingsStore } from "@/managers/stores/useWorldSettingsStore";
|
||||||
|
import type { HandTrackingSource } from "@/types/handTracking/handTracking";
|
||||||
import type { SubtitleLanguage } from "@/types/settings/settings";
|
import type { SubtitleLanguage } from "@/types/settings/settings";
|
||||||
import { isDebugEnabled } from "@/utils/debug/isDebugEnabled";
|
import { clearSiteVisited } from "@/utils/cookies/siteVisitCookie";
|
||||||
|
import { Debug } from "@/utils/debug/Debug";
|
||||||
|
|
||||||
function formatPercent(value: number): string {
|
function formatPercent(value: number): string {
|
||||||
return `${Math.round(value * 100)}%`;
|
return `${Math.round(value * 100)}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearCookies(): void {
|
|
||||||
document.cookie.split(";").forEach((cookie) => {
|
|
||||||
const cookieName = cookie.split("=")[0]?.trim();
|
|
||||||
if (!cookieName) return;
|
|
||||||
|
|
||||||
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VolumeSliderProps {
|
interface VolumeSliderProps {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
@@ -74,6 +70,26 @@ function formatChunkDistance(distance: number): string {
|
|||||||
return `${distance}m`;
|
return `${distance}m`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HAND_TRACKING_OPTIONS = [
|
||||||
|
{
|
||||||
|
description: "Calcul local",
|
||||||
|
icon: <Laptop size={14} aria-hidden="true" />,
|
||||||
|
label: "Sur cet ordi",
|
||||||
|
source: "browser",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Soulage l'ordi",
|
||||||
|
icon: <Server size={14} aria-hidden="true" />,
|
||||||
|
label: "Mode assisté",
|
||||||
|
source: "backend",
|
||||||
|
},
|
||||||
|
] as const satisfies readonly {
|
||||||
|
description: string;
|
||||||
|
icon: ReactNode;
|
||||||
|
label: string;
|
||||||
|
source: HandTrackingSource;
|
||||||
|
}[];
|
||||||
|
|
||||||
interface GraphicsPresetButtonProps {
|
interface GraphicsPresetButtonProps {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
preset: GraphicsPreset;
|
preset: GraphicsPreset;
|
||||||
@@ -108,6 +124,9 @@ function GraphicsPresetButton({
|
|||||||
|
|
||||||
export function GameSettingsMenu(): React.JSX.Element | null {
|
export function GameSettingsMenu(): React.JSX.Element | null {
|
||||||
const resetGame = useGameStore((state) => state.resetGame);
|
const resetGame = useGameStore((state) => state.resetGame);
|
||||||
|
const handTrackingSource = useDebugStore((debug) =>
|
||||||
|
debug.getHandTrackingSource(),
|
||||||
|
);
|
||||||
const graphicsPreset = useWorldSettingsStore(
|
const graphicsPreset = useWorldSettingsStore(
|
||||||
(state) => state.graphics.preset,
|
(state) => state.graphics.preset,
|
||||||
);
|
);
|
||||||
@@ -148,18 +167,17 @@ export function GameSettingsMenu(): React.JSX.Element | null {
|
|||||||
|
|
||||||
if (!isSettingsMenuOpen) return null;
|
if (!isSettingsMenuOpen) return null;
|
||||||
|
|
||||||
const handleQuit = (): void => {
|
const handleRestart = (): void => {
|
||||||
clearCookies();
|
resetGame();
|
||||||
|
clearSiteVisited();
|
||||||
|
setSettingsMenuOpen(false);
|
||||||
window.location.assign("/");
|
window.location.assign("/");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRestart = (): void => {
|
const handleHandTrackingSourceChange = (source: HandTrackingSource): void => {
|
||||||
resetGame();
|
Debug.getInstance().setHandTrackingSource(source);
|
||||||
window.location.reload();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const showDebugRestart = isDebugEnabled();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="game-settings-menu" role="dialog" aria-modal="true">
|
<div className="game-settings-menu" role="dialog" aria-modal="true">
|
||||||
<div className="game-settings-menu__panel">
|
<div className="game-settings-menu__panel">
|
||||||
@@ -185,7 +203,7 @@ export function GameSettingsMenu(): React.JSX.Element | null {
|
|||||||
>
|
>
|
||||||
<div className="game-settings-menu__section-title">
|
<div className="game-settings-menu__section-title">
|
||||||
<Gauge size={16} aria-hidden="true" />
|
<Gauge size={16} aria-hidden="true" />
|
||||||
<h3 id="graphics-settings-heading">Performance</h3>
|
<h3 id="graphics-settings-heading">Graphisme</h3>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="game-settings-menu__choice-group game-settings-menu__choice-group--presets"
|
className="game-settings-menu__choice-group game-settings-menu__choice-group--presets"
|
||||||
@@ -269,9 +287,38 @@ export function GameSettingsMenu(): React.JSX.Element | null {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
className="game-settings-menu__section game-settings-menu__section--right"
|
||||||
|
aria-labelledby="hand-tracking-settings-heading"
|
||||||
|
>
|
||||||
|
<div className="game-settings-menu__section-title">
|
||||||
|
<Hand size={16} aria-hidden="true" />
|
||||||
|
<h3 id="hand-tracking-settings-heading">Détection des mains</h3>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="game-settings-menu__choice-group game-settings-menu__choice-group--hand-tracking"
|
||||||
|
aria-label="Mode de détection des mains"
|
||||||
|
>
|
||||||
|
{HAND_TRACKING_OPTIONS.map((option) => (
|
||||||
|
<button
|
||||||
|
key={option.source}
|
||||||
|
type="button"
|
||||||
|
className={
|
||||||
|
handTrackingSource === option.source ? "active" : undefined
|
||||||
|
}
|
||||||
|
onClick={() => handleHandTrackingSourceChange(option.source)}
|
||||||
|
aria-pressed={handTrackingSource === option.source}
|
||||||
|
>
|
||||||
|
{option.icon}
|
||||||
|
<span>{option.label}</span>
|
||||||
|
<small>{option.description}</small>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showDebugRestart ? (
|
|
||||||
<button
|
<button
|
||||||
className="game-settings-menu__restart"
|
className="game-settings-menu__restart"
|
||||||
type="button"
|
type="button"
|
||||||
@@ -280,16 +327,6 @@ export function GameSettingsMenu(): React.JSX.Element | null {
|
|||||||
<RotateCcw size={14} aria-hidden="true" />
|
<RotateCcw size={14} aria-hidden="true" />
|
||||||
Recommencer
|
Recommencer
|
||||||
</button>
|
</button>
|
||||||
) : null}
|
|
||||||
|
|
||||||
<button
|
|
||||||
className="game-settings-menu__quit"
|
|
||||||
type="button"
|
|
||||||
onClick={handleQuit}
|
|
||||||
>
|
|
||||||
<LogOut size={14} aria-hidden="true" />
|
|
||||||
Quitter
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
+30
-21
@@ -1220,8 +1220,8 @@ canvas {
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
padding: clamp(18px, 4vw, 42px);
|
padding: clamp(18px, 4vw, 42px);
|
||||||
background:
|
background:
|
||||||
linear-gradient(180deg, rgba(4, 10, 18, 0.64), rgba(2, 6, 12, 0.86)),
|
linear-gradient(180deg, rgba(4, 10, 18, 0.72), rgba(2, 6, 12, 0.9)),
|
||||||
rgba(0, 0, 0, 0.72);
|
rgba(0, 0, 0, 0.82);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
backdrop-filter: blur(14px);
|
backdrop-filter: blur(14px);
|
||||||
@@ -1236,8 +1236,8 @@ canvas {
|
|||||||
border: 1px solid rgba(125, 211, 252, 0.38);
|
border: 1px solid rgba(125, 211, 252, 0.38);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background:
|
background:
|
||||||
linear-gradient(180deg, rgba(8, 20, 34, 0.94), rgba(3, 8, 14, 0.96)),
|
linear-gradient(180deg, rgba(8, 20, 34, 0.98), rgba(3, 8, 14, 0.99)),
|
||||||
rgba(4, 8, 12, 0.96);
|
rgba(4, 8, 12, 0.99);
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 28px 90px rgba(0, 0, 0, 0.58),
|
0 28px 90px rgba(0, 0, 0, 0.58),
|
||||||
inset 0 0 0 1px rgba(255, 255, 255, 0.05),
|
inset 0 0 0 1px rgba(255, 255, 255, 0.05),
|
||||||
@@ -1327,13 +1327,17 @@ canvas {
|
|||||||
padding: 14px;
|
padding: 14px;
|
||||||
border: 1px solid rgba(125, 211, 252, 0.2);
|
border: 1px solid rgba(125, 211, 252, 0.2);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: rgba(5, 14, 24, 0.64);
|
background: rgba(5, 14, 24, 0.78);
|
||||||
}
|
}
|
||||||
|
|
||||||
.game-settings-menu__section--wide {
|
.game-settings-menu__section--wide {
|
||||||
grid-column: 1 / -1;
|
grid-column: 1 / -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game-settings-menu__section--right {
|
||||||
|
grid-column: 2;
|
||||||
|
}
|
||||||
|
|
||||||
.game-settings-menu__section-title {
|
.game-settings-menu__section-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1408,8 +1412,7 @@ canvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.game-settings-menu__choice-group button,
|
.game-settings-menu__choice-group button,
|
||||||
.game-settings-menu__restart,
|
.game-settings-menu__restart {
|
||||||
.game-settings-menu__quit {
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -1419,7 +1422,7 @@ canvas {
|
|||||||
padding: 11px 12px;
|
padding: 11px 12px;
|
||||||
border: 1px solid rgba(125, 211, 252, 0.2);
|
border: 1px solid rgba(125, 211, 252, 0.2);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: rgba(6, 18, 30, 0.72);
|
background: rgba(6, 18, 30, 0.84);
|
||||||
color: #edfaff;
|
color: #edfaff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 0.88rem;
|
font-size: 0.88rem;
|
||||||
@@ -1451,12 +1454,21 @@ canvas {
|
|||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game-settings-menu__choice-group--hand-tracking button {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
justify-content: start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-settings-menu__choice-group--hand-tracking button small {
|
||||||
|
grid-column: 2;
|
||||||
|
}
|
||||||
|
|
||||||
.game-settings-menu__choice-group button:hover,
|
.game-settings-menu__choice-group button:hover,
|
||||||
.game-settings-menu__choice-group button:focus-visible,
|
.game-settings-menu__choice-group button:focus-visible,
|
||||||
.game-settings-menu__restart:hover,
|
.game-settings-menu__restart:hover,
|
||||||
.game-settings-menu__restart:focus-visible,
|
.game-settings-menu__restart:focus-visible {
|
||||||
.game-settings-menu__quit:hover,
|
|
||||||
.game-settings-menu__quit:focus-visible {
|
|
||||||
border-color: rgba(255, 255, 255, 0.64);
|
border-color: rgba(255, 255, 255, 0.64);
|
||||||
background: rgba(125, 211, 252, 0.16);
|
background: rgba(125, 211, 252, 0.16);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
@@ -1464,8 +1476,7 @@ canvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.game-settings-menu__choice-group button:active,
|
.game-settings-menu__choice-group button:active,
|
||||||
.game-settings-menu__restart:active,
|
.game-settings-menu__restart:active {
|
||||||
.game-settings-menu__quit:active {
|
|
||||||
transform: translateY(1px);
|
transform: translateY(1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1488,14 +1499,8 @@ canvas {
|
|||||||
|
|
||||||
.game-settings-menu__restart {
|
.game-settings-menu__restart {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
border-color: rgba(96, 165, 250, 0.35);
|
border-color: rgba(125, 211, 252, 0.35);
|
||||||
color: #bfdbfe;
|
color: #dff7ff;
|
||||||
}
|
|
||||||
|
|
||||||
.game-settings-menu__quit {
|
|
||||||
margin-top: 8px;
|
|
||||||
border-color: rgba(248, 113, 113, 0.35);
|
|
||||||
color: #fecaca;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
@@ -1512,6 +1517,10 @@ canvas {
|
|||||||
.game-settings-menu__choice-group--presets {
|
.game-settings-menu__choice-group--presets {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game-settings-menu__section--right {
|
||||||
|
grid-column: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Debug overlay panels */
|
/* Debug overlay panels */
|
||||||
|
|||||||
@@ -244,6 +244,11 @@ export class Debug {
|
|||||||
return this.controls.handTrackingSource;
|
return this.controls.handTrackingSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setHandTrackingSource(value: HandTrackingSource): void {
|
||||||
|
this.controls.handTrackingSource = value;
|
||||||
|
this.emit();
|
||||||
|
}
|
||||||
|
|
||||||
getFogEnabled(): boolean {
|
getFogEnabled(): boolean {
|
||||||
return this.controls.fogEnabled;
|
return this.controls.fogEnabled;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user