Corrigiu seleção de chapas e bloqueio

X-Lovable-Edit-ID: edt-1984935b-5500-4f44-84a9-a0d5f5eeb8db
Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-05-21 17:13:00 +00:00
2 changed files with 28 additions and 18 deletions
+27 -17
View File
@@ -10,15 +10,35 @@ interface ModelViewerProps {
url?: string; // legacy, ignored — uses store.models
}
/** Walk up the parent chain until we find a node tagged as `ifcElement`,
* or the model root. Returns null if neither found. */
function isPickableModelMesh(obj: THREE.Object3D): obj is THREE.Mesh {
if (!(obj instanceof THREE.Mesh)) return false;
if (obj.userData.__edgeLine) return false;
if (obj.geometry instanceof THREE.SphereGeometry) return false;
if (obj.geometry instanceof THREE.RingGeometry) return false;
if (obj.geometry instanceof THREE.PlaneGeometry) return false;
return true;
}
/** Walk up the parent chain until we find a node tagged as `ifcElement`.
* Falls back to the clicked mesh so older/demo GLBs without IFC metadata
* still support selection/highlight. */
export function findElementRoot(obj: THREE.Object3D | null): THREE.Object3D | null {
const fallback = isPickableModelMesh(obj as THREE.Object3D) ? obj : null;
let cur: THREE.Object3D | null = obj;
while (cur) {
if (cur.userData?.ifcElement) return cur;
cur = cur.parent;
}
return null;
return fallback;
}
function hasIfcAncestor(obj: THREE.Object3D): boolean {
let cur = obj.parent;
while (cur) {
if (cur.userData?.ifcElement) return true;
cur = cur.parent;
}
return false;
}
/** Stable key for an element across reloads: prefers ifcId, falls back to name. */
@@ -703,26 +723,16 @@ function SelectionHandler() {
mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
const hit = intersects.find((i) => {
const o = i.object;
if (!(o instanceof THREE.Mesh)) return false;
if (o.userData.__edgeLine) return false;
if (o.geometry instanceof THREE.SphereGeometry) return false;
if (o.geometry instanceof THREE.RingGeometry) return false;
if (o.geometry instanceof THREE.PlaneGeometry) return false;
return true;
});
const hit = intersects.find((i) => isPickableModelMesh(i.object));
if (!hit) return;
const element = findElementRoot(hit.object);
let cur: THREE.Object3D | null = hit.object;
let element: THREE.Object3D | null = null;
let modelId: string | null = null;
while (cur) {
if (!element && cur.userData?.ifcElement) element = cur;
if (!modelId && cur.userData?.modelId) modelId = cur.userData.modelId as string;
cur = cur.parent;
}
if (!element) element = hit.object;
if (!modelId) modelId = useModelStore.getState().activeModelId;
if (!modelId || !element) return;
const key = elementKey(modelId, element);
@@ -759,7 +769,7 @@ function VisibilityApplier() {
const modelId = root.userData?.modelId as string | undefined;
if (!modelId) return;
root.traverse((el) => {
if (!el.userData?.ifcElement) return;
if (!el.userData?.ifcElement && !(isPickableModelMesh(el) && !hasIfcAncestor(el))) return;
const key = elementKey(modelId, el);
const hidden = hiddenElementKeys.has(key);
const isolated = isolatedElementKeys ? !isolatedElementKeys.has(key) : false;
@@ -1044,7 +1054,7 @@ export function ModelViewerCanvas({ url }: ModelViewerProps) {
dampingFactor={0.1}
minDistance={0.05}
maxDistance={50}
enabled={!positionMode && !selectionMode}
enabled={!positionMode}
/>
</Canvas>
+1 -1
View File
@@ -514,7 +514,7 @@ export const useModelStore = create<ModelStore>((set, get) => ({
setSelectionMode: (on) => set((s) => ({
selectionMode: on,
measureMode: on ? false : s.measureMode,
positionMode: on ? false : s.positionMode,
positionMode: s.positionMode,
selectedElementKeys: on ? s.selectedElementKeys : new Set(),
})),
selectedElementKeys: new Set<string>(),