diff --git a/src/CadViewer.tsx b/src/CadViewer.tsx index 9accec9..0ba6dce 100644 --- a/src/CadViewer.tsx +++ b/src/CadViewer.tsx @@ -1,23 +1,10 @@ import type { AnySoupElement } from "@tscircuit/soup" import type * as React from "react" import type * as THREE from "three" -import { useConvertChildrenToSoup } from "./hooks/use-convert-children-to-soup" import { su } from "@tscircuit/soup-util" -import { useEffect, useMemo, useState, forwardRef } from "react" -import { createBoardGeomFromSoup } from "./soup-to-3d" -import { useStlsFromGeom } from "./hooks/use-stls-from-geom" -import { STLModel } from "./three-components/STLModel" +import { useState, forwardRef } from "react" import { CadViewerContainer } from "./CadViewerContainer" -import { MixedStlModel } from "./three-components/MixedStlModel" -import { Euler } from "three" -import { JscadModel } from "./three-components/JscadModel" -import { Footprinter3d } from "jscad-electronics" -import { FootprinterModel } from "./three-components/FootprinterModel" -import { tuple } from "./utils/tuple" -import { AnyCadComponent } from "./AnyCadComponent" -import { Text } from "@react-three/drei" -import { ThreeErrorBoundary } from "./three-components/ThreeErrorBoundary" -import { Error3d } from "./three-components/Error3d" +import { Pcb3D } from "./Pcb3D" interface Props { soup?: AnySoupElement[] @@ -32,57 +19,26 @@ export const CadViewer = forwardRef< name: string point: THREE.Vector3 }>(null) - soup ??= useConvertChildrenToSoup(children, soup) as any - - if (!soup) return null - - const boardGeom = useMemo(() => { - if (!soup.some((e) => e.type === "pcb_board")) return null - return createBoardGeomFromSoup(soup) - }, [soup]) - - const { stls: boardStls, loading } = useStlsFromGeom(boardGeom) - - const cad_components = su(soup).cad_component.list() return ( - {boardStls.map(({ stlUrl, color }, index) => ( - - ))} - {cad_components.map((cad_component) => ( - ( - - )} - > - { - const componentName = su(soup as any).source_component.getUsing({ - source_component_id: cad_component.source_component_id, - })?.name - setHoveredComponent({ - cad_component_id: cad_component.cad_component_id, - name: componentName ?? "", - point: e.point, - }) - }} - onUnhover={() => setHoveredComponent(null)} - cad_component={cad_component} - isHovered={ - hoveredComponent?.cad_component_id === - cad_component.cad_component_id - } - /> - - ))} + { + const componentName = su(soup as any).source_component.getUsing({ + source_component_id: e.cad_component.source_component_id, + })?.name + setHoveredComponent({ + cad_component_id: e.cad_component.cad_component_id, + name: componentName ?? "", + point: e.point, + }) + }} + onUnhover={() => setHoveredComponent(null)} + hoverAt={hoveredComponent?.cad_component_id} + > + {children} + ) }) diff --git a/src/Pcb3D.tsx b/src/Pcb3D.tsx new file mode 100644 index 0000000..f8f31af --- /dev/null +++ b/src/Pcb3D.tsx @@ -0,0 +1,86 @@ +import type * as React from "react" +import type { AnySoupElement } from "@tscircuit/soup" +import { useMemo } from "react" +import { su, type SoupUtilObjects } from "@tscircuit/soup-util" +import { useStlsFromGeom } from "./hooks/use-stls-from-geom" +import { createBoardGeomFromSoup } from "./soup-to-3d" +import { useConvertChildrenToSoup } from "./hooks/use-convert-children-to-soup" +import { STLModel } from "./three-components/STLModel" +import { ThreeErrorBoundary } from "./three-components/ThreeErrorBoundary" +import { AnyCadComponent, type tooltip } from "./AnyCadComponent" +import { Error3d } from "./three-components/Error3d" + +export interface RaycastEvent extends tooltip.RaycastEvent { + source_component: SoupUtilObjects["source_component"] + cad_component: ReturnType[0] +} + +export interface HoverProps + extends Omit, "isHovered"> { + hoverAt?: RaycastEvent["cad_component"]["cad_component_id"] +} + +export function Pcb3D({ + soup, + children, + onHover, + onUnhover, + hoverAt, +}: React.PropsWithChildren) { + soup ??= useConvertChildrenToSoup(children, soup) as any + + if (!soup) return null + + const boardGeom = useMemo(() => { + if (!soup.some((e) => e.type === "pcb_board")) return null + return createBoardGeomFromSoup(soup) + }, [soup]) + + const { stls: boardStls } = useStlsFromGeom(boardGeom) + + const soupUtil = su(soup) + const cad_components = soupUtil.cad_component.list() + + return [ + ...boardStls.map(({ stlUrl, color }, index) => ( + + )), + ...cad_components.map((cad_component) => ( + ( + + )} + > + + onHover({ + source_component: soupUtil.source_component, + cad_component, + ...e, + })) + } + onUnhover={ + onUnhover && + ((e) => + onUnhover({ + source_component: soupUtil.source_component, + cad_component, + ...e, + })) + } + cad_component={cad_component} + isHovered={hoverAt === cad_component.cad_component_id} + /> + + )), + ] +}