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 url?: string; // legacy, ignored — uses store.models
} }
/** Walk up the parent chain until we find a node tagged as `ifcElement`, function isPickableModelMesh(obj: THREE.Object3D): obj is THREE.Mesh {
* or the model root. Returns null if neither found. */ 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 { 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; let cur: THREE.Object3D | null = obj;
while (cur) { while (cur) {
if (cur.userData?.ifcElement) return cur; if (cur.userData?.ifcElement) return cur;
cur = cur.parent; 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. */ /** 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; mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
raycaster.setFromCamera(mouse, camera); raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children, true); const intersects = raycaster.intersectObjects(scene.children, true);
const hit = intersects.find((i) => { const hit = intersects.find((i) => isPickableModelMesh(i.object));
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;
});
if (!hit) return; if (!hit) return;
const element = findElementRoot(hit.object);
let cur: THREE.Object3D | null = hit.object; let cur: THREE.Object3D | null = hit.object;
let element: THREE.Object3D | null = null;
let modelId: string | null = null; let modelId: string | null = null;
while (cur) { while (cur) {
if (!element && cur.userData?.ifcElement) element = cur;
if (!modelId && cur.userData?.modelId) modelId = cur.userData.modelId as string; if (!modelId && cur.userData?.modelId) modelId = cur.userData.modelId as string;
cur = cur.parent; cur = cur.parent;
} }
if (!element) element = hit.object;
if (!modelId) modelId = useModelStore.getState().activeModelId; if (!modelId) modelId = useModelStore.getState().activeModelId;
if (!modelId || !element) return; if (!modelId || !element) return;
const key = elementKey(modelId, element); const key = elementKey(modelId, element);
@@ -759,7 +769,7 @@ function VisibilityApplier() {
const modelId = root.userData?.modelId as string | undefined; const modelId = root.userData?.modelId as string | undefined;
if (!modelId) return; if (!modelId) return;
root.traverse((el) => { root.traverse((el) => {
if (!el.userData?.ifcElement) return; if (!el.userData?.ifcElement && !(isPickableModelMesh(el) && !hasIfcAncestor(el))) return;
const key = elementKey(modelId, el); const key = elementKey(modelId, el);
const hidden = hiddenElementKeys.has(key); const hidden = hiddenElementKeys.has(key);
const isolated = isolatedElementKeys ? !isolatedElementKeys.has(key) : false; const isolated = isolatedElementKeys ? !isolatedElementKeys.has(key) : false;
@@ -1044,7 +1054,7 @@ export function ModelViewerCanvas({ url }: ModelViewerProps) {
dampingFactor={0.1} dampingFactor={0.1}
minDistance={0.05} minDistance={0.05}
maxDistance={50} maxDistance={50}
enabled={!positionMode && !selectionMode} enabled={!positionMode}
/> />
</Canvas> </Canvas>
+1 -1
View File
@@ -514,7 +514,7 @@ export const useModelStore = create<ModelStore>((set, get) => ({
setSelectionMode: (on) => set((s) => ({ setSelectionMode: (on) => set((s) => ({
selectionMode: on, selectionMode: on,
measureMode: on ? false : s.measureMode, measureMode: on ? false : s.measureMode,
positionMode: on ? false : s.positionMode, positionMode: s.positionMode,
selectedElementKeys: on ? s.selectedElementKeys : new Set(), selectedElementKeys: on ? s.selectedElementKeys : new Set(),
})), })),
selectedElementKeys: new Set<string>(), selectedElementKeys: new Set<string>(),