@tscircuit/3d-viewer 0.0.470 → 0.0.471

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.470",
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";
@@ -33088,6 +33097,72 @@ function createCopperTextTextureForLayer({
33088
33097
  return texture;
33089
33098
  }
33090
33099
 
33100
+ // src/utils/panel-outline-texture.ts
33101
+ import * as THREE22 from "three";
33102
+ import { su as su8 } from "@tscircuit/circuit-json-util";
33103
+ function createPanelOutlineTextureForLayer({
33104
+ layer,
33105
+ circuitJson,
33106
+ panelData,
33107
+ outlineColor = "black",
33108
+ traceTextureResolution
33109
+ }) {
33110
+ const boardsInPanel = su8(circuitJson).pcb_board.list().filter((b) => b.pcb_panel_id === panelData.pcb_board_id);
33111
+ if (boardsInPanel.length === 0) {
33112
+ return null;
33113
+ }
33114
+ const canvas = document.createElement("canvas");
33115
+ const canvasWidth = Math.floor(panelData.width * traceTextureResolution);
33116
+ const canvasHeight = Math.floor(panelData.height * traceTextureResolution);
33117
+ canvas.width = canvasWidth;
33118
+ canvas.height = canvasHeight;
33119
+ const ctx = canvas.getContext("2d");
33120
+ if (!ctx) return null;
33121
+ if (layer === "bottom") {
33122
+ ctx.translate(0, canvasHeight);
33123
+ ctx.scale(1, -1);
33124
+ }
33125
+ ctx.strokeStyle = outlineColor;
33126
+ ctx.lineWidth = 0.05 * traceTextureResolution;
33127
+ const canvasXFromPcb = (pcbX) => (pcbX - panelData.center.x + panelData.width / 2) * traceTextureResolution;
33128
+ const canvasYFromPcb = (pcbY) => (-(pcbY - panelData.center.y) + panelData.height / 2) * traceTextureResolution;
33129
+ boardsInPanel.forEach((board) => {
33130
+ if (board.outline && board.outline.length >= 2) {
33131
+ ctx.beginPath();
33132
+ board.outline.forEach((point2, index2) => {
33133
+ const x = canvasXFromPcb(point2.x);
33134
+ const y = canvasYFromPcb(point2.y);
33135
+ if (index2 === 0) {
33136
+ ctx.moveTo(x, y);
33137
+ } else {
33138
+ ctx.lineTo(x, y);
33139
+ }
33140
+ });
33141
+ ctx.closePath();
33142
+ ctx.stroke();
33143
+ } else {
33144
+ const width10 = board.width;
33145
+ const height10 = board.height;
33146
+ const { x: centerX, y: centerY } = board.center;
33147
+ const x = canvasXFromPcb(centerX - width10 / 2);
33148
+ const y = canvasYFromPcb(centerY + height10 / 2);
33149
+ ctx.strokeRect(
33150
+ x,
33151
+ y,
33152
+ width10 * traceTextureResolution,
33153
+ height10 * traceTextureResolution
33154
+ );
33155
+ }
33156
+ });
33157
+ const texture = new THREE22.CanvasTexture(canvas);
33158
+ texture.generateMipmaps = true;
33159
+ texture.minFilter = THREE22.LinearMipmapLinearFilter;
33160
+ texture.magFilter = THREE22.LinearFilter;
33161
+ texture.anisotropy = 16;
33162
+ texture.needsUpdate = true;
33163
+ return texture;
33164
+ }
33165
+
33091
33166
  // src/three-components/JscadBoardTextures.tsx
33092
33167
  function JscadBoardTextures({
33093
33168
  circuitJson,
@@ -33096,8 +33171,30 @@ function JscadBoardTextures({
33096
33171
  const { rootObject } = useThree();
33097
33172
  const { visibility } = useLayerVisibility();
33098
33173
  const boardData = useMemo19(() => {
33099
- const boards = su8(circuitJson).pcb_board.list();
33100
- return boards.length > 0 ? boards[0] : null;
33174
+ const panels = circuitJson.filter(
33175
+ (e) => e.type === "pcb_panel"
33176
+ );
33177
+ const boards = su9(circuitJson).pcb_board.list();
33178
+ if (panels.length > 0) {
33179
+ const panel = panels[0];
33180
+ const firstBoardInPanel = boards.find(
33181
+ (b) => b.pcb_panel_id === panel.pcb_panel_id
33182
+ );
33183
+ return {
33184
+ type: "pcb_board",
33185
+ pcb_board_id: panel.pcb_panel_id,
33186
+ center: panel.center,
33187
+ width: panel.width,
33188
+ height: panel.height,
33189
+ thickness: firstBoardInPanel?.thickness ?? 1.6,
33190
+ material: firstBoardInPanel?.material ?? "fr4",
33191
+ num_layers: firstBoardInPanel?.num_layers ?? 2
33192
+ };
33193
+ }
33194
+ const boardsNotInPanel = boards.filter(
33195
+ (b) => !b.pcb_panel_id
33196
+ );
33197
+ return boardsNotInPanel.length > 0 ? boardsNotInPanel[0] : null;
33101
33198
  }, [circuitJson]);
33102
33199
  const textures = useMemo19(() => {
33103
33200
  if (!boardData || !boardData.width || !boardData.height) return null;
@@ -33162,28 +33259,40 @@ function JscadBoardTextures({
33162
33259
  boardData,
33163
33260
  copperColor: `rgb(${Math.round(colors.copper[0] * 255)}, ${Math.round(colors.copper[1] * 255)}, ${Math.round(colors.copper[2] * 255)})`,
33164
33261
  traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33262
+ }),
33263
+ topPanelOutlines: createPanelOutlineTextureForLayer({
33264
+ layer: "top",
33265
+ circuitJson,
33266
+ panelData: boardData,
33267
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33268
+ }),
33269
+ bottomPanelOutlines: createPanelOutlineTextureForLayer({
33270
+ layer: "bottom",
33271
+ circuitJson,
33272
+ panelData: boardData,
33273
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33165
33274
  })
33166
33275
  };
33167
33276
  }, [circuitJson, boardData]);
33168
33277
  useEffect22(() => {
33169
33278
  if (!rootObject || !boardData || !textures) return;
33170
33279
  const meshes = [];
33171
- const createTexturePlane = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false) => {
33280
+ const createTexturePlane = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false, depthWrite = false) => {
33172
33281
  if (!texture) return null;
33173
- const planeGeom = new THREE22.PlaneGeometry(
33282
+ const planeGeom = new THREE23.PlaneGeometry(
33174
33283
  boardData.width,
33175
33284
  boardData.height
33176
33285
  );
33177
- const material = new THREE22.MeshBasicMaterial({
33286
+ const material = new THREE23.MeshBasicMaterial({
33178
33287
  map: texture,
33179
33288
  transparent: true,
33180
- side: THREE22.DoubleSide,
33181
- depthWrite: false,
33289
+ side: THREE23.DoubleSide,
33290
+ depthWrite,
33182
33291
  polygonOffset: usePolygonOffset,
33183
33292
  polygonOffsetFactor: usePolygonOffset ? -1 : 0,
33184
33293
  polygonOffsetUnits: usePolygonOffset ? -1 : 0
33185
33294
  });
33186
- const mesh = new THREE22.Mesh(planeGeom, material);
33295
+ const mesh = new THREE23.Mesh(planeGeom, material);
33187
33296
  mesh.position.set(boardData.center.x, boardData.center.y, zOffset);
33188
33297
  if (isBottomLayer) {
33189
33298
  mesh.rotation.set(Math.PI, 0, 0);
@@ -33290,13 +33399,41 @@ function JscadBoardTextures({
33290
33399
  rootObject.add(bottomCopperTextMesh);
33291
33400
  }
33292
33401
  }
33402
+ if (visibility.boardBody) {
33403
+ const topPanelOutlinesMesh = createTexturePlane(
33404
+ textures.topPanelOutlines,
33405
+ pcbThickness / 2 + SURFACE_OFFSET + 3e-3,
33406
+ // Above silkscreen
33407
+ false,
33408
+ "jscad-top-panel-outlines",
33409
+ false,
33410
+ true
33411
+ );
33412
+ if (topPanelOutlinesMesh) {
33413
+ meshes.push(topPanelOutlinesMesh);
33414
+ rootObject.add(topPanelOutlinesMesh);
33415
+ }
33416
+ const bottomPanelOutlinesMesh = createTexturePlane(
33417
+ textures.bottomPanelOutlines,
33418
+ -pcbThickness / 2 - SURFACE_OFFSET - 3e-3,
33419
+ // Below bottom silkscreen
33420
+ true,
33421
+ "jscad-bottom-panel-outlines",
33422
+ false,
33423
+ true
33424
+ );
33425
+ if (bottomPanelOutlinesMesh) {
33426
+ meshes.push(bottomPanelOutlinesMesh);
33427
+ rootObject.add(bottomPanelOutlinesMesh);
33428
+ }
33429
+ }
33293
33430
  return () => {
33294
33431
  meshes.forEach((mesh) => {
33295
33432
  if (mesh.parent === rootObject) {
33296
33433
  rootObject.remove(mesh);
33297
33434
  }
33298
33435
  mesh.geometry.dispose();
33299
- if (mesh.material instanceof THREE22.Material) {
33436
+ if (mesh.material instanceof THREE23.Material) {
33300
33437
  mesh.material.dispose();
33301
33438
  }
33302
33439
  });
@@ -33306,16 +33443,16 @@ function JscadBoardTextures({
33306
33443
  }
33307
33444
 
33308
33445
  // src/utils/preprocess-circuit-json.ts
33309
- import { su as su10 } from "@tscircuit/circuit-json-util";
33446
+ import { su as su11 } from "@tscircuit/circuit-json-util";
33310
33447
 
33311
33448
  // src/utils/create-faux-board.ts
33312
- import { su as su9, getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
33449
+ import { su as su10, getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
33313
33450
  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();
33451
+ const cadComponents = su10(circuitJson).cad_component.list();
33452
+ const pads = su10(circuitJson).pcb_smtpad.list();
33453
+ const holes = su10(circuitJson).pcb_hole.list();
33454
+ const platedHoles = su10(circuitJson).pcb_plated_hole.list();
33455
+ const vias = su10(circuitJson).pcb_via.list();
33319
33456
  if (cadComponents.length === 0 && pads.length === 0 && holes.length === 0 && platedHoles.length === 0 && vias.length === 0) {
33320
33457
  return null;
33321
33458
  }
@@ -33364,7 +33501,7 @@ function createFauxBoard(circuitJson) {
33364
33501
 
33365
33502
  // src/utils/preprocess-circuit-json.ts
33366
33503
  function addFauxBoardIfNeeded(circuitJson) {
33367
- const boards = su10(circuitJson).pcb_board.list();
33504
+ const boards = su11(circuitJson).pcb_board.list();
33368
33505
  if (boards.length > 0) {
33369
33506
  return circuitJson;
33370
33507
  }
@@ -33414,7 +33551,7 @@ var CadViewerJscad = forwardRef3(
33414
33551
  const initialCameraPosition = useMemo20(() => {
33415
33552
  if (!internalCircuitJson) return [5, -5, 5];
33416
33553
  try {
33417
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33554
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33418
33555
  if (!board) return [5, -5, 5];
33419
33556
  const { width: width10, height: height10 } = board;
33420
33557
  if (!width10 && !height10) {
@@ -33440,7 +33577,7 @@ var CadViewerJscad = forwardRef3(
33440
33577
  const isFauxBoard = useMemo20(() => {
33441
33578
  if (!internalCircuitJson) return false;
33442
33579
  try {
33443
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33580
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33444
33581
  return !!board && board.pcb_board_id === "faux-board";
33445
33582
  } catch (e) {
33446
33583
  return false;
@@ -33449,7 +33586,7 @@ var CadViewerJscad = forwardRef3(
33449
33586
  const boardDimensions = useMemo20(() => {
33450
33587
  if (!internalCircuitJson) return void 0;
33451
33588
  try {
33452
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33589
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33453
33590
  if (!board) return void 0;
33454
33591
  return { width: board.width ?? 0, height: board.height ?? 0 };
33455
33592
  } catch (e) {
@@ -33460,7 +33597,7 @@ var CadViewerJscad = forwardRef3(
33460
33597
  const boardCenter = useMemo20(() => {
33461
33598
  if (!internalCircuitJson) return void 0;
33462
33599
  try {
33463
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33600
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33464
33601
  if (!board || !board.center) return void 0;
33465
33602
  return { x: board.center.x, y: board.center.y };
33466
33603
  } catch (e) {
@@ -33470,7 +33607,7 @@ var CadViewerJscad = forwardRef3(
33470
33607
  }, [internalCircuitJson]);
33471
33608
  const pcbThickness = usePcbThickness(internalCircuitJson);
33472
33609
  const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
33473
- const cad_components = su11(internalCircuitJson).cad_component.list();
33610
+ const cad_components = su12(internalCircuitJson).cad_component.list();
33474
33611
  return /* @__PURE__ */ jsxs5(
33475
33612
  CadViewerContainer,
33476
33613
  {
@@ -33522,13 +33659,13 @@ var CadViewerJscad = forwardRef3(
33522
33659
  );
33523
33660
 
33524
33661
  // src/CadViewerManifold.tsx
33525
- import { su as su18 } from "@tscircuit/circuit-json-util";
33662
+ import { su as su19 } from "@tscircuit/circuit-json-util";
33526
33663
  import { useEffect as useEffect24, useMemo as useMemo22, useState as useState15 } from "react";
33527
33664
 
33528
33665
  // src/hooks/useManifoldBoardBuilder.ts
33529
33666
  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";
33667
+ import { su as su18 } from "@tscircuit/circuit-json-util";
33668
+ import * as THREE29 from "three";
33532
33669
 
33533
33670
  // src/utils/manifold/create-manifold-board.ts
33534
33671
  var arePointsClockwise3 = (points) => {
@@ -33589,17 +33726,17 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
33589
33726
  }
33590
33727
 
33591
33728
  // src/utils/manifold/process-copper-pours.ts
33592
- import * as THREE24 from "three";
33729
+ import * as THREE25 from "three";
33593
33730
 
33594
33731
  // src/utils/manifold-mesh-to-three-geometry.ts
33595
- import * as THREE23 from "three";
33732
+ import * as THREE24 from "three";
33596
33733
  function manifoldMeshToThreeGeometry(manifoldMesh) {
33597
- const geometry = new THREE23.BufferGeometry();
33734
+ const geometry = new THREE24.BufferGeometry();
33598
33735
  geometry.setAttribute(
33599
33736
  "position",
33600
- new THREE23.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
33737
+ new THREE24.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
33601
33738
  );
33602
- geometry.setIndex(new THREE23.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
33739
+ geometry.setIndex(new THREE24.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
33603
33740
  if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
33604
33741
  for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
33605
33742
  const start = manifoldMesh.runIndex[i];
@@ -33772,7 +33909,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33772
33909
  }
33773
33910
  const covered = pour.covered_with_solder_mask !== false;
33774
33911
  const pourColorArr = covered ? tracesMaterialColors[boardMaterial] ?? colors.fr4TracesWithoutMaskTan : colors.copper;
33775
- const pourColor = new THREE24.Color(...pourColorArr);
33912
+ const pourColor = new THREE25.Color(...pourColorArr);
33776
33913
  const threeGeom = manifoldMeshToThreeGeometry(pourOp.getMesh());
33777
33914
  copperPourGeoms.push({
33778
33915
  key: `coppour-${pour.pcb_copper_pour_id}`,
@@ -33785,7 +33922,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33785
33922
  }
33786
33923
 
33787
33924
  // src/utils/manifold/process-cutouts.ts
33788
- import { su as su12 } from "@tscircuit/circuit-json-util";
33925
+ import { su as su13 } from "@tscircuit/circuit-json-util";
33789
33926
 
33790
33927
  // src/utils/pad-geoms.ts
33791
33928
  var RECT_PAD_SEGMENTS2 = 64;
@@ -33877,7 +34014,7 @@ var arePointsClockwise5 = (points) => {
33877
34014
  };
33878
34015
  function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
33879
34016
  const cutoutOps = [];
33880
- const pcbCutouts = su12(circuitJson).pcb_cutout.list();
34017
+ const pcbCutouts = su13(circuitJson).pcb_cutout.list();
33881
34018
  for (const cutout of pcbCutouts) {
33882
34019
  let cutoutOp;
33883
34020
  const cutoutHeight = pcbThickness * 1.5;
@@ -33972,7 +34109,7 @@ function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThick
33972
34109
  }
33973
34110
 
33974
34111
  // src/utils/manifold/process-non-plated-holes.ts
33975
- import { su as su13 } from "@tscircuit/circuit-json-util";
34112
+ import { su as su14 } from "@tscircuit/circuit-json-util";
33976
34113
 
33977
34114
  // src/utils/hole-geoms.ts
33978
34115
  function createCircleHoleDrill({
@@ -34024,7 +34161,7 @@ function isRotatedPillHole(hole) {
34024
34161
  }
34025
34162
  function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
34026
34163
  const nonPlatedHoleBoardDrills = [];
34027
- const pcbHoles = su13(circuitJson).pcb_hole.list();
34164
+ const pcbHoles = su14(circuitJson).pcb_hole.list();
34028
34165
  const createPillOp = (width10, height10, depth) => {
34029
34166
  const pillOp = createRoundedRectPrism({
34030
34167
  Manifold,
@@ -34073,8 +34210,8 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
34073
34210
  }
34074
34211
 
34075
34212
  // src/utils/manifold/process-plated-holes.ts
34076
- import { su as su14 } from "@tscircuit/circuit-json-util";
34077
- import * as THREE25 from "three";
34213
+ import { su as su15 } from "@tscircuit/circuit-json-util";
34214
+ import * as THREE26 from "three";
34078
34215
  var arePointsClockwise6 = (points) => {
34079
34216
  let area = 0;
34080
34217
  for (let i = 0; i < points.length; i++) {
@@ -34095,11 +34232,11 @@ var createEllipsePoints = (width10, height10, segments) => {
34095
34232
  }
34096
34233
  return points;
34097
34234
  };
34098
- var COPPER_COLOR = new THREE25.Color(...colors.copper);
34235
+ var COPPER_COLOR = new THREE26.Color(...colors.copper);
34099
34236
  var PLATED_HOLE_LIP_HEIGHT = 0.05;
34100
34237
  function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
34101
34238
  const platedHoleBoardDrills = [];
34102
- const pcbPlatedHoles = su14(circuitJson).pcb_plated_hole.list();
34239
+ const pcbPlatedHoles = su15(circuitJson).pcb_plated_hole.list();
34103
34240
  const platedHoleCopperGeoms = [];
34104
34241
  const platedHoleCopperOpsForSubtract = [];
34105
34242
  const createPillOp = (width10, height10, depth) => {
@@ -34668,12 +34805,12 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
34668
34805
  }
34669
34806
 
34670
34807
  // 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);
34808
+ import { su as su16 } from "@tscircuit/circuit-json-util";
34809
+ import * as THREE27 from "three";
34810
+ var COPPER_COLOR2 = new THREE27.Color(...colors.copper);
34674
34811
  function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
34675
34812
  const smtPadGeoms = [];
34676
- const smtPads = su15(circuitJson).pcb_smtpad.list();
34813
+ const smtPads = su16(circuitJson).pcb_smtpad.list();
34677
34814
  smtPads.forEach((pad2, index2) => {
34678
34815
  const padBaseThickness = DEFAULT_SMT_PAD_THICKNESS;
34679
34816
  const zPos = pad2.layer === "bottom" ? -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper : pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper;
@@ -34708,8 +34845,8 @@ function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifold
34708
34845
  }
34709
34846
 
34710
34847
  // src/utils/manifold/process-vias.ts
34711
- import { su as su16 } from "@tscircuit/circuit-json-util";
34712
- import * as THREE27 from "three";
34848
+ import { su as su17 } from "@tscircuit/circuit-json-util";
34849
+ import * as THREE28 from "three";
34713
34850
 
34714
34851
  // src/utils/via-geoms.ts
34715
34852
  function createViaCopper2({
@@ -34762,10 +34899,10 @@ function createViaCopper2({
34762
34899
  }
34763
34900
 
34764
34901
  // src/utils/manifold/process-vias.ts
34765
- var COPPER_COLOR3 = new THREE27.Color(...colors.copper);
34902
+ var COPPER_COLOR3 = new THREE28.Color(...colors.copper);
34766
34903
  function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
34767
34904
  const viaBoardDrills = [];
34768
- const pcbVias = su16(circuitJson).pcb_via.list();
34905
+ const pcbVias = su17(circuitJson).pcb_via.list();
34769
34906
  const viaCopperGeoms = [];
34770
34907
  pcbVias.forEach((via, index2) => {
34771
34908
  if (typeof via.hole_diameter === "number") {
@@ -34825,26 +34962,28 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
34825
34962
  const panels = circuitJson.filter(
34826
34963
  (e) => e.type === "pcb_panel"
34827
34964
  );
34828
- const boards = su17(circuitJson).pcb_board.list();
34965
+ const boards = su18(circuitJson).pcb_board.list();
34829
34966
  if (panels.length > 0) {
34830
34967
  const panel = panels[0];
34968
+ const firstBoardInPanel = boards.find(
34969
+ (b) => b.pcb_panel_id === panel.pcb_panel_id
34970
+ );
34831
34971
  return {
34832
34972
  type: "pcb_board",
34833
34973
  pcb_board_id: panel.pcb_panel_id,
34834
34974
  center: panel.center,
34835
34975
  width: panel.width,
34836
34976
  height: panel.height,
34837
- thickness: 1.6,
34838
- // Default thickness
34839
- material: "fr4",
34840
- num_layers: 2
34977
+ thickness: firstBoardInPanel?.thickness ?? 1.6,
34978
+ material: firstBoardInPanel?.material ?? "fr4",
34979
+ num_layers: firstBoardInPanel?.num_layers ?? 2
34841
34980
  };
34842
34981
  }
34843
34982
  const boardsNotInPanel = boards.filter((b) => !b.pcb_panel_id);
34844
34983
  return boardsNotInPanel.length > 0 ? boardsNotInPanel[0] : null;
34845
34984
  }, [circuitJson]);
34846
34985
  const isFauxBoard = useMemo21(() => {
34847
- const boards = su17(circuitJson).pcb_board.list();
34986
+ const boards = su18(circuitJson).pcb_board.list();
34848
34987
  return boards.length > 0 && boards[0].pcb_board_id === "faux-board";
34849
34988
  }, [circuitJson]);
34850
34989
  useEffect23(() => {
@@ -34979,7 +35118,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
34979
35118
  {
34980
35119
  key: "plated-holes-union",
34981
35120
  geometry: cutPlatedGeom,
34982
- color: new THREE28.Color(
35121
+ color: new THREE29.Color(
34983
35122
  colors.copper[0],
34984
35123
  colors.copper[1],
34985
35124
  colors.copper[2]
@@ -35009,7 +35148,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35009
35148
  const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Tan;
35010
35149
  currentGeoms.board = {
35011
35150
  geometry: finalBoardGeom,
35012
- color: new THREE28.Color(
35151
+ color: new THREE29.Color(
35013
35152
  matColorArray[0],
35014
35153
  matColorArray[1],
35015
35154
  matColorArray[2]
@@ -35118,6 +35257,18 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35118
35257
  copperColor,
35119
35258
  traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35120
35259
  });
35260
+ currentTextures.topPanelOutlines = createPanelOutlineTextureForLayer({
35261
+ layer: "top",
35262
+ circuitJson,
35263
+ panelData: boardData,
35264
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35265
+ });
35266
+ currentTextures.bottomPanelOutlines = createPanelOutlineTextureForLayer({
35267
+ layer: "bottom",
35268
+ circuitJson,
35269
+ panelData: boardData,
35270
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35271
+ });
35121
35272
  setTextures(currentTextures);
35122
35273
  } catch (e) {
35123
35274
  console.error("Error processing geometry with Manifold in hook:", e);
@@ -35146,11 +35297,11 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35146
35297
  };
35147
35298
 
35148
35299
  // src/utils/manifold/create-three-geometry-meshes.ts
35149
- import * as THREE30 from "three";
35300
+ import * as THREE31 from "three";
35150
35301
 
35151
35302
  // src/utils/create-board-material.ts
35152
- import * as THREE29 from "three";
35153
- var DEFAULT_SIDE = THREE29.DoubleSide;
35303
+ import * as THREE30 from "three";
35304
+ var DEFAULT_SIDE = THREE30.DoubleSide;
35154
35305
  var createBoardMaterial = ({
35155
35306
  material,
35156
35307
  color,
@@ -35158,7 +35309,7 @@ var createBoardMaterial = ({
35158
35309
  isFaux = false
35159
35310
  }) => {
35160
35311
  if (material === "fr4") {
35161
- return new THREE29.MeshPhysicalMaterial({
35312
+ return new THREE30.MeshPhysicalMaterial({
35162
35313
  color,
35163
35314
  side,
35164
35315
  metalness: 0,
@@ -35172,7 +35323,7 @@ var createBoardMaterial = ({
35172
35323
  flatShading: true
35173
35324
  });
35174
35325
  }
35175
- return new THREE29.MeshStandardMaterial({
35326
+ return new THREE30.MeshStandardMaterial({
35176
35327
  color,
35177
35328
  side,
35178
35329
  flatShading: true,
@@ -35188,12 +35339,12 @@ function createGeometryMeshes(geoms) {
35188
35339
  const meshes = [];
35189
35340
  if (!geoms) return meshes;
35190
35341
  if (geoms.board && geoms.board.geometry) {
35191
- const mesh = new THREE30.Mesh(
35342
+ const mesh = new THREE31.Mesh(
35192
35343
  geoms.board.geometry,
35193
35344
  createBoardMaterial({
35194
35345
  material: geoms.board.material,
35195
35346
  color: geoms.board.color,
35196
- side: THREE30.DoubleSide,
35347
+ side: THREE31.DoubleSide,
35197
35348
  isFaux: geoms.board.isFaux
35198
35349
  })
35199
35350
  );
@@ -35203,11 +35354,11 @@ function createGeometryMeshes(geoms) {
35203
35354
  const createMeshesFromArray = (geomArray) => {
35204
35355
  if (geomArray) {
35205
35356
  geomArray.forEach((comp) => {
35206
- const mesh = new THREE30.Mesh(
35357
+ const mesh = new THREE31.Mesh(
35207
35358
  comp.geometry,
35208
- new THREE30.MeshStandardMaterial({
35359
+ new THREE31.MeshStandardMaterial({
35209
35360
  color: comp.color,
35210
- side: THREE30.DoubleSide,
35361
+ side: THREE31.DoubleSide,
35211
35362
  flatShading: true,
35212
35363
  // Consistent with board
35213
35364
  polygonOffset: true,
@@ -35228,25 +35379,24 @@ function createGeometryMeshes(geoms) {
35228
35379
  }
35229
35380
 
35230
35381
  // src/utils/manifold/create-three-texture-meshes.ts
35231
- import * as THREE31 from "three";
35382
+ import * as THREE32 from "three";
35232
35383
  function createTextureMeshes(textures, boardData, pcbThickness) {
35233
35384
  const meshes = [];
35234
35385
  if (!textures || !boardData || pcbThickness === null) return meshes;
35235
35386
  const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix, usePolygonOffset = false, renderOrder = 0) => {
35236
35387
  if (!texture) return null;
35237
- const planeGeom = new THREE31.PlaneGeometry(boardData.width, boardData.height);
35238
- const material = new THREE31.MeshBasicMaterial({
35388
+ const planeGeom = new THREE32.PlaneGeometry(boardData.width, boardData.height);
35389
+ const material = new THREE32.MeshBasicMaterial({
35239
35390
  map: texture,
35240
35391
  transparent: true,
35241
- side: THREE31.DoubleSide,
35242
- depthWrite: false,
35243
- // Important for layers to avoid z-fighting issues with board itself
35392
+ side: THREE32.DoubleSide,
35393
+ depthWrite: keySuffix === "panel-outlines",
35244
35394
  polygonOffset: usePolygonOffset,
35245
35395
  polygonOffsetFactor: usePolygonOffset ? -4 : 0,
35246
35396
  // Increased for better z-fighting prevention
35247
35397
  polygonOffsetUnits: usePolygonOffset ? -4 : 0
35248
35398
  });
35249
- const mesh = new THREE31.Mesh(planeGeom, material);
35399
+ const mesh = new THREE32.Mesh(planeGeom, material);
35250
35400
  mesh.position.set(boardData.center.x, boardData.center.y, yOffset);
35251
35401
  if (isBottomLayer) {
35252
35402
  mesh.rotation.set(Math.PI, 0, 0);
@@ -35362,6 +35512,26 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35362
35512
  // Render after soldermask
35363
35513
  );
35364
35514
  if (bottomCopperTextMesh) meshes.push(bottomCopperTextMesh);
35515
+ const topPanelOutlinesMesh = createTexturePlane(
35516
+ textures.topPanelOutlines,
35517
+ pcbThickness / 2 + 4e-3,
35518
+ // Above silkscreen
35519
+ false,
35520
+ "panel-outlines",
35521
+ false,
35522
+ 4
35523
+ );
35524
+ if (topPanelOutlinesMesh) meshes.push(topPanelOutlinesMesh);
35525
+ const bottomPanelOutlinesMesh = createTexturePlane(
35526
+ textures.bottomPanelOutlines,
35527
+ -pcbThickness / 2 - 4e-3,
35528
+ // Below bottom silkscreen
35529
+ true,
35530
+ "panel-outlines",
35531
+ false,
35532
+ 4
35533
+ );
35534
+ if (bottomPanelOutlinesMesh) meshes.push(bottomPanelOutlinesMesh);
35365
35535
  return meshes;
35366
35536
  }
35367
35537
 
@@ -35418,6 +35588,8 @@ var BoardMeshes = ({
35418
35588
  shouldShow = visibility.topCopper;
35419
35589
  } else if (mesh.name.includes("bottom-copper-text")) {
35420
35590
  shouldShow = visibility.bottomCopper;
35591
+ } else if (mesh.name.includes("panel-outlines")) {
35592
+ shouldShow = visibility.boardBody;
35421
35593
  }
35422
35594
  if (shouldShow) {
35423
35595
  rootObject.add(mesh);
@@ -35530,7 +35702,7 @@ try {
35530
35702
  [textures, boardData, pcbThickness]
35531
35703
  );
35532
35704
  const cadComponents = useMemo22(
35533
- () => su18(circuitJson).cad_component.list(),
35705
+ () => su19(circuitJson).cad_component.list(),
35534
35706
  [circuitJson]
35535
35707
  );
35536
35708
  const boardDimensions = useMemo22(() => {
@@ -42272,7 +42444,7 @@ var KeyboardShortcutsDialog = ({
42272
42444
 
42273
42445
  // src/CadViewer.tsx
42274
42446
  import { jsx as jsx37, jsxs as jsxs11 } from "react/jsx-runtime";
42275
- var DEFAULT_TARGET = new THREE32.Vector3(0, 0, 0);
42447
+ var DEFAULT_TARGET = new THREE33.Vector3(0, 0, 0);
42276
42448
  var INITIAL_CAMERA_POSITION = [5, -5, 5];
42277
42449
  var CadViewerInner = (props) => {
42278
42450
  const [engine, setEngine] = useState35("manifold");
@@ -42538,12 +42710,12 @@ var CadViewer = (props) => {
42538
42710
 
42539
42711
  // src/convert-circuit-json-to-3d-svg.ts
42540
42712
  var import_debug = __toESM(require_browser(), 1);
42541
- import { su as su19 } from "@tscircuit/circuit-json-util";
42542
- import * as THREE36 from "three";
42713
+ import { su as su20 } from "@tscircuit/circuit-json-util";
42714
+ import * as THREE37 from "three";
42543
42715
  import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
42544
42716
 
42545
42717
  // src/utils/create-geometry-from-polygons.ts
42546
- import * as THREE33 from "three";
42718
+ import * as THREE34 from "three";
42547
42719
  import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute2 } from "three";
42548
42720
  function createGeometryFromPolygons(polygons) {
42549
42721
  const geometry = new BufferGeometry3();
@@ -42557,12 +42729,12 @@ function createGeometryFromPolygons(polygons) {
42557
42729
  ...polygon3.vertices[i + 1]
42558
42730
  // Third vertex
42559
42731
  );
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)
42732
+ const v1 = new THREE34.Vector3(...polygon3.vertices[0]);
42733
+ const v2 = new THREE34.Vector3(...polygon3.vertices[i]);
42734
+ const v3 = new THREE34.Vector3(...polygon3.vertices[i + 1]);
42735
+ const normal = new THREE34.Vector3().crossVectors(
42736
+ new THREE34.Vector3().subVectors(v2, v1),
42737
+ new THREE34.Vector3().subVectors(v3, v1)
42566
42738
  ).normalize();
42567
42739
  normals.push(
42568
42740
  normal.x,
@@ -42586,10 +42758,10 @@ function createGeometryFromPolygons(polygons) {
42586
42758
  var import_modeling2 = __toESM(require_src(), 1);
42587
42759
  var import_jscad_planner2 = __toESM(require_dist(), 1);
42588
42760
  var jscadModeling2 = __toESM(require_src(), 1);
42589
- import * as THREE35 from "three";
42761
+ import * as THREE36 from "three";
42590
42762
 
42591
42763
  // src/utils/load-model.ts
42592
- import * as THREE34 from "three";
42764
+ import * as THREE35 from "three";
42593
42765
  import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
42594
42766
  import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
42595
42767
  import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
@@ -42597,12 +42769,12 @@ async function load3DModel(url) {
42597
42769
  if (url.endsWith(".stl")) {
42598
42770
  const loader = new STLLoader2();
42599
42771
  const geometry = await loader.loadAsync(url);
42600
- const material = new THREE34.MeshStandardMaterial({
42772
+ const material = new THREE35.MeshStandardMaterial({
42601
42773
  color: 8947848,
42602
42774
  metalness: 0.5,
42603
42775
  roughness: 0.5
42604
42776
  });
42605
- return new THREE34.Mesh(geometry, material);
42777
+ return new THREE35.Mesh(geometry, material);
42606
42778
  }
42607
42779
  if (url.endsWith(".obj")) {
42608
42780
  const loader = new OBJLoader2();
@@ -42635,9 +42807,9 @@ async function renderComponent(component, scene) {
42635
42807
  }
42636
42808
  if (component.rotation) {
42637
42809
  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)
42810
+ THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
42811
+ THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
42812
+ THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
42641
42813
  );
42642
42814
  }
42643
42815
  scene.add(model);
@@ -42651,13 +42823,13 @@ async function renderComponent(component, scene) {
42651
42823
  );
42652
42824
  if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
42653
42825
  const threeGeom = convertCSGToThreeGeom(jscadObject);
42654
- const material2 = new THREE35.MeshStandardMaterial({
42826
+ const material2 = new THREE36.MeshStandardMaterial({
42655
42827
  color: 8947848,
42656
42828
  metalness: 0.5,
42657
42829
  roughness: 0.5,
42658
- side: THREE35.DoubleSide
42830
+ side: THREE36.DoubleSide
42659
42831
  });
42660
- const mesh2 = new THREE35.Mesh(threeGeom, material2);
42832
+ const mesh2 = new THREE36.Mesh(threeGeom, material2);
42661
42833
  if (component.position) {
42662
42834
  mesh2.position.set(
42663
42835
  component.position.x ?? 0,
@@ -42667,9 +42839,9 @@ async function renderComponent(component, scene) {
42667
42839
  }
42668
42840
  if (component.rotation) {
42669
42841
  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)
42842
+ THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
42843
+ THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
42844
+ THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
42673
42845
  );
42674
42846
  }
42675
42847
  scene.add(mesh2);
@@ -42686,17 +42858,17 @@ async function renderComponent(component, scene) {
42686
42858
  if (!geom || !geom.polygons && !geom.sides) {
42687
42859
  continue;
42688
42860
  }
42689
- const color = new THREE35.Color(geomInfo.color);
42861
+ const color = new THREE36.Color(geomInfo.color);
42690
42862
  color.convertLinearToSRGB();
42691
42863
  const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
42692
42864
  const threeGeom = convertCSGToThreeGeom(geomWithColor);
42693
- const material2 = new THREE35.MeshStandardMaterial({
42865
+ const material2 = new THREE36.MeshStandardMaterial({
42694
42866
  vertexColors: true,
42695
42867
  metalness: 0.2,
42696
42868
  roughness: 0.8,
42697
- side: THREE35.DoubleSide
42869
+ side: THREE36.DoubleSide
42698
42870
  });
42699
- const mesh2 = new THREE35.Mesh(threeGeom, material2);
42871
+ const mesh2 = new THREE36.Mesh(threeGeom, material2);
42700
42872
  if (component.position) {
42701
42873
  mesh2.position.set(
42702
42874
  component.position.x ?? 0,
@@ -42706,22 +42878,22 @@ async function renderComponent(component, scene) {
42706
42878
  }
42707
42879
  if (component.rotation) {
42708
42880
  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)
42881
+ THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
42882
+ THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
42883
+ THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
42712
42884
  );
42713
42885
  }
42714
42886
  scene.add(mesh2);
42715
42887
  }
42716
42888
  return;
42717
42889
  }
42718
- const geometry = new THREE35.BoxGeometry(0.5, 0.5, 0.5);
42719
- const material = new THREE35.MeshStandardMaterial({
42890
+ const geometry = new THREE36.BoxGeometry(0.5, 0.5, 0.5);
42891
+ const material = new THREE36.MeshStandardMaterial({
42720
42892
  color: 16711680,
42721
42893
  transparent: true,
42722
42894
  opacity: 0.25
42723
42895
  });
42724
- const mesh = new THREE35.Mesh(geometry, material);
42896
+ const mesh = new THREE36.Mesh(geometry, material);
42725
42897
  if (component.position) {
42726
42898
  mesh.position.set(
42727
42899
  component.position.x ?? 0,
@@ -42742,11 +42914,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42742
42914
  padding = 20,
42743
42915
  zoom = 1.5
42744
42916
  } = options;
42745
- const scene = new THREE36.Scene();
42917
+ const scene = new THREE37.Scene();
42746
42918
  const renderer = new SVGRenderer();
42747
42919
  renderer.setSize(width10, height10);
42748
- renderer.setClearColor(new THREE36.Color(backgroundColor), 1);
42749
- const camera = new THREE36.OrthographicCamera();
42920
+ renderer.setClearColor(new THREE37.Color(backgroundColor), 1);
42921
+ const camera = new THREE37.OrthographicCamera();
42750
42922
  const aspect = width10 / height10;
42751
42923
  const frustumSize = 100;
42752
42924
  const halfFrustumSize = frustumSize / 2 / zoom;
@@ -42760,22 +42932,22 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42760
42932
  camera.position.set(position.x, position.y, position.z);
42761
42933
  camera.up.set(0, 1, 0);
42762
42934
  const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
42763
- camera.lookAt(new THREE36.Vector3(lookAt.x, lookAt.y, lookAt.z));
42935
+ camera.lookAt(new THREE37.Vector3(lookAt.x, lookAt.y, lookAt.z));
42764
42936
  camera.updateProjectionMatrix();
42765
- const ambientLight = new THREE36.AmbientLight(16777215, Math.PI / 2);
42937
+ const ambientLight = new THREE37.AmbientLight(16777215, Math.PI / 2);
42766
42938
  scene.add(ambientLight);
42767
- const pointLight = new THREE36.PointLight(16777215, Math.PI / 4);
42939
+ const pointLight = new THREE37.PointLight(16777215, Math.PI / 4);
42768
42940
  pointLight.position.set(-10, -10, 10);
42769
42941
  scene.add(pointLight);
42770
- const components = su19(circuitJson).cad_component.list();
42942
+ const components = su20(circuitJson).cad_component.list();
42771
42943
  for (const component of components) {
42772
42944
  await renderComponent(component, scene);
42773
42945
  }
42774
- const boardData = su19(circuitJson).pcb_board.list()[0];
42946
+ const boardData = su20(circuitJson).pcb_board.list()[0];
42775
42947
  const boardGeom = createBoardGeomFromCircuitJson(circuitJson);
42776
42948
  if (boardGeom) {
42777
42949
  const solderMaskColor = colors.fr4SolderMaskGreen;
42778
- const baseColor = new THREE36.Color(
42950
+ const baseColor = new THREE37.Color(
42779
42951
  solderMaskColor[0],
42780
42952
  solderMaskColor[1],
42781
42953
  solderMaskColor[2]
@@ -42787,28 +42959,28 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42787
42959
  const material = createBoardMaterial({
42788
42960
  material: boardData?.material,
42789
42961
  color: baseColor,
42790
- side: THREE36.DoubleSide
42962
+ side: THREE37.DoubleSide
42791
42963
  });
42792
- const mesh = new THREE36.Mesh(geometry, material);
42964
+ const mesh = new THREE37.Mesh(geometry, material);
42793
42965
  scene.add(mesh);
42794
42966
  }
42795
42967
  }
42796
- const gridColor = new THREE36.Color(8947848);
42797
- const gridHelper = new THREE36.GridHelper(100, 100, gridColor, gridColor);
42968
+ const gridColor = new THREE37.Color(8947848);
42969
+ const gridHelper = new THREE37.GridHelper(100, 100, gridColor, gridColor);
42798
42970
  gridHelper.rotation.x = Math.PI / 2;
42799
42971
  const materials = Array.isArray(gridHelper.material) ? gridHelper.material : [gridHelper.material];
42800
42972
  for (const mat of materials) {
42801
42973
  mat.transparent = true;
42802
42974
  mat.opacity = 0.3;
42803
- if (mat instanceof THREE36.LineBasicMaterial) {
42975
+ if (mat instanceof THREE37.LineBasicMaterial) {
42804
42976
  mat.color = gridColor;
42805
42977
  mat.vertexColors = false;
42806
42978
  }
42807
42979
  }
42808
42980
  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());
42981
+ const box = new THREE37.Box3().setFromObject(scene);
42982
+ const center = box.getCenter(new THREE37.Vector3());
42983
+ const size5 = box.getSize(new THREE37.Vector3());
42812
42984
  scene.position.sub(center);
42813
42985
  const maxDim = Math.max(size5.x, size5.y, size5.z);
42814
42986
  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.471",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",