'use client' import { useEffect, useMemo } from 'react' import * as THREE from 'three' import { buildGutterGeometry } from './geometry' import type { GutterNode } from './schema' /** * Translucent ghost of a gutter — built from the same `buildGutterGeometry` * the renderer commits, so the shape on screen during placement is the * shape that lands on click. * * No internal transform wrapper. Callers (placement tool + move tool) * mirror the GutterRenderer's transform chain around this component * (roof → segment → snap), so the ghost shares one bulletproof chain * with the committed mesh instead of a flattened-yaw shortcut that can * drift in edge cases. * * FrontSide matches the renderer; DoubleSide would render the inside * of the trough walls and visually thicken the ghost relative to the * placed gutter. */ const GutterPreview = ({ node }: { node: GutterNode }) => { const geometry = useMemo( () => buildGutterGeometry(node), [ node.length, node.size, node.thickness, node.profile, node.endCapLeft, node.endCapRight, node.hangerStyle, node.hangerSpacing, JSON.stringify(node.outlets), ], ) const material = useMemo( () => new THREE.MeshStandardMaterial({ color: 0xff_ff_ff, emissive: 0xff_ff_ff, emissiveIntensity: 0.12, roughness: 0.7, metalness: 0.2, transparent: true, opacity: 0.55, depthWrite: false, side: THREE.FrontSide, }), [], ) const edgesGeometry = useMemo(() => new THREE.EdgesGeometry(geometry, 25), [geometry]) useEffect( () => () => { geometry.dispose() edgesGeometry.dispose() material.dispose() }, [geometry, edgesGeometry, material], ) return ( <> {}} /> ) } export default GutterPreview