Skip to content

Add SOLIDREGION footprints, pad mask overrides, schematic graphics, multi-part symbols - #9

Open
CP0274 wants to merge 4 commits into
expired6978:mainfrom
CP0274:feat/solidregion-mask-graphics-multipart
Open

Add SOLIDREGION footprints, pad mask overrides, schematic graphics, multi-part symbols#9
CP0274 wants to merge 4 commits into
expired6978:mainfrom
CP0274:feat/solidregion-mask-graphics-multipart

Conversation

@CP0274

@CP0274 CP0274 commented Aug 10, 2026

Copy link
Copy Markdown

⚠️ Untested on Altium Designer

Everything in this PR was developed and tested against CircuitStudio only — I don't currently
have an Altium Designer install to verify against. The SDK surface used here (IPCB_Pad4,
IPCB_Text3, ISch_Polygon, IPCB_ComponentBody, IPCB_Region, ISch_Component part APIs) is the
same one this repo already targets, and the logic is adapted specifically for that API (not
copy-pasted from a CS-specific variant), but please treat this as needing a real AD smoke test
before merging, not as pre-verified.

Summary

Genuine feature/capability additions found while separately porting this plugin to
CircuitStudio, filtered down to the ones that are real gaps in the original write path — not
search/UI code and not CS-specific workarounds (e.g. the board-origin offset CS's 2D PCB
library editor needs is not included here).

  • SOLIDREGION footprint shapes. Filled copper-polygon shapes were parsed and then silently
    discarded (case "SOLIDREGION": return null;). Adds EeFootprintSolidRegion and
    EEPCB.CreateSolidRegion. "cutout" fill-rule regions are intentionally skipped — they're
    meant to subtract from an adjacent solid region, and rendering one standalone would produce
    a visible extra blob rather than a hole.

  • Paste/solder mask expansion overrides for pads. Two trailing fields in the PAD~...
    shape string were parsed but never applied. Now set via the same
    GetState_Cache()/SetState_Cache() pattern EeFootprintHole.cs already uses for holes.

  • 3D component-body layer assignment. EEPCB.CreateComponentBody never called
    SetState_V7Layer at all (every other shape in the file does), leaving bodies on whatever
    the internal default layer is instead of the side the SVGNODE's own layerid specifies.

  • Schematic graphic shapes (Polyline/Polygon/Path). Diode arrows and similar shapes were
    parsed from the start of this project but never drawn — only pins and a bounding rectangle
    ever made it onto the symbol. Adds EESCH.CreatePolygon and a mapping pass that calibrates
    each shape's raw coordinates against the actual pins on that axis (not the whole bounding
    box), so shapes land exactly on their pins rather than approximately.

  • Multi-part component support. Components with subparts (op-amps with multiple gates,
    large MCUs whose pins are split across several drawn "parts") previously only ever used the
    empty top-level placeholder data. Now each subpart becomes a real, selectable Altium "part"
    sharing one footprint.

  • Default Comment field. Was never set (GetState_SchComment(), the same pattern already
    used for the designator via GetState_SchDesignator()), so components always showed the "*"
    placeholder.

Test plan

  • Import a component with a filled copper region footprint shape (e.g. a ground pour pad)
    and confirm it renders as copper, not silently dropped
  • Import a component with an explicit paste/solder mask override (e.g. C20033862) and confirm it's reflected
    in the pad's properties
  • Import a component with a 3D model and confirm the body lands on the correct top/bottom layer
  • Import a component with schematic graphics (e.g. a diode) and confirm the arrow/graphic
    appears aligned with its pins
  • Import a multi-gate component (e.g. C20033862) and confirm all parts are selectable
    and only the intended pins appear per part
  • Confirm newly-imported components show a real value in the Comment field instead of "*"

CP0274 added 4 commits August 11, 2026 00:33
SOLIDREGION (filled copper polygon) shapes were parsed and then
discarded (case returned null). Adds EeFootprintSolidRegion, wired
into the shape dispatcher, plus EEPCB.CreateSolidRegion to build the
IPCB_Region. "cutout" fill-rule regions are intentionally skipped
(they're meant to subtract from an adjacent solid region - rendering
one standalone would produce a visible extra blob, not a hole).

Separately, EEPCB.CreateComponentBody never called SetState_V7Layer at
all, unlike every other shape type in the file (pads, tracks, arcs,
text) - a freshly-created 3D body was left at whatever the internal
default layer is instead of the side the SVGNODE's own layerid
specifies. Now resolves and applies the real layer, the same way every
sibling shape already does.
Two trailing fields in EasyEDA's PAD~... shape string (paste mask
expansion, solder mask expansion) were parsed as raw string parts but
never read or applied. Adds them as real properties and applies them
via pad.GetState_Cache()/SetState_Cache(), the same V7_PadCache
read-modify-write pattern EeFootprintHole.cs already uses to zero a
hole's solder mask expansion. EasyEDA only carries a single solder
value (no separate top/bottom), so both sides are set the same,
matching that existing convention.
…ymbols

Polyline/Polygon/Path shapes (diode arrows, etc.) were parsed from the
start of this project but never drawn - only pins and a single
bounding rectangle ever made it onto the schematic symbol. Adds
EESCH.CreatePolygon (SCH.TObjectId.ePolygon via ISch_Polygon,
1-indexed SetState_Vertex) and a graphics pass in SymbolDrawing that
maps each shape's raw EasyEDA coordinates onto the synthetic pin grid.

Pins are laid out synthetically (grid position by count/order),
independent of their original raw coordinates, so graphic shapes -
only meaningful at their original coordinates - need a coordinate
mapping to line up with them. Calibrates per-axis against the actual
pins drawn on that axis (min/max raw position vs. synthetic position)
rather than the whole bounding box, since EasyEDA's own graphic
coordinates coincide with pin raw coordinates in the source data -
this maps shapes exactly, not approximately. Falls back to a
bbox-proportional mapping per-axis when fewer than 2 pins with
distinct raw positions exist on that axis.

Also refactors CreateComponent into a shared DrawPart (draws one
part's pins/rectangle/graphics) plus a new CreateMultiPartComponent,
which is what real multi-part support (next commit) needs to draw
each subpart separately.
Component.cs gains Subparts/Subpart - multi-subpart components (op-amps
with multiple gates, large MCUs whose pins are split across several
drawn "parts") carry their real pin/shape data there instead of in the
top-level dataStr, which is empty ("shape": []) for these parts.
Without this property Newtonsoft silently dropped the whole "subparts"
array, so only an empty placeholder symbol was ever built.

EasyEDALoader.cs now dispatches to SymbolDrawing.CreateMultiPartComponent
when subparts are present, and moves SetState_Current_SchComponent to
before drawing instead of after - SetState_CurrentSchComponentPartId
(used per-subpart to draw each part) needs the library's own "current
component" context to already be the component being drawn, otherwise
every subpart's pins land in the same part regardless of the ID set.

Also sets the schematic component's default Comment field from the
part's Manufacturer Part number. Comment isn't a plain parameter you
add - it's a dedicated object retrieved via GetState_SchComment(), the
same pattern already used for the designator via
GetState_SchDesignator(). Previously nothing set it, so it stayed at
its "*" placeholder.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant