@@ -435,15 +435,45 @@ def get_all_drawings(self):
435
435
return drawings
436
436
437
437
def parse_pad (self , pad ):
438
- # type: (pcbnew.PAD) -> dict | None
439
- layers_set = list (pad .GetLayerSet ().Seq ())
438
+ # type: (pcbnew.PAD) -> list[dict]
439
+ custom_padstack = False
440
+ outer_layers = [(pcbnew .F_Cu , "F" ), (pcbnew .B_Cu , "B" )]
441
+ if hasattr (pad , 'Padstack' ):
442
+ padstack = pad .Padstack () # type: pcbnew.PADSTACK
443
+ layers_set = list (padstack .LayerSet ().Seq ())
444
+ custom_padstack = (
445
+ padstack .Mode () != padstack .MODE_NORMAL or \
446
+ padstack .UnconnectedLayerMode () == padstack .UNCONNECTED_LAYER_MODE_REMOVE_ALL
447
+ )
448
+ else :
449
+ layers_set = list (pad .GetLayerSet ().Seq ())
440
450
layers = []
441
- if pcbnew .F_Cu in layers_set :
442
- layers .append ("F" )
443
- if pcbnew .B_Cu in layers_set :
444
- layers .append ("B" )
451
+ for layer , letter in outer_layers :
452
+ if layer in layers_set :
453
+ layers .append (letter )
454
+ if not layers :
455
+ return []
456
+
457
+ if custom_padstack :
458
+ pads = []
459
+ for layer , letter in outer_layers :
460
+ if layer in layers_set and pad .FlashLayer (layer ):
461
+ pad_dict = self .parse_pad_layer (pad , layer )
462
+ pad_dict ["layers" ] = [letter ]
463
+ pads .append (pad_dict )
464
+ return pads
465
+ else :
466
+ pad_dict = self .parse_pad_layer (pad , layers_set [0 ])
467
+ pad_dict ["layers" ] = layers
468
+ return [pad_dict ]
469
+
470
+ def parse_pad_layer (self , pad , layer ):
471
+ # type: (pcbnew.PAD, int) -> dict | None
445
472
pos = self .normalize (pad .GetPosition ())
446
- size = self .normalize (pad .GetSize ())
473
+ try :
474
+ size = self .normalize (pad .GetSize (layer ))
475
+ except TypeError :
476
+ size = self .normalize (pad .GetSize ())
447
477
angle = self .normalize_angle (pad .GetOrientation ())
448
478
shape_lookup = {
449
479
pcbnew .PAD_SHAPE_RECT : "rect" ,
@@ -458,27 +488,36 @@ def parse_pad(self, pad):
458
488
shape_lookup [pcbnew .PAD_SHAPE_CUSTOM ] = "custom"
459
489
if hasattr (pcbnew , "PAD_SHAPE_CHAMFERED_RECT" ):
460
490
shape_lookup [pcbnew .PAD_SHAPE_CHAMFERED_RECT ] = "chamfrect"
461
- shape = shape_lookup .get (pad .GetShape (), "" )
491
+ try :
492
+ pad_shape = pad .GetShape (layer )
493
+ except TypeError :
494
+ pad_shape = pad .GetShape ()
495
+ shape = shape_lookup .get (pad_shape , "" )
462
496
if shape == "" :
463
- self .logger .info ("Unsupported pad shape %s, skipping." ,
464
- pad .GetShape ())
497
+ self .logger .info ("Unsupported pad shape %s, skipping." , pad_shape )
465
498
return None
466
499
pad_dict = {
467
- "layers" : layers ,
468
500
"pos" : pos ,
469
501
"size" : size ,
470
502
"angle" : angle ,
471
503
"shape" : shape
472
504
}
473
505
if shape == "custom" :
474
- polygon_set = pad .GetCustomShapeAsPolygon ()
506
+ polygon_set = pcbnew .SHAPE_POLY_SET ()
507
+ try :
508
+ pad .MergePrimitivesAsPolygon (layer , polygon_set )
509
+ except TypeError :
510
+ pad .MergePrimitivesAsPolygon (polygon_set )
475
511
if polygon_set .HasHoles ():
476
512
self .logger .warn ('Detected holes in custom pad polygons' )
477
513
pad_dict ["polygons" ] = self .parse_poly_set (polygon_set )
478
514
if shape == "trapezoid" :
479
515
# treat trapezoid as custom shape
480
516
pad_dict ["shape" ] = "custom"
481
- delta = self .normalize (pad .GetDelta ())
517
+ try :
518
+ delta = self .normalize (pad .GetDelta (layer ))
519
+ except TypeError :
520
+ delta = self .normalize (pad .GetDelta ())
482
521
pad_dict ["polygons" ] = [[
483
522
[size [0 ] / 2 + delta [1 ] / 2 , size [1 ] / 2 - delta [0 ] / 2 ],
484
523
[- size [0 ] / 2 - delta [1 ] / 2 , size [1 ] / 2 + delta [0 ] / 2 ],
@@ -487,10 +526,17 @@ def parse_pad(self, pad):
487
526
]]
488
527
489
528
if shape in ["roundrect" , "chamfrect" ]:
490
- pad_dict ["radius" ] = pad .GetRoundRectCornerRadius () * 1e-6
529
+ try :
530
+ pad_dict ["radius" ] = pad .GetRoundRectCornerRadius (layer ) * 1e-6
531
+ except TypeError :
532
+ pad_dict ["radius" ] = pad .GetRoundRectCornerRadius () * 1e-6
491
533
if shape == "chamfrect" :
492
- pad_dict ["chamfpos" ] = pad .GetChamferPositions ()
493
- pad_dict ["chamfratio" ] = pad .GetChamferRectRatio ()
534
+ try :
535
+ pad_dict ["chamfpos" ] = pad .GetChamferPositions (layer )
536
+ pad_dict ["chamfratio" ] = pad .GetChamferRectRatio (layer )
537
+ except TypeError :
538
+ pad_dict ["chamfpos" ] = pad .GetChamferPositions ()
539
+ pad_dict ["chamfratio" ] = pad .GetChamferRectRatio ()
494
540
if hasattr (pcbnew , 'PAD_ATTRIB_PTH' ):
495
541
through_hole_attributes = [pcbnew .PAD_ATTRIB_PTH ,
496
542
pcbnew .PAD_ATTRIB_NPTH ]
@@ -507,7 +553,10 @@ def parse_pad(self, pad):
507
553
else :
508
554
pad_dict ["type" ] = "smd"
509
555
if hasattr (pad , "GetOffset" ):
510
- pad_dict ["offset" ] = self .normalize (pad .GetOffset ())
556
+ try :
557
+ pad_dict ["offset" ] = self .normalize (pad .GetOffset (layer ))
558
+ except TypeError :
559
+ pad_dict ["offset" ] = self .normalize (pad .GetOffset ())
511
560
if self .config .include_nets :
512
561
pad_dict ["net" ] = pad .GetNetname ()
513
562
@@ -561,8 +610,7 @@ def parse_footprints(self):
561
610
# footprint pads
562
611
pads = []
563
612
for p in f .Pads ():
564
- pad_dict = self .parse_pad (p )
565
- if pad_dict is not None :
613
+ for pad_dict in self .parse_pad (p ):
566
614
pads .append ((p .GetPadName (), pad_dict ))
567
615
568
616
if pads :
0 commit comments