Skip to content

Commit

Permalink
add <Pcb3D />
Browse files Browse the repository at this point in the history
  • Loading branch information
DrSensor committed Jan 30, 2025
1 parent 5bd2445 commit d091471
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 63 deletions.
82 changes: 19 additions & 63 deletions src/CadViewer.tsx
Original file line number Diff line number Diff line change
@@ -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[]
Expand All @@ -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 (
<CadViewerContainer ref={ref} hoveredComponent={hoveredComponent}>
{boardStls.map(({ stlUrl, color }, index) => (
<STLModel
key={stlUrl}
stlUrl={stlUrl}
color={color}
opacity={index === 0 ? 0.95 : 1}
/>
))}
{cad_components.map((cad_component) => (
<ThreeErrorBoundary
key={cad_component.cad_component_id}
fallback={({ error }) => (
<Error3d cad_component={cad_component} error={error} />
)}
>
<AnyCadComponent
key={cad_component.cad_component_id}
onHover={(e) => {
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 ?? "<unknown>",
point: e.point,
})
}}
onUnhover={() => setHoveredComponent(null)}
cad_component={cad_component}
isHovered={
hoveredComponent?.cad_component_id ===
cad_component.cad_component_id
}
/>
</ThreeErrorBoundary>
))}
<Pcb3D
soup={soup}
onHover={(e) => {
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 ?? "<unknown>",
point: e.point,
})
}}
onUnhover={() => setHoveredComponent(null)}
hoverAt={hoveredComponent?.cad_component_id}
>
{children}
</Pcb3D>
</CadViewerContainer>
)
})
86 changes: 86 additions & 0 deletions src/Pcb3D.tsx
Original file line number Diff line number Diff line change
@@ -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<SoupUtilObjects["cad_component"]["list"]>[0]
}

export interface HoverProps
extends Omit<tooltip.HoverProps<RaycastEvent>, "isHovered"> {
hoverAt?: RaycastEvent["cad_component"]["cad_component_id"]
}

export function Pcb3D({
soup,
children,
onHover,
onUnhover,
hoverAt,
}: React.PropsWithChildren<HoverProps & { soup?: AnySoupElement[] }>) {
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) => (
<STLModel
key={stlUrl}
stlUrl={stlUrl}
color={color}
opacity={index === 0 ? 0.95 : 1}
/>
)),
...cad_components.map((cad_component) => (
<ThreeErrorBoundary
key={cad_component.cad_component_id}
fallback={({ error }) => (
<Error3d cad_component={cad_component} error={error} />
)}
>
<AnyCadComponent
key={cad_component.cad_component_id}
onHover={
onHover &&
((e) =>
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}
/>
</ThreeErrorBoundary>
)),
]
}

0 comments on commit d091471

Please sign in to comment.