Skip to content

Commit c24cf0c

Browse files
committed
Fix things. Change panel fiducials. Add save messageBox
1 parent 9a8ce80 commit c24cf0c

File tree

6 files changed

+379
-91
lines changed

6 files changed

+379
-91
lines changed

SparkFunKiCadPanelizer/dialog/dialog.py

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,25 @@ def get_version(rel_path: str) -> str:
3131

3232
_APP_VERSION = get_version("_version.py")
3333

34+
# try:
35+
# if hasattr(wx, "GetLibraryVersionInfo"):
36+
# WX_VERSION = wx.GetLibraryVersionInfo() # type: wx.VersionInfo
37+
# WX_VERSION = (WX_VERSION.Major, WX_VERSION.Minor, WX_VERSION.Micro)
38+
# else:
39+
# # old kicad used this (exact version doesnt matter)
40+
# WX_VERSION = (3, 0, 2)
41+
# except:
42+
# WX_VERSION = (3, 1, 6)
43+
44+
def get_btn_bitmap(bitmap):
45+
path = resource_path(bitmap)
46+
png = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
47+
48+
#if WX_VERSION >= (3, 1, 6):
49+
return wx.BitmapBundle(png)
50+
#else:
51+
#return png
52+
3453
def ParseFloat(InputString, DefaultValue=0.0):
3554
value = DefaultValue
3655
if InputString != "":
@@ -42,11 +61,27 @@ def ParseFloat(InputString, DefaultValue=0.0):
4261

4362
class Dialog(dialog_text_base.DialogPanelBase):
4463
def __init__(self, parent, config, layertable, ordering, panelizer, func):
64+
4565
dialog_text_base.DialogPanelBase.__init__(self, None)
4666

67+
self.panel = DialogPanel(self, config, layertable, ordering, panelizer, func)
68+
69+
best_size = self.BestSize
70+
# hack for some gtk themes that incorrectly calculate best size
71+
best_size.IncBy(dx=0, dy=30)
72+
self.SetClientSize(best_size)
73+
4774
self.SetTitle(_APP_NAME + " - " + _APP_VERSION)
48-
self.panel = DialogPanel(self,config,layertable,ordering,panelizer,func)
49-
75+
76+
# hack for new wxFormBuilder generating code incompatible with old wxPython
77+
# noinspection PyMethodOverriding
78+
def SetSizeHints(self, sz1, sz2):
79+
try:
80+
# wxPython 4
81+
super(Dialog, self).SetSizeHints(sz1, sz2)
82+
except TypeError:
83+
# wxPython 3
84+
self.SetSizeHintsSz(sz1, sz2)
5085

5186
class DialogPanel(dialog_text_base.DialogPanel):
5287
# The names of the config items need to match the names in dialog_text_base minus the m_
@@ -70,13 +105,9 @@ class DialogPanel(dialog_text_base.DialogPanel):
70105
}
71106

72107
def __init__(self, parent, config, layertable, ordering, panelizer, func):
108+
73109
dialog_text_base.DialogPanel.__init__(self, parent)
74110

75-
# hack for some gtk themes that incorrectly calculate best size
76-
#best_size = self.BestSize
77-
#best_size.IncBy(dx=0, dy=30)
78-
#self.SetClientSize(best_size)
79-
80111
self.config_file = config
81112

