131 lines
2.9 KiB
TypeScript
131 lines
2.9 KiB
TypeScript
import { z } from "zod/mini";
|
|
import type * as THREE from "three";
|
|
|
|
export const LOGICAL_WIDTH = 256;
|
|
export const LOGICAL_HEIGHT = 192;
|
|
|
|
export const SCREEN_SCALE = 2;
|
|
|
|
export const SCREEN_WIDTH = LOGICAL_WIDTH * SCREEN_SCALE;
|
|
export const SCREEN_HEIGHT = LOGICAL_HEIGHT * SCREEN_SCALE;
|
|
|
|
export const APP_COLORS = [
|
|
["#61829a", "#ba4900", "#fb0018", "#fb8afb"],
|
|
["#fb9200", "#f3e300", "#aafb00", "#00fb00"],
|
|
["#00a238", "#49db8a", "#30baf3", "#0059f3"],
|
|
["#000092", "#8a00d3", "#d300eb", "#fb0092"],
|
|
];
|
|
|
|
const STORAGE_ID = "nds-settings";
|
|
|
|
const settingsSchema = z.object({
|
|
color: z.object({
|
|
col: z.number(),
|
|
row: z.number(),
|
|
}),
|
|
renderingMode: z.enum(["3d", "2d"]),
|
|
volume: z.number(),
|
|
});
|
|
|
|
type Settings = z.infer<typeof settingsSchema>;
|
|
|
|
const defaultSettings = (): Settings => ({
|
|
color: { col: 0, row: 0 },
|
|
renderingMode: "3d",
|
|
volume: 0.5,
|
|
});
|
|
|
|
export const useAppStore = defineStore("app", {
|
|
state: () => {
|
|
let settings: Settings;
|
|
const stored = localStorage.getItem(STORAGE_ID);
|
|
try {
|
|
settings = settingsSchema.parse(JSON.parse(stored ?? ""));
|
|
} catch {
|
|
settings = defaultSettings();
|
|
}
|
|
|
|
return {
|
|
ready: false,
|
|
booted: false,
|
|
userHasInteracted: false,
|
|
settings,
|
|
previousScreen: "home" as AppScreen,
|
|
screen: "home" as AppScreen,
|
|
visitedGallery: false,
|
|
camera: null as THREE.Camera | null,
|
|
hintsVisible: false,
|
|
hintsAllowed: false,
|
|
lagDetected: false,
|
|
};
|
|
},
|
|
|
|
actions: {
|
|
setColor(col: number, row: number) {
|
|
this.settings.color = { col, row };
|
|
},
|
|
|
|
setRenderingMode(mode: Settings["renderingMode"]) {
|
|
this.ready = mode === "2d";
|
|
this.settings.renderingMode = mode;
|
|
this.lagDetected = false;
|
|
this.save();
|
|
},
|
|
|
|
navigateTo(screen: AppScreen) {
|
|
this.previousScreen = this.screen;
|
|
this.screen = screen;
|
|
|
|
const achievements = useAchievementsStore();
|
|
|
|
switch (screen) {
|
|
case "projects":
|
|
achievements.unlock("projects_visit");
|
|
break;
|
|
|
|
case "gallery":
|
|
this.visitedGallery = true;
|
|
break;
|
|
|
|
case "contact":
|
|
achievements.unlock("contact_visit");
|
|
break;
|
|
}
|
|
},
|
|
|
|
allowHints() {
|
|
this.hintsAllowed = true;
|
|
},
|
|
|
|
disallowHints() {
|
|
this.hintsAllowed = false;
|
|
this.hintsVisible = false;
|
|
},
|
|
|
|
showHints() {
|
|
if (!this.hintsAllowed) return;
|
|
this.hintsVisible = true;
|
|
},
|
|
|
|
hideHints() {
|
|
this.hintsVisible = false;
|
|
},
|
|
|
|
setCamera(camera: THREE.Camera) {
|
|
this.camera = camera;
|
|
},
|
|
|
|
save() {
|
|
localStorage.setItem(STORAGE_ID, JSON.stringify(this.settings));
|
|
},
|
|
},
|
|
|
|
getters: {
|
|
color: (state) => ({
|
|
col: state.settings.color.col,
|
|
row: state.settings.color.row,
|
|
hex: APP_COLORS[state.settings.color.row]![state.settings.color.col]!,
|
|
}),
|
|
},
|
|
});
|