@tscircuit/3d-viewer 0.0.470 → 0.0.472

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -83,6 +83,8 @@ interface ManifoldTextures {
83
83
  bottomSoldermask?: THREE.CanvasTexture | null;
84
84
  topCopperText?: THREE.CanvasTexture | null;
85
85
  bottomCopperText?: THREE.CanvasTexture | null;
86
+ topPanelOutlines?: THREE.CanvasTexture | null;
87
+ bottomPanelOutlines?: THREE.CanvasTexture | null;
86
88
  }
87
89
  interface UseManifoldBoardBuilderResult {
88
90
  geoms: ManifoldGeoms | null;
package/dist/index.js CHANGED
@@ -14229,10 +14229,10 @@ var require_browser = __commonJS({
14229
14229
 
14230
14230
  // src/CadViewer.tsx
14231
14231
  import { useState as useState35, useCallback as useCallback21, useRef as useRef26, useEffect as useEffect43 } from "react";
14232
- import * as THREE32 from "three";
14232
+ import * as THREE33 from "three";
14233
14233
 
14234
14234
  // src/CadViewerJscad.tsx
14235
- import { su as su11 } from "@tscircuit/circuit-json-util";
14235
+ import { su as su12 } from "@tscircuit/circuit-json-util";
14236
14236
  import { forwardRef as forwardRef3, useMemo as useMemo20 } from "react";
14237
14237
 
14238
14238
  // src/AnyCadComponent.tsx
@@ -28509,7 +28509,7 @@ import * as THREE15 from "three";
28509
28509
  // package.json
28510
28510
  var package_default = {
28511
28511
  name: "@tscircuit/3d-viewer",
28512
- version: "0.0.469",
28512
+ version: "0.0.471",
28513
28513
  main: "./dist/index.js",
28514
28514
  module: "./dist/index.js",
28515
28515
  type: "module",
@@ -29782,6 +29782,10 @@ var createSimplifiedBoardGeom = (circuitJson) => {
29782
29782
  let pcbThickness = 1.2;
29783
29783
  if (panels.length > 0) {
29784
29784
  boardOrPanel = panels[0];
29785
+ const firstBoardInPanel = boards.find(
29786
+ (b) => b.pcb_panel_id === boardOrPanel.pcb_panel_id
29787
+ );
29788
+ pcbThickness = firstBoardInPanel?.thickness ?? 1.2;
29785
29789
  } else {
29786
29790
  const boardsNotInPanel = boards.filter(
29787
29791
  (b) => !b.pcb_panel_id
@@ -29807,7 +29811,10 @@ var createSimplifiedBoardGeom = (circuitJson) => {
29807
29811
  center: [boardOrPanel.center.x, boardOrPanel.center.y, 0]
29808
29812
  });
29809
29813
  }
29810
- const material = boardMaterialColors["material" in boardOrPanel ? boardOrPanel.material ?? "fr4" : "fr4"] ?? colors.fr4Tan;
29814
+ const materialName = "material" in boardOrPanel && boardOrPanel.material ? boardOrPanel.material : panels.length > 0 ? boards.find(
29815
+ (b) => b.pcb_panel_id === boardOrPanel.pcb_panel_id
29816
+ )?.material ?? "fr4" : "fr4";
29817
+ const material = boardMaterialColors[materialName] ?? colors.fr4Tan;
29811
29818
  return [(0, import_colors.colorize)(material, boardGeom)];
29812
29819
  };
29813
29820
  var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
@@ -30612,16 +30619,18 @@ var BoardGeomBuilder = class {
30612
30619
  const boards = su3(circuitJson).pcb_board.list();
30613
30620
  if (panels.length > 0) {
30614
30621
  const panel = panels[0];
30622
+ const firstBoardInPanel = boards.find(
30623
+ (b) => b.pcb_panel_id === panel.pcb_panel_id
30624
+ );
30615
30625
  this.board = {
30616
30626
  type: "pcb_board",
30617
30627
  pcb_board_id: panel.pcb_panel_id,
30618
30628
  center: panel.center,
30619
30629
  width: panel.width,
30620
30630
  height: panel.height,
30621
- thickness: 1.6,
30622
- // Default thickness
30623
- material: "fr4",
30624
- num_layers: 2
30631
+ thickness: firstBoardInPanel?.thickness ?? 1.6,
30632
+ material: firstBoardInPanel?.material ?? "fr4",
30633
+ num_layers: firstBoardInPanel?.num_layers ?? 2
30625
30634
  };
30626
30635
  } else {
30627
30636
  const boardsNotInPanel = boards.filter((b) => !b.pcb_panel_id);
@@ -31618,8 +31627,8 @@ var ThreeErrorBoundary = class extends React11.Component {
31618
31627
 
31619
31628
  // src/three-components/JscadBoardTextures.tsx
31620
31629
  import { useEffect as useEffect22, useMemo as useMemo19 } from "react";
31621
- import * as THREE22 from "three";
31622
- import { su as su8 } from "@tscircuit/circuit-json-util";
31630
+ import * as THREE23 from "three";
31631
+ import { su as su9 } from "@tscircuit/circuit-json-util";
31623
31632
 
31624
31633
  // src/utils/soldermask-texture.ts
31625
31634
  import * as THREE18 from "three";
@@ -32411,6 +32420,7 @@ function createSilkscreenTextureForLayer({
32411
32420
  const pcbSilkscreenRects = su6(circuitJson).pcb_silkscreen_rect.list();
32412
32421
  const pcbSilkscreenCircles = su6(circuitJson).pcb_silkscreen_circle.list();
32413
32422
  const pcbFabricationNoteRects = su6(circuitJson).pcb_fabrication_note_rect.list();
32423
+ const pcbNoteLines = su6(circuitJson).pcb_note_line.list();
32414
32424
  const textsOnLayer = pcbSilkscreenTexts.filter((t) => t.layer === layer);
32415
32425
  const pathsOnLayer = pcbSilkscreenPaths.filter((p) => p.layer === layer);
32416
32426
  const linesOnLayer = pcbSilkscreenLines.filter((l) => l.layer === layer);
@@ -32419,7 +32429,10 @@ function createSilkscreenTextureForLayer({
32419
32429
  const fabricationNoteRectsOnLayer = pcbFabricationNoteRects.filter(
32420
32430
  (r) => r.layer === layer
32421
32431
  );
32422
- if (textsOnLayer.length === 0 && pathsOnLayer.length === 0 && linesOnLayer.length === 0 && rectsOnLayer.length === 0 && circlesOnLayer.length === 0 && fabricationNoteRectsOnLayer.length === 0) {
32432
+ const noteLinesOnLayer = pcbNoteLines.filter(
32433
+ (l) => l.layer === layer
32434
+ );
32435
+ if (textsOnLayer.length === 0 && pathsOnLayer.length === 0 && linesOnLayer.length === 0 && rectsOnLayer.length === 0 && circlesOnLayer.length === 0 && fabricationNoteRectsOnLayer.length === 0 && noteLinesOnLayer.length === 0) {
32423
32436
  return null;
32424
32437
  }
32425
32438
  const canvas = document.createElement("canvas");
@@ -32450,6 +32463,36 @@ function createSilkscreenTextureForLayer({
32450
32463
  ctx.lineTo(canvasXFromPcb(endXmm), canvasYFromPcb(endYmm));
32451
32464
  ctx.stroke();
32452
32465
  });
32466
+ noteLinesOnLayer.forEach((lineEl) => {
32467
+ const startXmm = parseDimensionToMm(lineEl.x1) ?? 0;
32468
+ const startYmm = parseDimensionToMm(lineEl.y1) ?? 0;
32469
+ const endXmm = parseDimensionToMm(lineEl.x2) ?? 0;
32470
+ const endYmm = parseDimensionToMm(lineEl.y2) ?? 0;
32471
+ if (startXmm === endXmm && startYmm === endYmm) return;
32472
+ ctx.save();
32473
+ let strokeColor = silkscreenColor;
32474
+ if (lineEl.color) {
32475
+ strokeColor = parseFabricationNoteColor(lineEl.color);
32476
+ } else {
32477
+ strokeColor = "rgb(255, 243, 204)";
32478
+ }
32479
+ ctx.strokeStyle = strokeColor;
32480
+ ctx.beginPath();
32481
+ ctx.lineWidth = coerceDimensionToMm(lineEl.stroke_width, 0.1) * traceTextureResolution;
32482
+ ctx.lineCap = "round";
32483
+ const isDashed = lineEl.is_dashed ?? false;
32484
+ if (isDashed) {
32485
+ const dashLength = Math.max(ctx.lineWidth * 2, 1);
32486
+ ctx.setLineDash([dashLength, dashLength]);
32487
+ }
32488
+ ctx.moveTo(canvasXFromPcb(startXmm), canvasYFromPcb(startYmm));
32489
+ ctx.lineTo(canvasXFromPcb(endXmm), canvasYFromPcb(endYmm));
32490
+ ctx.stroke();
32491
+ if (isDashed) {
32492
+ ctx.setLineDash([]);
32493
+ }
32494
+ ctx.restore();
32495
+ });
32453
32496
  pathsOnLayer.forEach((path) => {
32454
32497
  if (path.route.length < 2) return;
32455
32498
  ctx.beginPath();
@@ -33088,6 +33131,72 @@ function createCopperTextTextureForLayer({
33088
33131
  return texture;
33089
33132
  }
33090
33133
 
33134
+ // src/utils/panel-outline-texture.ts
33135
+ import * as THREE22 from "three";
33136
+ import { su as su8 } from "@tscircuit/circuit-json-util";
33137
+ function createPanelOutlineTextureForLayer({
33138
+ layer,
33139
+ circuitJson,
33140
+ panelData,
33141
+ outlineColor = "black",
33142
+ traceTextureResolution
33143
+ }) {
33144
+ const boardsInPanel = su8(circuitJson).pcb_board.list().filter((b) => b.pcb_panel_id === panelData.pcb_board_id);
33145
+ if (boardsInPanel.length === 0) {
33146
+ return null;
33147
+ }
33148
+ const canvas = document.createElement("canvas");
33149
+ const canvasWidth = Math.floor(panelData.width * traceTextureResolution);
33150
+ const canvasHeight = Math.floor(panelData.height * traceTextureResolution);
33151
+ canvas.width = canvasWidth;
33152
+ canvas.height = canvasHeight;
33153
+ const ctx = canvas.getContext("2d");
33154
+ if (!ctx) return null;
33155
+ if (layer === "bottom") {
33156
+ ctx.translate(0, canvasHeight);
33157
+ ctx.scale(1, -1);
33158
+ }
33159
+ ctx.strokeStyle = outlineColor;
33160
+ ctx.lineWidth = 0.05 * traceTextureResolution;
33161
+ const canvasXFromPcb = (pcbX) => (pcbX - panelData.center.x + panelData.width / 2) * traceTextureResolution;
33162
+ const canvasYFromPcb = (pcbY) => (-(pcbY - panelData.center.y) + panelData.height / 2) * traceTextureResolution;
33163
+ boardsInPanel.forEach((board) => {
33164
+ if (board.outline && board.outline.length >= 2) {
33165
+ ctx.beginPath();
33166
+ board.outline.forEach((point2, index2) => {
33167
+ const x = canvasXFromPcb(point2.x);
33168
+ const y = canvasYFromPcb(point2.y);
33169
+ if (index2 === 0) {
33170
+ ctx.moveTo(x, y);
33171
+ } else {
33172
+ ctx.lineTo(x, y);
33173
+ }
33174
+ });
33175
+ ctx.closePath();
33176
+ ctx.stroke();
33177
+ } else {
33178
+ const width10 = board.width;
33179
+ const height10 = board.height;
33180
+ const { x: centerX, y: centerY } = board.center;
33181
+ const x = canvasXFromPcb(centerX - width10 / 2);
33182
+ const y = canvasYFromPcb(centerY + height10 / 2);
33183
+ ctx.strokeRect(
33184
+ x,
33185
+ y,
33186
+ width10 * traceTextureResolution,
33187
+ height10 * traceTextureResolution
33188
+ );
33189
+ }
33190
+ });
33191
+ const texture = new THREE22.CanvasTexture(canvas);
33192
+ texture.generateMipmaps = true;
33193
+ texture.minFilter = THREE22.LinearMipmapLinearFilter;
33194
+ texture.magFilter = THREE22.LinearFilter;
33195
+ texture.anisotropy = 16;
33196
+ texture.needsUpdate = true;
33197
+ return texture;
33198
+ }
33199
+
33091
33200
  // src/three-components/JscadBoardTextures.tsx
33092
33201
  function JscadBoardTextures({
33093
33202
  circuitJson,
@@ -33096,8 +33205,30 @@ function JscadBoardTextures({
33096
33205
  const { rootObject } = useThree();
33097
33206
  const { visibility } = useLayerVisibility();
33098
33207
  const boardData = useMemo19(() => {
33099
- const boards = su8(circuitJson).pcb_board.list();
33100
- return boards.length > 0 ? boards[0] : null;
33208
+ const panels = circuitJson.filter(
33209
+ (e) => e.type === "pcb_panel"
33210
+ );
33211
+ const boards = su9(circuitJson).pcb_board.list();
33212
+ if (panels.length > 0) {
33213
+ const panel = panels[0];
33214
+ const firstBoardInPanel = boards.find(
33215
+ (b) => b.pcb_panel_id === panel.pcb_panel_id
33216
+ );
33217
+ return {
33218
+ type: "pcb_board",
33219
+ pcb_board_id: panel.pcb_panel_id,
33220
+ center: panel.center,
33221
+ width: panel.width,
33222
+ height: panel.height,
33223
+ thickness: firstBoardInPanel?.thickness ?? 1.6,
33224
+ material: firstBoardInPanel?.material ?? "fr4",
33225
+ num_layers: firstBoardInPanel?.num_layers ?? 2
33226
+ };
33227
+ }
33228
+ const boardsNotInPanel = boards.filter(
33229
+ (b) => !b.pcb_panel_id
33230
+ );
33231
+ return boardsNotInPanel.length > 0 ? boardsNotInPanel[0] : null;
33101
33232
  }, [circuitJson]);
33102
33233
  const textures = useMemo19(() => {
33103
33234
  if (!boardData || !boardData.width || !boardData.height) return null;
@@ -33162,28 +33293,40 @@ function JscadBoardTextures({
33162
33293
  boardData,
33163
33294
  copperColor: `rgb(${Math.round(colors.copper[0] * 255)}, ${Math.round(colors.copper[1] * 255)}, ${Math.round(colors.copper[2] * 255)})`,
33164
33295
  traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33296
+ }),
33297
+ topPanelOutlines: createPanelOutlineTextureForLayer({
33298
+ layer: "top",
33299
+ circuitJson,
33300
+ panelData: boardData,
33301
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33302
+ }),
33303
+ bottomPanelOutlines: createPanelOutlineTextureForLayer({
33304
+ layer: "bottom",
33305
+ circuitJson,
33306
+ panelData: boardData,
33307
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33165
33308
  })
33166
33309
  };
33167
33310
  }, [circuitJson, boardData]);
33168
33311
  useEffect22(() => {
33169
33312
  if (!rootObject || !boardData || !textures) return;
33170
33313
  const meshes = [];
33171
- const createTexturePlane = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false) => {
33314
+ const createTexturePlane = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false, depthWrite = false) => {
33172
33315
  if (!texture) return null;
33173
- const planeGeom = new THREE22.PlaneGeometry(
33316
+ const planeGeom = new THREE23.PlaneGeometry(
33174
33317
  boardData.width,
33175
33318
  boardData.height
33176
33319
  );
33177
- const material = new THREE22.MeshBasicMaterial({
33320
+ const material = new THREE23.MeshBasicMaterial({
33178
33321
  map: texture,
33179
33322
  transparent: true,
33180
- side: THREE22.DoubleSide,
33181
- depthWrite: false,
33323
+ side: THREE23.DoubleSide,
33324
+ depthWrite,
33182
33325
  polygonOffset: usePolygonOffset,
33183
33326
  polygonOffsetFactor: usePolygonOffset ? -1 : 0,
33184
33327
  polygonOffsetUnits: usePolygonOffset ? -1 : 0
33185
33328
  });
33186
- const mesh = new THREE22.Mesh(planeGeom, material);
33329
+ const mesh = new THREE23.Mesh(planeGeom, material);
33187
33330
  mesh.position.set(boardData.center.x, boardData.center.y, zOffset);
33188
33331
  if (isBottomLayer) {
33189
33332
  mesh.rotation.set(Math.PI, 0, 0);
@@ -33290,13 +33433,41 @@ function JscadBoardTextures({
33290
33433
  rootObject.add(bottomCopperTextMesh);
33291
33434
  }
33292
33435
  }
33436
+ if (visibility.boardBody) {
33437
+ const topPanelOutlinesMesh = createTexturePlane(
33438
+ textures.topPanelOutlines,
33439
+ pcbThickness / 2 + SURFACE_OFFSET + 3e-3,
33440
+ // Above silkscreen
33441
+ false,
33442
+ "jscad-top-panel-outlines",
33443
+ false,
33444
+ true
33445
+ );
33446
+ if (topPanelOutlinesMesh) {
33447
+ meshes.push(topPanelOutlinesMesh);
33448
+ rootObject.add(topPanelOutlinesMesh);
33449
+ }
33450
+ const bottomPanelOutlinesMesh = createTexturePlane(
33451
+ textures.bottomPanelOutlines,
33452
+ -pcbThickness / 2 - SURFACE_OFFSET - 3e-3,
33453
+ // Below bottom silkscreen
33454
+ true,
33455
+ "jscad-bottom-panel-outlines",
33456
+ false,
33457
+ true
33458
+ );
33459
+ if (bottomPanelOutlinesMesh) {
33460
+ meshes.push(bottomPanelOutlinesMesh);
33461
+ rootObject.add(bottomPanelOutlinesMesh);
33462
+ }
33463
+ }
33293
33464
  return () => {
33294
33465
  meshes.forEach((mesh) => {
33295
33466
  if (mesh.parent === rootObject) {
33296
33467
  rootObject.remove(mesh);
33297
33468
  }
33298
33469
  mesh.geometry.dispose();
33299
- if (mesh.material instanceof THREE22.Material) {
33470
+ if (mesh.material instanceof THREE23.Material) {
33300
33471
  mesh.material.dispose();
33301
33472
  }
33302
33473
  });
@@ -33306,16 +33477,16 @@ function JscadBoardTextures({
33306
33477
  }
33307
33478
 
33308
33479
  // src/utils/preprocess-circuit-json.ts
33309
- import { su as su10 } from "@tscircuit/circuit-json-util";
33480
+ import { su as su11 } from "@tscircuit/circuit-json-util";
33310
33481
 
33311
33482
  // src/utils/create-faux-board.ts
33312
- import { su as su9, getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
33483
+ import { su as su10, getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
33313
33484
  function createFauxBoard(circuitJson) {
33314
- const cadComponents = su9(circuitJson).cad_component.list();
33315
- const pads = su9(circuitJson).pcb_smtpad.list();
33316
- const holes = su9(circuitJson).pcb_hole.list();
33317
- const platedHoles = su9(circuitJson).pcb_plated_hole.list();
33318
- const vias = su9(circuitJson).pcb_via.list();
33485
+ const cadComponents = su10(circuitJson).cad_component.list();
33486
+ const pads = su10(circuitJson).pcb_smtpad.list();
33487
+ const holes = su10(circuitJson).pcb_hole.list();
33488
+ const platedHoles = su10(circuitJson).pcb_plated_hole.list();
33489
+ const vias = su10(circuitJson).pcb_via.list();
33319
33490
  if (cadComponents.length === 0 && pads.length === 0 && holes.length === 0 && platedHoles.length === 0 && vias.length === 0) {
33320
33491
  return null;
33321
33492
  }
@@ -33364,7 +33535,7 @@ function createFauxBoard(circuitJson) {
33364
33535
 
33365
33536
  // src/utils/preprocess-circuit-json.ts
33366
33537
  function addFauxBoardIfNeeded(circuitJson) {
33367
- const boards = su10(circuitJson).pcb_board.list();
33538
+ const boards = su11(circuitJson).pcb_board.list();
33368
33539
  if (boards.length > 0) {
33369
33540
  return circuitJson;
33370
33541
  }
@@ -33414,7 +33585,7 @@ var CadViewerJscad = forwardRef3(
33414
33585
  const initialCameraPosition = useMemo20(() => {
33415
33586
  if (!internalCircuitJson) return [5, -5, 5];
33416
33587
  try {
33417
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33588
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33418
33589
  if (!board) return [5, -5, 5];
33419
33590
  const { width: width10, height: height10 } = board;
33420
33591
  if (!width10 && !height10) {
@@ -33440,7 +33611,7 @@ var CadViewerJscad = forwardRef3(
33440
33611
  const isFauxBoard = useMemo20(() => {
33441
33612
  if (!internalCircuitJson) return false;
33442
33613
  try {
33443
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33614
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33444
33615
  return !!board && board.pcb_board_id === "faux-board";
33445
33616
  } catch (e) {
33446
33617
  return false;
@@ -33449,7 +33620,7 @@ var CadViewerJscad = forwardRef3(
33449
33620
  const boardDimensions = useMemo20(() => {
33450
33621
  if (!internalCircuitJson) return void 0;
33451
33622
  try {
33452
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33623
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33453
33624
  if (!board) return void 0;
33454
33625
  return { width: board.width ?? 0, height: board.height ?? 0 };
33455
33626
  } catch (e) {
@@ -33460,7 +33631,7 @@ var CadViewerJscad = forwardRef3(
33460
33631
  const boardCenter = useMemo20(() => {
33461
33632
  if (!internalCircuitJson) return void 0;
33462
33633
  try {
33463
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33634
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33464
33635
  if (!board || !board.center) return void 0;
33465
33636
  return { x: board.center.x, y: board.center.y };
33466
33637
  } catch (e) {
@@ -33470,7 +33641,7 @@ var CadViewerJscad = forwardRef3(
33470
33641
  }, [internalCircuitJson]);
33471
33642
  const pcbThickness = usePcbThickness(internalCircuitJson);
33472
33643
  const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
33473
- const cad_components = su11(internalCircuitJson).cad_component.list();
33644
+ const cad_components = su12(internalCircuitJson).cad_component.list();
33474
33645
  return /* @__PURE__ */ jsxs5(
33475
33646
  CadViewerContainer,
33476
33647
  {
@@ -33522,13 +33693,13 @@ var CadViewerJscad = forwardRef3(
33522
33693
  );
33523
33694
 
33524
33695
  // src/CadViewerManifold.tsx
33525
- import { su as su18 } from "@tscircuit/circuit-json-util";
33696
+ import { su as su19 } from "@tscircuit/circuit-json-util";
33526
33697
  import { useEffect as useEffect24, useMemo as useMemo22, useState as useState15 } from "react";
33527
33698
 
33528
33699
  // src/hooks/useManifoldBoardBuilder.ts
33529
33700
  import { useState as useState14, useEffect as useEffect23, useMemo as useMemo21, useRef as useRef9 } from "react";
33530
- import { su as su17 } from "@tscircuit/circuit-json-util";
33531
- import * as THREE28 from "three";
33701
+ import { su as su18 } from "@tscircuit/circuit-json-util";
33702
+ import * as THREE29 from "three";
33532
33703
 
33533
33704
  // src/utils/manifold/create-manifold-board.ts
33534
33705
  var arePointsClockwise3 = (points) => {
@@ -33589,17 +33760,17 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
33589
33760
  }
33590
33761
 
33591
33762
  // src/utils/manifold/process-copper-pours.ts
33592
- import * as THREE24 from "three";
33763
+ import * as THREE25 from "three";
33593
33764
 
33594
33765
  // src/utils/manifold-mesh-to-three-geometry.ts
33595
- import * as THREE23 from "three";
33766
+ import * as THREE24 from "three";
33596
33767
  function manifoldMeshToThreeGeometry(manifoldMesh) {
33597
- const geometry = new THREE23.BufferGeometry();
33768
+ const geometry = new THREE24.BufferGeometry();
33598
33769
  geometry.setAttribute(
33599
33770
  "position",
33600
- new THREE23.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
33771
+ new THREE24.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
33601
33772
  );
33602
- geometry.setIndex(new THREE23.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
33773
+ geometry.setIndex(new THREE24.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
33603
33774
  if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
33604
33775
  for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
33605
33776
  const start = manifoldMesh.runIndex[i];
@@ -33772,7 +33943,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33772
33943
  }
33773
33944
  const covered = pour.covered_with_solder_mask !== false;
33774
33945
  const pourColorArr = covered ? tracesMaterialColors[boardMaterial] ?? colors.fr4TracesWithoutMaskTan : colors.copper;
33775
- const pourColor = new THREE24.Color(...pourColorArr);
33946
+ const pourColor = new THREE25.Color(...pourColorArr);
33776
33947
  const threeGeom = manifoldMeshToThreeGeometry(pourOp.getMesh());
33777
33948
  copperPourGeoms.push({
33778
33949
  key: `coppour-${pour.pcb_copper_pour_id}`,
@@ -33785,7 +33956,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33785
33956
  }
33786
33957
 
33787
33958
  // src/utils/manifold/process-cutouts.ts
33788
- import { su as su12 } from "@tscircuit/circuit-json-util";
33959
+ import { su as su13 } from "@tscircuit/circuit-json-util";
33789
33960
 
33790
33961
  // src/utils/pad-geoms.ts
33791
33962
  var RECT_PAD_SEGMENTS2 = 64;
@@ -33877,7 +34048,7 @@ var arePointsClockwise5 = (points) => {
33877
34048
  };
33878
34049
  function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
33879
34050
  const cutoutOps = [];
33880
- const pcbCutouts = su12(circuitJson).pcb_cutout.list();
34051
+ const pcbCutouts = su13(circuitJson).pcb_cutout.list();
33881
34052
  for (const cutout of pcbCutouts) {
33882
34053
  let cutoutOp;
33883
34054
  const cutoutHeight = pcbThickness * 1.5;
@@ -33972,7 +34143,7 @@ function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThick
33972
34143
  }
33973
34144
 
33974
34145
  // src/utils/manifold/process-non-plated-holes.ts
33975
- import { su as su13 } from "@tscircuit/circuit-json-util";
34146
+ import { su as su14 } from "@tscircuit/circuit-json-util";
33976
34147
 
33977
34148
  // src/utils/hole-geoms.ts
33978
34149
  function createCircleHoleDrill({
@@ -34024,7 +34195,7 @@ function isRotatedPillHole(hole) {
34024
34195
  }
34025
34196
  function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
34026
34197
  const nonPlatedHoleBoardDrills = [];
34027
- const pcbHoles = su13(circuitJson).pcb_hole.list();
34198
+ const pcbHoles = su14(circuitJson).pcb_hole.list();
34028
34199
  const createPillOp = (width10, height10, depth) => {
34029
34200
  const pillOp = createRoundedRectPrism({
34030
34201
  Manifold,
@@ -34073,8 +34244,8 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
34073
34244
  }
34074
34245
 
34075
34246
  // src/utils/manifold/process-plated-holes.ts
34076
- import { su as su14 } from "@tscircuit/circuit-json-util";
34077
- import * as THREE25 from "three";
34247
+ import { su as su15 } from "@tscircuit/circuit-json-util";
34248
+ import * as THREE26 from "three";
34078
34249
  var arePointsClockwise6 = (points) => {
34079
34250
  let area = 0;
34080
34251
  for (let i = 0; i < points.length; i++) {
@@ -34095,11 +34266,11 @@ var createEllipsePoints = (width10, height10, segments) => {
34095
34266
  }
34096
34267
  return points;
34097
34268
  };
34098
- var COPPER_COLOR = new THREE25.Color(...colors.copper);
34269
+ var COPPER_COLOR = new THREE26.Color(...colors.copper);
34099
34270
  var PLATED_HOLE_LIP_HEIGHT = 0.05;
34100
34271
  function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
34101
34272
  const platedHoleBoardDrills = [];
34102
- const pcbPlatedHoles = su14(circuitJson).pcb_plated_hole.list();
34273
+ const pcbPlatedHoles = su15(circuitJson).pcb_plated_hole.list();
34103
34274
  const platedHoleCopperGeoms = [];
34104
34275
  const platedHoleCopperOpsForSubtract = [];
34105
34276
  const createPillOp = (width10, height10, depth) => {
@@ -34668,12 +34839,12 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
34668
34839
  }
34669
34840
 
34670
34841
  // src/utils/manifold/process-smt-pads.ts
34671
- import { su as su15 } from "@tscircuit/circuit-json-util";
34672
- import * as THREE26 from "three";
34673
- var COPPER_COLOR2 = new THREE26.Color(...colors.copper);
34842
+ import { su as su16 } from "@tscircuit/circuit-json-util";
34843
+ import * as THREE27 from "three";
34844
+ var COPPER_COLOR2 = new THREE27.Color(...colors.copper);
34674
34845
  function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
34675
34846
  const smtPadGeoms = [];
34676
- const smtPads = su15(circuitJson).pcb_smtpad.list();
34847
+ const smtPads = su16(circuitJson).pcb_smtpad.list();
34677
34848
  smtPads.forEach((pad2, index2) => {
34678
34849
  const padBaseThickness = DEFAULT_SMT_PAD_THICKNESS;
34679
34850
  const zPos = pad2.layer === "bottom" ? -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper : pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper;
@@ -34708,8 +34879,8 @@ function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifold
34708
34879
  }
34709
34880
 
34710
34881
  // src/utils/manifold/process-vias.ts
34711
- import { su as su16 } from "@tscircuit/circuit-json-util";
34712
- import * as THREE27 from "three";
34882
+ import { su as su17 } from "@tscircuit/circuit-json-util";
34883
+ import * as THREE28 from "three";
34713
34884
 
34714
34885
  // src/utils/via-geoms.ts
34715
34886
  function createViaCopper2({
@@ -34762,10 +34933,10 @@ function createViaCopper2({
34762
34933
  }
34763
34934
 
34764
34935
  // src/utils/manifold/process-vias.ts
34765
- var COPPER_COLOR3 = new THREE27.Color(...colors.copper);
34936
+ var COPPER_COLOR3 = new THREE28.Color(...colors.copper);
34766
34937
  function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
34767
34938
  const viaBoardDrills = [];
34768
- const pcbVias = su16(circuitJson).pcb_via.list();
34939
+ const pcbVias = su17(circuitJson).pcb_via.list();
34769
34940
  const viaCopperGeoms = [];
34770
34941
  pcbVias.forEach((via, index2) => {
34771
34942
  if (typeof via.hole_diameter === "number") {
@@ -34825,26 +34996,28 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
34825
34996
  const panels = circuitJson.filter(
34826
34997
  (e) => e.type === "pcb_panel"
34827
34998
  );
34828
- const boards = su17(circuitJson).pcb_board.list();
34999
+ const boards = su18(circuitJson).pcb_board.list();
34829
35000
  if (panels.length > 0) {
34830
35001
  const panel = panels[0];
35002
+ const firstBoardInPanel = boards.find(
35003
+ (b) => b.pcb_panel_id === panel.pcb_panel_id
35004
+ );
34831
35005
  return {
34832
35006
  type: "pcb_board",
34833
35007
  pcb_board_id: panel.pcb_panel_id,
34834
35008
  center: panel.center,
34835
35009
  width: panel.width,
34836
35010
  height: panel.height,
34837
- thickness: 1.6,
34838
- // Default thickness
34839
- material: "fr4",
34840
- num_layers: 2
35011
+ thickness: firstBoardInPanel?.thickness ?? 1.6,
35012
+ material: firstBoardInPanel?.material ?? "fr4",
35013
+ num_layers: firstBoardInPanel?.num_layers ?? 2
34841
35014
  };
34842
35015
  }
34843
35016
  const boardsNotInPanel = boards.filter((b) => !b.pcb_panel_id);
34844
35017
  return boardsNotInPanel.length > 0 ? boardsNotInPanel[0] : null;
34845
35018
  }, [circuitJson]);
34846
35019
  const isFauxBoard = useMemo21(() => {
34847
- const boards = su17(circuitJson).pcb_board.list();
35020
+ const boards = su18(circuitJson).pcb_board.list();
34848
35021
  return boards.length > 0 && boards[0].pcb_board_id === "faux-board";
34849
35022
  }, [circuitJson]);
34850
35023
  useEffect23(() => {
@@ -34979,7 +35152,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
34979
35152
  {
34980
35153
  key: "plated-holes-union",
34981
35154
  geometry: cutPlatedGeom,
34982
- color: new THREE28.Color(
35155
+ color: new THREE29.Color(
34983
35156
  colors.copper[0],
34984
35157
  colors.copper[1],
34985
35158
  colors.copper[2]
@@ -35009,7 +35182,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35009
35182
  const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Tan;
35010
35183
  currentGeoms.board = {
35011
35184
  geometry: finalBoardGeom,
35012
- color: new THREE28.Color(
35185
+ color: new THREE29.Color(
35013
35186
  matColorArray[0],
35014
35187
  matColorArray[1],
35015
35188
  matColorArray[2]
@@ -35118,6 +35291,18 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35118
35291
  copperColor,
35119
35292
  traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35120
35293
  });
35294
+ currentTextures.topPanelOutlines = createPanelOutlineTextureForLayer({
35295
+ layer: "top",
35296
+ circuitJson,
35297
+ panelData: boardData,
35298
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35299
+ });
35300
+ currentTextures.bottomPanelOutlines = createPanelOutlineTextureForLayer({
35301
+ layer: "bottom",
35302
+ circuitJson,
35303
+ panelData: boardData,
35304
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35305
+ });
35121
35306
  setTextures(currentTextures);
35122
35307
  } catch (e) {
35123
35308
  console.error("Error processing geometry with Manifold in hook:", e);
@@ -35146,11 +35331,11 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35146
35331
  };
35147
35332
 
35148
35333
  // src/utils/manifold/create-three-geometry-meshes.ts
35149
- import * as THREE30 from "three";
35334
+ import * as THREE31 from "three";
35150
35335
 
35151
35336
  // src/utils/create-board-material.ts
35152
- import * as THREE29 from "three";
35153
- var DEFAULT_SIDE = THREE29.DoubleSide;
35337
+ import * as THREE30 from "three";
35338
+ var DEFAULT_SIDE = THREE30.DoubleSide;
35154
35339
  var createBoardMaterial = ({
35155
35340
  material,
35156
35341
  color,
@@ -35158,7 +35343,7 @@ var createBoardMaterial = ({
35158
35343
  isFaux = false
35159
35344
  }) => {
35160
35345
  if (material === "fr4") {
35161
- return new THREE29.MeshPhysicalMaterial({
35346
+ return new THREE30.MeshPhysicalMaterial({
35162
35347
  color,
35163
35348
  side,
35164
35349
  metalness: 0,
@@ -35172,7 +35357,7 @@ var createBoardMaterial = ({
35172
35357
  flatShading: true
35173
35358
  });
35174
35359
  }
35175
- return new THREE29.MeshStandardMaterial({
35360
+ return new THREE30.MeshStandardMaterial({
35176
35361
  color,
35177
35362
  side,
35178
35363
  flatShading: true,
@@ -35188,12 +35373,12 @@ function createGeometryMeshes(geoms) {
35188
35373
  const meshes = [];
35189
35374
  if (!geoms) return meshes;
35190
35375
  if (geoms.board && geoms.board.geometry) {
35191
- const mesh = new THREE30.Mesh(
35376
+ const mesh = new THREE31.Mesh(
35192
35377
  geoms.board.geometry,
35193
35378
  createBoardMaterial({
35194
35379
  material: geoms.board.material,
35195
35380
  color: geoms.board.color,
35196
- side: THREE30.DoubleSide,
35381
+ side: THREE31.DoubleSide,
35197
35382
  isFaux: geoms.board.isFaux
35198
35383
  })
35199
35384
  );
@@ -35203,11 +35388,11 @@ function createGeometryMeshes(geoms) {
35203
35388
  const createMeshesFromArray = (geomArray) => {
35204
35389
  if (geomArray) {
35205
35390
  geomArray.forEach((comp) => {
35206
- const mesh = new THREE30.Mesh(
35391
+ const mesh = new THREE31.Mesh(
35207
35392
  comp.geometry,
35208
- new THREE30.MeshStandardMaterial({
35393
+ new THREE31.MeshStandardMaterial({
35209
35394
  color: comp.color,
35210
- side: THREE30.DoubleSide,
35395
+ side: THREE31.DoubleSide,
35211
35396
  flatShading: true,
35212
35397
  // Consistent with board
35213
35398
  polygonOffset: true,
@@ -35228,25 +35413,24 @@ function createGeometryMeshes(geoms) {
35228
35413
  }
35229
35414
 
35230
35415
  // src/utils/manifold/create-three-texture-meshes.ts
35231
- import * as THREE31 from "three";
35416
+ import * as THREE32 from "three";
35232
35417
  function createTextureMeshes(textures, boardData, pcbThickness) {
35233
35418
  const meshes = [];
35234
35419
  if (!textures || !boardData || pcbThickness === null) return meshes;
35235
35420
  const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix, usePolygonOffset = false, renderOrder = 0) => {
35236
35421
  if (!texture) return null;
35237
- const planeGeom = new THREE31.PlaneGeometry(boardData.width, boardData.height);
35238
- const material = new THREE31.MeshBasicMaterial({
35422
+ const planeGeom = new THREE32.PlaneGeometry(boardData.width, boardData.height);
35423
+ const material = new THREE32.MeshBasicMaterial({
35239
35424
  map: texture,
35240
35425
  transparent: true,
35241
- side: THREE31.DoubleSide,
35242
- depthWrite: false,
35243
- // Important for layers to avoid z-fighting issues with board itself
35426
+ side: THREE32.DoubleSide,
35427
+ depthWrite: keySuffix === "panel-outlines",
35244
35428
  polygonOffset: usePolygonOffset,
35245
35429
  polygonOffsetFactor: usePolygonOffset ? -4 : 0,
35246
35430
  // Increased for better z-fighting prevention
35247
35431
  polygonOffsetUnits: usePolygonOffset ? -4 : 0
35248
35432
  });
35249
- const mesh = new THREE31.Mesh(planeGeom, material);
35433
+ const mesh = new THREE32.Mesh(planeGeom, material);
35250
35434
  mesh.position.set(boardData.center.x, boardData.center.y, yOffset);
35251
35435
  if (isBottomLayer) {
35252
35436
  mesh.rotation.set(Math.PI, 0, 0);
@@ -35362,6 +35546,26 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35362
35546
  // Render after soldermask
35363
35547
  );
35364
35548
  if (bottomCopperTextMesh) meshes.push(bottomCopperTextMesh);
35549
+ const topPanelOutlinesMesh = createTexturePlane(
35550
+ textures.topPanelOutlines,
35551
+ pcbThickness / 2 + 4e-3,
35552
+ // Above silkscreen
35553
+ false,
35554
+ "panel-outlines",
35555
+ false,
35556
+ 4
35557
+ );
35558
+ if (topPanelOutlinesMesh) meshes.push(topPanelOutlinesMesh);
35559
+ const bottomPanelOutlinesMesh = createTexturePlane(
35560
+ textures.bottomPanelOutlines,
35561
+ -pcbThickness / 2 - 4e-3,
35562
+ // Below bottom silkscreen
35563
+ true,
35564
+ "panel-outlines",
35565
+ false,
35566
+ 4
35567
+ );
35568
+ if (bottomPanelOutlinesMesh) meshes.push(bottomPanelOutlinesMesh);
35365
35569
  return meshes;
35366
35570
  }
35367
35571
 
@@ -35418,6 +35622,8 @@ var BoardMeshes = ({
35418
35622
  shouldShow = visibility.topCopper;
35419
35623
  } else if (mesh.name.includes("bottom-copper-text")) {
35420
35624
  shouldShow = visibility.bottomCopper;
35625
+ } else if (mesh.name.includes("panel-outlines")) {
35626
+ shouldShow = visibility.boardBody;
35421
35627
  }
35422
35628
  if (shouldShow) {
35423
35629
  rootObject.add(mesh);
@@ -35530,7 +35736,7 @@ try {
35530
35736
  [textures, boardData, pcbThickness]
35531
35737
  );
35532
35738
  const cadComponents = useMemo22(
35533
- () => su18(circuitJson).cad_component.list(),
35739
+ () => su19(circuitJson).cad_component.list(),
35534
35740
  [circuitJson]
35535
35741
  );
35536
35742
  const boardDimensions = useMemo22(() => {
@@ -42272,7 +42478,7 @@ var KeyboardShortcutsDialog = ({
42272
42478
 
42273
42479
  // src/CadViewer.tsx
42274
42480
  import { jsx as jsx37, jsxs as jsxs11 } from "react/jsx-runtime";
42275
- var DEFAULT_TARGET = new THREE32.Vector3(0, 0, 0);
42481
+ var DEFAULT_TARGET = new THREE33.Vector3(0, 0, 0);
42276
42482
  var INITIAL_CAMERA_POSITION = [5, -5, 5];
42277
42483
  var CadViewerInner = (props) => {
42278
42484
  const [engine, setEngine] = useState35("manifold");
@@ -42538,12 +42744,12 @@ var CadViewer = (props) => {
42538
42744
 
42539
42745
  // src/convert-circuit-json-to-3d-svg.ts
42540
42746
  var import_debug = __toESM(require_browser(), 1);
42541
- import { su as su19 } from "@tscircuit/circuit-json-util";
42542
- import * as THREE36 from "three";
42747
+ import { su as su20 } from "@tscircuit/circuit-json-util";
42748
+ import * as THREE37 from "three";
42543
42749
  import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
42544
42750
 
42545
42751
  // src/utils/create-geometry-from-polygons.ts
42546
- import * as THREE33 from "three";
42752
+ import * as THREE34 from "three";
42547
42753
  import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute2 } from "three";
42548
42754
  function createGeometryFromPolygons(polygons) {
42549
42755
  const geometry = new BufferGeometry3();
@@ -42557,12 +42763,12 @@ function createGeometryFromPolygons(polygons) {
42557
42763
  ...polygon3.vertices[i + 1]
42558
42764
  // Third vertex
42559
42765
  );
42560
- const v1 = new THREE33.Vector3(...polygon3.vertices[0]);
42561
- const v2 = new THREE33.Vector3(...polygon3.vertices[i]);
42562
- const v3 = new THREE33.Vector3(...polygon3.vertices[i + 1]);
42563
- const normal = new THREE33.Vector3().crossVectors(
42564
- new THREE33.Vector3().subVectors(v2, v1),
42565
- new THREE33.Vector3().subVectors(v3, v1)
42766
+ const v1 = new THREE34.Vector3(...polygon3.vertices[0]);
42767
+ const v2 = new THREE34.Vector3(...polygon3.vertices[i]);
42768
+ const v3 = new THREE34.Vector3(...polygon3.vertices[i + 1]);
42769
+ const normal = new THREE34.Vector3().crossVectors(
42770
+ new THREE34.Vector3().subVectors(v2, v1),
42771
+ new THREE34.Vector3().subVectors(v3, v1)
42566
42772
  ).normalize();
42567
42773
  normals.push(
42568
42774
  normal.x,
@@ -42586,10 +42792,10 @@ function createGeometryFromPolygons(polygons) {
42586
42792
  var import_modeling2 = __toESM(require_src(), 1);
42587
42793
  var import_jscad_planner2 = __toESM(require_dist(), 1);
42588
42794
  var jscadModeling2 = __toESM(require_src(), 1);
42589
- import * as THREE35 from "three";
42795
+ import * as THREE36 from "three";
42590
42796
 
42591
42797
  // src/utils/load-model.ts
42592
- import * as THREE34 from "three";
42798
+ import * as THREE35 from "three";
42593
42799
  import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
42594
42800
  import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
42595
42801
  import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
@@ -42597,12 +42803,12 @@ async function load3DModel(url) {
42597
42803
  if (url.endsWith(".stl")) {
42598
42804
  const loader = new STLLoader2();
42599
42805
  const geometry = await loader.loadAsync(url);
42600
- const material = new THREE34.MeshStandardMaterial({
42806
+ const material = new THREE35.MeshStandardMaterial({
42601
42807
  color: 8947848,
42602
42808
  metalness: 0.5,
42603
42809
  roughness: 0.5
42604
42810
  });
42605
- return new THREE34.Mesh(geometry, material);
42811
+ return new THREE35.Mesh(geometry, material);
42606
42812
  }
42607
42813
  if (url.endsWith(".obj")) {
42608
42814
  const loader = new OBJLoader2();
@@ -42635,9 +42841,9 @@ async function renderComponent(component, scene) {
42635
42841
  }
42636
42842
  if (component.rotation) {
42637
42843
  model.rotation.set(
42638
- THREE35.MathUtils.degToRad(component.rotation.x ?? 0),
42639
- THREE35.MathUtils.degToRad(component.rotation.y ?? 0),
42640
- THREE35.MathUtils.degToRad(component.rotation.z ?? 0)
42844
+ THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
42845
+ THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
42846
+ THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
42641
42847
  );
42642
42848
  }
42643
42849
  scene.add(model);
@@ -42651,13 +42857,13 @@ async function renderComponent(component, scene) {
42651
42857
  );
42652
42858
  if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
42653
42859
  const threeGeom = convertCSGToThreeGeom(jscadObject);
42654
- const material2 = new THREE35.MeshStandardMaterial({
42860
+ const material2 = new THREE36.MeshStandardMaterial({
42655
42861
  color: 8947848,
42656
42862
  metalness: 0.5,
42657
42863
  roughness: 0.5,
42658
- side: THREE35.DoubleSide
42864
+ side: THREE36.DoubleSide
42659
42865
  });
42660
- const mesh2 = new THREE35.Mesh(threeGeom, material2);
42866
+ const mesh2 = new THREE36.Mesh(threeGeom, material2);
42661
42867
  if (component.position) {
42662
42868
  mesh2.position.set(
42663
42869
  component.position.x ?? 0,
@@ -42667,9 +42873,9 @@ async function renderComponent(component, scene) {
42667
42873
  }
42668
42874
  if (component.rotation) {
42669
42875
  mesh2.rotation.set(
42670
- THREE35.MathUtils.degToRad(component.rotation.x ?? 0),
42671
- THREE35.MathUtils.degToRad(component.rotation.y ?? 0),
42672
- THREE35.MathUtils.degToRad(component.rotation.z ?? 0)
42876
+ THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
42877
+ THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
42878
+ THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
42673
42879
  );
42674
42880
  }
42675
42881
  scene.add(mesh2);
@@ -42686,17 +42892,17 @@ async function renderComponent(component, scene) {
42686
42892
  if (!geom || !geom.polygons && !geom.sides) {
42687
42893
  continue;
42688
42894
  }
42689
- const color = new THREE35.Color(geomInfo.color);
42895
+ const color = new THREE36.Color(geomInfo.color);
42690
42896
  color.convertLinearToSRGB();
42691
42897
  const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
42692
42898
  const threeGeom = convertCSGToThreeGeom(geomWithColor);
42693
- const material2 = new THREE35.MeshStandardMaterial({
42899
+ const material2 = new THREE36.MeshStandardMaterial({
42694
42900
  vertexColors: true,
42695
42901
  metalness: 0.2,
42696
42902
  roughness: 0.8,
42697
- side: THREE35.DoubleSide
42903
+ side: THREE36.DoubleSide
42698
42904
  });
42699
- const mesh2 = new THREE35.Mesh(threeGeom, material2);
42905
+ const mesh2 = new THREE36.Mesh(threeGeom, material2);
42700
42906
  if (component.position) {
42701
42907
  mesh2.position.set(
42702
42908
  component.position.x ?? 0,
@@ -42706,22 +42912,22 @@ async function renderComponent(component, scene) {
42706
42912
  }
42707
42913
  if (component.rotation) {
42708
42914
  mesh2.rotation.set(
42709
- THREE35.MathUtils.degToRad(component.rotation.x ?? 0),
42710
- THREE35.MathUtils.degToRad(component.rotation.y ?? 0),
42711
- THREE35.MathUtils.degToRad(component.rotation.z ?? 0)
42915
+ THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
42916
+ THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
42917
+ THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
42712
42918
  );
42713
42919
  }
42714
42920
  scene.add(mesh2);
42715
42921
  }
42716
42922
  return;
42717
42923
  }
42718
- const geometry = new THREE35.BoxGeometry(0.5, 0.5, 0.5);
42719
- const material = new THREE35.MeshStandardMaterial({
42924
+ const geometry = new THREE36.BoxGeometry(0.5, 0.5, 0.5);
42925
+ const material = new THREE36.MeshStandardMaterial({
42720
42926
  color: 16711680,
42721
42927
  transparent: true,
42722
42928
  opacity: 0.25
42723
42929
  });
42724
- const mesh = new THREE35.Mesh(geometry, material);
42930
+ const mesh = new THREE36.Mesh(geometry, material);
42725
42931
  if (component.position) {
42726
42932
  mesh.position.set(
42727
42933
  component.position.x ?? 0,
@@ -42742,11 +42948,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42742
42948
  padding = 20,
42743
42949
  zoom = 1.5
42744
42950
  } = options;
42745
- const scene = new THREE36.Scene();
42951
+ const scene = new THREE37.Scene();
42746
42952
  const renderer = new SVGRenderer();
42747
42953
  renderer.setSize(width10, height10);
42748
- renderer.setClearColor(new THREE36.Color(backgroundColor), 1);
42749
- const camera = new THREE36.OrthographicCamera();
42954
+ renderer.setClearColor(new THREE37.Color(backgroundColor), 1);
42955
+ const camera = new THREE37.OrthographicCamera();
42750
42956
  const aspect = width10 / height10;
42751
42957
  const frustumSize = 100;
42752
42958
  const halfFrustumSize = frustumSize / 2 / zoom;
@@ -42760,22 +42966,22 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42760
42966
  camera.position.set(position.x, position.y, position.z);
42761
42967
  camera.up.set(0, 1, 0);
42762
42968
  const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
42763
- camera.lookAt(new THREE36.Vector3(lookAt.x, lookAt.y, lookAt.z));
42969
+ camera.lookAt(new THREE37.Vector3(lookAt.x, lookAt.y, lookAt.z));
42764
42970
  camera.updateProjectionMatrix();
42765
- const ambientLight = new THREE36.AmbientLight(16777215, Math.PI / 2);
42971
+ const ambientLight = new THREE37.AmbientLight(16777215, Math.PI / 2);
42766
42972
  scene.add(ambientLight);
42767
- const pointLight = new THREE36.PointLight(16777215, Math.PI / 4);
42973
+ const pointLight = new THREE37.PointLight(16777215, Math.PI / 4);
42768
42974
  pointLight.position.set(-10, -10, 10);
42769
42975
  scene.add(pointLight);
42770
- const components = su19(circuitJson).cad_component.list();
42976
+ const components = su20(circuitJson).cad_component.list();
42771
42977
  for (const component of components) {
42772
42978
  await renderComponent(component, scene);
42773
42979
  }
42774
- const boardData = su19(circuitJson).pcb_board.list()[0];
42980
+ const boardData = su20(circuitJson).pcb_board.list()[0];
42775
42981
  const boardGeom = createBoardGeomFromCircuitJson(circuitJson);
42776
42982
  if (boardGeom) {
42777
42983
  const solderMaskColor = colors.fr4SolderMaskGreen;
42778
- const baseColor = new THREE36.Color(
42984
+ const baseColor = new THREE37.Color(
42779
42985
  solderMaskColor[0],
42780
42986
  solderMaskColor[1],
42781
42987
  solderMaskColor[2]
@@ -42787,28 +42993,28 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42787
42993
  const material = createBoardMaterial({
42788
42994
  material: boardData?.material,
42789
42995
  color: baseColor,
42790
- side: THREE36.DoubleSide
42996
+ side: THREE37.DoubleSide
42791
42997
  });
42792
- const mesh = new THREE36.Mesh(geometry, material);
42998
+ const mesh = new THREE37.Mesh(geometry, material);
42793
42999
  scene.add(mesh);
42794
43000
  }
42795
43001
  }
42796
- const gridColor = new THREE36.Color(8947848);
42797
- const gridHelper = new THREE36.GridHelper(100, 100, gridColor, gridColor);
43002
+ const gridColor = new THREE37.Color(8947848);
43003
+ const gridHelper = new THREE37.GridHelper(100, 100, gridColor, gridColor);
42798
43004
  gridHelper.rotation.x = Math.PI / 2;
42799
43005
  const materials = Array.isArray(gridHelper.material) ? gridHelper.material : [gridHelper.material];
42800
43006
  for (const mat of materials) {
42801
43007
  mat.transparent = true;
42802
43008
  mat.opacity = 0.3;
42803
- if (mat instanceof THREE36.LineBasicMaterial) {
43009
+ if (mat instanceof THREE37.LineBasicMaterial) {
42804
43010
  mat.color = gridColor;
42805
43011
  mat.vertexColors = false;
42806
43012
  }
42807
43013
  }
42808
43014
  scene.add(gridHelper);
42809
- const box = new THREE36.Box3().setFromObject(scene);
42810
- const center = box.getCenter(new THREE36.Vector3());
42811
- const size5 = box.getSize(new THREE36.Vector3());
43015
+ const box = new THREE37.Box3().setFromObject(scene);
43016
+ const center = box.getCenter(new THREE37.Vector3());
43017
+ const size5 = box.getSize(new THREE37.Vector3());
42812
43018
  scene.position.sub(center);
42813
43019
  const maxDim = Math.max(size5.x, size5.y, size5.z);
42814
43020
  if (maxDim > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.470",
3
+ "version": "0.0.472",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",