82113
self.layertable = layertable
@@ -151,7 +182,7 @@ def LoadSettings(self, params):
151182
self.vscore.LayersGrid.SetCellValue(0, 0, "1") # Default to the first layer
152183
else:
153184
try:
154-
obj = getattr(self, "m_{}".format(key))
185+
obj = getattr(self.general, "m_{}".format(key))
155186
if hasattr(obj, "SetValue"):
156187
obj.SetValue(value)
157188
elif hasattr(obj, "SetStringSelection"):
@@ -170,9 +201,9 @@ def CurrentSettings(self):
170201
if self.vscore_layer in item:
171202
for row in range(self.vscore.LayersGrid.GetNumberRows()):
172203
if self.vscore.LayersGrid.GetCellValue(row, 0) == "1":
173-
params.update({'vScoreLayer': self.LayersGrid.GetCellValue(row, 1)})
204+
params.update({self.vscore_layer: self.vscore.LayersGrid.GetCellValue(row, 1)})
174205
else:
175-
obj = getattr(self, "m_{}".format(item))
206+
obj = getattr(self.general, "m_{}".format(item))
176207
if hasattr(obj, "GetValue"):
177208
params.update({item: obj.GetValue()})
178209
elif hasattr(obj, "GetStringSelection"):
@@ -190,18 +221,58 @@ def OnCancelClick(self, e):
190221
self.GetParent().EndModal(wx.ID_CANCEL)
191222

192223
class GeneralPanel(dialog_text_base.GeneralPanelBase):
224+
193225
def __init__(self, parent):
194226
dialog_text_base.GeneralPanelBase.__init__(self, parent)
195227

