({
data,
highlightedIds,
cameraTarget,
showLabels,
display = DEFAULT_DISPLAY_SETTINGS,
onNodeClick,
}: GraphSceneProps)
| 122 | export type { CameraTarget }; |
| 123 | |
| 124 | export function GraphScene({ |
| 125 | data, |
| 126 | highlightedIds, |
| 127 | cameraTarget, |
| 128 | showLabels, |
| 129 | display = DEFAULT_DISPLAY_SETTINGS, |
| 130 | onNodeClick, |
| 131 | }: GraphSceneProps) { |
| 132 | const [hovered, setHovered] = useState<GraphNode | null>(null); |
| 133 | const controlsRef = useRef<OrbitControlsImpl | null>(null); |
| 134 | |
| 135 | /* Adaptive density defaults × user multipliers. The automatic scale keeps |
| 136 | * contrast roughly constant as the graph grows; the sliders nudge it. |
| 137 | * NodeCloud applies `nodeBoost` directly (no internal density scaling), |
| 138 | * whereas EdgeLines scales by edge density itself — so it receives only the |
| 139 | * user edge-brightness multiplier to avoid double-applying. */ |
| 140 | const nodeBoost = nodeBoostScale(data.nodes.length) * display.nodeGlow; |
| 141 | const bloomIntensity = |
| 142 | BASE_BLOOM_INTENSITY * bloomIntensityScale(data.nodes.length) * display.bloom; |
| 143 | |
| 144 | return ( |
| 145 | <Canvas |
| 146 | camera={{ position: [0, 0, 800], fov: 50, near: 0.1, far: 100000 }} |
| 147 | style={{ background: "#06090f" }} |
| 148 | dpr={GRAPH_CANVAS_DPR} |
| 149 | gl={{ |
| 150 | antialias: false, |
| 151 | alpha: false, |
| 152 | powerPreference: "high-performance", |
| 153 | }} |
| 154 | > |
| 155 | <color attach="background" args={["#06090f"]} /> |
| 156 | <ambientLight intensity={0.5} /> |
| 157 | <pointLight position={[500, 500, 500]} intensity={0.6} /> |
| 158 | <pointLight |
| 159 | position={[-300, -200, -300]} |
| 160 | intensity={0.4} |
| 161 | color="#6040ff" |
| 162 | /> |
| 163 | |
| 164 | <EdgeLines |
| 165 | nodes={data.nodes} |
| 166 | edges={data.edges} |
| 167 | highlightedIds={highlightedIds} |
| 168 | brightness={display.edgeBrightness} |
| 169 | /> |
| 170 | <NodeCloud |
| 171 | nodes={data.nodes} |
| 172 | highlightedIds={highlightedIds} |
| 173 | onHover={setHovered} |
| 174 | onClick={onNodeClick} |
| 175 | boost={nodeBoost} |
| 176 | /> |
| 177 | {showLabels && <NodeLabels nodes={data.nodes} highlightedIds={highlightedIds} />} |
| 178 | |
| 179 | {/* Satellite galaxies for cross-repo linked projects */} |
| 180 | {data.linked_projects?.map((lp: LinkedProject) => { |
| 181 | const offsetNodes = lp.nodes.map((n) => ({ |
nothing calls this directly
no test coverage detected