import { create } from "zustand"; import { availableModels } from "../data/availableModels.ts"; export interface Vector3D { x: number; y: number; z: number; } export interface HueShift { red: number; green: number; blue: number; } export interface Model3D { id: string; sourceId: string; name: string; url: string; position: Vector3D; rotation: Vector3D; hueShift: HueShift; } export interface AvailableModel { id: string; name: string; url: string; } const CAMERA_VIEWS = [ "perspective", "ortho-top", "ortho-front", "ortho-side", ] as const; export type CameraView = (typeof CAMERA_VIEWS)[number]; export function isValidCameraView(value: string): value is CameraView { return CAMERA_VIEWS.includes(value as CameraView); } export interface StoreState { models: Model3D[]; selectedModelId: string | null; cameraView: CameraView; backdropUrl: string | null; availableModels: AvailableModel[]; sidebarOpen: boolean; addModel: (sourceId: string, position: Vector3D) => void; removeModel: (id: string) => void; selectModel: (id: string | null) => void; updateModel: ( id: string, updates: Partial>, ) => void; setCameraView: (view: CameraView) => void; setBackdrop: (url: string | null) => void; toggleSidebar: () => void; closeSidebar: () => void; } export const useStore = create((set, get) => ({ models: [], selectedModelId: null, cameraView: "perspective", backdropUrl: null, availableModels, sidebarOpen: false, addModel: (sourceId: string, position: Vector3D) => { const { availableModels } = get(); const source = availableModels.find((model) => model.id === sourceId); if (!source) return; const newModel: Model3D = { id: crypto.randomUUID(), sourceId, name: source.name, url: source.url, position, rotation: { x: 0, y: 0, z: 0 }, hueShift: { red: 0, green: 0, blue: 0 }, }; set((state) => ({ models: [...state.models, newModel], selectedModelId: newModel.id, })); }, removeModel: (id: string) => { set((state) => ({ models: state.models.filter((model) => model.id !== id), selectedModelId: state.selectedModelId === id ? null : state.selectedModelId, })); }, selectModel: (id: string | null) => { set({ selectedModelId: id }); }, updateModel: ( id: string, updates: Partial>, ) => { set((state) => ({ models: state.models.map((model) => model.id === id ? { ...model, ...updates } : model, ), })); }, setCameraView: (view: CameraView) => { set({ cameraView: view }); }, setBackdrop: (url: string | null) => { set({ backdropUrl: url }); }, toggleSidebar: () => { set((state) => ({ sidebarOpen: !state.sidebarOpen })); }, closeSidebar: () => { set({ sidebarOpen: false }); }, }));