228+
self.m_buttonFiducialsHelp.SetLabelText("")
229+
# Icon by Icons8 https://icons8.com : https://icons8.com/icon/63308/info
230+
self.m_buttonFiducialsHelp.SetBitmap(get_btn_bitmap("info-15.png"))
231+
232+
self.m_buttonEdgeHelp.SetLabelText("")
233+
# Icon by Icons8 https://icons8.com : https://icons8.com/icon/63308/info
234+
self.m_buttonEdgeHelp.SetBitmap(get_btn_bitmap("info-15.png"))
235+
236+
def ClickFiducialsHelp( self, event ):
237+
wx.MessageBox("\
238+
By default, the panel fiducials are placed in\n\
239+
the top and bottom edges. Normally we\n\
240+
recommend leaving them there.\n\
241+
\n\
242+
Selecting this option moves them to the left\n\
243+
and right edges.\n\
244+
\n\
245+
This can be useful when using horizontal gaps\n\
246+
and vertical v-scores. It avoids the panel\n\
247+
having to be scrapped if an edge has been\n\
248+
snapped off and the fiducials are missing.\
249+
", 'Info', wx.OK | wx.ICON_INFORMATION)
250+
251+
def ClickEdgeHelp( self, event ):
252+
wx.MessageBox("\
253+
Select this option if you are panelizing\n\
254+
a MicroMod Processor or Function Board.\n\
255+
\n\
256+
The bottom and top edges will be exposed\n\
257+
so the fingers and chamfered edge can be\n\
258+
manufactured. The top row of PCBs is\n\
259+
rotated automatically.\
260+
", 'Info', wx.OK | wx.ICON_INFORMATION)
261+
196262
class VScorePanel(dialog_text_base.VScorePanelBase):
263+
197264
def __init__(self, parent):
198265
dialog_text_base.VScorePanelBase.__init__(self, parent)
199266

267+
self.Layout()
268+
self.LayersGrid.SetColSize(0, 50)
269+
self.LayersGrid.SetColSize(1, self.GetParent().GetClientSize().x - 80)
270+
200271
def OnLayersGridCellClicked(self, event):
201272
self.LayersGrid.ClearSelection()
202273
#self.LayersGrid.SelectRow(event.Row)
203274
if event.Col == 0:
204275
for row in range(self.LayersGrid.GetNumberRows()):
205276
val = "1" if (row == event.Row) else "0" # JSON style
206-
self.LayersGrid.SetCellValue(event.Row, event.Col, val)
277+
self.LayersGrid.SetCellValue(row, 0, val)
207278

SparkFunKiCadPanelizer/dialog/dialog_text_base.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def __init__( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.
5353
bSizer7 = wx.BoxSizer( wx.VERTICAL )
5454

5555
self.notebook = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.NB_TOP|wx.BORDER_DEFAULT )
56-
self.notebook.SetMinSize( wx.Size( 300,600 ) )
56+
self.notebook.SetMinSize( wx.Size( 350,450 ) )
5757

5858

5959
bSizer7.Add( self.notebook, 1, wx.EXPAND |wx.ALL, 5 )
@@ -214,8 +214,20 @@ def __init__( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.
214214

215215
sbSizer4.Add( fgSizer3, 1, wx.EXPAND, 5 )
216216

217+
fgSizer5 = wx.FlexGridSizer( 0, 2, 0, 0 )
218+
fgSizer5.SetFlexibleDirection( wx.BOTH )
219+
fgSizer5.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
220+
217221
self.m_productionExposeCheck = wx.CheckBox( sbSizer4.GetStaticBox(), wx.ID_ANY, _(u"Expose Bottom/Card Edge"), wx.DefaultPosition, wx.DefaultSize, 0 )
218-
sbSizer4.Add( self.m_productionExposeCheck, 0, wx.ALL, 5 )
222+
fgSizer5.Add( self.m_productionExposeCheck, 0, wx.ALL, 5 )
223+
224+
self.m_buttonEdgeHelp = wx.Button( sbSizer4.GetStaticBox(), wx.ID_ANY, _(u"MyButton"), wx.DefaultPosition, wx.DefaultSize, 0 )
225+
self.m_buttonEdgeHelp.SetMinSize( wx.Size( 15,15 ) )
226+
227+
fgSizer5.Add( self.m_buttonEdgeHelp, 0, wx.ALL, 5 )
228+
229+
230+
sbSizer4.Add( fgSizer5, 1, wx.EXPAND, 5 )
219231

220232

221233
bMainSizer.Add( sbSizer4, 0, wx.EXPAND, 5 )
@@ -225,10 +237,22 @@ def __init__( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.
225237
self.Layout()
226238
bMainSizer.Fit( self )
227239

240+
# Connect Events
241+
self.m_buttonFiducialsHelp.Bind( wx.EVT_BUTTON, self.ClickFiducialsHelp )
242+
self.m_buttonEdgeHelp.Bind( wx.EVT_BUTTON, self.ClickEdgeHelp )
243+
228244
def __del__( self ):
229245
pass
230246

231247

248+
# Virtual event handlers, override them in your derived class
249+
def ClickFiducialsHelp( self, event ):
250+
pass
251+
252+
def ClickEdgeHelp( self, event ):
253+
pass
254+
255+
232256
###########################################################################
233257
## Class VScorePanelBase
234258
###########################################################################
@@ -242,9 +266,9 @@ def __init__( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.
242266

243267
sbSizer5 = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, _(u"V-Score Layer:") ), wx.VERTICAL )
244268

245-
fgSizer4 = wx.FlexGridSizer( 0, 2, 0, 0 )
246-
fgSizer4.SetFlexibleDirection( wx.BOTH )
247-
fgSizer4.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
269+
LayersGridSizer = wx.FlexGridSizer( 0, 2, 0, 0 )
270+
LayersGridSizer.SetFlexibleDirection( wx.BOTH )
271+
LayersGridSizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
248272

249273
self.LayersGrid = wx.grid.Grid( sbSizer5.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
250274

@@ -274,10 +298,10 @@ def __init__( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.
274298

275299
# Cell Defaults
276300
self.LayersGrid.SetDefaultCellAlignment( wx.ALIGN_LEFT, wx.ALIGN_TOP )
277-
fgSizer4.Add( self.LayersGrid, 0, wx.ALL|wx.EXPAND, 5 )
301+
LayersGridSizer.Add( self.LayersGrid, 0, wx.ALL|wx.EXPAND, 5 )
278302

279303

280-
sbSizer5.Add( fgSizer4, 1, wx.EXPAND, 5 )
304+
sbSizer5.Add( LayersGridSizer, 1, wx.EXPAND, 5 )
281305

282306

283307
bSizer11.Add( sbSizer5, 1, wx.EXPAND, 5 )

SparkFunKiCadPanelizer/panelizer/panelizer.py

Lines changed: 92 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,11 @@ def startPanelizer(self, args, board=None, ordering=None, logger=None):
113113
# Panel fiducial parameters
114114
FIDUCIAL_MASK = 3.0 # mm - Fiducial_1.5mm_Mask3mm
115115
FIDUCIAL_OFFSET = 2.5 # mm
116-
FIDUCIAL_FOOTPRINT = "Fiducial_1.5mm_Mask3mm"
116+
FIDUCIAL_FOOTPRINT_BIG = "Fiducial_1.5mm_Mask3mm"
117+
FIDUCIAL_FOOTPRINT_SMALL = "Fiducial_1mm_Mask3mm"
118+
119+
# Text for empty edges
120+
EMPTY_EDGE_TEXT = "SparkFun"
117121

118122
# Minimum spacer for exposed edge panels
119123
MINIMUM_SPACER = 6.35 # mm
@@ -199,6 +203,17 @@ def startPanelizer(self, args, board=None, ordering=None, logger=None):
199203
panelOutputFile = os.path.split(board.GetFileName())[1] # Get the file path tail
200204
panelOutputFile = os.path.join(panelOutputPath, os.path.splitext(panelOutputFile)[0] + "_panelized.kicad_pcb")
201205

206+
# Check if PCB needs to be saved
207+
#if board.IsModified(): # This doesn't work. Need to find something that does...
208+
if wx.GetApp() is not None:
209+
resp = wx.MessageBox("Do you want to save the PCB first?",
210+
'Save PCB?', wx.YES_NO | wx.ICON_INFORMATION)
211+
if resp == wx.YES:
212+
report += "Board saved by user.\n"
213+
board.Save(board.GetFileName())
214+
else:
215+
board.Save(board.GetFileName())
216+
202217
if board is None:
203218
report += "Could not load board. Quitting.\n"
204219
sysExit = 2
@@ -939,39 +954,45 @@ def startPanelizer(self, args, board=None, ordering=None, logger=None):
939954
if FIDUCIALS_LR:
940955
fiducials.append([
941956
int(panelCenter.x - (panelWidth / 2 - VERTICAL_EDGE_RAIL_WIDTH / 2 * SCALE)),
942-
int(panelCenter.y - (panelHeight / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * HORIZONTAL_EDGE_RAIL_WIDTH)))
957+
int(panelCenter.y + (panelHeight / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * HORIZONTAL_EDGE_RAIL_WIDTH))),
958+
FIDUCIAL_FOOTPRINT_BIG
943959
])
944960
fiducials.append([
945961
int(panelCenter.x - (panelWidth / 2 - VERTICAL_EDGE_RAIL_WIDTH / 2 * SCALE)),
946-
int(panelCenter.y + (panelHeight / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * HORIZONTAL_EDGE_RAIL_WIDTH)))
962+
int(panelCenter.y - (panelHeight / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * HORIZONTAL_EDGE_RAIL_WIDTH))),
963+
FIDUCIAL_FOOTPRINT_SMALL
947964
])
948965
fiducials.append([
949966
int(panelCenter.x + (panelWidth / 2 - VERTICAL_EDGE_RAIL_WIDTH / 2 * SCALE)),
950-
int(panelCenter.y - (panelHeight / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * HORIZONTAL_EDGE_RAIL_WIDTH)))
967+
int(panelCenter.y - (panelHeight / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * HORIZONTAL_EDGE_RAIL_WIDTH))),
968+
FIDUCIAL_FOOTPRINT_SMALL
951969
])
952970
if FIDUCIALS_TB:
953971
fiducials.append([
954972
int(panelCenter.x - (panelWidth / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * VERTICAL_EDGE_RAIL_WIDTH))),
955-
int(panelCenter.y + (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH / 2 * SCALE))
973+
int(panelCenter.y + (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH / 2 * SCALE)),
974+
FIDUCIAL_FOOTPRINT_BIG
956975
])
957976
fiducials.append([
958-
int(panelCenter.x + (panelWidth / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * VERTICAL_EDGE_RAIL_WIDTH))),
959-
int(panelCenter.y - (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH / 2 * SCALE))
977+
int(panelCenter.x - (panelWidth / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * VERTICAL_EDGE_RAIL_WIDTH))),
978+
int(panelCenter.y - (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH / 2 * SCALE)),
979+
FIDUCIAL_FOOTPRINT_SMALL
960980
])
961981
fiducials.append([
962-
int(panelCenter.x - (panelWidth / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * VERTICAL_EDGE_RAIL_WIDTH))),
963-
int(panelCenter.y - (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH / 2 * SCALE))
982+
int(panelCenter.x + (panelWidth / 2 - (SCALE * FIDUCIAL_OFFSET + SCALE * VERTICAL_EDGE_RAIL_WIDTH))),
983+
int(panelCenter.y - (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH / 2 * SCALE)),
984+
FIDUCIAL_FOOTPRINT_SMALL
964985
])
965986
for pos in fiducials:
966987
# Front / Top
967-
fiducial = pcbnew.FootprintLoad(fiducialPath, FIDUCIAL_FOOTPRINT)
988+
fiducial = pcbnew.FootprintLoad(fiducialPath, pos[2])
968989
fiducial.SetReference("") # Clear the reference silk
969990
fiducial.SetValue("")
970991
board.Add(fiducial)
971992
fiducial.SetPosition(pcbnew.VECTOR2I(pos[0], pos[1]))
972993

