From 6b16009b5bca6819b648bc729e628cdffbb38e9f Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 17:11:54 +0000 Subject: [PATCH 1/5] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/components/three/ModelViewer.tsx | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/components/three/ModelViewer.tsx b/src/components/three/ModelViewer.tsx index 81200d6..24e460e 100644 --- a/src/components/three/ModelViewer.tsx +++ b/src/components/three/ModelViewer.tsx @@ -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. */ From 4f8a4129fde25defab5cf4a4d1c79b0deba181c7 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 17:12:03 +0000 Subject: [PATCH 2/5] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/components/three/ModelViewer.tsx | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/components/three/ModelViewer.tsx b/src/components/three/ModelViewer.tsx index 24e460e..9c4132e 100644 --- a/src/components/three/ModelViewer.tsx +++ b/src/components/three/ModelViewer.tsx @@ -723,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); From 247b2c0abb183e31dc6461b4226f9cbd9fc59189 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 17:12:09 +0000 Subject: [PATCH 3/5] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/components/three/ModelViewer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/three/ModelViewer.tsx b/src/components/three/ModelViewer.tsx index 9c4132e..b6cbf11 100644 --- a/src/components/three/ModelViewer.tsx +++ b/src/components/three/ModelViewer.tsx @@ -769,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; From a46451f8d02b60e38c2cd963cee7c7192097ab44 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 17:12:15 +0000 Subject: [PATCH 4/5] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/components/three/ModelViewer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/three/ModelViewer.tsx b/src/components/three/ModelViewer.tsx index b6cbf11..91350cd 100644 --- a/src/components/three/ModelViewer.tsx +++ b/src/components/three/ModelViewer.tsx @@ -1054,7 +1054,7 @@ export function ModelViewerCanvas({ url }: ModelViewerProps) { dampingFactor={0.1} minDistance={0.05} maxDistance={50} - enabled={!positionMode && !selectionMode} + enabled={!positionMode} /> From 043c8dad8ca441e3cd272f31eb6b9a8696bd921a Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 17:12:24 +0000 Subject: [PATCH 5/5] Changes Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com> --- src/stores/useModelStore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/useModelStore.ts b/src/stores/useModelStore.ts index 11182e9..6bb5177 100644 --- a/src/stores/useModelStore.ts +++ b/src/stores/useModelStore.ts @@ -514,7 +514,7 @@ export const useModelStore = create((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(),