diff --git a/src/components/three/ModelViewer.tsx b/src/components/three/ModelViewer.tsx index 1ac27b2..3774e8d 100644 --- a/src/components/three/ModelViewer.tsx +++ b/src/components/three/ModelViewer.tsx @@ -731,6 +731,7 @@ function SmartSnapHandler() { function HoverDetector() { const { camera, scene, gl } = useThree(); const setHoverInfo = useModelStore((s) => s.setHoverInfo); + const setHoverIfcProps = useModelStore((s) => s.setHoverIfcProps); const raycaster = useMemo(() => new THREE.Raycaster(), []); const mouse = useMemo(() => new THREE.Vector2(), []); const hoverTimer = useRef | null>(null); @@ -764,8 +765,8 @@ function HoverDetector() { lastHitKey.current = ''; lastHitExpressId.current = 0; setHoverInfo(null); + setHoverIfcProps(null); clearTimers(); - toast.dismiss('ifc-hover-info'); return; } @@ -778,40 +779,9 @@ function HoverDetector() { const props = elementRoot?.userData?.properties; if (props && (props.name || props.material || props.tag)) { - const infoLines: string[] = []; - if (props.tag || props.name) { - infoLines.push(`Peça: ${props.tag || props.name}`); - } - if (props.material) { - infoLines.push(`Material: ${props.material}`); - } - - const lengthKey = Object.keys(props).find(k => { - const kl = k.toLowerCase(); - return kl.includes('length') || kl.includes('comprimento') || kl.includes('lengthvalue'); - }); - - if (lengthKey && props[lengthKey]) { - infoLines.push(`Comprimento: ${props[lengthKey]}`); - } else { - const commonLengthKeys = ['Length', 'Comprimento', 'LengthValue', 'height', 'comprimento']; - for (const key of commonLengthKeys) { - if (props[key]) { - infoLines.push(`Comprimento: ${props[key]}`); - break; - } - } - } - - if (infoLines.length > 0) { - toast(infoLines.join(' | '), { - id: 'ifc-hover-info', - duration: 8000, - position: 'bottom-center', - }); - } + setHoverIfcProps(props); } else { - toast.dismiss('ifc-hover-info'); + setHoverIfcProps(null); } } @@ -879,8 +849,8 @@ function HoverDetector() { lastHitKey.current = ''; lastHitExpressId.current = 0; setHoverInfo(null); + setHoverIfcProps(null); clearTimers(); - toast.dismiss('ifc-hover-info'); }; gl.domElement.addEventListener('pointermove', onMove); @@ -889,9 +859,9 @@ function HoverDetector() { gl.domElement.removeEventListener('pointermove', onMove); gl.domElement.removeEventListener('pointerleave', onLeave); clearTimers(); - toast.dismiss('ifc-hover-info'); + setHoverIfcProps(null); }; - }, [camera, scene, gl, raycaster, mouse, setHoverInfo]); + }, [camera, scene, gl, raycaster, mouse, setHoverInfo, setHoverIfcProps]); return null; } diff --git a/src/pages/Viewer.tsx b/src/pages/Viewer.tsx index 4cb3b0c..92ab215 100644 --- a/src/pages/Viewer.tsx +++ b/src/pages/Viewer.tsx @@ -35,7 +35,8 @@ const Viewer = () => { fineTuning, sectionEnabled, sectionInvert, - sectionLevel + sectionLevel, + hoverIfcProps } = useModelStore(); const fileInputRef = useRef(null); const [converting, setConverting] = useState(false); @@ -366,6 +367,37 @@ const Viewer = () => { {/* 3D Canvas with floating controls */}
+ {hoverIfcProps && ( +
+
+
+ + Propriedades IFC +
+ + {Object.entries(hoverIfcProps).map(([key, value]) => { + if (!value) return null; + let displayKey = key; + if (key === 'name') displayKey = 'Nome'; + else if (key === 'tag') displayKey = 'Marca'; + else if (key === 'material') displayKey = 'Material'; + else if (key === 'objectType') displayKey = 'Tipo'; + else if (key === 'description') displayKey = 'Descrição'; + + return ( +
+ {displayKey} + {value} +
+ ); + })} +
+
+ )} {isFullscreen ? (