generic selection / hover

This commit is contained in:
wass08
2026-01-21 11:40:42 +09:00
parent b1d6f61e4f
commit 09515107cb
2 changed files with 151 additions and 203 deletions
+41 -31
View File
@@ -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;