Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export function NormalComponent_doInitialPcbFootprintStringRender(
result.footprintCircuitJson,
)
component.addAll(fpComponents)
component._markDirty("InitializePortsFromChildren")
} catch (err) {
const db = component.root?.db
if (db && component.source_component_id && component.pcb_component_id) {
Expand Down Expand Up @@ -102,7 +101,6 @@ export function NormalComponent_doInitialPcbFootprintStringRender(
soup as any,
)
component.addAll(fpComponents)
component._markDirty("InitializePortsFromChildren")
} catch (err) {
const db = component.root?.db
if (db && component.source_component_id && component.pcb_component_id) {
Expand Down Expand Up @@ -174,13 +172,6 @@ export function NormalComponent_doInitialPcbFootprintStringRender(
if (!Array.isArray(result) && result.cadModel) {
component._asyncFootprintCadModel = result.cadModel
}
// Ensure existing Ports re-run PcbPortRender now that pads exist
for (const child of component.children) {
if (child.componentName === "Port") {
child._markDirty?.("PcbPortRender")
}
}
component._markDirty("InitializePortsFromChildren")
} catch (err) {
const db = component.root?.db
if (db && component.source_component_id && component.pcb_component_id) {
Expand Down
20 changes: 16 additions & 4 deletions lib/components/base-components/Renderable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ export abstract class Renderable implements IRenderable {
return this._asyncEffects.some((effect) => !effect.complete)
}

private _hasIncompleteAsyncEffectsInSubtreeForPhase(
protected _hasIncompleteAsyncEffectsInSubtreeForPhase(
phase: RenderPhase,
): boolean {
// Check self
Expand All @@ -249,6 +249,14 @@ export abstract class Renderable implements IRenderable {
return false
}

private _getRootRenderable(): Renderable {
let node: Renderable = this
while (node.parent && node.parent instanceof Renderable) {
node = node.parent
}
return node
}

getCurrentRenderPhase(): RenderPhase | null {
return this._currentRenderPhase
}
Expand Down Expand Up @@ -307,10 +315,14 @@ export abstract class Renderable implements IRenderable {
if (hasIncompleteEffects) return
}

// Check declared async dependencies for this phase within subtree
const deps = asyncPhaseDependencies[phase] || []
for (const depPhase of deps) {
if (this._hasIncompleteAsyncEffectsInSubtreeForPhase(depPhase)) return
if (deps.length > 0) {
const root = this._getRootRenderable()
const checkNode = (root.children?.[0] as any) || root
for (const depPhase of deps) {
if (checkNode._hasIncompleteAsyncEffectsInSubtreeForPhase?.(depPhase))
return
}
}

this._emitRenderLifecycleEvent(phase, "start")
Expand Down
3 changes: 3 additions & 0 deletions lib/components/primitive-components/Port/Port.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ export class Port extends PrimitiveComponent<typeof portProps> {
*/
registerMatch(component: PrimitiveComponent) {
this.matchedComponents.push(component)
if (this.renderPhaseStates.PcbPortRender.initialized && !this.pcb_port_id) {
this._markDirty("PcbPortRender")
}
}
getNameAndAliases() {
const { _parsedProps: props } = this
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions tests/repros/repro-kicad-footprint-pcbpath-selector1.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { test, expect } from "bun:test"
import { getTestFixture } from "tests/fixtures/get-test-fixture"
import kicadModJson from "tests/fixtures/assets/R_0402_1005Metric.json" with {
type: "json",
}

test("trace pcbPath selectors work with kicad footprints", async () => {
const { circuit } = getTestFixture()

circuit.platform = {
footprintLibraryMap: {
kicad: async (footprintName: string) => {
return {
footprintCircuitJson: kicadModJson,
}
},
},
}

circuit.add(
<board width="10mm" height="10mm">
<resistor
name="R1"
resistance="10k"
footprint="kicad:Resistor_SMD/R_0402_1005Metric"
pcbX={-3}
pcbY={0}
/>
<resistor
name="R2"
resistance="10k"
footprint="kicad:Resistor_SMD/R_0402_1005Metric"
pcbX={3}
pcbY={0}
/>
<trace
from=".R1 > .pin2"
to=".R2 > .pin1"
pcbPathRelativeTo=".R1 > .pin2"
pcbPath={["R1.pin2", { x: 0, y: 4 }, "R2.pin1"]}
thickness="0.5mm"
/>
</board>,
)

await circuit.renderUntilSettled()

const selectorErrors = circuit.db.pcb_trace_error
.list()
.filter((e) => e.message?.includes("Could not resolve pcbPath selector"))
expect(selectorErrors.length).toBe(0)

const pcbTrace = circuit.db.pcb_trace.list()[0]
expect(pcbTrace).toBeDefined()
expect(pcbTrace.route.length).toBeGreaterThanOrEqual(3)

await expect(circuit).toMatchPcbSnapshot(import.meta.path)
})