@tscircuit/core 0.0.28 → 0.0.30
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 +27 -8
- package/dist/index.js +150 -62
- package/lib/Project.ts +16 -15
- package/lib/components/base-components/NormalComponent.ts +88 -15
- package/lib/components/base-components/PrimitiveComponent.ts +8 -11
- package/lib/components/base-components/Renderable.ts +2 -1
- package/lib/components/normal-components/Board.ts +2 -2
- package/lib/components/normal-components/Capacitor.ts +1 -1
- package/lib/components/normal-components/Chip.ts +3 -3
- package/lib/components/normal-components/Jumper.ts +3 -3
- package/lib/components/normal-components/Resistor.ts +1 -1
- package/lib/components/primitive-components/Net.ts +2 -2
- package/lib/components/primitive-components/PlatedHole.ts +14 -1
- package/lib/components/primitive-components/Port.ts +4 -4
- package/lib/components/primitive-components/SilkscreenPath.ts +1 -1
- package/lib/components/primitive-components/SmtPad.ts +14 -1
- package/lib/components/primitive-components/Trace.ts +5 -5
- package/lib/components/primitive-components/TraceHint.ts +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -9,9 +9,11 @@ import * as Props from '@tscircuit/props';
|
|
|
9
9
|
import { traceProps, groupProps, boardProps, footprintProps, smtPadProps, resistorProps, ledProps, capacitorProps, traceHintProps, chipProps, jumperProps, silkscreenPathProps, platedHoleProps } from '@tscircuit/props';
|
|
10
10
|
|
|
11
11
|
declare class Circuit {
|
|
12
|
-
|
|
12
|
+
firstChild: PrimitiveComponent | null;
|
|
13
13
|
children: PrimitiveComponent[];
|
|
14
14
|
db: SoupUtilObjects;
|
|
15
|
+
root: Circuit | null;
|
|
16
|
+
isRoot: boolean;
|
|
15
17
|
_hasRenderedAtleastOnce: boolean;
|
|
16
18
|
constructor();
|
|
17
19
|
add(componentOrElm: PrimitiveComponent | ReactElement): void;
|
|
@@ -27,8 +29,8 @@ declare class Circuit {
|
|
|
27
29
|
previewName: string;
|
|
28
30
|
tscircuitApiKey?: string;
|
|
29
31
|
}): Promise<void>;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
computeSchematicGlobalTransform(): Matrix;
|
|
33
|
+
computePcbGlobalTransform(): Matrix;
|
|
32
34
|
selectAll(selector: string): PrimitiveComponent[];
|
|
33
35
|
selectOne(selector: string, opts?: {
|
|
34
36
|
type?: "component" | "port";
|
|
@@ -36,7 +38,7 @@ declare class Circuit {
|
|
|
36
38
|
}
|
|
37
39
|
declare const Project: typeof Circuit;
|
|
38
40
|
|
|
39
|
-
declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "CreateNetsFromProps", "CreateTracesFromProps", "SourceRender", "SourceParentAttachment", "PortDiscovery", "PortMatching", "SourceTraceRender", "SchematicComponentRender", "SchematicLayout", "SchematicPortRender", "SchematicTraceRender", "PcbComponentRender", "PcbPortRender", "PcbPrimitiveRender", "PcbParentAttachment", "PcbLayout", "PcbTraceRender", "PcbRouteNetIslands", "
|
|
41
|
+
declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "InitializePortsFromChildren", "CreateNetsFromProps", "CreateTracesFromProps", "SourceRender", "SourceParentAttachment", "PortDiscovery", "PortMatching", "SourceTraceRender", "SchematicComponentRender", "SchematicLayout", "SchematicPortRender", "SchematicTraceRender", "PcbComponentRender", "PcbPortRender", "PcbPrimitiveRender", "PcbParentAttachment", "PcbLayout", "PcbTraceRender", "PcbRouteNetIslands", "PcbComponentSizeCalculation", "CadModelRender"];
|
|
40
42
|
type RenderPhase = (typeof orderedRenderPhases)[number];
|
|
41
43
|
type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
|
|
42
44
|
type RenderPhaseStates = Record<RenderPhase, {
|
|
@@ -91,7 +93,6 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
|
|
|
91
93
|
children: PrimitiveComponent[];
|
|
92
94
|
childrenPendingRemoval: PrimitiveComponent[];
|
|
93
95
|
get config(): BaseComponentConfig;
|
|
94
|
-
project: Circuit | null;
|
|
95
96
|
props: z.input<ZodProps>;
|
|
96
97
|
_parsedProps: z.infer<ZodProps>;
|
|
97
98
|
componentName: string;
|
|
@@ -103,14 +104,13 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
|
|
|
103
104
|
* subcircuits and their selectors will not interact with each other (even if the
|
|
104
105
|
* components share the same names) unless you explicitly break out some ports
|
|
105
106
|
*/
|
|
106
|
-
get isSubcircuit():
|
|
107
|
+
get isSubcircuit(): any;
|
|
107
108
|
source_group_id: string | null;
|
|
108
109
|
source_component_id: string | null;
|
|
109
110
|
schematic_component_id: string | null;
|
|
110
111
|
pcb_component_id: string | null;
|
|
111
112
|
cad_component_id: string | null;
|
|
112
113
|
constructor(props: z.input<ZodProps>);
|
|
113
|
-
setProject(project: Circuit): void;
|
|
114
114
|
setProps(props: Partial<z.input<ZodProps>>): void;
|
|
115
115
|
/**
|
|
116
116
|
* Computes a transformation matrix from the props of this component for PCB
|
|
@@ -152,6 +152,7 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
|
|
|
152
152
|
x: number;
|
|
153
153
|
y: number;
|
|
154
154
|
};
|
|
155
|
+
get root(): Circuit | null;
|
|
155
156
|
onAddToParent(parent: PrimitiveComponent): void;
|
|
156
157
|
/**
|
|
157
158
|
* Called whenever the props change
|
|
@@ -170,6 +171,10 @@ declare abstract class PrimitiveComponent<ZodProps extends ZodType = any> extend
|
|
|
170
171
|
getNameAndAliases(): string[];
|
|
171
172
|
isMatchingNameOrAlias(name: string): boolean;
|
|
172
173
|
isMatchingAnyOf(aliases: Array<string | number>): boolean;
|
|
174
|
+
getPcbSize(): {
|
|
175
|
+
width: number;
|
|
176
|
+
height: number;
|
|
177
|
+
};
|
|
173
178
|
doesSelectorMatch(selector: string): boolean;
|
|
174
179
|
getSubcircuit(): PrimitiveComponent;
|
|
175
180
|
selectAll(selector: string): PrimitiveComponent[];
|
|
@@ -548,9 +553,15 @@ declare class NormalComponent<ZodProps extends ZodType = any, PortNames extends
|
|
|
548
553
|
*/
|
|
549
554
|
doInitialSchematicComponentRender(): void;
|
|
550
555
|
doInitialPcbComponentRender(): void;
|
|
551
|
-
|
|
556
|
+
/**
|
|
557
|
+
* At this stage, the smtpads/pcb primitives are placed, so we can compute
|
|
558
|
+
* the width/height of the component
|
|
559
|
+
*/
|
|
560
|
+
doInitialPcbComponentSizeCalculation(): void;
|
|
552
561
|
_renderReactSubtree(element: ReactElement): ReactSubtree;
|
|
562
|
+
doInitialInitializePortsFromChildren(): void;
|
|
553
563
|
doInitialReactSubtreesRender(): void;
|
|
564
|
+
_hasExistingPortExactly(port1: Port): boolean;
|
|
554
565
|
add(componentOrElm: PrimitiveComponent | ReactElement): void;
|
|
555
566
|
getPortsFromFootprint(): Port[];
|
|
556
567
|
getPortsFromSchematicSymbol(): Port[];
|
|
@@ -705,6 +716,10 @@ declare class SmtPad extends PrimitiveComponent<typeof smtPadProps> {
|
|
|
705
716
|
height?: string | number | undefined;
|
|
706
717
|
}>]>;
|
|
707
718
|
};
|
|
719
|
+
getPcbSize(): {
|
|
720
|
+
width: number;
|
|
721
|
+
height: number;
|
|
722
|
+
};
|
|
708
723
|
doInitialPortMatching(): void;
|
|
709
724
|
doInitialPcbPrimitiveRender(): void;
|
|
710
725
|
}
|
|
@@ -3329,6 +3344,10 @@ declare class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
|
|
|
3329
3344
|
portHints?: (string | number)[] | undefined;
|
|
3330
3345
|
}>]>;
|
|
3331
3346
|
};
|
|
3347
|
+
getPcbSize(): {
|
|
3348
|
+
width: number;
|
|
3349
|
+
height: number;
|
|
3350
|
+
};
|
|
3332
3351
|
doInitialPortMatching(): void;
|
|
3333
3352
|
doInitialPcbPrimitiveRender(): void;
|
|
3334
3353
|
}
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ import "react";
|
|
|
37
37
|
var orderedRenderPhases = [
|
|
38
38
|
"ReactSubtreesRender",
|
|
39
39
|
// probably going to be removed b/c subtrees should render instantly
|
|
40
|
+
"InitializePortsFromChildren",
|
|
40
41
|
"CreateNetsFromProps",
|
|
41
42
|
"CreateTracesFromProps",
|
|
42
43
|
"SourceRender",
|
|
@@ -56,8 +57,8 @@ var orderedRenderPhases = [
|
|
|
56
57
|
"PcbLayout",
|
|
57
58
|
"PcbTraceRender",
|
|
58
59
|
"PcbRouteNetIslands",
|
|
59
|
-
"
|
|
60
|
-
"
|
|
60
|
+
"PcbComponentSizeCalculation",
|
|
61
|
+
"CadModelRender"
|
|
61
62
|
];
|
|
62
63
|
var globalRenderCounter = 0;
|
|
63
64
|
var Renderable = class {
|
|
@@ -169,7 +170,6 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
169
170
|
zodProps: z.object({}).passthrough()
|
|
170
171
|
};
|
|
171
172
|
}
|
|
172
|
-
project = null;
|
|
173
173
|
props;
|
|
174
174
|
_parsedProps;
|
|
175
175
|
componentName = "";
|
|
@@ -183,7 +183,7 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
183
183
|
*/
|
|
184
184
|
get isSubcircuit() {
|
|
185
185
|
return Boolean(this.props.subcircuit) || // Implied opaque group for top-level group
|
|
186
|
-
this.lowercaseComponentName === "group" && this?.parent?.
|
|
186
|
+
this.lowercaseComponentName === "group" && this?.parent?.isRoot;
|
|
187
187
|
}
|
|
188
188
|
source_group_id = null;
|
|
189
189
|
source_component_id = null;
|
|
@@ -204,12 +204,6 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
204
204
|
this.lowercaseComponentName = this.componentName.toLowerCase();
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
|
-
setProject(project) {
|
|
208
|
-
this.project = project;
|
|
209
|
-
for (const c of this.children) {
|
|
210
|
-
c.setProject(project);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
207
|
setProps(props) {
|
|
214
208
|
const newProps = this.config.zodProps.parse({
|
|
215
209
|
...this.props,
|
|
@@ -315,9 +309,11 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
315
309
|
getGlobalSchematicPosition() {
|
|
316
310
|
return applyToPoint(this.computeSchematicGlobalTransform(), { x: 0, y: 0 });
|
|
317
311
|
}
|
|
312
|
+
get root() {
|
|
313
|
+
return this.parent?.root ?? null;
|
|
314
|
+
}
|
|
318
315
|
onAddToParent(parent) {
|
|
319
316
|
this.parent = parent;
|
|
320
|
-
this.project = parent.project;
|
|
321
317
|
}
|
|
322
318
|
/**
|
|
323
319
|
* Called whenever the props change
|
|
@@ -370,6 +366,9 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
370
366
|
(a) => aliases.map((a2) => a2.toString()).includes(a)
|
|
371
367
|
);
|
|
372
368
|
}
|
|
369
|
+
getPcbSize() {
|
|
370
|
+
throw new Error(`getPcbSize not implemented for ${this.componentName}`);
|
|
371
|
+
}
|
|
373
372
|
doesSelectorMatch(selector) {
|
|
374
373
|
const myTypeNames = [this.componentName, this.lowercaseComponentName];
|
|
375
374
|
const myClassNames = [this._parsedProps.name].filter(Boolean);
|
|
@@ -578,7 +577,7 @@ var Port = class extends PrimitiveComponent {
|
|
|
578
577
|
return connectedTraces;
|
|
579
578
|
}
|
|
580
579
|
doInitialSourceRender() {
|
|
581
|
-
const { db } = this.
|
|
580
|
+
const { db } = this.root;
|
|
582
581
|
const { _parsedProps: props } = this;
|
|
583
582
|
const port_hints = this.getNameAndAliases();
|
|
584
583
|
const source_port = db.source_port.insert({
|
|
@@ -590,7 +589,7 @@ var Port = class extends PrimitiveComponent {
|
|
|
590
589
|
this.source_port_id = source_port.source_port_id;
|
|
591
590
|
}
|
|
592
591
|
doInitialSourceParentAttachment() {
|
|
593
|
-
const { db } = this.
|
|
592
|
+
const { db } = this.root;
|
|
594
593
|
if (!this.parent?.source_component_id) {
|
|
595
594
|
throw new Error(
|
|
596
595
|
`${this.getString()} has no parent source component (parent: ${this.parent?.getString()})`
|
|
@@ -607,7 +606,7 @@ var Port = class extends PrimitiveComponent {
|
|
|
607
606
|
* to exist)
|
|
608
607
|
*/
|
|
609
608
|
doInitialPcbPortRender() {
|
|
610
|
-
const { db } = this.
|
|
609
|
+
const { db } = this.root;
|
|
611
610
|
const { matchedComponents } = this;
|
|
612
611
|
if (!this.parent?.pcb_component_id) {
|
|
613
612
|
throw new Error(
|
|
@@ -637,7 +636,7 @@ var Port = class extends PrimitiveComponent {
|
|
|
637
636
|
}
|
|
638
637
|
}
|
|
639
638
|
doInitialSchematicPortRender() {
|
|
640
|
-
const { db } = this.
|
|
639
|
+
const { db } = this.root;
|
|
641
640
|
const { _parsedProps: props } = this;
|
|
642
641
|
if (!this.parent) return;
|
|
643
642
|
const center = this.getGlobalSchematicPosition();
|
|
@@ -840,6 +839,18 @@ var SmtPad = class extends PrimitiveComponent {
|
|
|
840
839
|
zodProps: smtPadProps
|
|
841
840
|
};
|
|
842
841
|
}
|
|
842
|
+
getPcbSize() {
|
|
843
|
+
const { _parsedProps: props } = this;
|
|
844
|
+
if (props.shape === "circle") {
|
|
845
|
+
return { width: props.radius * 2, height: props.radius * 2 };
|
|
846
|
+
}
|
|
847
|
+
if (props.shape === "rect") {
|
|
848
|
+
return { width: props.width, height: props.height };
|
|
849
|
+
}
|
|
850
|
+
throw new Error(
|
|
851
|
+
`getPcbSize for shape "${props.shape}" not implemented for ${this.componentName}`
|
|
852
|
+
);
|
|
853
|
+
}
|
|
843
854
|
doInitialPortMatching() {
|
|
844
855
|
const parentPorts = (this.parent?.children ?? []).filter(
|
|
845
856
|
(c) => c.componentName === "Port"
|
|
@@ -856,7 +867,7 @@ var SmtPad = class extends PrimitiveComponent {
|
|
|
856
867
|
}
|
|
857
868
|
}
|
|
858
869
|
doInitialPcbPrimitiveRender() {
|
|
859
|
-
const { db } = this.
|
|
870
|
+
const { db } = this.root;
|
|
860
871
|
const { _parsedProps: props } = this;
|
|
861
872
|
if (!props.portHints) return;
|
|
862
873
|
const position = this.getGlobalPcbPosition();
|
|
@@ -904,7 +915,7 @@ var SilkscreenPath = class extends PrimitiveComponent {
|
|
|
904
915
|
};
|
|
905
916
|
}
|
|
906
917
|
doInitialPcbPrimitiveRender() {
|
|
907
|
-
const { db } = this.
|
|
918
|
+
const { db } = this.root;
|
|
908
919
|
const { _parsedProps: props } = this;
|
|
909
920
|
const layer = props.layer ?? "top";
|
|
910
921
|
if (layer !== "top" && layer !== "bottom") {
|
|
@@ -944,6 +955,18 @@ var PlatedHole = class extends PrimitiveComponent {
|
|
|
944
955
|
zodProps: platedHoleProps
|
|
945
956
|
};
|
|
946
957
|
}
|
|
958
|
+
getPcbSize() {
|
|
959
|
+
const { _parsedProps: props } = this;
|
|
960
|
+
if (props.shape === "circle") {
|
|
961
|
+
return { width: props.outerDiameter, height: props.outerDiameter };
|
|
962
|
+
}
|
|
963
|
+
if (props.shape === "oval") {
|
|
964
|
+
return { width: props.outerWidth, height: props.outerHeight };
|
|
965
|
+
}
|
|
966
|
+
throw new Error(
|
|
967
|
+
`getPcbSize for shape "${props.shape}" not implemented for ${this.componentName}`
|
|
968
|
+
);
|
|
969
|
+
}
|
|
947
970
|
doInitialPortMatching() {
|
|
948
971
|
const parentPorts = (this.parent?.children ?? []).filter(
|
|
949
972
|
(c) => c.componentName === "Port"
|
|
@@ -960,7 +983,7 @@ var PlatedHole = class extends PrimitiveComponent {
|
|
|
960
983
|
}
|
|
961
984
|
}
|
|
962
985
|
doInitialPcbPrimitiveRender() {
|
|
963
|
-
const { db } = this.
|
|
986
|
+
const { db } = this.root;
|
|
964
987
|
const { _parsedProps: props } = this;
|
|
965
988
|
if (!props.portHints) return;
|
|
966
989
|
const position = this.getGlobalPcbPosition();
|
|
@@ -1058,7 +1081,7 @@ var Net = class extends PrimitiveComponent {
|
|
|
1058
1081
|
return `net.${this.props.name}`;
|
|
1059
1082
|
}
|
|
1060
1083
|
doInitialSourceComponentRender() {
|
|
1061
|
-
const { db } = this.
|
|
1084
|
+
const { db } = this.root;
|
|
1062
1085
|
const { _parsedProps: props } = this;
|
|
1063
1086
|
const net = db.source_net.insert({
|
|
1064
1087
|
name: props.name,
|
|
@@ -1107,7 +1130,7 @@ var Net = class extends PrimitiveComponent {
|
|
|
1107
1130
|
* such that the nets are fully connected
|
|
1108
1131
|
*/
|
|
1109
1132
|
doInitialPcbRouteNetIslands() {
|
|
1110
|
-
const { db } = this.
|
|
1133
|
+
const { db } = this.root;
|
|
1111
1134
|
const { _parsedProps: props } = this;
|
|
1112
1135
|
const traces = this._getAllDirectlyConnectedTraces().filter(
|
|
1113
1136
|
(trace) => (trace._portsRoutedOnPcb?.length ?? 0) > 0
|
|
@@ -1213,6 +1236,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1213
1236
|
*/
|
|
1214
1237
|
initPorts() {
|
|
1215
1238
|
const { config } = this;
|
|
1239
|
+
const portsToCreate = [];
|
|
1216
1240
|
if (config.schematicSymbolName) {
|
|
1217
1241
|
const sym = symbols3[`${config.schematicSymbolName}_horz`];
|
|
1218
1242
|
if (!sym) return;
|
|
@@ -1220,27 +1244,31 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1220
1244
|
const port = getPortFromHints(symPort.labels);
|
|
1221
1245
|
if (port) {
|
|
1222
1246
|
port.schematicSymbolPortDef = symPort;
|
|
1223
|
-
|
|
1247
|
+
portsToCreate.push(port);
|
|
1224
1248
|
}
|
|
1225
1249
|
}
|
|
1250
|
+
this.addAll(portsToCreate);
|
|
1226
1251
|
return;
|
|
1227
1252
|
}
|
|
1228
1253
|
const portsFromFootprint = this.getPortsFromFootprint();
|
|
1229
|
-
|
|
1254
|
+
portsToCreate.push(...portsFromFootprint);
|
|
1230
1255
|
const pinLabels = this._parsedProps.pinLabels;
|
|
1231
1256
|
if (pinLabels) {
|
|
1232
1257
|
for (let [pinNumber, label] of Object.entries(pinLabels)) {
|
|
1233
1258
|
pinNumber = pinNumber.replace("pin", "");
|
|
1234
|
-
const
|
|
1235
|
-
|
|
1259
|
+
const existingPort = portsToCreate.find(
|
|
1260
|
+
(p) => p._parsedProps.pinNumber === Number(pinNumber)
|
|
1261
|
+
);
|
|
1262
|
+
if (!existingPort) {
|
|
1236
1263
|
throw new Error(
|
|
1237
1264
|
`Could not find port for pin number ${pinNumber} in chip ${this.getString()}`
|
|
1238
1265
|
);
|
|
1239
1266
|
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1267
|
+
existingPort.externallyAddedAliases.push(label);
|
|
1268
|
+
existingPort.props.name = label;
|
|
1242
1269
|
}
|
|
1243
1270
|
}
|
|
1271
|
+
this.addAll(portsToCreate);
|
|
1244
1272
|
}
|
|
1245
1273
|
_addChildrenFromStringFootprint() {
|
|
1246
1274
|
const { footprint } = this.props;
|
|
@@ -1278,7 +1306,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1278
1306
|
doInitialSourceRender() {
|
|
1279
1307
|
const ftype = this.config.sourceFtype;
|
|
1280
1308
|
if (!ftype) return;
|
|
1281
|
-
const { db } = this.
|
|
1309
|
+
const { db } = this.root;
|
|
1282
1310
|
const { _parsedProps: props } = this;
|
|
1283
1311
|
const source_component = db.source_component.insert({
|
|
1284
1312
|
ftype,
|
|
@@ -1295,7 +1323,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1295
1323
|
* You can override this method to do more complicated things.
|
|
1296
1324
|
*/
|
|
1297
1325
|
doInitialSchematicComponentRender() {
|
|
1298
|
-
const { db } = this.
|
|
1326
|
+
const { db } = this.root;
|
|
1299
1327
|
const { schematicSymbolName } = this.config;
|
|
1300
1328
|
if (!schematicSymbolName) return;
|
|
1301
1329
|
const symbol_name = `${this.config.schematicSymbolName}_horz`;
|
|
@@ -1314,11 +1342,11 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1314
1342
|
this.schematic_component_id = schematic_component2.schematic_component_id;
|
|
1315
1343
|
}
|
|
1316
1344
|
doInitialPcbComponentRender() {
|
|
1317
|
-
const { db } = this.
|
|
1345
|
+
const { db } = this.root;
|
|
1318
1346
|
const { _parsedProps: props } = this;
|
|
1319
1347
|
const pcb_component = db.pcb_component.insert({
|
|
1320
|
-
center:
|
|
1321
|
-
// width/height are computed in the
|
|
1348
|
+
center: this.getGlobalPcbPosition(),
|
|
1349
|
+
// width/height are computed in the PcbComponentSizeCalculation phase
|
|
1322
1350
|
width: 0,
|
|
1323
1351
|
height: 0,
|
|
1324
1352
|
layer: props.layer ?? "top",
|
|
@@ -1327,9 +1355,34 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1327
1355
|
});
|
|
1328
1356
|
this.pcb_component_id = pcb_component.pcb_component_id;
|
|
1329
1357
|
}
|
|
1330
|
-
|
|
1331
|
-
|
|
1358
|
+
/**
|
|
1359
|
+
* At this stage, the smtpads/pcb primitives are placed, so we can compute
|
|
1360
|
+
* the width/height of the component
|
|
1361
|
+
*/
|
|
1362
|
+
doInitialPcbComponentSizeCalculation() {
|
|
1363
|
+
if (!this.pcb_component_id) return;
|
|
1364
|
+
const { db } = this.root;
|
|
1332
1365
|
const { _parsedProps: props } = this;
|
|
1366
|
+
let minX = Infinity;
|
|
1367
|
+
let minY = Infinity;
|
|
1368
|
+
let maxX = -Infinity;
|
|
1369
|
+
let maxY = -Infinity;
|
|
1370
|
+
for (const child of this.children) {
|
|
1371
|
+
if (child.isPcbPrimitive) {
|
|
1372
|
+
const { x, y } = child.getGlobalPcbPosition();
|
|
1373
|
+
const { width: width2, height: height2 } = child.getPcbSize();
|
|
1374
|
+
minX = Math.min(minX, x - width2 / 2);
|
|
1375
|
+
minY = Math.min(minY, y - height2 / 2);
|
|
1376
|
+
maxX = Math.max(maxX, x + width2 / 2);
|
|
1377
|
+
maxY = Math.max(maxY, y + height2 / 2);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
const width = maxX - minX;
|
|
1381
|
+
const height = maxY - minY;
|
|
1382
|
+
db.pcb_component.update(this.pcb_component_id, {
|
|
1383
|
+
width,
|
|
1384
|
+
height
|
|
1385
|
+
});
|
|
1333
1386
|
}
|
|
1334
1387
|
_renderReactSubtree(element) {
|
|
1335
1388
|
return {
|
|
@@ -1337,6 +1390,9 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1337
1390
|
component: createInstanceFromReactElement(element)
|
|
1338
1391
|
};
|
|
1339
1392
|
}
|
|
1393
|
+
doInitialInitializePortsFromChildren() {
|
|
1394
|
+
this.initPorts();
|
|
1395
|
+
}
|
|
1340
1396
|
doInitialReactSubtreesRender() {
|
|
1341
1397
|
if (isReactElement2(this.props.footprint)) {
|
|
1342
1398
|
if (this.reactSubtrees.some((rs) => rs.element === this.props.footprint))
|
|
@@ -1346,6 +1402,16 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1346
1402
|
this.add(subtree.component);
|
|
1347
1403
|
}
|
|
1348
1404
|
}
|
|
1405
|
+
_hasExistingPortExactly(port1) {
|
|
1406
|
+
const existingPorts = this.children.filter(
|
|
1407
|
+
(c) => c.componentName === "Port"
|
|
1408
|
+
);
|
|
1409
|
+
return existingPorts.some((port2) => {
|
|
1410
|
+
const aliases1 = port1.getNameAndAliases();
|
|
1411
|
+
const aliases2 = port2.getNameAndAliases();
|
|
1412
|
+
return aliases1.length === aliases2.length && aliases1.every((alias) => aliases2.includes(alias));
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1349
1415
|
add(componentOrElm) {
|
|
1350
1416
|
let component;
|
|
1351
1417
|
if (isReactElement2(componentOrElm)) {
|
|
@@ -1355,6 +1421,20 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1355
1421
|
} else {
|
|
1356
1422
|
component = componentOrElm;
|
|
1357
1423
|
}
|
|
1424
|
+
if (component.componentName === "Port") {
|
|
1425
|
+
if (this._hasExistingPortExactly(component)) return;
|
|
1426
|
+
const existingPorts = this.children.filter(
|
|
1427
|
+
(c) => c.componentName === "Port"
|
|
1428
|
+
);
|
|
1429
|
+
const conflictingPort = existingPorts.find(
|
|
1430
|
+
(p) => p.isMatchingAnyOf(component.getNameAndAliases())
|
|
1431
|
+
);
|
|
1432
|
+
if (conflictingPort) {
|
|
1433
|
+
throw new Error(
|
|
1434
|
+
`Conflicting ports added. Port 1: ${conflictingPort}, Port 2: ${component}`
|
|
1435
|
+
);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1358
1438
|
super.add(component);
|
|
1359
1439
|
}
|
|
1360
1440
|
getPortsFromFootprint() {
|
|
@@ -1382,6 +1462,11 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1382
1462
|
if (!newPort) continue;
|
|
1383
1463
|
newPorts2.push(newPort);
|
|
1384
1464
|
}
|
|
1465
|
+
if (newPorts2.length === 0) {
|
|
1466
|
+
throw new Error(
|
|
1467
|
+
`No ports found in chip ${this} (define a schPortArrangement, a footprint or add portHints to elements of the footprint)`
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1385
1470
|
return newPorts2;
|
|
1386
1471
|
}
|
|
1387
1472
|
const newPorts = [];
|
|
@@ -1474,7 +1559,7 @@ var Board = class extends Group {
|
|
|
1474
1559
|
};
|
|
1475
1560
|
}
|
|
1476
1561
|
doInitialPcbComponentRender() {
|
|
1477
|
-
const { db } = this.
|
|
1562
|
+
const { db } = this.root;
|
|
1478
1563
|
const { _parsedProps: props } = this;
|
|
1479
1564
|
if (!props.width || !props.height) {
|
|
1480
1565
|
throw new Error("Board width and height or an outline are required");
|
|
@@ -1487,7 +1572,7 @@ var Board = class extends Group {
|
|
|
1487
1572
|
this.pcb_board_id = pcb_board.pcb_board_id;
|
|
1488
1573
|
}
|
|
1489
1574
|
removePcbComponentRender() {
|
|
1490
|
-
const { db } = this.
|
|
1575
|
+
const { db } = this.root;
|
|
1491
1576
|
if (!this.pcb_board_id) return;
|
|
1492
1577
|
db.pcb_board.delete(this.pcb_board_id);
|
|
1493
1578
|
this.pcb_board_id = null;
|
|
@@ -1700,7 +1785,7 @@ var Trace = class extends PrimitiveComponent {
|
|
|
1700
1785
|
);
|
|
1701
1786
|
}
|
|
1702
1787
|
_findConnectedPorts() {
|
|
1703
|
-
const { db } = this.
|
|
1788
|
+
const { db } = this.root;
|
|
1704
1789
|
const { _parsedProps: props, parent } = this;
|
|
1705
1790
|
if (!parent) throw new Error("Trace has no parent");
|
|
1706
1791
|
const portSelectors = this.getTracePortPathSelectors();
|
|
@@ -1784,7 +1869,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1784
1869
|
createNetsFromProps(this, this.getTracePathNetSelectors());
|
|
1785
1870
|
}
|
|
1786
1871
|
doInitialSourceTraceRender() {
|
|
1787
|
-
const { db } = this.
|
|
1872
|
+
const { db } = this.root;
|
|
1788
1873
|
const { _parsedProps: props, parent } = this;
|
|
1789
1874
|
if (!parent) {
|
|
1790
1875
|
this.renderError("Trace has no parent");
|
|
@@ -1800,7 +1885,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1800
1885
|
this.source_trace_id = trace.source_trace_id;
|
|
1801
1886
|
}
|
|
1802
1887
|
doInitialPcbTraceRender() {
|
|
1803
|
-
const { db } = this.
|
|
1888
|
+
const { db } = this.root;
|
|
1804
1889
|
const { _parsedProps: props, parent } = this;
|
|
1805
1890
|
if (!parent) throw new Error("Trace has no parent");
|
|
1806
1891
|
const { allPortsFound, ports } = this._findConnectedPorts();
|
|
@@ -1881,7 +1966,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1881
1966
|
`Could not find a common layer (using hints) for trace ${this.getString()}`
|
|
1882
1967
|
);
|
|
1883
1968
|
}
|
|
1884
|
-
const obstacles = getObstaclesFromSoup(this.
|
|
1969
|
+
const obstacles = getObstaclesFromSoup(this.root.db.toArray());
|
|
1885
1970
|
markObstaclesAsConnected(
|
|
1886
1971
|
obstacles,
|
|
1887
1972
|
orderedRouteObjectives,
|
|
@@ -1947,7 +2032,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1947
2032
|
this.pcb_trace_id = pcb_trace.pcb_trace_id;
|
|
1948
2033
|
}
|
|
1949
2034
|
doInitialSchematicTraceRender() {
|
|
1950
|
-
const { db } = this.
|
|
2035
|
+
const { db } = this.root;
|
|
1951
2036
|
const { _parsedProps: props, parent } = this;
|
|
1952
2037
|
if (!parent) throw new Error("Trace has no parent");
|
|
1953
2038
|
const { allPortsFound, portsWithSelectors: ports } = this._findConnectedPorts();
|
|
@@ -2041,7 +2126,7 @@ var Resistor = class extends NormalComponent {
|
|
|
2041
2126
|
}
|
|
2042
2127
|
}
|
|
2043
2128
|
doInitialSourceRender() {
|
|
2044
|
-
const { db } = this.
|
|
2129
|
+
const { db } = this.root;
|
|
2045
2130
|
const { _parsedProps: props } = this;
|
|
2046
2131
|
const source_component = db.source_component.insert({
|
|
2047
2132
|
ftype: "simple_resistor",
|
|
@@ -2119,7 +2204,7 @@ var Capacitor = class extends NormalComponent {
|
|
|
2119
2204
|
}
|
|
2120
2205
|
}
|
|
2121
2206
|
doInitialSourceRender() {
|
|
2122
|
-
const { db } = this.
|
|
2207
|
+
const { db } = this.root;
|
|
2123
2208
|
const { _parsedProps: props } = this;
|
|
2124
2209
|
const source_component = db.source_component.insert({
|
|
2125
2210
|
ftype: "simple_capacitor",
|
|
@@ -2139,7 +2224,7 @@ import { applyToPoint as applyToPoint4 } from "transformation-matrix";
|
|
|
2139
2224
|
var TraceHint = class extends PrimitiveComponent {
|
|
2140
2225
|
matchedPort = null;
|
|
2141
2226
|
doInitialPortMatching() {
|
|
2142
|
-
const { db } = this.
|
|
2227
|
+
const { db } = this.root;
|
|
2143
2228
|
const { _parsedProps: props, parent } = this;
|
|
2144
2229
|
if (!parent) return;
|
|
2145
2230
|
if (parent.componentName === "Trace") {
|
|
@@ -2470,7 +2555,7 @@ var Chip = class extends NormalComponent {
|
|
|
2470
2555
|
};
|
|
2471
2556
|
}
|
|
2472
2557
|
doInitialSourceRender() {
|
|
2473
|
-
const { db } = this.
|
|
2558
|
+
const { db } = this.root;
|
|
2474
2559
|
const { _parsedProps: props } = this;
|
|
2475
2560
|
const source_component = db.source_component.insert({
|
|
2476
2561
|
ftype: "simple_chip",
|
|
@@ -2481,7 +2566,7 @@ var Chip = class extends NormalComponent {
|
|
|
2481
2566
|
this.source_component_id = source_component.source_component_id;
|
|
2482
2567
|
}
|
|
2483
2568
|
doInitialSchematicComponentRender() {
|
|
2484
|
-
const { db } = this.
|
|
2569
|
+
const { db } = this.root;
|
|
2485
2570
|
const { _parsedProps: props } = this;
|
|
2486
2571
|
const ports = this.children.filter((child) => child instanceof Port);
|
|
2487
2572
|
const pinSpacing = props.schPinSpacing ?? 0.2;
|
|
@@ -2513,7 +2598,7 @@ var Chip = class extends NormalComponent {
|
|
|
2513
2598
|
this.schematic_component_id = schematic_component2.schematic_component_id;
|
|
2514
2599
|
}
|
|
2515
2600
|
doInitialPcbComponentRender() {
|
|
2516
|
-
const { db } = this.
|
|
2601
|
+
const { db } = this.root;
|
|
2517
2602
|
const { _parsedProps: props } = this;
|
|
2518
2603
|
const pcb_component = db.pcb_component.insert({
|
|
2519
2604
|
center: { x: props.pcbX ?? 0, y: props.pcbY ?? 0 },
|
|
@@ -2539,7 +2624,7 @@ var Jumper = class extends NormalComponent {
|
|
|
2539
2624
|
};
|
|
2540
2625
|
}
|
|
2541
2626
|
doInitialSourceRender() {
|
|
2542
|
-
const { db } = this.
|
|
2627
|
+
const { db } = this.root;
|
|
2543
2628
|
const { _parsedProps: props } = this;
|
|
2544
2629
|
const source_component = db.source_component.insert({
|
|
2545
2630
|
ftype: "simple_chip",
|
|
@@ -2551,7 +2636,7 @@ var Jumper = class extends NormalComponent {
|
|
|
2551
2636
|
this.source_component_id = source_component.source_component_id;
|
|
2552
2637
|
}
|
|
2553
2638
|
doInitialSchematicComponentRender() {
|
|
2554
|
-
const { db } = this.
|
|
2639
|
+
const { db } = this.root;
|
|
2555
2640
|
const { _parsedProps: props } = this;
|
|
2556
2641
|
const ports = this.children.filter((child) => child instanceof Port);
|
|
2557
2642
|
const pinSpacing = props.schPinSpacing ?? 0.2;
|
|
@@ -2586,7 +2671,7 @@ var Jumper = class extends NormalComponent {
|
|
|
2586
2671
|
this.schematic_component_id = schematic_component2.schematic_component_id;
|
|
2587
2672
|
}
|
|
2588
2673
|
doInitialPcbComponentRender() {
|
|
2589
|
-
const { db } = this.
|
|
2674
|
+
const { db } = this.root;
|
|
2590
2675
|
const { _parsedProps: props } = this;
|
|
2591
2676
|
const pcb_component = db.pcb_component.insert({
|
|
2592
2677
|
center: { x: props.pcbX ?? 0, y: props.pcbY ?? 0 },
|
|
@@ -2607,13 +2692,16 @@ import { su } from "@tscircuit/soup-util";
|
|
|
2607
2692
|
import { isValidElement as isValidElement2 } from "react";
|
|
2608
2693
|
import { identity as identity5 } from "transformation-matrix";
|
|
2609
2694
|
var Circuit = class {
|
|
2610
|
-
|
|
2695
|
+
firstChild = null;
|
|
2611
2696
|
children;
|
|
2612
2697
|
db;
|
|
2698
|
+
root = null;
|
|
2699
|
+
isRoot = true;
|
|
2613
2700
|
_hasRenderedAtleastOnce = false;
|
|
2614
2701
|
constructor() {
|
|
2615
2702
|
this.children = [];
|
|
2616
2703
|
this.db = su([]);
|
|
2704
|
+
this.root = this;
|
|
2617
2705
|
}
|
|
2618
2706
|
add(componentOrElm) {
|
|
2619
2707
|
let component;
|
|
@@ -2625,9 +2713,9 @@ var Circuit = class {
|
|
|
2625
2713
|
this.children.push(component);
|
|
2626
2714
|
}
|
|
2627
2715
|
_guessRootComponent() {
|
|
2628
|
-
if (this.
|
|
2716
|
+
if (this.firstChild) return;
|
|
2629
2717
|
if (this.children.length === 1) {
|
|
2630
|
-
this.
|
|
2718
|
+
this.firstChild = this.children[0];
|
|
2631
2719
|
return;
|
|
2632
2720
|
}
|
|
2633
2721
|
if (this.children.length === 0) {
|
|
@@ -2638,7 +2726,7 @@ var Circuit = class {
|
|
|
2638
2726
|
if (this.children.length > 0) {
|
|
2639
2727
|
const board = this.children.find((c) => c.componentName === "Board") ?? null;
|
|
2640
2728
|
if (board) {
|
|
2641
|
-
this.
|
|
2729
|
+
this.firstChild = board;
|
|
2642
2730
|
return;
|
|
2643
2731
|
}
|
|
2644
2732
|
}
|
|
@@ -2647,13 +2735,13 @@ var Circuit = class {
|
|
|
2647
2735
|
);
|
|
2648
2736
|
}
|
|
2649
2737
|
render() {
|
|
2650
|
-
if (!this.
|
|
2738
|
+
if (!this.firstChild) {
|
|
2651
2739
|
this._guessRootComponent();
|
|
2652
2740
|
}
|
|
2653
|
-
const {
|
|
2654
|
-
if (!
|
|
2655
|
-
|
|
2656
|
-
|
|
2741
|
+
const { firstChild, db } = this;
|
|
2742
|
+
if (!firstChild) throw new Error("Project has no root component");
|
|
2743
|
+
firstChild.parent = this;
|
|
2744
|
+
firstChild.runRenderCycle();
|
|
2657
2745
|
this._hasRenderedAtleastOnce = true;
|
|
2658
2746
|
}
|
|
2659
2747
|
getSoup() {
|
|
@@ -2677,17 +2765,17 @@ var Circuit = class {
|
|
|
2677
2765
|
const previewOpts = typeof previewNameOrOpts === "object" ? previewNameOrOpts : { previewName: previewNameOrOpts };
|
|
2678
2766
|
throw new Error("project.preview is not yet implemented");
|
|
2679
2767
|
}
|
|
2680
|
-
|
|
2768
|
+
computeSchematicGlobalTransform() {
|
|
2681
2769
|
return identity5();
|
|
2682
2770
|
}
|
|
2683
|
-
|
|
2771
|
+
computePcbGlobalTransform() {
|
|
2684
2772
|
return identity5();
|
|
2685
2773
|
}
|
|
2686
2774
|
selectAll(selector) {
|
|
2687
|
-
return this.
|
|
2775
|
+
return this.firstChild?.selectAll(selector) ?? [];
|
|
2688
2776
|
}
|
|
2689
2777
|
selectOne(selector, opts) {
|
|
2690
|
-
return this.
|
|
2778
|
+
return this.firstChild?.selectOne(selector, opts) ?? null;
|
|
2691
2779
|
}
|
|
2692
2780
|
};
|
|
2693
2781
|
var Project = Circuit;
|
package/lib/Project.ts
CHANGED
|
@@ -7,15 +7,18 @@ import { createInstanceFromReactElement } from "./fiber/create-instance-from-rea
|
|
|
7
7
|
import { identity, type Matrix } from "transformation-matrix"
|
|
8
8
|
|
|
9
9
|
export class Circuit {
|
|
10
|
-
|
|
10
|
+
firstChild: PrimitiveComponent | null = null
|
|
11
11
|
children: PrimitiveComponent[]
|
|
12
12
|
db: SoupUtilObjects
|
|
13
|
+
root: Circuit | null = null
|
|
14
|
+
isRoot = true
|
|
13
15
|
|
|
14
16
|
_hasRenderedAtleastOnce = false
|
|
15
17
|
|
|
16
18
|
constructor() {
|
|
17
19
|
this.children = []
|
|
18
20
|
this.db = su([])
|
|
21
|
+
this.root = this
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
add(componentOrElm: PrimitiveComponent | ReactElement) {
|
|
@@ -30,9 +33,9 @@ export class Circuit {
|
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
_guessRootComponent() {
|
|
33
|
-
if (this.
|
|
36
|
+
if (this.firstChild) return
|
|
34
37
|
if (this.children.length === 1) {
|
|
35
|
-
this.
|
|
38
|
+
this.firstChild = this.children[0]
|
|
36
39
|
return
|
|
37
40
|
}
|
|
38
41
|
if (this.children.length === 0) {
|
|
@@ -46,7 +49,7 @@ export class Circuit {
|
|
|
46
49
|
this.children.find((c) => c.componentName === "Board") ?? null
|
|
47
50
|
|
|
48
51
|
if (board) {
|
|
49
|
-
this.
|
|
52
|
+
this.firstChild = board
|
|
50
53
|
return
|
|
51
54
|
}
|
|
52
55
|
}
|
|
@@ -56,16 +59,14 @@ export class Circuit {
|
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
render() {
|
|
59
|
-
if (!this.
|
|
62
|
+
if (!this.firstChild) {
|
|
60
63
|
this._guessRootComponent()
|
|
61
64
|
}
|
|
62
|
-
const {
|
|
65
|
+
const { firstChild, db } = this
|
|
63
66
|
|
|
64
|
-
if (!
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
rootComponent.runRenderCycle()
|
|
67
|
+
if (!firstChild) throw new Error("Project has no root component")
|
|
68
|
+
firstChild.parent = this as any
|
|
69
|
+
firstChild.runRenderCycle()
|
|
69
70
|
this._hasRenderedAtleastOnce = true
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -103,23 +104,23 @@ export class Circuit {
|
|
|
103
104
|
throw new Error("project.preview is not yet implemented")
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
|
|
107
|
+
computeSchematicGlobalTransform(): Matrix {
|
|
107
108
|
return identity()
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
|
|
111
|
+
computePcbGlobalTransform(): Matrix {
|
|
111
112
|
return identity()
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
selectAll(selector: string): PrimitiveComponent[] {
|
|
115
|
-
return this.
|
|
116
|
+
return this.firstChild?.selectAll(selector) ?? []
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
selectOne(
|
|
119
120
|
selector: string,
|
|
120
121
|
opts?: { type?: "component" | "port" },
|
|
121
122
|
): PrimitiveComponent | null {
|
|
122
|
-
return this.
|
|
123
|
+
return this.firstChild?.selectOne(selector, opts) ?? null
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
126
|
|
|
@@ -68,6 +68,7 @@ export class NormalComponent<
|
|
|
68
68
|
*/
|
|
69
69
|
initPorts() {
|
|
70
70
|
const { config } = this
|
|
71
|
+
const portsToCreate: Port[] = []
|
|
71
72
|
if (config.schematicSymbolName) {
|
|
72
73
|
const sym = symbols[
|
|
73
74
|
`${config.schematicSymbolName}_horz` as keyof typeof symbols
|
|
@@ -79,32 +80,36 @@ export class NormalComponent<
|
|
|
79
80
|
|
|
80
81
|
if (port) {
|
|
81
82
|
port.schematicSymbolPortDef = symPort
|
|
82
|
-
|
|
83
|
+
portsToCreate.push(port)
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
this.addAll(portsToCreate)
|
|
86
88
|
return
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
const portsFromFootprint = this.getPortsFromFootprint()
|
|
90
|
-
|
|
91
|
-
this.addAll(portsFromFootprint)
|
|
92
|
+
portsToCreate.push(...portsFromFootprint)
|
|
92
93
|
|
|
93
94
|
const pinLabels: Record<string, string> | undefined =
|
|
94
95
|
this._parsedProps.pinLabels
|
|
95
96
|
if (pinLabels) {
|
|
96
97
|
for (let [pinNumber, label] of Object.entries(pinLabels)) {
|
|
97
98
|
pinNumber = pinNumber.replace("pin", "")
|
|
98
|
-
const
|
|
99
|
-
|
|
99
|
+
const existingPort = portsToCreate.find(
|
|
100
|
+
(p) => p._parsedProps.pinNumber === Number(pinNumber),
|
|
101
|
+
)
|
|
102
|
+
if (!existingPort) {
|
|
100
103
|
throw new Error(
|
|
101
104
|
`Could not find port for pin number ${pinNumber} in chip ${this.getString()}`,
|
|
102
105
|
)
|
|
103
106
|
}
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
existingPort.externallyAddedAliases.push(label)
|
|
108
|
+
existingPort.props.name = label
|
|
106
109
|
}
|
|
107
110
|
}
|
|
111
|
+
|
|
112
|
+
this.addAll(portsToCreate)
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
_addChildrenFromStringFootprint() {
|
|
@@ -148,7 +153,7 @@ export class NormalComponent<
|
|
|
148
153
|
doInitialSourceRender() {
|
|
149
154
|
const ftype = this.config.sourceFtype
|
|
150
155
|
if (!ftype) return
|
|
151
|
-
const { db } = this.
|
|
156
|
+
const { db } = this.root!
|
|
152
157
|
const { _parsedProps: props } = this
|
|
153
158
|
const source_component = db.source_component.insert({
|
|
154
159
|
ftype,
|
|
@@ -166,7 +171,7 @@ export class NormalComponent<
|
|
|
166
171
|
* You can override this method to do more complicated things.
|
|
167
172
|
*/
|
|
168
173
|
doInitialSchematicComponentRender() {
|
|
169
|
-
const { db } = this.
|
|
174
|
+
const { db } = this.root!
|
|
170
175
|
const { schematicSymbolName } = this.config
|
|
171
176
|
if (!schematicSymbolName) return
|
|
172
177
|
// TODO switch between horizontal and vertical based on schRotation
|
|
@@ -191,11 +196,11 @@ export class NormalComponent<
|
|
|
191
196
|
}
|
|
192
197
|
|
|
193
198
|
doInitialPcbComponentRender() {
|
|
194
|
-
const { db } = this.
|
|
199
|
+
const { db } = this.root!
|
|
195
200
|
const { _parsedProps: props } = this
|
|
196
201
|
const pcb_component = db.pcb_component.insert({
|
|
197
|
-
center:
|
|
198
|
-
// width/height are computed in the
|
|
202
|
+
center: this.getGlobalPcbPosition(),
|
|
203
|
+
// width/height are computed in the PcbComponentSizeCalculation phase
|
|
199
204
|
width: 0,
|
|
200
205
|
height: 0,
|
|
201
206
|
layer: props.layer ?? "top",
|
|
@@ -205,11 +210,38 @@ export class NormalComponent<
|
|
|
205
210
|
this.pcb_component_id = pcb_component.pcb_component_id
|
|
206
211
|
}
|
|
207
212
|
|
|
208
|
-
|
|
209
|
-
|
|
213
|
+
/**
|
|
214
|
+
* At this stage, the smtpads/pcb primitives are placed, so we can compute
|
|
215
|
+
* the width/height of the component
|
|
216
|
+
*/
|
|
217
|
+
doInitialPcbComponentSizeCalculation(): void {
|
|
218
|
+
if (!this.pcb_component_id) return
|
|
219
|
+
const { db } = this.root!
|
|
210
220
|
const { _parsedProps: props } = this
|
|
211
221
|
|
|
212
|
-
|
|
222
|
+
let minX = Infinity
|
|
223
|
+
let minY = Infinity
|
|
224
|
+
let maxX = -Infinity
|
|
225
|
+
let maxY = -Infinity
|
|
226
|
+
|
|
227
|
+
for (const child of this.children) {
|
|
228
|
+
if (child.isPcbPrimitive) {
|
|
229
|
+
const { x, y } = child.getGlobalPcbPosition()
|
|
230
|
+
const { width, height } = child.getPcbSize()
|
|
231
|
+
minX = Math.min(minX, x - width / 2)
|
|
232
|
+
minY = Math.min(minY, y - height / 2)
|
|
233
|
+
maxX = Math.max(maxX, x + width / 2)
|
|
234
|
+
maxY = Math.max(maxY, y + height / 2)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const width = maxX - minX
|
|
239
|
+
const height = maxY - minY
|
|
240
|
+
|
|
241
|
+
db.pcb_component.update(this.pcb_component_id!, {
|
|
242
|
+
width,
|
|
243
|
+
height,
|
|
244
|
+
})
|
|
213
245
|
}
|
|
214
246
|
|
|
215
247
|
_renderReactSubtree(element: ReactElement): ReactSubtree {
|
|
@@ -219,6 +251,10 @@ export class NormalComponent<
|
|
|
219
251
|
}
|
|
220
252
|
}
|
|
221
253
|
|
|
254
|
+
doInitialInitializePortsFromChildren(): void {
|
|
255
|
+
this.initPorts()
|
|
256
|
+
}
|
|
257
|
+
|
|
222
258
|
doInitialReactSubtreesRender(): void {
|
|
223
259
|
if (isReactElement(this.props.footprint)) {
|
|
224
260
|
if (this.reactSubtrees.some((rs) => rs.element === this.props.footprint))
|
|
@@ -229,6 +265,20 @@ export class NormalComponent<
|
|
|
229
265
|
}
|
|
230
266
|
}
|
|
231
267
|
|
|
268
|
+
_hasExistingPortExactly(port1: Port): boolean {
|
|
269
|
+
const existingPorts = this.children.filter(
|
|
270
|
+
(c) => c.componentName === "Port",
|
|
271
|
+
) as Port[]
|
|
272
|
+
return existingPorts.some((port2) => {
|
|
273
|
+
const aliases1 = port1.getNameAndAliases()
|
|
274
|
+
const aliases2 = port2.getNameAndAliases()
|
|
275
|
+
return (
|
|
276
|
+
aliases1.length === aliases2.length &&
|
|
277
|
+
aliases1.every((alias) => aliases2.includes(alias))
|
|
278
|
+
)
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
|
|
232
282
|
add(componentOrElm: PrimitiveComponent | ReactElement) {
|
|
233
283
|
let component: PrimitiveComponent
|
|
234
284
|
if (isReactElement(componentOrElm)) {
|
|
@@ -239,6 +289,23 @@ export class NormalComponent<
|
|
|
239
289
|
component = componentOrElm as PrimitiveComponent
|
|
240
290
|
}
|
|
241
291
|
|
|
292
|
+
if (component.componentName === "Port") {
|
|
293
|
+
if (this._hasExistingPortExactly(component as Port)) return
|
|
294
|
+
// Check if this port is already contained in the children, skip if it's
|
|
295
|
+
// already defined
|
|
296
|
+
const existingPorts = this.children.filter(
|
|
297
|
+
(c) => c.componentName === "Port",
|
|
298
|
+
) as Port[]
|
|
299
|
+
const conflictingPort = existingPorts.find((p) =>
|
|
300
|
+
p.isMatchingAnyOf(component.getNameAndAliases()),
|
|
301
|
+
)
|
|
302
|
+
if (conflictingPort) {
|
|
303
|
+
throw new Error(
|
|
304
|
+
`Conflicting ports added. Port 1: ${conflictingPort}, Port 2: ${component}`,
|
|
305
|
+
)
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
242
309
|
super.add(component)
|
|
243
310
|
}
|
|
244
311
|
|
|
@@ -277,6 +344,12 @@ export class NormalComponent<
|
|
|
277
344
|
newPorts.push(newPort)
|
|
278
345
|
}
|
|
279
346
|
|
|
347
|
+
if (newPorts.length === 0) {
|
|
348
|
+
throw new Error(
|
|
349
|
+
`No ports found in chip ${this} (define a schPortArrangement, a footprint or add portHints to elements of the footprint)`,
|
|
350
|
+
)
|
|
351
|
+
}
|
|
352
|
+
|
|
280
353
|
return newPorts
|
|
281
354
|
}
|
|
282
355
|
|
|
@@ -41,7 +41,6 @@ export abstract class PrimitiveComponent<
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
project: Circuit | null = null
|
|
45
44
|
props: z.input<ZodProps>
|
|
46
45
|
_parsedProps: z.infer<ZodProps>
|
|
47
46
|
|
|
@@ -60,8 +59,7 @@ export abstract class PrimitiveComponent<
|
|
|
60
59
|
return (
|
|
61
60
|
Boolean(this.props.subcircuit) ||
|
|
62
61
|
// Implied opaque group for top-level group
|
|
63
|
-
(this.lowercaseComponentName === "group" &&
|
|
64
|
-
this?.parent?.props?.name === "$root")
|
|
62
|
+
(this.lowercaseComponentName === "group" && (this?.parent as any)?.isRoot)
|
|
65
63
|
)
|
|
66
64
|
}
|
|
67
65
|
|
|
@@ -86,13 +84,6 @@ export abstract class PrimitiveComponent<
|
|
|
86
84
|
}
|
|
87
85
|
}
|
|
88
86
|
|
|
89
|
-
setProject(project: Circuit) {
|
|
90
|
-
this.project = project
|
|
91
|
-
for (const c of this.children) {
|
|
92
|
-
c.setProject(project)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
87
|
setProps(props: Partial<z.input<ZodProps>>) {
|
|
97
88
|
const newProps = this.config.zodProps.parse({
|
|
98
89
|
...this.props,
|
|
@@ -227,9 +218,12 @@ export abstract class PrimitiveComponent<
|
|
|
227
218
|
return applyToPoint(this.computeSchematicGlobalTransform(), { x: 0, y: 0 })
|
|
228
219
|
}
|
|
229
220
|
|
|
221
|
+
get root(): Circuit | null {
|
|
222
|
+
return this.parent?.root ?? null
|
|
223
|
+
}
|
|
224
|
+
|
|
230
225
|
onAddToParent(parent: PrimitiveComponent) {
|
|
231
226
|
this.parent = parent
|
|
232
|
-
this.project = parent.project
|
|
233
227
|
}
|
|
234
228
|
|
|
235
229
|
/**
|
|
@@ -298,6 +292,9 @@ export abstract class PrimitiveComponent<
|
|
|
298
292
|
aliases.map((a) => a.toString()).includes(a),
|
|
299
293
|
)
|
|
300
294
|
}
|
|
295
|
+
getPcbSize(): { width: number; height: number } {
|
|
296
|
+
throw new Error(`getPcbSize not implemented for ${this.componentName}`)
|
|
297
|
+
}
|
|
301
298
|
|
|
302
299
|
doesSelectorMatch(selector: string): boolean {
|
|
303
300
|
const myTypeNames = [this.componentName, this.lowercaseComponentName]
|
|
@@ -3,6 +3,7 @@ import { Component, createElement, type ReactElement } from "react"
|
|
|
3
3
|
|
|
4
4
|
export const orderedRenderPhases = [
|
|
5
5
|
"ReactSubtreesRender", // probably going to be removed b/c subtrees should render instantly
|
|
6
|
+
"InitializePortsFromChildren",
|
|
6
7
|
"CreateNetsFromProps",
|
|
7
8
|
"CreateTracesFromProps",
|
|
8
9
|
"SourceRender",
|
|
@@ -21,8 +22,8 @@ export const orderedRenderPhases = [
|
|
|
21
22
|
"PcbLayout",
|
|
22
23
|
"PcbTraceRender",
|
|
23
24
|
"PcbRouteNetIslands",
|
|
25
|
+
"PcbComponentSizeCalculation",
|
|
24
26
|
"CadModelRender",
|
|
25
|
-
"PcbAnalysis",
|
|
26
27
|
] as const
|
|
27
28
|
|
|
28
29
|
export type RenderPhase = (typeof orderedRenderPhases)[number]
|
|
@@ -18,7 +18,7 @@ export class Board extends Group<typeof boardProps> {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
doInitialPcbComponentRender(): void {
|
|
21
|
-
const { db } = this.
|
|
21
|
+
const { db } = this.root!
|
|
22
22
|
const { _parsedProps: props } = this
|
|
23
23
|
|
|
24
24
|
if (!props.width || !props.height) {
|
|
@@ -36,7 +36,7 @@ export class Board extends Group<typeof boardProps> {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
removePcbComponentRender(): void {
|
|
39
|
-
const { db } = this.
|
|
39
|
+
const { db } = this.root!
|
|
40
40
|
if (!this.pcb_board_id) return
|
|
41
41
|
db.pcb_board.delete(this.pcb_board_id!)
|
|
42
42
|
this.pcb_board_id = null
|
|
@@ -54,7 +54,7 @@ export class Capacitor extends NormalComponent<
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
doInitialSourceRender() {
|
|
57
|
-
const { db } = this.
|
|
57
|
+
const { db } = this.root!
|
|
58
58
|
const { _parsedProps: props } = this
|
|
59
59
|
const source_component = db.source_component.insert({
|
|
60
60
|
ftype: "simple_capacitor",
|
|
@@ -22,7 +22,7 @@ export class Chip<PinLabels extends string = never> extends NormalComponent<
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
doInitialSourceRender(): void {
|
|
25
|
-
const { db } = this.
|
|
25
|
+
const { db } = this.root!
|
|
26
26
|
const { _parsedProps: props } = this
|
|
27
27
|
|
|
28
28
|
const source_component = db.source_component.insert({
|
|
@@ -36,7 +36,7 @@ export class Chip<PinLabels extends string = never> extends NormalComponent<
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
doInitialSchematicComponentRender() {
|
|
39
|
-
const { db } = this.
|
|
39
|
+
const { db } = this.root!
|
|
40
40
|
const { _parsedProps: props } = this
|
|
41
41
|
|
|
42
42
|
const ports = this.children.filter((child) => child instanceof Port)
|
|
@@ -81,7 +81,7 @@ export class Chip<PinLabels extends string = never> extends NormalComponent<
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
doInitialPcbComponentRender() {
|
|
84
|
-
const { db } = this.
|
|
84
|
+
const { db } = this.root!
|
|
85
85
|
const { _parsedProps: props } = this
|
|
86
86
|
|
|
87
87
|
const pcb_component = db.pcb_component.insert({
|
|
@@ -22,7 +22,7 @@ export class Jumper<PinLabels extends string = never> extends NormalComponent<
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
doInitialSourceRender(): void {
|
|
25
|
-
const { db } = this.
|
|
25
|
+
const { db } = this.root!
|
|
26
26
|
const { _parsedProps: props } = this
|
|
27
27
|
|
|
28
28
|
const source_component = db.source_component.insert({
|
|
@@ -36,7 +36,7 @@ export class Jumper<PinLabels extends string = never> extends NormalComponent<
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
doInitialSchematicComponentRender() {
|
|
39
|
-
const { db } = this.
|
|
39
|
+
const { db } = this.root!
|
|
40
40
|
const { _parsedProps: props } = this
|
|
41
41
|
|
|
42
42
|
const ports = this.children.filter((child) => child instanceof Port)
|
|
@@ -84,7 +84,7 @@ export class Jumper<PinLabels extends string = never> extends NormalComponent<
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
doInitialPcbComponentRender() {
|
|
87
|
-
const { db } = this.
|
|
87
|
+
const { db } = this.root!
|
|
88
88
|
const { _parsedProps: props } = this
|
|
89
89
|
|
|
90
90
|
const pcb_component = db.pcb_component.insert({
|
|
@@ -43,7 +43,7 @@ export class Resistor extends NormalComponent<
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
doInitialSourceRender() {
|
|
46
|
-
const { db } = this.
|
|
46
|
+
const { db } = this.root!
|
|
47
47
|
const { _parsedProps: props } = this
|
|
48
48
|
const source_component = db.source_component.insert({
|
|
49
49
|
ftype: "simple_resistor",
|
|
@@ -18,7 +18,7 @@ export class Net extends PrimitiveComponent<typeof netProps> {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
doInitialSourceComponentRender(): void {
|
|
21
|
-
const { db } = this.
|
|
21
|
+
const { db } = this.root!
|
|
22
22
|
const { _parsedProps: props } = this
|
|
23
23
|
|
|
24
24
|
const net = db.source_net.insert({
|
|
@@ -77,7 +77,7 @@ export class Net extends PrimitiveComponent<typeof netProps> {
|
|
|
77
77
|
* such that the nets are fully connected
|
|
78
78
|
*/
|
|
79
79
|
doInitialPcbRouteNetIslands(): void {
|
|
80
|
-
const { db } = this.
|
|
80
|
+
const { db } = this.root!
|
|
81
81
|
const { _parsedProps: props } = this
|
|
82
82
|
|
|
83
83
|
const traces = this._getAllDirectlyConnectedTraces().filter(
|
|
@@ -14,6 +14,19 @@ export class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
getPcbSize(): { width: number; height: number } {
|
|
18
|
+
const { _parsedProps: props } = this
|
|
19
|
+
if (props.shape === "circle") {
|
|
20
|
+
return { width: props.outerDiameter, height: props.outerDiameter }
|
|
21
|
+
}
|
|
22
|
+
if (props.shape === "oval") {
|
|
23
|
+
return { width: props.outerWidth, height: props.outerHeight }
|
|
24
|
+
}
|
|
25
|
+
throw new Error(
|
|
26
|
+
`getPcbSize for shape "${(props as any).shape}" not implemented for ${this.componentName}`,
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
17
30
|
doInitialPortMatching(): void {
|
|
18
31
|
const parentPorts = (this.parent?.children ?? []).filter(
|
|
19
32
|
(c) => c.componentName === "Port",
|
|
@@ -33,7 +46,7 @@ export class PlatedHole extends PrimitiveComponent<typeof platedHoleProps> {
|
|
|
33
46
|
}
|
|
34
47
|
|
|
35
48
|
doInitialPcbPrimitiveRender(): void {
|
|
36
|
-
const { db } = this.
|
|
49
|
+
const { db } = this.root!
|
|
37
50
|
const { _parsedProps: props } = this
|
|
38
51
|
if (!props.portHints) return
|
|
39
52
|
const position = this.getGlobalPcbPosition()
|
|
@@ -116,7 +116,7 @@ export class Port extends PrimitiveComponent<typeof portProps> {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
doInitialSourceRender(): void {
|
|
119
|
-
const { db } = this.
|
|
119
|
+
const { db } = this.root!
|
|
120
120
|
const { _parsedProps: props } = this
|
|
121
121
|
|
|
122
122
|
const port_hints = this.getNameAndAliases()
|
|
@@ -132,7 +132,7 @@ export class Port extends PrimitiveComponent<typeof portProps> {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
doInitialSourceParentAttachment(): void {
|
|
135
|
-
const { db } = this.
|
|
135
|
+
const { db } = this.root!
|
|
136
136
|
if (!this.parent?.source_component_id) {
|
|
137
137
|
throw new Error(
|
|
138
138
|
`${this.getString()} has no parent source component (parent: ${this.parent?.getString()})`,
|
|
@@ -152,7 +152,7 @@ export class Port extends PrimitiveComponent<typeof portProps> {
|
|
|
152
152
|
* to exist)
|
|
153
153
|
*/
|
|
154
154
|
doInitialPcbPortRender(): void {
|
|
155
|
-
const { db } = this.
|
|
155
|
+
const { db } = this.root!
|
|
156
156
|
const { matchedComponents } = this
|
|
157
157
|
|
|
158
158
|
if (!this.parent?.pcb_component_id) {
|
|
@@ -191,7 +191,7 @@ export class Port extends PrimitiveComponent<typeof portProps> {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
doInitialSchematicPortRender(): void {
|
|
194
|
-
const { db } = this.
|
|
194
|
+
const { db } = this.root!
|
|
195
195
|
const { _parsedProps: props } = this
|
|
196
196
|
|
|
197
197
|
if (!this.parent) return
|
|
@@ -18,6 +18,19 @@ export class SmtPad extends PrimitiveComponent<typeof smtPadProps> {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
getPcbSize(): { width: number; height: number } {
|
|
22
|
+
const { _parsedProps: props } = this
|
|
23
|
+
if (props.shape === "circle") {
|
|
24
|
+
return { width: props.radius! * 2, height: props.radius! * 2 }
|
|
25
|
+
}
|
|
26
|
+
if (props.shape === "rect") {
|
|
27
|
+
return { width: props.width!, height: props.height! }
|
|
28
|
+
}
|
|
29
|
+
throw new Error(
|
|
30
|
+
`getPcbSize for shape "${(props as any).shape}" not implemented for ${this.componentName}`,
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
21
34
|
doInitialPortMatching(): void {
|
|
22
35
|
const parentPorts = (this.parent?.children ?? []).filter(
|
|
23
36
|
(c) => c.componentName === "Port",
|
|
@@ -37,7 +50,7 @@ export class SmtPad extends PrimitiveComponent<typeof smtPadProps> {
|
|
|
37
50
|
}
|
|
38
51
|
|
|
39
52
|
doInitialPcbPrimitiveRender(): void {
|
|
40
|
-
const { db } = this.
|
|
53
|
+
const { db } = this.root!
|
|
41
54
|
const { _parsedProps: props } = this
|
|
42
55
|
if (!props.portHints) return
|
|
43
56
|
const position = this.getGlobalPcbPosition()
|
|
@@ -104,7 +104,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
104
104
|
ports?: undefined
|
|
105
105
|
portsWithSelectors?: undefined
|
|
106
106
|
} {
|
|
107
|
-
const { db } = this.
|
|
107
|
+
const { db } = this.root!
|
|
108
108
|
const { _parsedProps: props, parent } = this
|
|
109
109
|
|
|
110
110
|
if (!parent) throw new Error("Trace has no parent")
|
|
@@ -215,7 +215,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
doInitialSourceTraceRender(): void {
|
|
218
|
-
const { db } = this.
|
|
218
|
+
const { db } = this.root!
|
|
219
219
|
const { _parsedProps: props, parent } = this
|
|
220
220
|
|
|
221
221
|
if (!parent) {
|
|
@@ -238,7 +238,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
doInitialPcbTraceRender(): void {
|
|
241
|
-
const { db } = this.
|
|
241
|
+
const { db } = this.root!
|
|
242
242
|
const { _parsedProps: props, parent } = this
|
|
243
243
|
|
|
244
244
|
if (!parent) throw new Error("Trace has no parent")
|
|
@@ -365,7 +365,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
365
365
|
|
|
366
366
|
// Cache the PCB obstacles, they'll be needed for each segment between
|
|
367
367
|
// ports/hints
|
|
368
|
-
const obstacles = getObstaclesFromSoup(this.
|
|
368
|
+
const obstacles = getObstaclesFromSoup(this.root!.db.toArray())
|
|
369
369
|
markObstaclesAsConnected(
|
|
370
370
|
obstacles,
|
|
371
371
|
orderedRouteObjectives,
|
|
@@ -445,7 +445,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
445
445
|
}
|
|
446
446
|
|
|
447
447
|
doInitialSchematicTraceRender(): void {
|
|
448
|
-
const { db } = this.
|
|
448
|
+
const { db } = this.root!
|
|
449
449
|
const { _parsedProps: props, parent } = this
|
|
450
450
|
|
|
451
451
|
if (!parent) throw new Error("Trace has no parent")
|
|
@@ -8,7 +8,7 @@ export class TraceHint extends PrimitiveComponent<typeof traceHintProps> {
|
|
|
8
8
|
matchedPort: Port | null = null
|
|
9
9
|
|
|
10
10
|
doInitialPortMatching(): void {
|
|
11
|
-
const { db } = this.
|
|
11
|
+
const { db } = this.root!
|
|
12
12
|
const { _parsedProps: props, parent } = this
|
|
13
13
|
|
|
14
14
|
if (!parent) return
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"module": "index.ts",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.30",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"files": [
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@tscircuit/infgrid-ijump-astar": "^0.0.6",
|
|
35
|
-
"@tscircuit/props": "^0.0.
|
|
35
|
+
"@tscircuit/props": "^0.0.52",
|
|
36
36
|
"@tscircuit/soup": "^0.0.58",
|
|
37
37
|
"@tscircuit/soup-util": "0.0.18",
|
|
38
38
|
"footprinter": "^0.0.44",
|