@tscircuit/cli 0.1.900 → 0.1.902

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/lib/index.js CHANGED
@@ -47857,7 +47857,7 @@ var require_utils2 = __commonJS((exports2) => {
47857
47857
  }
47858
47858
  }
47859
47859
  };
47860
- function identity4(input) {
47860
+ function identity5(input) {
47861
47861
  return input;
47862
47862
  }
47863
47863
  function stringToArrayLike(str, array) {
@@ -47933,7 +47933,7 @@ var require_utils2 = __commonJS((exports2) => {
47933
47933
  }
47934
47934
  var transform = {};
47935
47935
  transform["string"] = {
47936
- string: identity4,
47936
+ string: identity5,
47937
47937
  array: function(input) {
47938
47938
  return stringToArrayLike(input, new Array(input.length));
47939
47939
  },
@@ -47949,7 +47949,7 @@ var require_utils2 = __commonJS((exports2) => {
47949
47949
  };
47950
47950
  transform["array"] = {
47951
47951
  string: arrayLikeToString,
47952
- array: identity4,
47952
+ array: identity5,
47953
47953
  arraybuffer: function(input) {
47954
47954
  return new Uint8Array(input).buffer;
47955
47955
  },
@@ -47967,7 +47967,7 @@ var require_utils2 = __commonJS((exports2) => {
47967
47967
  array: function(input) {
47968
47968
  return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));
47969
47969
  },
47970
- arraybuffer: identity4,
47970
+ arraybuffer: identity5,
47971
47971
  uint8array: function(input) {
47972
47972
  return new Uint8Array(input);
47973
47973
  },
@@ -47983,7 +47983,7 @@ var require_utils2 = __commonJS((exports2) => {
47983
47983
  arraybuffer: function(input) {
47984
47984
  return input.buffer;
47985
47985
  },
47986
- uint8array: identity4,
47986
+ uint8array: identity5,
47987
47987
  nodebuffer: function(input) {
47988
47988
  return nodejsUtils.newBufferFrom(input);
47989
47989
  }
@@ -47999,7 +47999,7 @@ var require_utils2 = __commonJS((exports2) => {
47999
47999
  uint8array: function(input) {
48000
48000
  return arrayLikeToArrayLike(input, new Uint8Array(input.length));
48001
48001
  },
48002
- nodebuffer: identity4
48002
+ nodebuffer: identity5
48003
48003
  };
48004
48004
  exports2.transformTo = function(outputType, input) {
48005
48005
  if (!input) {
@@ -60414,7 +60414,7 @@ var getNodeHandler = (winterSpec, { port, middleware = [] }) => {
60414
60414
  }));
60415
60415
  };
60416
60416
  // package.json
60417
- var version = "0.1.899";
60417
+ var version = "0.1.901";
60418
60418
  var package_default = {
60419
60419
  name: "@tscircuit/cli",
60420
60420
  main: "dist/cli/main.js",
@@ -60445,7 +60445,7 @@ var package_default = {
60445
60445
  chokidar: "4.0.1",
60446
60446
  "circuit-json": "0.0.325",
60447
60447
  "circuit-json-to-gltf": "^0.0.58",
60448
- "circuit-json-to-kicad": "^0.0.52",
60448
+ "circuit-json-to-kicad": "^0.0.71",
60449
60449
  "circuit-json-to-readable-netlist": "^0.0.13",
60450
60450
  "circuit-json-to-spice": "^0.0.10",
60451
60451
  "circuit-json-to-tscircuit": "^0.0.9",
@@ -63075,44 +63075,62 @@ import {
63075
63075
  Setup
63076
63076
  } from "kicadts";
63077
63077
  import { PcbNet } from "kicadts";
63078
- import { Footprint, FootprintModel } from "kicadts";
63079
- import { applyToPoint as applyToPoint9 } from "transformation-matrix";
63078
+ import { Footprint } from "kicadts";
63079
+ import { applyToPoint as applyToPoint10 } from "transformation-matrix";
63080
+ import { FpCircle, Stroke as Stroke3 } from "kicadts";
63081
+ import { FpCircle as FpCircle2, Stroke as Stroke4 } from "kicadts";
63082
+ import { FpRect, Stroke as Stroke5 } from "kicadts";
63083
+ import { FpRect as FpRect2, Stroke as Stroke6 } from "kicadts";
63084
+ import { FpRect as FpRect3, Stroke as Stroke7 } from "kicadts";
63085
+ import { FpPoly, Pts as Pts3, Xy as Xy3, Stroke as Stroke8 } from "kicadts";
63086
+ import"kicadts";
63087
+ import { FpText, TextEffects as TextEffects4, TextEffectsFont as TextEffectsFont4 } from "kicadts";
63088
+ import { applyToPoint as applyToPoint5, rotate, identity } from "transformation-matrix";
63089
+ import { FpText as FpText3, TextEffects as TextEffects5, TextEffectsFont as TextEffectsFont5 } from "kicadts";
63090
+ import { applyToPoint as applyToPoint6, rotate as rotate2, identity as identity2 } from "transformation-matrix";
63091
+ import { FootprintModel } from "kicadts";
63080
63092
  import {
63081
63093
  FootprintPad,
63082
63094
  PadPrimitives,
63083
63095
  PadPrimitiveGrPoly,
63084
- Pts as Pts3,
63085
- Xy as Xy3,
63096
+ Pts as Pts4,
63097
+ Xy as Xy4,
63086
63098
  PadOptions,
63087
63099
  PadNet
63088
63100
  } from "kicadts";
63089
63101
  import {
63090
- applyToPoint as applyToPoint5,
63102
+ applyToPoint as applyToPoint7,
63091
63103
  compose as compose2,
63092
63104
  translate as translate2,
63093
63105
  scale as scale2,
63094
- rotate
63106
+ rotate as rotate3
63095
63107
  } from "transformation-matrix";
63096
63108
  import { FootprintPad as FootprintPad2, PadDrill, PadNet as PadNet2 } from "kicadts";
63097
- import { applyToPoint as applyToPoint6, rotate as rotate2, identity } from "transformation-matrix";
63098
- import { FootprintPad as FootprintPad3, PadDrill as PadDrill2 } from "kicadts";
63099
- import { applyToPoint as applyToPoint7, rotate as rotate3, identity as identity2 } from "transformation-matrix";
63100
- import { FpText, TextEffects as TextEffects4, TextEffectsFont as TextEffectsFont4 } from "kicadts";
63101
63109
  import { applyToPoint as applyToPoint8, rotate as rotate4, identity as identity3 } from "transformation-matrix";
63110
+ import { FootprintPad as FootprintPad3, PadDrill as PadDrill2 } from "kicadts";
63111
+ import { applyToPoint as applyToPoint9, rotate as rotate5, identity as identity4 } from "transformation-matrix";
63102
63112
  import { Segment, SegmentNet } from "kicadts";
63103
- import { applyToPoint as applyToPoint10 } from "transformation-matrix";
63104
- import { Via, ViaNet } from "kicadts";
63105
63113
  import { applyToPoint as applyToPoint11 } from "transformation-matrix";
63114
+ import { Via, ViaNet } from "kicadts";
63115
+ import { applyToPoint as applyToPoint12 } from "transformation-matrix";
63106
63116
  import { GrLine } from "kicadts";
63107
- import { applyToPoint as applyToPoint13 } from "transformation-matrix";
63108
63117
  import {
63118
+ At,
63109
63119
  GrText,
63110
- TextEffects as TextEffects5,
63111
- TextEffectsFont as TextEffectsFont5,
63112
- TextEffectsJustify as TextEffectsJustify3,
63113
- At
63120
+ TextEffects as TextEffects6,
63121
+ TextEffectsFont as TextEffectsFont6,
63122
+ TextEffectsJustify as TextEffectsJustify3
63114
63123
  } from "kicadts";
63115
- import { applyToPoint as applyToPoint12 } from "transformation-matrix";
63124
+ import { applyToPoint as applyToPoint13 } from "transformation-matrix";
63125
+ import { applyToPoint as applyToPoint15 } from "transformation-matrix";
63126
+ import {
63127
+ GrText as GrText2,
63128
+ TextEffects as TextEffects7,
63129
+ TextEffectsFont as TextEffectsFont7,
63130
+ TextEffectsJustify as TextEffectsJustify4,
63131
+ At as At2
63132
+ } from "kicadts";
63133
+ import { applyToPoint as applyToPoint14 } from "transformation-matrix";
63116
63134
  import { cju as cju3 } from "@tscircuit/circuit-json-util";
63117
63135
  import { cju as cju4 } from "@tscircuit/circuit-json-util";
63118
63136
  import { parseKicadSexpr, KicadSch as KicadSch2 } from "kicadts";
@@ -63120,12 +63138,12 @@ import {
63120
63138
  parseKicadSexpr as parseKicadSexpr2,
63121
63139
  KicadPcb as KicadPcb2,
63122
63140
  FootprintModel as FootprintModel2,
63123
- At as At2,
63141
+ At as At3,
63124
63142
  EmbeddedFonts as EmbeddedFonts4,
63125
63143
  FootprintAttr,
63126
63144
  Property,
63127
- TextEffects as TextEffects6,
63128
- TextEffectsFont as TextEffectsFont6
63145
+ TextEffects as TextEffects8,
63146
+ TextEffectsFont as TextEffectsFont8
63129
63147
  } from "kicadts";
63130
63148
  import { KicadSymbolLib } from "kicadts";
63131
63149
  import { parseKicadMod } from "kicadts";
@@ -63133,8 +63151,8 @@ import {
63133
63151
  parseKicadSexpr as parseKicadSexpr3,
63134
63152
  Footprint as Footprint3,
63135
63153
  Property as Property2,
63136
- TextEffects as TextEffects7,
63137
- TextEffectsFont as TextEffectsFont7
63154
+ TextEffects as TextEffects9,
63155
+ TextEffectsFont as TextEffectsFont9
63138
63156
  } from "kicadts";
63139
63157
  import { parseKicadMod as parseKicadMod2 } from "kicadts";
63140
63158
  import {
@@ -63142,9 +63160,9 @@ import {
63142
63160
  SymbolPinNames as SymbolPinNames2,
63143
63161
  SymbolPinNumbers as SymbolPinNumbers2,
63144
63162
  SymbolProperty as SymbolProperty4,
63145
- TextEffects as TextEffects8,
63146
- TextEffectsFont as TextEffectsFont8,
63147
- TextEffectsJustify as TextEffectsJustify4
63163
+ TextEffects as TextEffects10,
63164
+ TextEffectsFont as TextEffectsFont10,
63165
+ TextEffectsJustify as TextEffectsJustify5
63148
63166
  } from "kicadts";
63149
63167
  import { KicadSymbolLib as KicadSymbolLib2 } from "kicadts";
63150
63168
  var ConverterStage = class {
@@ -63398,7 +63416,7 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63398
63416
  schematicComponent,
63399
63417
  description: this.getDescription(sourceComp),
63400
63418
  keywords: this.getKeywords(sourceComp),
63401
- fpFilters: this.getFpFilters(sourceComp),
63419
+ fpFilters: this.getFpFilters(sourceComp, schematicSymbol.name),
63402
63420
  footprintRef: footprintName ? `tscircuit:${footprintName}` : "",
63403
63421
  referencePrefix: getReferencePrefixForComponent(sourceComp)
63404
63422
  });
@@ -63408,9 +63426,23 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63408
63426
  const circles = circuitJson.filter((el) => el.type === "schematic_circle" && el.schematic_symbol_id === schematicSymbolId);
63409
63427
  const lines = circuitJson.filter((el) => el.type === "schematic_line" && el.schematic_symbol_id === schematicSymbolId);
63410
63428
  const paths = circuitJson.filter((el) => el.type === "schematic_path" && el.schematic_symbol_id === schematicSymbolId);
63411
- let ports = circuitJson.filter((el) => el.type === "schematic_port" && el.schematic_symbol_id === schematicSymbolId);
63429
+ let ports = circuitJson.filter((el) => el.type === "schematic_port" && ("schematic_symbol_id" in el) && el.schematic_symbol_id === schematicSymbolId);
63412
63430
  if (ports.length === 0 && schematicComponentId) {
63413
- ports = circuitJson.filter((el) => el.type === "schematic_port" && el.schematic_component_id === schematicComponentId && el.display_pin_label);
63431
+ ports = circuitJson.filter((el) => el.type === "schematic_port" && el.schematic_component_id === schematicComponentId && el.display_pin_label !== undefined);
63432
+ if (ports.length === 0) {
63433
+ const allPorts = circuitJson.filter((el) => el.type === "schematic_port" && el.schematic_component_id === schematicComponentId);
63434
+ const seenPinNumbers = /* @__PURE__ */ new Set;
63435
+ ports = allPorts.filter((port) => {
63436
+ const pinNum = port.pin_number;
63437
+ if (pinNum !== undefined) {
63438
+ if (seenPinNumbers.has(pinNum)) {
63439
+ return false;
63440
+ }
63441
+ seenPinNumbers.add(pinNum);
63442
+ }
63443
+ return true;
63444
+ });
63445
+ }
63414
63446
  }
63415
63447
  const primitives2 = [];
63416
63448
  for (const circle of circles) {
@@ -63419,7 +63451,8 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63419
63451
  x: circle.center?.x ?? 0,
63420
63452
  y: circle.center?.y ?? 0,
63421
63453
  radius: circle.radius ?? 0.5,
63422
- fill: circle.is_filled ?? false
63454
+ fill: circle.is_filled ?? false,
63455
+ fillColor: circle.fill_color
63423
63456
  });
63424
63457
  }
63425
63458
  for (const line of lines) {
@@ -63435,7 +63468,9 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63435
63468
  if (path7.points && path7.points.length > 0) {
63436
63469
  primitives2.push({
63437
63470
  type: "path",
63438
- points: path7.points
63471
+ points: path7.points,
63472
+ fill: path7.is_filled ?? false,
63473
+ fillColor: path7.fill_color
63439
63474
  });
63440
63475
  }
63441
63476
  }
@@ -63645,7 +63680,10 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63645
63680
  return "U IC chip";
63646
63681
  return "";
63647
63682
  }
63648
- getFpFilters(sourceComp) {
63683
+ getFpFilters(sourceComp, symbolName) {
63684
+ if (symbolName) {
63685
+ return `${symbolName}*`;
63686
+ }
63649
63687
  if (sourceComp?.ftype === "simple_resistor")
63650
63688
  return "R_*";
63651
63689
  if (sourceComp?.ftype === "simple_capacitor")
@@ -63662,10 +63700,12 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63662
63700
  const drawingSymbol = new SchematicSymbol({
63663
63701
  libraryId: `${libId.split(":")[1]}_0_1`
63664
63702
  });
63665
- const symbolScale = this.ctx.c2kMatSch?.a || 15;
63703
+ const GRID_ALIGNED_SCALE = 15.24;
63704
+ const standardScale = this.ctx.c2kMatSch?.a || 15;
63705
+ const symbolScale = isChip ? standardScale : GRID_ALIGNED_SCALE;
63666
63706
  for (const primitive of symbolData.primitives || []) {
63667
63707
  if (primitive.type === "path" && primitive.points) {
63668
- const fillType = isChip ? "background" : "none";
63708
+ const fillType = isChip || primitive.fill ? "background" : "none";
63669
63709
  const polyline = this.createPolylineFromPoints({
63670
63710
  points: primitive.points,
63671
63711
  scale: symbolScale,
@@ -63730,7 +63770,7 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63730
63770
  stroke.type = "default";
63731
63771
  c._sxStroke = stroke;
63732
63772
  const fill = new SymbolCircleFill;
63733
- fill.type = primitive.fill ? "outline" : "none";
63773
+ fill.type = primitive.fill ? "background" : "none";
63734
63774
  c._sxFill = fill;
63735
63775
  return circle;
63736
63776
  }
@@ -63750,7 +63790,9 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63750
63790
  pin.pinGraphicStyle = "line";
63751
63791
  const { x, y, angle } = this.calculatePinPosition(port, symbolData.center, symbolData.size, isChip, i, schematicComponent);
63752
63792
  pin.at = [x, y, angle];
63753
- pin.length = isChip ? 6 : 1.27;
63793
+ const CHIP_PIN_LENGTH = 6;
63794
+ const CUSTOM_SYMBOL_PIN_LENGTH = 2.54;
63795
+ pin.length = isChip ? CHIP_PIN_LENGTH : CUSTOM_SYMBOL_PIN_LENGTH;
63754
63796
  const nameFont = new TextEffectsFont;
63755
63797
  nameFont.size = { height: 1.27, width: 1.27 };
63756
63798
  const nameEffects = new TextEffects({ font: nameFont });
@@ -63769,11 +63811,13 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63769
63811
  return pinSymbol;
63770
63812
  }
63771
63813
  calculatePinPosition(port, center, size, isChip, portIndex, schematicComponent) {
63772
- const symbolScale = this.ctx.c2kMatSch?.a || 15;
63814
+ const GRID_ALIGNED_SCALE = 15.24;
63815
+ const standardScale = this.ctx.c2kMatSch?.a || 15;
63816
+ const symbolScale = isChip ? standardScale : GRID_ALIGNED_SCALE;
63773
63817
  let portX = port.x ?? 0;
63774
63818
  let portY = port.y ?? 0;
63775
63819
  let usingCircuitJsonPort = false;
63776
- if (portIndex !== undefined && schematicComponent) {
63820
+ if (isChip && portIndex !== undefined && schematicComponent) {
63777
63821
  const schematicPorts = this.ctx.db.schematic_port.list().filter((p) => p.schematic_component_id === schematicComponent.schematic_component_id).sort((a, b) => (a.pin_number || 0) - (b.pin_number || 0));
63778
63822
  if (schematicPorts[portIndex]) {
63779
63823
  const schPort = schematicPorts[portIndex];
@@ -63807,7 +63851,7 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63807
63851
  }
63808
63852
  let x = scaled.x;
63809
63853
  let y = scaled.y;
63810
- const chipPinLength = 6;
63854
+ const CHIP_PIN_LENGTH = 6;
63811
63855
  if (isChip && size) {
63812
63856
  const halfWidth = size.width / 2 * symbolScale;
63813
63857
  const halfHeight = size.height / 2 * symbolScale;
@@ -63822,34 +63866,26 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
63822
63866
  let angle = 0;
63823
63867
  if (isHorizontalPin) {
63824
63868
  if (dx > 0) {
63869
+ angle = 180;
63825
63870
  if (isChip) {
63826
- angle = 180;
63827
- x = x + chipPinLength;
63828
- } else {
63829
- angle = 0;
63871
+ x = x + CHIP_PIN_LENGTH;
63830
63872
  }
63831
63873
  } else {
63874
+ angle = 0;
63832
63875
  if (isChip) {
63833
- angle = 0;
63834
- x = x - chipPinLength;
63835
- } else {
63836
- angle = 180;
63876
+ x = x - CHIP_PIN_LENGTH;
63837
63877
  }
63838
63878
  }
63839
63879
  } else {
63840
63880
  if (dy > 0) {
63881
+ angle = 270;
63841
63882
  if (isChip) {
63842
- angle = 270;
63843
- y = y + chipPinLength;
63844
- } else {
63845
- angle = 90;
63883
+ y = y + CHIP_PIN_LENGTH;
63846
63884
  }
63847
63885
  } else {
63886
+ angle = 90;
63848
63887
  if (isChip) {
63849
- angle = 90;
63850
- y = y - chipPinLength;
63851
- } else {
63852
- angle = 270;
63888
+ y = y - CHIP_PIN_LENGTH;
63853
63889
  }
63854
63890
  }
63855
63891
  }
@@ -64091,6 +64127,13 @@ var AddSchematicSymbolsStage = class extends ConverterStage {
64091
64127
  description: "Switch"
64092
64128
  };
64093
64129
  }
64130
+ if (sourceComp.ftype === "simple_potentiometer") {
64131
+ return {
64132
+ reference,
64133
+ value: sourceComp.display_max_resistance || "",
64134
+ description: "Potentiometer"
64135
+ };
64136
+ }
64094
64137
  return {
64095
64138
  reference,
64096
64139
  value: name,
@@ -64495,10 +64538,13 @@ var CircuitJsonToKicadSchConverter = class {
64495
64538
  };
64496
64539
  var InitializePcbStage = class extends ConverterStage {
64497
64540
  _step() {
64498
- const { kicadPcb } = this.ctx;
64541
+ const { kicadPcb, db } = this.ctx;
64499
64542
  if (!kicadPcb) {
64500
64543
  throw new Error("KicadPcb instance not initialized in context");
64501
64544
  }
64545
+ const pcbBoard = db.pcb_board?.list()?.[0];
64546
+ const numLayers = pcbBoard?.num_layers ?? 2;
64547
+ this.ctx.numLayers = numLayers;
64502
64548
  kicadPcb.version = 20241229;
64503
64549
  const paper = new Paper2;
64504
64550
  paper.size = "A4";
@@ -64511,27 +64557,13 @@ var InitializePcbStage = class extends ConverterStage {
64511
64557
  kicadPcb.setup = setup;
64512
64558
  const layers = new PcbLayers;
64513
64559
  const layerDefinitions = [
64514
- new PcbLayerDefinition({ index: 0, name: "F.Cu", type: "signal" }),
64515
- new PcbLayerDefinition({ index: 2, name: "B.Cu", type: "signal" }),
64516
- new PcbLayerDefinition({ index: 9, name: "F.Adhes", type: "user" }),
64517
- new PcbLayerDefinition({ index: 11, name: "B.Adhes", type: "user" }),
64518
- new PcbLayerDefinition({ index: 13, name: "F.Paste", type: "user" }),
64519
- new PcbLayerDefinition({ index: 15, name: "B.Paste", type: "user" }),
64520
- new PcbLayerDefinition({ index: 5, name: "F.SilkS", type: "user" }),
64521
- new PcbLayerDefinition({ index: 7, name: "B.SilkS", type: "user" }),
64522
- new PcbLayerDefinition({ index: 1, name: "F.Mask", type: "user" }),
64523
- new PcbLayerDefinition({ index: 3, name: "B.Mask", type: "user" }),
64524
- new PcbLayerDefinition({ index: 20, name: "Dwgs.User", type: "user" }),
64525
- new PcbLayerDefinition({ index: 21, name: "Cmts.User", type: "user" }),
64526
- new PcbLayerDefinition({ index: 22, name: "Eco1.User", type: "user" }),
64527
- new PcbLayerDefinition({ index: 23, name: "Eco2.User", type: "user" }),
64528
- new PcbLayerDefinition({ index: 24, name: "Edge.Cuts", type: "user" }),
64529
- new PcbLayerDefinition({ index: 25, name: "Margin", type: "user" }),
64530
- new PcbLayerDefinition({ index: 17, name: "B.CrtYd", type: "user" }),
64531
- new PcbLayerDefinition({ index: 16, name: "F.CrtYd", type: "user" }),
64532
- new PcbLayerDefinition({ index: 19, name: "B.Fab", type: "user" }),
64533
- new PcbLayerDefinition({ index: 18, name: "F.Fab", type: "user" })
64560
+ new PcbLayerDefinition({ index: 0, name: "F.Cu", type: "signal" })
64534
64561
  ];
64562
+ for (let i = 1;i < numLayers - 1; i++) {
64563
+ layerDefinitions.push(new PcbLayerDefinition({ index: i, name: `In${i}.Cu`, type: "signal" }));
64564
+ }
64565
+ layerDefinitions.push(new PcbLayerDefinition({ index: 31, name: "B.Cu", type: "signal" }));
64566
+ layerDefinitions.push(new PcbLayerDefinition({ index: 32, name: "B.Adhes", type: "user" }), new PcbLayerDefinition({ index: 33, name: "F.Adhes", type: "user" }), new PcbLayerDefinition({ index: 34, name: "B.Paste", type: "user" }), new PcbLayerDefinition({ index: 35, name: "F.Paste", type: "user" }), new PcbLayerDefinition({ index: 36, name: "B.SilkS", type: "user" }), new PcbLayerDefinition({ index: 37, name: "F.SilkS", type: "user" }), new PcbLayerDefinition({ index: 38, name: "B.Mask", type: "user" }), new PcbLayerDefinition({ index: 39, name: "F.Mask", type: "user" }), new PcbLayerDefinition({ index: 40, name: "Dwgs.User", type: "user" }), new PcbLayerDefinition({ index: 41, name: "Cmts.User", type: "user" }), new PcbLayerDefinition({ index: 42, name: "Eco1.User", type: "user" }), new PcbLayerDefinition({ index: 43, name: "Eco2.User", type: "user" }), new PcbLayerDefinition({ index: 44, name: "Edge.Cuts", type: "user" }), new PcbLayerDefinition({ index: 45, name: "Margin", type: "user" }), new PcbLayerDefinition({ index: 46, name: "B.CrtYd", type: "user" }), new PcbLayerDefinition({ index: 47, name: "F.CrtYd", type: "user" }), new PcbLayerDefinition({ index: 48, name: "B.Fab", type: "user" }), new PcbLayerDefinition({ index: 49, name: "F.Fab", type: "user" }));
64535
64567
  layers.definitions = layerDefinitions;
64536
64568
  kicadPcb.layers = layers;
64537
64569
  this.finished = true;
@@ -64617,6 +64649,269 @@ function generateDeterministicUuid(data) {
64617
64649
  const hash = simpleHash(data);
64618
64650
  return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20, 32)}`;
64619
64651
  }
64652
+ function convertSilkscreenCircles(silkscreenCircles, componentCenter) {
64653
+ const fpCircles = [];
64654
+ for (const circle of silkscreenCircles) {
64655
+ const relX = circle.center.x - componentCenter.x;
64656
+ const relY = -(circle.center.y - componentCenter.y);
64657
+ const layerMap = {
64658
+ top: "F.SilkS",
64659
+ bottom: "B.SilkS"
64660
+ };
64661
+ const kicadLayer = layerMap[circle.layer] || circle.layer || "F.SilkS";
64662
+ const fpCircle = new FpCircle({
64663
+ center: { x: relX, y: relY },
64664
+ end: { x: relX + circle.radius, y: relY },
64665
+ layer: kicadLayer,
64666
+ stroke: new Stroke3,
64667
+ fill: false
64668
+ });
64669
+ if (fpCircle.stroke) {
64670
+ fpCircle.stroke.width = circle.stroke_width || 0.05;
64671
+ fpCircle.stroke.type = "default";
64672
+ }
64673
+ fpCircles.push(fpCircle);
64674
+ }
64675
+ return fpCircles;
64676
+ }
64677
+ function convertCourtyardCircles(courtyardCircles, componentCenter) {
64678
+ const fpCircles = [];
64679
+ for (const circle of courtyardCircles) {
64680
+ const relX = circle.center.x - componentCenter.x;
64681
+ const relY = -(circle.center.y - componentCenter.y);
64682
+ const layerMap = {
64683
+ top: "F.CrtYd",
64684
+ bottom: "B.CrtYd"
64685
+ };
64686
+ const kicadLayer = layerMap[circle.layer] || "F.CrtYd";
64687
+ const fpCircle = new FpCircle2({
64688
+ center: { x: relX, y: relY },
64689
+ end: { x: relX + circle.radius, y: relY },
64690
+ layer: kicadLayer,
64691
+ stroke: new Stroke4,
64692
+ fill: false
64693
+ });
64694
+ if (fpCircle.stroke) {
64695
+ fpCircle.stroke.width = 0.05;
64696
+ fpCircle.stroke.type = "default";
64697
+ }
64698
+ fpCircles.push(fpCircle);
64699
+ }
64700
+ return fpCircles;
64701
+ }
64702
+ function convertFabricationNoteRects(fabRects, componentCenter) {
64703
+ const fpRects = [];
64704
+ for (const rect of fabRects) {
64705
+ const relX = rect.center.x - componentCenter.x;
64706
+ const relY = -(rect.center.y - componentCenter.y);
64707
+ const halfW = rect.width / 2;
64708
+ const halfH = rect.height / 2;
64709
+ const layerMap = {
64710
+ top: "F.Fab",
64711
+ bottom: "B.Fab"
64712
+ };
64713
+ const kicadLayer = layerMap[rect.layer] || rect.layer || "F.Fab";
64714
+ const fpRect = new FpRect({
64715
+ start: { x: relX - halfW, y: relY - halfH },
64716
+ end: { x: relX + halfW, y: relY + halfH },
64717
+ layer: kicadLayer,
64718
+ stroke: new Stroke5,
64719
+ fill: false
64720
+ });
64721
+ if (fpRect.stroke) {
64722
+ fpRect.stroke.width = rect.stroke_width || 0.1;
64723
+ fpRect.stroke.type = "default";
64724
+ }
64725
+ fpRects.push(fpRect);
64726
+ }
64727
+ return fpRects;
64728
+ }
64729
+ function convertNoteRects(noteRects, componentCenter) {
64730
+ const fpRects = [];
64731
+ for (const rect of noteRects) {
64732
+ const relX = rect.center.x - componentCenter.x;
64733
+ const relY = -(rect.center.y - componentCenter.y);
64734
+ const halfW = rect.width / 2;
64735
+ const halfH = rect.height / 2;
64736
+ const kicadLayer = "F.Fab";
64737
+ const fpRect = new FpRect2({
64738
+ start: { x: relX - halfW, y: relY - halfH },
64739
+ end: { x: relX + halfW, y: relY + halfH },
64740
+ layer: kicadLayer,
64741
+ stroke: new Stroke6,
64742
+ fill: false
64743
+ });
64744
+ if (fpRect.stroke) {
64745
+ fpRect.stroke.width = rect.stroke_width || 0.1;
64746
+ fpRect.stroke.type = "default";
64747
+ }
64748
+ fpRects.push(fpRect);
64749
+ }
64750
+ return fpRects;
64751
+ }
64752
+ function convertCourtyardRects(courtyardRects, componentCenter) {
64753
+ const fpRects = [];
64754
+ for (const rect of courtyardRects) {
64755
+ const relX = rect.center.x - componentCenter.x;
64756
+ const relY = -(rect.center.y - componentCenter.y);
64757
+ const halfW = rect.width / 2;
64758
+ const halfH = rect.height / 2;
64759
+ const layerMap = {
64760
+ top: "F.CrtYd",
64761
+ bottom: "B.CrtYd"
64762
+ };
64763
+ const kicadLayer = layerMap[rect.layer] || "F.CrtYd";
64764
+ const fpRect = new FpRect3({
64765
+ start: { x: relX - halfW, y: relY - halfH },
64766
+ end: { x: relX + halfW, y: relY + halfH },
64767
+ layer: kicadLayer,
64768
+ stroke: new Stroke7,
64769
+ fill: false
64770
+ });
64771
+ if (fpRect.stroke) {
64772
+ fpRect.stroke.width = 0.05;
64773
+ fpRect.stroke.type = "default";
64774
+ }
64775
+ fpRects.push(fpRect);
64776
+ }
64777
+ return fpRects;
64778
+ }
64779
+ function convertCourtyardOutlines(courtyardOutlines, componentCenter) {
64780
+ const fpPolys = [];
64781
+ for (const outline of courtyardOutlines) {
64782
+ if (!outline.outline || outline.outline.length < 2)
64783
+ continue;
64784
+ const layerMap = {
64785
+ top: "F.CrtYd",
64786
+ bottom: "B.CrtYd"
64787
+ };
64788
+ const kicadLayer = layerMap[outline.layer] || "F.CrtYd";
64789
+ const xyPoints = outline.outline.map((point) => {
64790
+ const relX = point.x - componentCenter.x;
64791
+ const relY = -(point.y - componentCenter.y);
64792
+ return new Xy3(relX, relY);
64793
+ });
64794
+ const fpPoly = new FpPoly;
64795
+ fpPoly.points = new Pts3(xyPoints);
64796
+ fpPoly.layer = kicadLayer;
64797
+ fpPoly.fill = false;
64798
+ const stroke = new Stroke8;
64799
+ stroke.width = 0.05;
64800
+ stroke.type = "default";
64801
+ fpPoly.stroke = stroke;
64802
+ fpPolys.push(fpPoly);
64803
+ }
64804
+ return fpPolys;
64805
+ }
64806
+ function createFpTextFromCircuitJson({
64807
+ textElement,
64808
+ componentCenter,
64809
+ componentRotation = 0
64810
+ }) {
64811
+ if (!textElement.text || !textElement.anchor_position) {
64812
+ return null;
64813
+ }
64814
+ const relativeX = textElement.anchor_position.x - componentCenter.x;
64815
+ const relativeY = -(textElement.anchor_position.y - componentCenter.y);
64816
+ const rotationMatrix = componentRotation !== 0 ? rotate(componentRotation * Math.PI / 180) : identity();
64817
+ const rotatedPos = applyToPoint5(rotationMatrix, {
64818
+ x: relativeX,
64819
+ y: relativeY
64820
+ });
64821
+ const relativePosition = {
64822
+ x: rotatedPos.x,
64823
+ y: rotatedPos.y
64824
+ };
64825
+ const layerMap = {
64826
+ top: "F.SilkS",
64827
+ bottom: "B.SilkS"
64828
+ };
64829
+ const kicadLayer = layerMap[textElement.layer] || textElement.layer || "F.SilkS";
64830
+ const fontSize = (textElement.font_size || 1) / 1.5;
64831
+ const font = new TextEffectsFont4;
64832
+ font.size = { width: fontSize, height: fontSize };
64833
+ const textEffects = new TextEffects4({
64834
+ font
64835
+ });
64836
+ const rotation = textElement.ccw_rotation || 0;
64837
+ return new FpText({
64838
+ type: "user",
64839
+ text: textElement.text,
64840
+ position: {
64841
+ x: relativePosition.x,
64842
+ y: relativePosition.y,
64843
+ angle: rotation
64844
+ },
64845
+ layer: kicadLayer,
64846
+ effects: textEffects
64847
+ });
64848
+ }
64849
+ function convertSilkscreenTexts(silkscreenTexts, componentCenter, componentRotation, sourceComponentName) {
64850
+ const fpTexts = [];
64851
+ for (const textElement of silkscreenTexts) {
64852
+ const fpText = createFpTextFromCircuitJson({
64853
+ textElement,
64854
+ componentCenter,
64855
+ componentRotation
64856
+ });
64857
+ if (fpText) {
64858
+ if (sourceComponentName && textElement.text === sourceComponentName) {
64859
+ fpText.type = "reference";
64860
+ }
64861
+ fpTexts.push(fpText);
64862
+ }
64863
+ }
64864
+ return fpTexts;
64865
+ }
64866
+ function convertNoteTexts(noteTexts, componentCenter, componentRotation) {
64867
+ const fpTexts = [];
64868
+ for (const textElement of noteTexts) {
64869
+ const relX = textElement.anchor_position.x - componentCenter.x;
64870
+ const relY = -(textElement.anchor_position.y - componentCenter.y);
64871
+ const rotationMatrix = componentRotation !== 0 ? rotate2(componentRotation * Math.PI / 180) : identity2();
64872
+ const rotatedPos = applyToPoint6(rotationMatrix, { x: relX, y: relY });
64873
+ const fontSize = textElement.font_size || 1;
64874
+ const font = new TextEffectsFont5;
64875
+ font.size = { width: fontSize, height: fontSize };
64876
+ const textEffects = new TextEffects5({ font });
64877
+ const fpText = new FpText3({
64878
+ type: "user",
64879
+ text: textElement.text,
64880
+ position: { x: rotatedPos.x, y: rotatedPos.y, angle: 0 },
64881
+ layer: "F.Fab",
64882
+ effects: textEffects
64883
+ });
64884
+ fpTexts.push(fpText);
64885
+ }
64886
+ return fpTexts;
64887
+ }
64888
+ function create3DModelsFromCadComponent(cadComponent, componentCenter) {
64889
+ const models = [];
64890
+ const modelUrl = cadComponent.model_step_url || cadComponent.model_wrl_url;
64891
+ if (!modelUrl)
64892
+ return models;
64893
+ const model = new FootprintModel(modelUrl);
64894
+ if (cadComponent.position) {
64895
+ model.offset = {
64896
+ x: (cadComponent.position.x || 0) - componentCenter.x,
64897
+ y: -((cadComponent.position.y || 0) - componentCenter.y),
64898
+ z: cadComponent.position.z || 0
64899
+ };
64900
+ }
64901
+ if (cadComponent.rotation) {
64902
+ model.rotate = {
64903
+ x: cadComponent.rotation.x || 0,
64904
+ y: cadComponent.rotation.y || 0,
64905
+ z: cadComponent.rotation.z || 0
64906
+ };
64907
+ }
64908
+ if (cadComponent.model_unit_to_mm_scale_factor) {
64909
+ const scale4 = cadComponent.model_unit_to_mm_scale_factor;
64910
+ model.scale = { x: scale4, y: scale4, z: scale4 };
64911
+ }
64912
+ models.push(model);
64913
+ return models;
64914
+ }
64620
64915
  function createSmdPadFromCircuitJson({
64621
64916
  pcbPad,
64622
64917
  componentCenter,
@@ -64637,8 +64932,8 @@ function createSmdPadFromCircuitJson({
64637
64932
  } else {
64638
64933
  throw new Error("Pad must have either x/y coordinates or points array");
64639
64934
  }
64640
- const cj2kicadMatrix = compose2(componentRotation !== 0 ? rotate(componentRotation * Math.PI / 180) : { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, scale2(1, -1), translate2(-componentCenter.x, -componentCenter.y));
64641
- const rotatedPos = applyToPoint5(cj2kicadMatrix, {
64935
+ const cj2kicadMatrix = compose2(componentRotation !== 0 ? rotate3(componentRotation * Math.PI / 180) : { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, scale2(1, -1), translate2(-componentCenter.x, -componentCenter.y));
64936
+ const rotatedPos = applyToPoint7(cj2kicadMatrix, {
64642
64937
  x: padX,
64643
64938
  y: padY
64644
64939
  });
@@ -64661,11 +64956,11 @@ function createSmdPadFromCircuitJson({
64661
64956
  const points = pcbPad.points;
64662
64957
  const pointTransformMatrix = compose2(scale2(1, -1), translate2(-padX, -padY));
64663
64958
  const relativePoints = points.map((p) => {
64664
- const transformed = applyToPoint5(pointTransformMatrix, { x: p.x, y: p.y });
64665
- return new Xy3(transformed.x, transformed.y);
64959
+ const transformed = applyToPoint7(pointTransformMatrix, { x: p.x, y: p.y });
64960
+ return new Xy4(transformed.x, transformed.y);
64666
64961
  });
64667
64962
  const grPoly = new PadPrimitiveGrPoly;
64668
- grPoly.contours = [new Pts3(relativePoints)];
64963
+ grPoly.contours = [new Pts4(relativePoints)];
64669
64964
  grPoly.width = 0;
64670
64965
  grPoly.filled = true;
64671
64966
  padPrimitives = new PadPrimitives;
@@ -64706,6 +65001,24 @@ function createSmdPadFromCircuitJson({
64706
65001
  }
64707
65002
  return pad;
64708
65003
  }
65004
+ function convertSmdPads(pcbPads, componentCenter, componentRotation, componentId, startPadNumber, getNetInfo) {
65005
+ const pads = [];
65006
+ let padNumber = startPadNumber;
65007
+ for (const pcbPad of pcbPads) {
65008
+ const netInfo = getNetInfo(pcbPad.pcb_port_id);
65009
+ const pad = createSmdPadFromCircuitJson({
65010
+ pcbPad,
65011
+ componentCenter,
65012
+ padNumber,
65013
+ componentRotation,
65014
+ netInfo,
65015
+ componentId
65016
+ });
65017
+ pads.push(pad);
65018
+ padNumber++;
65019
+ }
65020
+ return { pads, nextPadNumber: padNumber };
65021
+ }
64709
65022
  function createThruHolePadFromCircuitJson({
64710
65023
  platedHole,
64711
65024
  componentCenter,
@@ -64719,8 +65032,8 @@ function createThruHolePadFromCircuitJson({
64719
65032
  }
64720
65033
  const relativeX = platedHole.x - componentCenter.x;
64721
65034
  const relativeY = -(platedHole.y - componentCenter.y);
64722
- const rotationMatrix = componentRotation !== 0 ? rotate2(componentRotation * Math.PI / 180) : identity();
64723
- const rotatedPos = applyToPoint6(rotationMatrix, {
65035
+ const rotationMatrix = componentRotation !== 0 ? rotate4(componentRotation * Math.PI / 180) : identity3();
65036
+ const rotatedPos = applyToPoint8(rotationMatrix, {
64724
65037
  x: relativeX,
64725
65038
  y: relativeY
64726
65039
  });
@@ -64736,7 +65049,7 @@ function createThruHolePadFromCircuitJson({
64736
65049
  y: platedHole.hole_offset_y ?? 0
64737
65050
  };
64738
65051
  if (rawOffset.x !== 0 || rawOffset.y !== 0) {
64739
- const rotatedOffset = applyToPoint6(rotationMatrix, {
65052
+ const rotatedOffset = applyToPoint8(rotationMatrix, {
64740
65053
  x: -rawOffset.x,
64741
65054
  y: rawOffset.y
64742
65055
  });
@@ -64819,6 +65132,26 @@ function createThruHolePadFromCircuitJson({
64819
65132
  }
64820
65133
  return pad;
64821
65134
  }
65135
+ function convertPlatedHoles(platedHoles, componentCenter, componentRotation, componentId, startPadNumber, getNetInfo) {
65136
+ const pads = [];
65137
+ let padNumber = startPadNumber;
65138
+ for (const platedHole of platedHoles) {
65139
+ const netInfo = getNetInfo(platedHole.pcb_port_id);
65140
+ const pad = createThruHolePadFromCircuitJson({
65141
+ platedHole,
65142
+ componentCenter,
65143
+ padNumber,
65144
+ componentRotation,
65145
+ netInfo,
65146
+ componentId
65147
+ });
65148
+ if (pad) {
65149
+ pads.push(pad);
65150
+ padNumber++;
65151
+ }
65152
+ }
65153
+ return { pads, nextPadNumber: padNumber };
65154
+ }
64822
65155
  function createNpthPadFromCircuitJson({
64823
65156
  pcbHole,
64824
65157
  componentCenter,
@@ -64829,8 +65162,8 @@ function createNpthPadFromCircuitJson({
64829
65162
  }
64830
65163
  const relativeX = pcbHole.x - componentCenter.x;
64831
65164
  const relativeY = -(pcbHole.y - componentCenter.y);
64832
- const rotationMatrix = componentRotation !== 0 ? rotate3(componentRotation * Math.PI / 180) : identity2();
64833
- const rotatedPos = applyToPoint7(rotationMatrix, {
65165
+ const rotationMatrix = componentRotation !== 0 ? rotate5(componentRotation * Math.PI / 180) : identity4();
65166
+ const rotatedPos = applyToPoint9(rotationMatrix, {
64834
65167
  x: relativeX,
64835
65168
  y: relativeY
64836
65169
  });
@@ -64872,48 +65205,19 @@ function createNpthPadFromCircuitJson({
64872
65205
  uuid: crypto.randomUUID()
64873
65206
  });
64874
65207
  }
64875
- function createFpTextFromCircuitJson({
64876
- textElement,
64877
- componentCenter,
64878
- componentRotation = 0
64879
- }) {
64880
- if (!textElement.text || !textElement.anchor_position) {
64881
- return null;
65208
+ function convertNpthHoles(pcbHoles, componentCenter, componentRotation) {
65209
+ const pads = [];
65210
+ for (const pcbHole of pcbHoles) {
65211
+ const pad = createNpthPadFromCircuitJson({
65212
+ pcbHole,
65213
+ componentCenter,
65214
+ componentRotation
65215
+ });
65216
+ if (pad) {
65217
+ pads.push(pad);
65218
+ }
64882
65219
  }
64883
- const relativeX = textElement.anchor_position.x - componentCenter.x;
64884
- const relativeY = -(textElement.anchor_position.y - componentCenter.y);
64885
- const rotationMatrix = componentRotation !== 0 ? rotate4(componentRotation * Math.PI / 180) : identity3();
64886
- const rotatedPos = applyToPoint8(rotationMatrix, {
64887
- x: relativeX,
64888
- y: relativeY
64889
- });
64890
- const relativePosition = {
64891
- x: rotatedPos.x,
64892
- y: rotatedPos.y
64893
- };
64894
- const layerMap = {
64895
- top: "F.SilkS",
64896
- bottom: "B.SilkS"
64897
- };
64898
- const kicadLayer = layerMap[textElement.layer] || textElement.layer || "F.SilkS";
64899
- const fontSize = (textElement.font_size || 1) / 1.5;
64900
- const font = new TextEffectsFont4;
64901
- font.size = { width: fontSize, height: fontSize };
64902
- const textEffects = new TextEffects4({
64903
- font
64904
- });
64905
- const rotation = textElement.ccw_rotation || 0;
64906
- return new FpText({
64907
- type: "user",
64908
- text: textElement.text,
64909
- position: {
64910
- x: relativePosition.x,
64911
- y: relativePosition.y,
64912
- angle: rotation
64913
- },
64914
- layer: kicadLayer,
64915
- effects: textEffects
64916
- });
65220
+ return pads;
64917
65221
  }
64918
65222
  var AddFootprintsStage = class extends ConverterStage {
64919
65223
  componentsProcessed = 0;
@@ -64939,33 +65243,6 @@ var AddFootprintsStage = class extends ConverterStage {
64939
65243
  const cadComponents = this.ctx.db.cad_component?.list() || [];
64940
65244
  return cadComponents.find((cad) => cad.pcb_component_id === pcbComponentId);
64941
65245
  }
64942
- create3DModelsFromCadComponent(cadComponent, componentCenter) {
64943
- const models = [];
64944
- const modelUrl = cadComponent.model_step_url || cadComponent.model_wrl_url;
64945
- if (!modelUrl)
64946
- return models;
64947
- const model = new FootprintModel(modelUrl);
64948
- if (cadComponent.position) {
64949
- model.offset = {
64950
- x: (cadComponent.position.x || 0) - componentCenter.x,
64951
- y: -((cadComponent.position.y || 0) - componentCenter.y),
64952
- z: cadComponent.position.z || 0
64953
- };
64954
- }
64955
- if (cadComponent.rotation) {
64956
- model.rotate = {
64957
- x: cadComponent.rotation.x || 0,
64958
- y: cadComponent.rotation.y || 0,
64959
- z: cadComponent.rotation.z || 0
64960
- };
64961
- }
64962
- if (cadComponent.model_unit_to_mm_scale_factor) {
64963
- const scale4 = cadComponent.model_unit_to_mm_scale_factor;
64964
- model.scale = { x: scale4, y: scale4, z: scale4 };
64965
- }
64966
- models.push(model);
64967
- return models;
64968
- }
64969
65246
  constructor(input, ctx) {
64970
65247
  super(input, ctx);
64971
65248
  this.pcbComponents = this.ctx.db.pcb_component.list();
@@ -64986,7 +65263,7 @@ var AddFootprintsStage = class extends ConverterStage {
64986
65263
  const sourceComponent = component.source_component_id ? this.ctx.db.source_component.get(component.source_component_id) : null;
64987
65264
  const cadComponent = this.getCadComponentForPcbComponent(component.pcb_component_id);
64988
65265
  const footprintName = sourceComponent ? getKicadCompatibleComponentName(sourceComponent, cadComponent) : "Unknown";
64989
- const transformedPos = applyToPoint9(c2kMatPcb, {
65266
+ const transformedPos = applyToPoint10(c2kMatPcb, {
64990
65267
  x: component.center.x,
64991
65268
  y: component.center.y
64992
65269
  });
@@ -64999,66 +65276,43 @@ var AddFootprintsStage = class extends ConverterStage {
64999
65276
  });
65000
65277
  const fpTexts = footprint.fpTexts;
65001
65278
  const pcbSilkscreenTexts = this.ctx.db.pcb_silkscreen_text?.list().filter((text) => text.pcb_component_id === component.pcb_component_id) || [];
65002
- for (const textElement of pcbSilkscreenTexts) {
65003
- const fpText = createFpTextFromCircuitJson({
65004
- textElement,
65005
- componentCenter: component.center,
65006
- componentRotation: component.rotation || 0
65007
- });
65008
- if (fpText) {
65009
- if (sourceComponent?.name && textElement.text === sourceComponent.name) {
65010
- fpText.type = "reference";
65011
- }
65012
- fpTexts.push(fpText);
65013
- }
65014
- }
65279
+ fpTexts.push(...convertSilkscreenTexts(pcbSilkscreenTexts, component.center, component.rotation || 0, sourceComponent?.name));
65280
+ const pcbNoteTexts = this.ctx.db.pcb_note_text?.list().filter((text) => text.pcb_component_id === component.pcb_component_id) || [];
65281
+ fpTexts.push(...convertNoteTexts(pcbNoteTexts, component.center, component.rotation || 0));
65015
65282
  footprint.fpTexts = fpTexts;
65016
- const pcbPads = this.ctx.db.pcb_smtpad?.list().filter((pad) => pad.pcb_component_id === component.pcb_component_id) || [];
65017
65283
  const fpPads = footprint.fpPads;
65018
- let padNumber = 1;
65019
- for (const pcbPad of pcbPads) {
65020
- const netInfo = this.getNetInfoForPcbPort(pcbPad.pcb_port_id);
65021
- const pad = createSmdPadFromCircuitJson({
65022
- pcbPad,
65023
- componentCenter: component.center,
65024
- padNumber,
65025
- componentRotation: component.rotation || 0,
65026
- netInfo,
65027
- componentId: component.pcb_component_id
65028
- });
65029
- fpPads.push(pad);
65030
- padNumber++;
65031
- }
65284
+ const getNetInfo = (pcbPortId) => this.getNetInfoForPcbPort(pcbPortId);
65285
+ const pcbPads = this.ctx.db.pcb_smtpad?.list().filter((pad) => pad.pcb_component_id === component.pcb_component_id) || [];
65286
+ const { pads: smdPads, nextPadNumber } = convertSmdPads(pcbPads, component.center, component.rotation || 0, component.pcb_component_id, 1, getNetInfo);
65287
+ fpPads.push(...smdPads);
65032
65288
  const pcbPlatedHoles = this.ctx.db.pcb_plated_hole?.list().filter((hole) => hole.pcb_component_id === component.pcb_component_id) || [];
65033
- for (const platedHole of pcbPlatedHoles) {
65034
- const netInfo = this.getNetInfoForPcbPort(platedHole.pcb_port_id);
65035
- const pad = createThruHolePadFromCircuitJson({
65036
- platedHole,
65037
- componentCenter: component.center,
65038
- padNumber,
65039
- componentRotation: component.rotation || 0,
65040
- netInfo,
65041
- componentId: component.pcb_component_id
65042
- });
65043
- if (pad) {
65044
- fpPads.push(pad);
65045
- padNumber++;
65046
- }
65047
- }
65289
+ const { pads: thruHolePads } = convertPlatedHoles(pcbPlatedHoles, component.center, component.rotation || 0, component.pcb_component_id, nextPadNumber, getNetInfo);
65290
+ fpPads.push(...thruHolePads);
65048
65291
  const pcbHoles = this.ctx.db.pcb_hole?.list().filter((hole) => hole.subcircuit_id === component.subcircuit_id) || [];
65049
- for (const pcbHole of pcbHoles) {
65050
- const pad = createNpthPadFromCircuitJson({
65051
- pcbHole,
65052
- componentCenter: component.center,
65053
- componentRotation: component.rotation || 0
65054
- });
65055
- if (pad) {
65056
- fpPads.push(pad);
65057
- }
65058
- }
65292
+ const npthPads = convertNpthHoles(pcbHoles, component.center, component.rotation || 0);
65293
+ fpPads.push(...npthPads);
65059
65294
  footprint.fpPads = fpPads;
65295
+ const pcbSilkscreenCircles = this.ctx.db.pcb_silkscreen_circle?.list().filter((circle) => circle.pcb_component_id === component.pcb_component_id) || [];
65296
+ const fpCircles = footprint.fpCircles ?? [];
65297
+ fpCircles.push(...convertSilkscreenCircles(pcbSilkscreenCircles, component.center));
65298
+ const pcbCourtyardCircles = this.ctx.db.pcb_courtyard_circle?.list().filter((circle) => circle.pcb_component_id === component.pcb_component_id) || [];
65299
+ fpCircles.push(...convertCourtyardCircles(pcbCourtyardCircles, component.center));
65300
+ footprint.fpCircles = fpCircles;
65301
+ const pcbFabRects = this.ctx.db.pcb_fabrication_note_rect?.list().filter((rect) => rect.pcb_component_id === component.pcb_component_id) || [];
65302
+ const fpRects = footprint.fpRects ?? [];
65303
+ fpRects.push(...convertFabricationNoteRects(pcbFabRects, component.center));
65304
+ const pcbNoteRects = this.ctx.db.pcb_note_rect?.list().filter((rect) => rect.pcb_component_id === component.pcb_component_id) || [];
65305
+ fpRects.push(...convertNoteRects(pcbNoteRects, component.center));
65306
+ const pcbCourtyardRects = this.ctx.db.pcb_courtyard_rect?.list().filter((rect) => rect.pcb_component_id === component.pcb_component_id) || [];
65307
+ fpRects.push(...convertCourtyardRects(pcbCourtyardRects, component.center));
65308
+ footprint.fpRects = fpRects;
65309
+ const pcbCourtyardOutlines = this.ctx.db.pcb_courtyard_outline?.list().filter((outline) => outline.pcb_component_id === component.pcb_component_id) || [];
65310
+ const fpPolys = convertCourtyardOutlines(pcbCourtyardOutlines, component.center);
65311
+ if (fpPolys.length > 0) {
65312
+ footprint.fpPolys = fpPolys;
65313
+ }
65060
65314
  if (cadComponent) {
65061
- const models = this.create3DModelsFromCadComponent(cadComponent, component.center);
65315
+ const models = create3DModelsFromCadComponent(cadComponent, component.center);
65062
65316
  if (models.length > 0) {
65063
65317
  footprint.models = models;
65064
65318
  }
@@ -65072,6 +65326,29 @@ var AddFootprintsStage = class extends ConverterStage {
65072
65326
  return this.ctx.kicadPcb;
65073
65327
  }
65074
65328
  };
65329
+ var circuitJsonLayerToKicadLayer = {
65330
+ top: "F.Cu",
65331
+ bottom: "B.Cu",
65332
+ inner1: "In1.Cu",
65333
+ inner2: "In2.Cu",
65334
+ inner3: "In3.Cu",
65335
+ inner4: "In4.Cu",
65336
+ inner5: "In5.Cu",
65337
+ inner6: "In6.Cu"
65338
+ };
65339
+ function getKicadLayer(circuitJsonLayer) {
65340
+ if (!circuitJsonLayer)
65341
+ return "F.Cu";
65342
+ return circuitJsonLayerToKicadLayer[circuitJsonLayer] || circuitJsonLayer || "F.Cu";
65343
+ }
65344
+ function getViaLayers(numLayers) {
65345
+ const layers = ["F.Cu"];
65346
+ for (let i = 1;i < numLayers - 1; i++) {
65347
+ layers.push(`In${i}.Cu`);
65348
+ }
65349
+ layers.push("B.Cu");
65350
+ return layers;
65351
+ }
65075
65352
  var AddTracesStage = class extends ConverterStage {
65076
65353
  tracesProcessed = 0;
65077
65354
  pcbTraces = [];
@@ -65096,14 +65373,15 @@ var AddTracesStage = class extends ConverterStage {
65096
65373
  this.tracesProcessed++;
65097
65374
  return;
65098
65375
  }
65376
+ let lastKnownLayer = trace.route[0]?.layer;
65099
65377
  for (let i = 0;i < trace.route.length - 1; i++) {
65100
65378
  const startPoint = trace.route[i];
65101
65379
  const endPoint = trace.route[i + 1];
65102
- const transformedStart = applyToPoint10(c2kMatPcb, {
65380
+ const transformedStart = applyToPoint11(c2kMatPcb, {
65103
65381
  x: startPoint.x,
65104
65382
  y: startPoint.y
65105
65383
  });
65106
- const transformedEnd = applyToPoint10(c2kMatPcb, {
65384
+ const transformedEnd = applyToPoint11(c2kMatPcb, {
65107
65385
  x: endPoint.x,
65108
65386
  y: endPoint.y
65109
65387
  });
@@ -65135,11 +65413,8 @@ var AddTracesStage = class extends ConverterStage {
65135
65413
  netInfo = pcbNetMap.get(connectivityKey);
65136
65414
  }
65137
65415
  }
65138
- const layerMap = {
65139
- top: "F.Cu",
65140
- bottom: "B.Cu"
65141
- };
65142
- const kicadLayer = layerMap[startPoint.layer] || startPoint.layer || "F.Cu";
65416
+ const segmentLayerSource = startPoint.layer ?? endPoint.layer ?? lastKnownLayer;
65417
+ const kicadLayer = getKicadLayer(segmentLayerSource);
65143
65418
  const segmentData = `segment:${transformedStart.x},${transformedStart.y}:${transformedEnd.x},${transformedEnd.y}:${kicadLayer}:${netInfo?.id ?? 0}`;
65144
65419
  const segment = new Segment({
65145
65420
  start: { x: transformedStart.x, y: transformedStart.y },
@@ -65152,6 +65427,12 @@ var AddTracesStage = class extends ConverterStage {
65152
65427
  const segments = kicadPcb.segments;
65153
65428
  segments.push(segment);
65154
65429
  kicadPcb.segments = segments;
65430
+ if (startPoint.layer) {
65431
+ lastKnownLayer = startPoint.layer;
65432
+ }
65433
+ if (endPoint.layer) {
65434
+ lastKnownLayer = endPoint.layer;
65435
+ }
65155
65436
  }
65156
65437
  this.tracesProcessed++;
65157
65438
  }
@@ -65179,7 +65460,7 @@ var AddViasStage = class extends ConverterStage {
65179
65460
  return;
65180
65461
  }
65181
65462
  const via = this.pcbVias[this.viasProcessed];
65182
- const transformedPos = applyToPoint11(c2kMatPcb, {
65463
+ const transformedPos = applyToPoint12(c2kMatPcb, {
65183
65464
  x: via.x,
65184
65465
  y: via.y
65185
65466
  });
@@ -65221,12 +65502,14 @@ var AddViasStage = class extends ConverterStage {
65221
65502
  netInfo = pcbNetMap.get(connectivityKey);
65222
65503
  }
65223
65504
  }
65505
+ const numLayers = this.ctx.numLayers ?? 2;
65506
+ const viaLayers = via.layers ? via.layers.map((l) => l === "top" ? "F.Cu" : l === "bottom" ? "B.Cu" : `In${l.replace("inner", "")}.Cu`) : getViaLayers(numLayers);
65224
65507
  const viaData = `via:${transformedPos.x},${transformedPos.y}:${via.outer_diameter || 0.8}:${via.hole_diameter || 0.4}:${netInfo?.id ?? 0}`;
65225
65508
  const kicadVia = new Via({
65226
65509
  at: [transformedPos.x, transformedPos.y],
65227
65510
  size: via.outer_diameter || 0.8,
65228
65511
  drill: via.hole_diameter || 0.4,
65229
- layers: ["F.Cu", "B.Cu"],
65512
+ layers: viaLayers,
65230
65513
  net: new ViaNet(netInfo?.id ?? 0),
65231
65514
  uuid: generateDeterministicUuid(viaData)
65232
65515
  });
@@ -65239,6 +65522,62 @@ var AddViasStage = class extends ConverterStage {
65239
65522
  return this.ctx.kicadPcb;
65240
65523
  }
65241
65524
  };
65525
+ function createFabricationNoteTextFromCircuitJson({
65526
+ textElement,
65527
+ c2kMatPcb
65528
+ }) {
65529
+ if (!textElement.text || !textElement.anchor_position) {
65530
+ return null;
65531
+ }
65532
+ const transformedPos = applyToPoint13(c2kMatPcb, {
65533
+ x: textElement.anchor_position.x,
65534
+ y: textElement.anchor_position.y
65535
+ });
65536
+ const layerMap = {
65537
+ top: "F.Fab",
65538
+ bottom: "B.Fab"
65539
+ };
65540
+ const kicadLayer = layerMap[textElement.layer] || textElement.layer || "F.Fab";
65541
+ const fontSize = (textElement.font_size || 1) / 1.5;
65542
+ const font = new TextEffectsFont6;
65543
+ font.size = { width: fontSize, height: fontSize };
65544
+ const justify = new TextEffectsJustify3;
65545
+ const anchorAlignment = textElement.anchor_alignment || "center";
65546
+ switch (anchorAlignment) {
65547
+ case "top_left":
65548
+ justify.horizontal = "left";
65549
+ justify.vertical = "top";
65550
+ break;
65551
+ case "top_right":
65552
+ justify.horizontal = "right";
65553
+ justify.vertical = "top";
65554
+ break;
65555
+ case "bottom_left":
65556
+ justify.horizontal = "left";
65557
+ justify.vertical = "bottom";
65558
+ break;
65559
+ case "bottom_right":
65560
+ justify.horizontal = "right";
65561
+ justify.vertical = "bottom";
65562
+ break;
65563
+ case "center":
65564
+ break;
65565
+ }
65566
+ const textEffects = new TextEffects6({
65567
+ font
65568
+ });
65569
+ if (anchorAlignment !== "center") {
65570
+ textEffects.justify = justify;
65571
+ }
65572
+ const position = new At([transformedPos.x, transformedPos.y, 0]);
65573
+ const grText = new GrText({
65574
+ text: textElement.text,
65575
+ layer: kicadLayer,
65576
+ effects: textEffects
65577
+ });
65578
+ grText.position = position;
65579
+ return grText;
65580
+ }
65242
65581
  function createGrTextFromCircuitJson({
65243
65582
  textElement,
65244
65583
  c2kMatPcb
@@ -65246,7 +65585,7 @@ function createGrTextFromCircuitJson({
65246
65585
  if (!textElement.text || !textElement.anchor_position) {
65247
65586
  return null;
65248
65587
  }
65249
- const transformedPos = applyToPoint12(c2kMatPcb, {
65588
+ const transformedPos = applyToPoint14(c2kMatPcb, {
65250
65589
  x: textElement.anchor_position.x,
65251
65590
  y: textElement.anchor_position.y
65252
65591
  });
@@ -65256,9 +65595,9 @@ function createGrTextFromCircuitJson({
65256
65595
  };
65257
65596
  const kicadLayer = layerMap[textElement.layer] || textElement.layer || "F.SilkS";
65258
65597
  const fontSize = (textElement.font_size || 1) / 1.5;
65259
- const font = new TextEffectsFont5;
65598
+ const font = new TextEffectsFont7;
65260
65599
  font.size = { width: fontSize, height: fontSize };
65261
- const justify = new TextEffectsJustify3;
65600
+ const justify = new TextEffectsJustify4;
65262
65601
  const anchorAlignment = textElement.anchor_alignment || "center";
65263
65602
  switch (anchorAlignment) {
65264
65603
  case "top_left":
@@ -65280,15 +65619,15 @@ function createGrTextFromCircuitJson({
65280
65619
  case "center":
65281
65620
  break;
65282
65621
  }
65283
- const textEffects = new TextEffects5({
65622
+ const textEffects = new TextEffects7({
65284
65623
  font
65285
65624
  });
65286
65625
  if (anchorAlignment !== "center") {
65287
65626
  textEffects.justify = justify;
65288
65627
  }
65289
65628
  const rotation = textElement.ccw_rotation || 0;
65290
- const position = new At([transformedPos.x, transformedPos.y, rotation]);
65291
- const grText = new GrText({
65629
+ const position = new At2([transformedPos.x, transformedPos.y, rotation]);
65630
+ const grText = new GrText2({
65292
65631
  text: textElement.text,
65293
65632
  layer: kicadLayer,
65294
65633
  effects: textEffects
@@ -65314,11 +65653,11 @@ var AddGraphicsStage = class extends ConverterStage {
65314
65653
  const endPoint = path7.route[i + 1];
65315
65654
  if (!startPoint || !endPoint)
65316
65655
  continue;
65317
- const transformedStart = applyToPoint13(c2kMatPcb, {
65656
+ const transformedStart = applyToPoint15(c2kMatPcb, {
65318
65657
  x: startPoint.x,
65319
65658
  y: startPoint.y
65320
65659
  });
65321
- const transformedEnd = applyToPoint13(c2kMatPcb, {
65660
+ const transformedEnd = applyToPoint15(c2kMatPcb, {
65322
65661
  x: endPoint.x,
65323
65662
  y: endPoint.y
65324
65663
  });
@@ -65350,6 +65689,18 @@ var AddGraphicsStage = class extends ConverterStage {
65350
65689
  kicadPcb.graphicTexts = graphicTexts;
65351
65690
  }
65352
65691
  }
65692
+ const fabricationNoteTexts = this.ctx.db.pcb_fabrication_note_text?.list() || [];
65693
+ for (const textElement of fabricationNoteTexts) {
65694
+ const grText = createFabricationNoteTextFromCircuitJson({
65695
+ textElement,
65696
+ c2kMatPcb
65697
+ });
65698
+ if (grText) {
65699
+ const graphicTexts = kicadPcb.graphicTexts;
65700
+ graphicTexts.push(grText);
65701
+ kicadPcb.graphicTexts = graphicTexts;
65702
+ }
65703
+ }
65353
65704
  const pcbBoards = this.ctx.db.pcb_board?.list() || [];
65354
65705
  if (pcbBoards.length > 0) {
65355
65706
  const board = pcbBoards[0];
@@ -65370,7 +65721,7 @@ var AddGraphicsStage = class extends ConverterStage {
65370
65721
  { x: board.center.x - halfWidth, y: board.center.y + halfHeight }
65371
65722
  ];
65372
65723
  }
65373
- const transformedCorners = corners.map((corner) => applyToPoint13(c2kMatPcb, corner));
65724
+ const transformedCorners = corners.map((corner) => applyToPoint15(c2kMatPcb, corner));
65374
65725
  for (let i = 0;i < transformedCorners.length; i++) {
65375
65726
  const start = transformedCorners[i];
65376
65727
  const end = transformedCorners[(i + 1) % transformedCorners.length];
@@ -65568,6 +65919,9 @@ var ExtractSymbolsStage = class extends ConverterStage {
65568
65919
  if (!uniqueSymbols.has(symbolName)) {
65569
65920
  symbol.libraryId = symbolName;
65570
65921
  this.updateFootprintProperty(symbol, fpLibraryName);
65922
+ if (!isCustom) {
65923
+ this.snapPinPositionsToGrid(symbol);
65924
+ }
65571
65925
  uniqueSymbols.set(symbolName, {
65572
65926
  symbolName,
65573
65927
  symbol,
@@ -65601,10 +65955,34 @@ var ExtractSymbolsStage = class extends ConverterStage {
65601
65955
  const name = parts.length > 1 ? parts[1] : parts[0];
65602
65956
  return name?.replace(/[\\\/]/g, "-").trim() || "symbol";
65603
65957
  }
65958
+ snapPinPositionsToGrid(symbol) {
65959
+ const KICAD_GRID = 1.27;
65960
+ for (const subSymbol of symbol.subSymbols ?? []) {
65961
+ for (const pin of subSymbol.pins ?? []) {
65962
+ if (pin.at) {
65963
+ pin.at.x = Math.round(pin.at.x / KICAD_GRID) * KICAD_GRID;
65964
+ pin.at.y = Math.round(pin.at.y / KICAD_GRID) * KICAD_GRID;
65965
+ }
65966
+ }
65967
+ for (const polyline of subSymbol.polylines ?? []) {
65968
+ if (polyline.points?.points) {
65969
+ for (const pt of polyline.points.points) {
65970
+ if ("x" in pt && "y" in pt) {
65971
+ pt.x = Math.round(pt.x / KICAD_GRID) * KICAD_GRID;
65972
+ pt.y = Math.round(pt.y / KICAD_GRID) * KICAD_GRID;
65973
+ }
65974
+ }
65975
+ }
65976
+ }
65977
+ }
65978
+ }
65604
65979
  getOutput() {
65605
65980
  return this.ctx.libraryOutput;
65606
65981
  }
65607
65982
  };
65983
+ var KICAD_FP_VERSION = 20240108;
65984
+ var KICAD_FP_GENERATOR = "pcbnew";
65985
+ var KICAD_FP_GENERATOR_VERSION = "8.0";
65608
65986
  function getBasename(filePath) {
65609
65987
  const parts = filePath.split(/[/\\]/);
65610
65988
  return parts[parts.length - 1] || filePath;
@@ -65668,9 +66046,12 @@ var ExtractFootprintsStage = class extends ConverterStage {
65668
66046
  const footprintName = (parts.length > 1 ? parts[1] : parts[0])?.replace(/[\\\/]/g, "-").trim() || "footprint";
65669
66047
  const isBuiltin = !customFootprintNames.has(footprintName);
65670
66048
  footprint.libraryLink = footprintName;
65671
- footprint.position = At2.from([0, 0, 0]);
66049
+ footprint.position = At3.from([0, 0, 0]);
65672
66050
  footprint.locked = false;
65673
66051
  footprint.placed = false;
66052
+ footprint.version = KICAD_FP_VERSION;
66053
+ footprint.generator = KICAD_FP_GENERATOR;
66054
+ footprint.generatorVersion = KICAD_FP_GENERATOR_VERSION;
65674
66055
  if (!footprint.descr) {
65675
66056
  footprint.descr = "";
65676
66057
  }
@@ -65694,15 +66075,32 @@ var ExtractFootprintsStage = class extends ConverterStage {
65694
66075
  footprint.path = undefined;
65695
66076
  footprint.sheetfile = undefined;
65696
66077
  footprint.sheetname = undefined;
65697
- const defaultFont = new TextEffectsFont6;
66078
+ const defaultFont = new TextEffectsFont8;
65698
66079
  defaultFont.size = { width: 1.27, height: 1.27 };
65699
66080
  defaultFont.thickness = 0.15;
65700
- const defaultEffects = new TextEffects6({ font: defaultFont });
66081
+ const defaultEffects = new TextEffects8({ font: defaultFont });
66082
+ const fpPads = footprint.fpPads ?? [];
66083
+ let minY = 0;
66084
+ let maxY = 0;
66085
+ for (const pad of fpPads) {
66086
+ const at = pad.at;
66087
+ const size = pad.size;
66088
+ if (at && size) {
66089
+ const padY = at.y ?? 0;
66090
+ const padHeight = size.height ?? 0;
66091
+ const padTop = padY - padHeight / 2;
66092
+ const padBottom = padY + padHeight / 2;
66093
+ minY = Math.min(minY, padTop);
66094
+ maxY = Math.max(maxY, padBottom);
66095
+ }
66096
+ }
66097
+ const refY = minY - 0.5;
66098
+ const valY = maxY + 0.5;
65701
66099
  footprint.properties = [
65702
66100
  new Property({
65703
66101
  key: "Reference",
65704
- value: "Ref**",
65705
- position: [0, 0, 0],
66102
+ value: "REF**",
66103
+ position: [0, refY, 0],
65706
66104
  layer: "F.SilkS",
65707
66105
  uuid: generateDeterministicUuid(`${footprintName}-property-Reference`),
65708
66106
  effects: defaultEffects
@@ -65710,7 +66108,7 @@ var ExtractFootprintsStage = class extends ConverterStage {
65710
66108
  new Property({
65711
66109
  key: "Value",
65712
66110
  value: "Val**",
65713
- position: [0, 0, 0],
66111
+ position: [0, valY, 0],
65714
66112
  layer: "F.Fab",
65715
66113
  uuid: generateDeterministicUuid(`${footprintName}-property-Value`),
65716
66114
  effects: defaultEffects
@@ -65952,6 +66350,23 @@ function renameKicadFootprint(params2) {
65952
66350
  model3dSourcePaths: kicadFootprint.model3dSourcePaths
65953
66351
  };
65954
66352
  }
66353
+ function createTextEffects(metadataEffects) {
66354
+ const font = new TextEffectsFont9;
66355
+ if (metadataEffects?.font?.size) {
66356
+ font.size = {
66357
+ width: Number(metadataEffects.font.size.x),
66358
+ height: Number(metadataEffects.font.size.y)
66359
+ };
66360
+ } else {
66361
+ font.size = { width: 1.27, height: 1.27 };
66362
+ }
66363
+ if (metadataEffects?.font?.thickness !== undefined) {
66364
+ font.thickness = Number(metadataEffects.font.thickness);
66365
+ } else {
66366
+ font.thickness = 0.15;
66367
+ }
66368
+ return new TextEffects9({ font });
66369
+ }
65955
66370
  function applyKicadFootprintMetadata(kicadModString, metadata, footprintName) {
65956
66371
  try {
65957
66372
  const parsed = parseKicadSexpr3(kicadModString);
@@ -65970,10 +66385,6 @@ function applyKicadFootprintMetadata(kicadModString, metadata, footprintName) {
65970
66385
  }
65971
66386
  if (metadata.embeddedFonts !== undefined) {}
65972
66387
  if (metadata.properties) {
65973
- const defaultFont = new TextEffectsFont7;
65974
- defaultFont.size = { width: 1.27, height: 1.27 };
65975
- defaultFont.thickness = 0.15;
65976
- const defaultEffects = new TextEffects7({ font: defaultFont });
65977
66388
  const newProperties = [];
65978
66389
  const refMeta = metadata.properties.Reference;
65979
66390
  newProperties.push(new Property2({
@@ -65986,7 +66397,7 @@ function applyKicadFootprintMetadata(kicadModString, metadata, footprintName) {
65986
66397
  ] : [0, 0, 0],
65987
66398
  layer: refMeta?.layer ?? "F.SilkS",
65988
66399
  uuid: refMeta?.uuid ?? generateDeterministicUuid(`${footprintName}-property-Reference`),
65989
- effects: defaultEffects,
66400
+ effects: createTextEffects(refMeta?.effects),
65990
66401
  hidden: refMeta?.hide
65991
66402
  }));
65992
66403
  const valMeta = metadata.properties.Value;
@@ -66000,7 +66411,7 @@ function applyKicadFootprintMetadata(kicadModString, metadata, footprintName) {
66000
66411
  ] : [0, 0, 0],
66001
66412
  layer: valMeta?.layer ?? "F.Fab",
66002
66413
  uuid: valMeta?.uuid ?? generateDeterministicUuid(`${footprintName}-property-Value`),
66003
- effects: defaultEffects,
66414
+ effects: createTextEffects(valMeta?.effects),
66004
66415
  hidden: valMeta?.hide
66005
66416
  }));
66006
66417
  const dsMeta = metadata.properties.Datasheet;
@@ -66014,7 +66425,7 @@ function applyKicadFootprintMetadata(kicadModString, metadata, footprintName) {
66014
66425
  ] : [0, 0, 0],
66015
66426
  layer: dsMeta?.layer ?? "F.Fab",
66016
66427
  uuid: dsMeta?.uuid ?? generateDeterministicUuid(`${footprintName}-property-Datasheet`),
66017
- effects: defaultEffects,
66428
+ effects: createTextEffects(dsMeta?.effects),
66018
66429
  hidden: dsMeta?.hide ?? true
66019
66430
  }));
66020
66431
  const descMeta = metadata.properties.Description;
@@ -66028,7 +66439,7 @@ function applyKicadFootprintMetadata(kicadModString, metadata, footprintName) {
66028
66439
  ] : [0, 0, 0],
66029
66440
  layer: descMeta?.layer ?? "F.Fab",
66030
66441
  uuid: descMeta?.uuid ?? generateDeterministicUuid(`${footprintName}-property-Description`),
66031
- effects: defaultEffects,
66442
+ effects: createTextEffects(descMeta?.effects),
66032
66443
  hidden: descMeta?.hide ?? true
66033
66444
  }));
66034
66445
  footprint.properties = newProperties;
@@ -66191,16 +66602,16 @@ var toNumber = (value, fallback) => {
66191
66602
  return fallback;
66192
66603
  return parsed;
66193
66604
  };
66194
- var createTextEffects = (effectsMeta, fallback) => {
66605
+ var createTextEffects2 = (effectsMeta, fallback) => {
66195
66606
  if (!effectsMeta)
66196
66607
  return fallback;
66197
- const effects = new TextEffects8({
66608
+ const effects = new TextEffects10({
66198
66609
  font: fallback?.font,
66199
66610
  justify: fallback?.justify,
66200
66611
  hiddenText: fallback?.hiddenText ?? false
66201
66612
  });
66202
66613
  if (!effects.font) {
66203
- const defaultFont = new TextEffectsFont8;
66614
+ const defaultFont = new TextEffectsFont10;
66204
66615
  defaultFont.size = { width: DEFAULT_TEXT_SIZE, height: DEFAULT_TEXT_SIZE };
66205
66616
  effects.font = defaultFont;
66206
66617
  }
@@ -66245,7 +66656,7 @@ var createJustify = (justifyInput) => {
66245
66656
  if (!options.horizontal && !options.vertical && !options.mirror) {
66246
66657
  return;
66247
66658
  }
66248
- return new TextEffectsJustify4(options);
66659
+ return new TextEffectsJustify5(options);
66249
66660
  };
66250
66661
  var applySymbolProperty = (symbol, key, propertyMeta) => {
66251
66662
  const existingProperty = symbol.properties.find((prop) => prop.key === key);
@@ -66255,7 +66666,7 @@ var applySymbolProperty = (symbol, key, propertyMeta) => {
66255
66666
  toNumber(propertyMeta.at.y, 0),
66256
66667
  toNumber(propertyMeta.at.rotation, 0)
66257
66668
  ] : existingProperty?.at;
66258
- const nextEffects = createTextEffects(propertyMeta.effects, existingProperty?.effects);
66669
+ const nextEffects = createTextEffects2(propertyMeta.effects, existingProperty?.effects);
66259
66670
  if (existingProperty) {
66260
66671
  existingProperty.value = propertyMeta.value;
66261
66672
  if (nextId !== undefined) {
@@ -66315,7 +66726,9 @@ function applyKicadSymbolMetadata(kicadSymbol, metadata) {
66315
66726
  }
66316
66727
  return kicadSymbol;
66317
66728
  }
66729
+ var addedSymbolNames = /* @__PURE__ */ new Set;
66318
66730
  function classifyKicadSymbols(ctx) {
66731
+ addedSymbolNames.clear();
66319
66732
  for (const extractedKicadComponent of ctx.extractedKicadComponents) {
66320
66733
  classifySymbolsForComponent({
66321
66734
  ctx,
@@ -66333,25 +66746,21 @@ function classifySymbolsForComponent({
66333
66746
  const metadata = ctx.symbolMetadataMap.get(tscircuitComponentName);
66334
66747
  for (const kicadSymbol of kicadSymbols) {
66335
66748
  if (!kicadSymbol.isBuiltin) {
66336
- if (!hasAddedUserSymbol) {
66337
- hasAddedUserSymbol = true;
66338
- const renamedSymbol = renameKicadSymbol({
66749
+ const symbolName = kicadSymbol.symbolName;
66750
+ if (addedSymbolNames.has(symbolName)) {
66751
+ continue;
66752
+ }
66753
+ addedSymbolNames.add(symbolName);
66754
+ if (hasCustomFootprint) {
66755
+ updateKicadSymbolFootprint({
66339
66756
  kicadSymbol,
66340
- newKicadSymbolName: tscircuitComponentName
66757
+ kicadLibraryName: ctx.kicadLibraryName,
66758
+ kicadFootprintName: tscircuitComponentName,
66759
+ isPcm: ctx.isPcm
66341
66760
  });
66342
- if (hasCustomFootprint) {
66343
- updateKicadSymbolFootprint({
66344
- kicadSymbol: renamedSymbol,
66345
- kicadLibraryName: ctx.kicadLibraryName,
66346
- kicadFootprintName: tscircuitComponentName,
66347
- isPcm: ctx.isPcm
66348
- });
66349
- }
66350
- const updatedSymbol = metadata ? applyKicadSymbolMetadata(renamedSymbol, metadata) : renamedSymbol;
66351
- addUserSymbol({ ctx, kicadSymbol: updatedSymbol });
66352
- } else {
66353
- addUserSymbol({ ctx, kicadSymbol });
66354
66761
  }
66762
+ const updatedSymbol = metadata ? applyKicadSymbolMetadata(kicadSymbol, metadata) : kicadSymbol;
66763
+ addUserSymbol({ ctx, kicadSymbol: updatedSymbol });
66355
66764
  } else if (hasCustomFootprint && !hasAddedUserSymbol) {
66356
66765
  hasAddedUserSymbol = true;
66357
66766
  const renamedSymbol = renameKicadSymbol({
@@ -66378,10 +66787,11 @@ function addUserSymbol({
66378
66787
  ctx,
66379
66788
  kicadSymbol
66380
66789
  }) {
66381
- const alreadyExists = ctx.userKicadSymbols.some((s) => s.symbolName === kicadSymbol.symbolName);
66382
- if (!alreadyExists) {
66383
- ctx.userKicadSymbols.push(kicadSymbol);
66790
+ const alreadyExistsByName = ctx.userKicadSymbols.some((s) => s.symbolName === kicadSymbol.symbolName);
66791
+ if (alreadyExistsByName) {
66792
+ return;
66384
66793
  }
66794
+ ctx.userKicadSymbols.push(kicadSymbol);
66385
66795
  }
66386
66796
  function addBuiltinSymbol({
66387
66797
  ctx,
@@ -67075,6 +67485,7 @@ var projectConfigSchema = z21.object({
67075
67485
  kicadLibrary: z21.boolean().optional(),
67076
67486
  kicadPcm: z21.boolean().optional(),
67077
67487
  previewImages: z21.boolean().optional(),
67488
+ glbs: z21.boolean().optional(),
67078
67489
  typescriptLibrary: z21.boolean().optional()
67079
67490
  }).optional()
67080
67491
  });