973994
# Back / Bottom
974-
fiducial = pcbnew.FootprintLoad(fiducialPath, FIDUCIAL_FOOTPRINT)
995+
fiducial = pcbnew.FootprintLoad(fiducialPath, pos[2])
975996
fiducial.SetReference("") # Clear the reference silk
976997
fiducial.SetValue("")
977998
board.Add(fiducial)
@@ -1054,6 +1075,66 @@ def startPanelizer(self, args, board=None, ordering=None, logger=None):
10541075
titleblock_text.SetTextAngle(pcbnew.EDA_ANGLE(-900, pcbnew.TENTHS_OF_A_DEGREE_T))
10551076
board.Add(titleblock_text)
10561077

1078+
# If rails are present but don't contain copper or silk, add something so JLCPCB picks up the correct panel size
1079+
# Bottom Edge
1080+
if (HORIZONTAL_EDGE_RAIL_WIDTH > 0.0) and (not FIDUCIALS_TB) and (not HORIZONTAL_EDGE_RAIL_TEXT):
1081+
hrail_text = pcbnew.PCB_TEXT(board)
1082+
hrail_text.SetText(EMPTY_EDGE_TEXT)
1083+
hrail_text.SetTextSize(pcbnew.VECTOR2I(int(SCALE * RAIL_TEXT_SIZE), int(SCALE * RAIL_TEXT_SIZE)))
1084+
hrail_text.SetLayer(pcbnew.F_SilkS)
1085+
hrail_text.SetHorizJustify(pcbnew.GR_TEXT_H_ALIGN_LEFT)
1086+
hrail_text.SetPosition(
1087+
pcbnew.VECTOR2I(
1088+
int(panelCenter.x - (panelWidth / 2 - VERTICAL_EDGE_RAIL_WIDTH * SCALE - SCALE * FIDUCIAL_OFFSET * 2)),
1089+
int(panelCenter.y + (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH / 2 * SCALE))
1090+
)
1091+
)
1092+
board.Add(hrail_text)
1093+
# Top Edge
1094+
if (HORIZONTAL_EDGE_RAIL_WIDTH > 0.0) and (not FIDUCIALS_TB) and (not TITLE_X):
1095+
titleblock_text = pcbnew.PCB_TEXT(board)
1096+
titleblock_text.SetText(EMPTY_EDGE_TEXT)
1097+
titleblock_text.SetTextSize(pcbnew.VECTOR2I(int(SCALE * RAIL_TEXT_SIZE), int(SCALE * RAIL_TEXT_SIZE)))
1098+
titleblock_text.SetLayer(pcbnew.F_SilkS)
1099+
titleblock_text.SetHorizJustify(pcbnew.GR_TEXT_H_ALIGN_LEFT)
1100+
titleblock_text.SetPosition(
1101+
pcbnew.VECTOR2I(
1102+
int(panelCenter.x - (panelWidth / 2 - VERTICAL_EDGE_RAIL_WIDTH * SCALE - SCALE * FIDUCIAL_OFFSET * 2)),
1103+
int(panelCenter.y - (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH / 2 * SCALE))
1104+
)
1105+
)
1106+
board.Add(titleblock_text)
1107+
# Left Edge
1108+
if (VERTICAL_EDGE_RAIL_WIDTH > 0.0) and (not FIDUCIALS_LR) and (not VERTICAL_EDGE_RAIL_TEXT):
1109+
vrail_text = pcbnew.PCB_TEXT(board)
1110+
vrail_text.SetText(EMPTY_EDGE_TEXT)
1111+
vrail_text.SetTextSize(pcbnew.VECTOR2I(int(SCALE * RAIL_TEXT_SIZE), int(SCALE * RAIL_TEXT_SIZE)))
1112+
vrail_text.SetLayer(pcbnew.F_SilkS)
1113+
vrail_text.SetHorizJustify(pcbnew.GR_TEXT_H_ALIGN_LEFT)
1114+
vrail_text.SetPosition(
1115+
pcbnew.VECTOR2I(
1116+
int(panelCenter.x - (panelWidth / 2 - VERTICAL_EDGE_RAIL_WIDTH / 2 * SCALE)),
1117+
int(panelCenter.y - (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH * SCALE - SCALE * FIDUCIAL_OFFSET * 2))
1118+
)
1119+
)
1120+
vrail_text.SetTextAngle(pcbnew.EDA_ANGLE(-900, pcbnew.TENTHS_OF_A_DEGREE_T)) # rotate if on vrail
1121+
board.Add(vrail_text)
1122+
# Right Edge
1123+
if (VERTICAL_EDGE_RAIL_WIDTH > 0.0) and (not FIDUCIALS_LR) and (not TITLE_Y):
1124+
titleblock_text = pcbnew.PCB_TEXT(board)
1125+
titleblock_text.SetText(EMPTY_EDGE_TEXT)
1126+
titleblock_text.SetTextSize(pcbnew.VECTOR2I(int(SCALE * RAIL_TEXT_SIZE), int(SCALE * RAIL_TEXT_SIZE)))
1127+
titleblock_text.SetLayer(pcbnew.F_SilkS)
1128+
titleblock_text.SetHorizJustify(pcbnew.GR_TEXT_H_ALIGN_LEFT)
1129+
titleblock_text.SetPosition(
1130+
pcbnew.VECTOR2I(
1131+
int(panelCenter.x + (panelWidth / 2 - VERTICAL_EDGE_RAIL_WIDTH / 2 * SCALE)),
1132+
int(panelCenter.y - (panelHeight / 2 - HORIZONTAL_EDGE_RAIL_WIDTH * SCALE - SCALE * FIDUCIAL_OFFSET * 2))
1133+
)
1134+
)
1135+
titleblock_text.SetTextAngle(pcbnew.EDA_ANGLE(-900, pcbnew.TENTHS_OF_A_DEGREE_T))
1136+
board.Add(titleblock_text)
1137+
10571138
# Save output
10581139
board.SetFileName(panelOutputFile)
10591140
board.Save(panelOutputFile)

0 commit comments

Comments
 (0)