diff --git a/lib/components/base-components/NormalComponent/NormalComponent.ts b/lib/components/base-components/NormalComponent/NormalComponent.ts index e824cb5c3..467a50377 100644 --- a/lib/components/base-components/NormalComponent/NormalComponent.ts +++ b/lib/components/base-components/NormalComponent/NormalComponent.ts @@ -1760,7 +1760,7 @@ export class NormalComponent< const { db } = this.root! const { boardThickness = 0 } = this._getBoard() ?? {} const cadModelProp = this._parsedProps.cadModel - const cadModel = + let cadModel = cadModelProp === undefined ? this._asyncFootprintCadModel : cadModelProp const footprintString = this.getFootprinterString() ?? undefined @@ -1778,8 +1778,19 @@ export class NormalComponent< // Use post-layout bounds const bounds = this._getPcbCircuitJsonBounds() + let cadModelFootprinterString: string | undefined if (typeof cadModel === "string") { - throw new Error("String cadModel not yet implemented") + if ( + parseLibraryFootprintRef(cadModel) || + isHttpUrl(cadModel) || + isStaticAssetPath(cadModel) + ) { + throw new Error( + `${this.getString()} cadModel string must be a Footprinter string, received "${cadModel}"`, + ) + } + cadModelFootprinterString = cadModel + cadModel = undefined } const sourceRotationOffset = @@ -1824,7 +1835,11 @@ export class NormalComponent< : preLayoutRotation const isBottomLayer = computedLayer === "bottom" - if (!cadModel && !footprintIsFootprinterString) { + if ( + !cadModel && + !cadModelFootprinterString && + !footprintIsFootprinterString + ) { const cad_component = db.cad_component.insert({ position: { x: bounds.center.x, @@ -1852,10 +1867,9 @@ export class NormalComponent< const rotationWithOffset = totalRotation + (rotationOffset.z ?? 0) const cadRotationZ = normalizeDegrees(rotationWithOffset) - let footprinterStringForCadComponent: string | undefined - if (!cadModel && footprintIsFootprinterString) { - footprinterStringForCadComponent = footprintString - } + const footprinterStringForCadComponent = + cadModelFootprinterString ?? + (!cadModel && footprintIsFootprinterString ? footprintString : undefined) const cad_model = db.cad_component.insert({ // TODO z maybe depends on layer diff --git a/tests/components/normal-components/__snapshots__/chip-cad-model-footprinter-string-simple-3d.snap.png b/tests/components/normal-components/__snapshots__/chip-cad-model-footprinter-string-simple-3d.snap.png new file mode 100644 index 000000000..3ddd79b7b Binary files /dev/null and b/tests/components/normal-components/__snapshots__/chip-cad-model-footprinter-string-simple-3d.snap.png differ diff --git a/tests/components/normal-components/chip-cad-model-footprinter-string.test.tsx b/tests/components/normal-components/chip-cad-model-footprinter-string.test.tsx new file mode 100644 index 000000000..344ee3d84 --- /dev/null +++ b/tests/components/normal-components/chip-cad-model-footprinter-string.test.tsx @@ -0,0 +1,41 @@ +import { expect, test } from "bun:test" +import { Chip } from "lib/components/normal-components/Chip" +import { getTestFixture } from "tests/fixtures/get-test-fixture" + +test('cadModel="soic8" generates CAD independently of the PCB footprint', async () => { + const { circuit } = getTestFixture() + + circuit.add( + + + + + + + , + ) + + const chip = circuit.selectOne("chip") as Chip + chip._asyncFootprintCadModel = { + glbUrl: "https://example.com/library-model.glb", + } + + circuit.render() + + const cadComponents = circuit.db.cad_component.list() + expect(cadComponents).toHaveLength(1) + expect(cadComponents[0]).toMatchObject({ + footprinter_string: "soic8", + }) + expect(cadComponents[0]?.show_as_bounding_box).toBeUndefined() + expect(cadComponents[0]?.model_glb_url).toBeUndefined() + + await expect(circuit).toMatchSimple3dSnapshot(import.meta.path) +})