generic selection / hover
This commit is contained in:
@@ -1,58 +1,68 @@
|
||||
'use client'
|
||||
"use client";
|
||||
|
||||
import type { BuildingNode, ItemNode, LevelNode, Zone } from '@pascal-app/core'
|
||||
import type { Object3D } from 'three'
|
||||
import type {
|
||||
AnyNode,
|
||||
BaseNode,
|
||||
BuildingNode,
|
||||
LevelNode,
|
||||
Zone,
|
||||
} from "@pascal-app/core";
|
||||
import type { Object3D } from "three";
|
||||
|
||||
import { create } from 'zustand'
|
||||
import { create } from "zustand";
|
||||
|
||||
type SelectionPath = {
|
||||
buildingId: BuildingNode['id'] | null
|
||||
levelId: LevelNode['id'] | null
|
||||
zoneId: Zone['id'] | null
|
||||
selectedIds: ItemNode['id'][] // For items/assets (multi-select)
|
||||
}
|
||||
buildingId: BuildingNode["id"] | null;
|
||||
levelId: LevelNode["id"] | null;
|
||||
zoneId: Zone["id"] | null;
|
||||
selectedIds: BaseNode["id"][]; // For items/assets (multi-select)
|
||||
};
|
||||
|
||||
type Outliner = {
|
||||
selectedObjects: Object3D[]
|
||||
hoveredObjects: Object3D[]
|
||||
}
|
||||
selectedObjects: Object3D[];
|
||||
hoveredObjects: Object3D[];
|
||||
};
|
||||
|
||||
type ViewerState = {
|
||||
selection: SelectionPath
|
||||
levelMode: 'stacked' | 'exploded' | 'solo' | 'manual'
|
||||
selection: SelectionPath;
|
||||
hoveredId: AnyNode["id"] | null;
|
||||
setHoveredId: (id: AnyNode["id"] | null) => void;
|
||||
|
||||
// Actions
|
||||
setLevelMode: (mode: 'stacked' | 'exploded' | 'solo' | 'manual') => void
|
||||
levelMode: "stacked" | "exploded" | "solo" | "manual";
|
||||
setLevelMode: (mode: "stacked" | "exploded" | "solo" | "manual") => void;
|
||||
|
||||
// Smart selection update
|
||||
setSelection: (updates: Partial<SelectionPath>) => void
|
||||
resetSelection: () => void
|
||||
setSelection: (updates: Partial<SelectionPath>) => void;
|
||||
resetSelection: () => void;
|
||||
|
||||
outliner: Outliner // No setter as we will manipulate directly the arrays
|
||||
}
|
||||
outliner: Outliner; // No setter as we will manipulate directly the arrays
|
||||
};
|
||||
|
||||
const useViewer = create<ViewerState>()((set, get) => ({
|
||||
selection: { buildingId: null, levelId: null, zoneId: null, selectedIds: [] },
|
||||
levelMode: 'stacked',
|
||||
hoveredId: null,
|
||||
setHoveredId: (id) => set({ hoveredId: id }),
|
||||
|
||||
levelMode: "stacked",
|
||||
setLevelMode: (mode) => set({ levelMode: mode }),
|
||||
|
||||
setSelection: (updates) =>
|
||||
set((state) => {
|
||||
const newSelection = { ...state.selection, ...updates }
|
||||
const newSelection = { ...state.selection, ...updates };
|
||||
|
||||
// Hierarchy Guard: If we change a high-level parent, reset the children
|
||||
if (updates.buildingId !== undefined) {
|
||||
newSelection.levelId = null
|
||||
newSelection.zoneId = null
|
||||
newSelection.selectedIds = []
|
||||
newSelection.levelId = null;
|
||||
newSelection.zoneId = null;
|
||||
newSelection.selectedIds = [];
|
||||
} else if (updates.levelId !== undefined) {
|
||||
newSelection.zoneId = null
|
||||
newSelection.selectedIds = []
|
||||
newSelection.zoneId = null;
|
||||
newSelection.selectedIds = [];
|
||||
} else if (updates.zoneId !== undefined) {
|
||||
newSelection.selectedIds = []
|
||||
newSelection.selectedIds = [];
|
||||
}
|
||||
|
||||
return { selection: newSelection }
|
||||
return { selection: newSelection };
|
||||
}),
|
||||
|
||||
resetSelection: () =>
|
||||
@@ -66,6 +76,6 @@ const useViewer = create<ViewerState>()((set, get) => ({
|
||||
}),
|
||||
|
||||
outliner: { selectedObjects: [], hoveredObjects: [] },
|
||||
}))
|
||||
}));
|
||||
|
||||
export default useViewer
|
||||
export default useViewer;
|
||||
|
||||
Reference in New Issue
Block a user