250 lines
9.5 KiB
TypeScript
250 lines
9.5 KiB
TypeScript
import { create } from 'zustand';
|
|
import { immer } from 'zustand/middleware/immer';
|
|
|
|
interface WallStore {
|
|
walls: Wall[];
|
|
setWalls: (walls: Wall[]) => void;
|
|
addWall: (wall: Wall) => void;
|
|
updateWall: (uuid: string, updated: Partial<Wall>) => Wall | undefined;
|
|
removeWall: (uuid: string) => void;
|
|
clearWalls: () => void;
|
|
removeWallByPoints: (Points: [Point, Point]) => Wall | undefined;
|
|
addDecal: (wallUuid: string, decal: Decal) => void;
|
|
updateDecal: (decalUuid: string, decal: Decal) => Wall | undefined;
|
|
removeDecal: (decalUuid: string) => Wall | undefined;
|
|
updateDecalPosition: (decalUuid: string, position: [number, number, number]) => Wall | undefined;
|
|
updateDecalRotation: (decalUuid: string, rotation: number) => void;
|
|
updateDecalScale: (decalUuid: string, scale: number) => void;
|
|
|
|
removePoint: (pointUuid: string) => Wall[];
|
|
setPosition: (pointUuid: string, position: [number, number, number]) => Wall[] | [];
|
|
setLayer: (pointUuid: string, layer: number) => void;
|
|
|
|
getWallById: (uuid: string) => Wall | undefined;
|
|
getWallsByPointId: (uuid: string) => Wall[] | [];
|
|
getWallByPoints: (points: Point[]) => Wall | undefined;
|
|
getWallPointById: (uuid: string) => Point | undefined;
|
|
getConnectedPoints: (uuid: string) => Point[];
|
|
getConnectedWallsByWallId: (wallUuid: string, skipSelf: boolean) => Wall[];
|
|
}
|
|
|
|
export const createWallStore = () => {
|
|
return create<WallStore>()(
|
|
immer((set, get) => ({
|
|
walls: [],
|
|
|
|
setWalls: (walls) => set((state) => {
|
|
state.walls = walls;
|
|
}),
|
|
|
|
addWall: (wall) => set((state) => {
|
|
state.walls.push(wall);
|
|
}),
|
|
|
|
updateWall: (uuid, updated) => {
|
|
let updatedWall: Wall | undefined;
|
|
set((state) => {
|
|
const wall = state.walls.find(w => w.wallUuid === uuid);
|
|
if (wall) {
|
|
Object.assign(wall, updated);
|
|
updatedWall = JSON.parse(JSON.stringify(wall));
|
|
}
|
|
});
|
|
return updatedWall;
|
|
},
|
|
|
|
removeWall: (uuid) => set((state) => {
|
|
state.walls = state.walls.filter(w => w.wallUuid !== uuid);
|
|
}),
|
|
|
|
clearWalls: () => {
|
|
set((state) => {
|
|
state.walls = [];
|
|
})
|
|
},
|
|
|
|
removeWallByPoints: (points) => {
|
|
let removedWall: Wall | undefined;
|
|
const [pointA, pointB] = points;
|
|
|
|
set((state) => {
|
|
state.walls = state.walls.filter(wall => {
|
|
const wallPoints = wall.points.map(p => p.pointUuid);
|
|
const hasBothPoints = wallPoints.includes(pointA.pointUuid) && wallPoints.includes(pointB.pointUuid);
|
|
|
|
if (hasBothPoints) {
|
|
removedWall = JSON.parse(JSON.stringify(wall));
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
});
|
|
|
|
return removedWall;
|
|
},
|
|
|
|
addDecal: (wallUuid, decal) => set((state) => {
|
|
const wallToUpdate = state.walls.find(w => w.wallUuid === wallUuid);
|
|
if (wallToUpdate) {
|
|
wallToUpdate.decals.push(decal);
|
|
}
|
|
}),
|
|
|
|
updateDecal: (decalUuid, decal) => {
|
|
let affectedWall: Wall | undefined;
|
|
set((state) => {
|
|
for (const wall of state.walls) {
|
|
const decalToUpdate = wall.decals.find(d => d.decalUuid === decalUuid);
|
|
if (decalToUpdate) {
|
|
Object.assign(decalToUpdate, decal);
|
|
affectedWall = JSON.parse(JSON.stringify(wall));
|
|
}
|
|
}
|
|
});
|
|
return affectedWall;
|
|
},
|
|
|
|
removeDecal: (decalUuid) => {
|
|
let affectedWall: Wall | undefined;
|
|
set((state) => {
|
|
for (const wall of state.walls) {
|
|
const hasDecal = wall.decals.some(d => d.decalUuid === decalUuid);
|
|
if (hasDecal) {
|
|
wall.decals = wall.decals.filter(d => d.decalUuid !== decalUuid);
|
|
affectedWall = JSON.parse(JSON.stringify(wall));
|
|
}
|
|
}
|
|
});
|
|
return affectedWall;
|
|
},
|
|
|
|
updateDecalPosition: (decalUuid, position) => {
|
|
let affectedWall: Wall | undefined;
|
|
set((state) => {
|
|
for (const wall of state.walls) {
|
|
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
|
|
if (decal) {
|
|
decal.decalPosition = position;
|
|
affectedWall = JSON.parse(JSON.stringify(wall));
|
|
break;
|
|
}
|
|
}
|
|
})
|
|
return affectedWall;
|
|
},
|
|
|
|
updateDecalRotation: (decalUuid, rotation) => set((state) => {
|
|
for (const wall of state.walls) {
|
|
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
|
|
if (decal) {
|
|
decal.decalRotation = rotation;
|
|
break;
|
|
}
|
|
}
|
|
}),
|
|
|
|
updateDecalScale: (decalUuid, scale) => set((state) => {
|
|
for (const wall of state.walls) {
|
|
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
|
|
if (decal) {
|
|
decal.decalScale = scale;
|
|
break;
|
|
}
|
|
}
|
|
}),
|
|
|
|
removePoint: (pointUuid) => {
|
|
const removedWalls: Wall[] = [];
|
|
set((state) => {
|
|
state.walls = state.walls.filter((wall) => {
|
|
const hasPoint = wall.points.some(p => p.pointUuid === pointUuid);
|
|
if (hasPoint) {
|
|
removedWalls.push(JSON.parse(JSON.stringify(wall)));
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
});
|
|
return removedWalls;
|
|
},
|
|
|
|
setPosition: (pointUuid, position) => {
|
|
let updatedWalls: Wall[] = [];
|
|
set((state) => {
|
|
for (const wall of state.walls) {
|
|
const point = wall.points.find(p => p.pointUuid === pointUuid);
|
|
if (point) {
|
|
point.position = position;
|
|
updatedWalls.push(wall);
|
|
}
|
|
}
|
|
});
|
|
return updatedWalls;
|
|
},
|
|
|
|
setLayer: (pointUuid, layer) => set((state) => {
|
|
for (const wall of state.walls) {
|
|
const point = wall.points.find(p => p.pointUuid === pointUuid);
|
|
if (point) {
|
|
point.layer = layer;
|
|
}
|
|
}
|
|
}),
|
|
|
|
getWallById: (uuid) => {
|
|
return get().walls.find(w => w.wallUuid === uuid);
|
|
},
|
|
|
|
getWallsByPointId: (uuid) => {
|
|
return get().walls.filter((a) => {
|
|
return JSON.parse(JSON.stringify(a.points.some((p) => p.pointUuid === uuid)));
|
|
})
|
|
},
|
|
|
|
getWallByPoints: (point) => {
|
|
for (const wall of get().walls) {
|
|
if (((wall.points[0].pointUuid === point[0].pointUuid) || (wall.points[1].pointUuid === point[0].pointUuid)) &&
|
|
((wall.points[0].pointUuid === point[1].pointUuid) || (wall.points[1].pointUuid === point[1].pointUuid))) {
|
|
return wall;
|
|
}
|
|
}
|
|
return undefined;
|
|
},
|
|
|
|
getWallPointById: (uuid) => {
|
|
for (const wall of get().walls) {
|
|
const point = wall.points.find(p => p.pointUuid === uuid);
|
|
if (point) return point;
|
|
}
|
|
return undefined;
|
|
},
|
|
|
|
getConnectedPoints: (uuid) => {
|
|
const connected: Point[] = [];
|
|
for (const wall of get().walls) {
|
|
for (const point of wall.points) {
|
|
if (point.pointUuid === uuid) {
|
|
connected.push(...wall.points.filter(p => p.pointUuid !== uuid));
|
|
}
|
|
}
|
|
}
|
|
return connected;
|
|
},
|
|
|
|
getConnectedWallsByWallId: (wallUuid, skipSelf) => {
|
|
const wall = get().walls.find(w => w.wallUuid === wallUuid);
|
|
if (!wall) return [];
|
|
|
|
const pointUuids = wall.points.map(p => p.pointUuid);
|
|
|
|
return get().walls.filter(w => {
|
|
if (skipSelf && w.wallUuid === wallUuid) return false;
|
|
return w.points.some(p => pointUuids.includes(p.pointUuid));
|
|
});
|
|
},
|
|
|
|
}))
|
|
)
|
|
}
|
|
|
|
export type WallStoreType = ReturnType<typeof createWallStore>; |