diff options
-rw-r--r-- | main_dialog.fbp | 416 | ||||
-rw-r--r-- | mesh_dialog.py | 142 | ||||
-rw-r--r-- | mesh_plugin_dialog.py | 39 |
3 files changed, 556 insertions, 41 deletions
diff --git a/main_dialog.fbp b/main_dialog.fbp index 9852735..d97f4c0 100644 --- a/main_dialog.fbp +++ b/main_dialog.fbp @@ -48,7 +48,7 @@ <property name="minimum_size"></property> <property name="name">MainDialog</property> <property name="pos"></property> - <property name="size">632,458</property> + <property name="size">632,580</property> <property name="style">wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSTAY_ON_TOP</property> <property name="subclass">; ; forward_declare</property> <property name="title">Security Mesh Generator Plugin</property> @@ -64,6 +64,68 @@ <property name="permission">none</property> <object class="sizeritem" expanded="true"> <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label"><font color="red"><b>Warning: Board outline not found</b></font></property> + <property name="markup">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_warningLabel</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxALIGN_CENTER_HORIZONTAL</property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <property name="wrap">-1</property> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> <property name="flag">wxEXPAND</property> <property name="proportion">1</property> <object class="wxFlexGridSizer" expanded="true"> @@ -1333,6 +1395,358 @@ </object> </object> </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="spacer" expanded="true"> + <property name="height">0</property> + <property name="permission">protected</property> + <property name="width">0</property> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">1</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Respect zone keepouts</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_useKeepoutCheckbox</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="spacer" expanded="true"> + <property name="height">0</property> + <property name="permission">protected</property> + <property name="width">0</property> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">1</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Respect board outline</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_useOutlineCheckbox</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="spacer" expanded="true"> + <property name="height">0</property> + <property name="permission">protected</property> + <property name="width">0</property> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">1</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Save layout visualizations</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_vizCheckbox</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Visualization output directory</property> + <property name="markup">0</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticText14</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <property name="wrap">-1</property> + </object> + </object> + <object class="sizeritem" expanded="true"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxTextCtrl" expanded="true"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_accept_files">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="maxlength"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_vizTextfield</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; ; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + </object> + </object> </object> </object> <object class="sizeritem" expanded="true"> diff --git a/mesh_dialog.py b/mesh_dialog.py index 9812bba..17dcf6a 100644 --- a/mesh_dialog.py +++ b/mesh_dialog.py @@ -8,6 +8,7 @@ from itertools import count, islice import json import re from os import path +import os import wx @@ -30,16 +31,20 @@ class AbortError(SystemError): @dataclasses.dataclass class GeneratorSettings: - edge_clearance: float = 1.5 # mm - anchor: str = None # Footprint designator - chamfer: float = 0.0 # unit fraction - mask_layer_id: int = 0 # kicad layer id, populated later - random_seed: str = None - randomness: float = 1.0 + edge_clearance: float = 1.5 # mm + anchor: str = None # Footprint designator + chamfer: float = 0.0 # unit fraction + mask_layer_id: int = 0 # kicad layer id, populated later + random_seed: str = None + randomness: float = 1.0 + use_keepouts: bool = True + use_outline: bool = True + save_visualization: bool = True + visualization_path: str = 'mesh_visualizations' def serialize(self): d = dataclasses.asdict(self) - d['kimesh_settings_version'] = '2.0.0' + d['kimesh_settings_version'] = '2.1.0' return json.dumps(d).encode() @classmethod @@ -47,7 +52,7 @@ class GeneratorSettings: d = json.loads(data.decode()) version = d.pop('kimesh_settings_version') vtup = tuple(map(int, version.split('.'))) - if vtup > (2, 0, 0): + if vtup > (2, 1, 0): raise cls.VersionError("Project kimesh settings file is too new for this plugin's version.") return cls(**d) @@ -69,6 +74,7 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog): self.nets = { str(wxs) for wxs, netinfo in board.GetNetsByName().items() } self.update_net_label(None) + self.update_outline_warning() self.Fit() @@ -104,9 +110,64 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog): self.m_seedInput.Value = settings.random_seed or '' self.m_randomnessSpin.Value = settings.randomness*100.0 self.m_edgeClearanceSpin.Value = settings.edge_clearance + self.m_useOutlineCheckbox.Value = settings.use_outline + self.m_useKeepoutCheckbox.Value = settings.use_keepouts + self.m_vizTextfield.Value = settings.visualization_path + self.m_vizCheckbox.Value = settings.save_visualization self.SetMinSize(self.GetSize()) + @contextmanager + def viz(self, filename): + if self.m_vizCheckbox.Value: + val = self.m_vizTextfield.Value + project_dir = path.dirname(self.board.GetFileName()) + if val: + val = path.join(project_dir, val) + if not os.path.isdir(val): + os.mkdir(val) + filename = path.join(val, filename) + + filename = path.join(project_dir, filename) + with open(filename, 'w') as f: + wrapper = DebugOutputWrapper(f) + yield wrapper + wrapper.save() + + else: + wrapper = DebugOutputWrapper(None) + yield wrapper + + def board_has_outline(self): + # KiCad's API is absolutely insane. As long as the board has an outline, the board outline function works + # alright. Now imagine the Edge.Cuts layer is empty. What would be a sane thing to do? I guess raising an error + # would be the best, with the second best being to return something like the hull of all objects on the other + # layers. Alas, KiCad doesn't do either. Instead, KiCad returns the union of the shapes of all objects on the + # **VISIBLE** layers, so the result of that outline function changes with which layers the user has set to + # visible. Whyyyyy :( + # + # We have to work around this to avoid presenting the user with a foot-gun in case they hide their mesh + # definition layer. + # + edge_cuts = self.board.GetLayerID('Edge.Cuts') + outline_objs = [] + for drawing in self.board.GetDrawings(): + if drawing.GetLayer() == edge_cuts: + return True + else: + return False + + def update_outline_warning(self): + outlines = pcbnew.SHAPE_POLY_SET() + self.board.GetBoardPolygonOutlines(outlines) + board_outlines = list(self.poly_set_to_shapely(outlines)) + board_mask = shapely.ops.unary_union(board_outlines) + + if not self.board_has_outline() or board_mask.is_empty: + self.m_warningLabel.SetLabelMarkup('<b>Warning: Board outline not found</b>') + else: + self.m_warningLabel.SetLabelMarkup('') + def get_matching_nets(self): prefix = self.m_net_prefix.Value return { net for net in self.nets if net.startswith(prefix) } @@ -170,7 +231,11 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog): chamfer = float(self.m_chamferSpin.Value)/100.0, mask_layer_id = self.m_maskLayerChoice.GetSelection(), random_seed = str(self.m_seedInput.Value) or None, - randomness = float(self.m_randomnessSpin.Value)/100.0) + randomness = float(self.m_randomnessSpin.Value)/100.0, + use_outline = self.m_useOutlineCheckbox.Value, + use_keepouts = self.m_useKeepoutCheckbox.Value, + visualization_path = self.m_vizTextfield.Value, + save_visualization = self.m_vizCheckbox.Value) except ValueError as e: return wx.MessageDialog(self, "Invalid input value: {}.".format(e), "Invalid input").ShowModal() @@ -198,29 +263,37 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog): keepouts.append(zone.Outline()) print(f'Found {len(keepouts)} keepout areas.') - outlines = pcbnew.SHAPE_POLY_SET() - self.board.GetBoardPolygonOutlines(outlines) - board_outlines = list(self.poly_set_to_shapely(outlines)) - board_mask = shapely.ops.unary_union(board_outlines) - board_mask = board_mask.buffer(-settings.edge_clearance) - print('board outline bounds:', board_mask.bounds) - if board_mask.is_empty: - return wx.MessageDialog(self, "Error: Could not find the board outline, or board edge clearance is set too high.").ShowModal() + if self.board_has_outline() and self.m_useOutlineCheckbox.Value: # Avoid foot-gun due to insane API. See note in the function. + outlines = pcbnew.SHAPE_POLY_SET() + self.board.GetBoardPolygonOutlines(outlines) + board_outlines = list(self.poly_set_to_shapely(outlines)) + board_mask = shapely.ops.unary_union(board_outlines) + mask = board_mask.buffer(-settings.edge_clearance) + print('board outline bounds:', mask.bounds) + if mask.is_empty: + return wx.MessageDialog(self, "Error: Board edge clearance is set too high. There is nothing left for the mesh after applying clearance.").ShowModal() + else: + mask = None zone_outlines = [ outline for zone in mesh_zones for outline in self.poly_set_to_shapely(zone) ] zone_mask = shapely.ops.unary_union(zone_outlines) if zone_mask.is_empty: - mask = board_mask + return wx.MessageDialog(self, "Error: Empty mesh outline on mesh outline layer. Make sure the mesh outline is defined with polygon objects only. Other shapes are not supported yet.").ShowModal() + elif mask is None: + mask = zone_mask else: - mask = zone_mask.intersection(board_mask) + mask = zone_mask.intersection(mask) print('Mesh mask bounds:', zone_mask.bounds) - keepout_outlines = [ outline for zone in keepouts for outline in self.poly_set_to_shapely(zone) ] - keepout_mask = shapely.ops.unary_union(keepout_outlines) - if not keepout_mask.is_empty: - mask = shapely.difference(mask, keepout_mask) - print('keepout mask bounds:', keepout_mask.bounds) - print('resulting mask bounds:', mask.bounds) + if self.m_useKeepoutCheckbox.Value: + keepout_outlines = [ outline for zone in keepouts for outline in self.poly_set_to_shapely(zone) ] + keepout_mask = shapely.ops.unary_union(keepout_outlines) + if not keepout_mask.is_empty: + mask = shapely.difference(mask, keepout_mask) + print('keepout mask bounds:', keepout_mask.bounds) + print('resulting mask bounds:', mask.bounds) + if mask.is_empty: + return wx.MessageDialog(self, "Error: After applying all keepouts, and intersecting with the board's outline, the mesh outline is empty.") try: def warn(msg): @@ -307,7 +380,7 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog): grid.append(row) num_valid = 0 - with DebugOutput('dbg_grid.svg') as dbg: + with self.viz('mesh_grid.svg') as dbg: dbg.add(mask, color='#00000020') for y, row in enumerate(grid, start=grid_y0): @@ -389,10 +462,10 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog): not_visited = { (x, y) for x in range(grid_x0, grid_x0+grid_cols) for y in range(grid_y0, grid_y0+grid_rows) if is_valid(grid[y-grid_y0][x-grid_x0]) } num_to_visit = len(not_visited) track_count = 0 - with DebugOutput('dbg_cells.svg') as dbg_cells,\ - DebugOutput('dbg_composite.svg') as dbg_composite,\ - DebugOutput('dbg_tiles.svg') as dbg_tiles,\ - DebugOutput('dbg_traces.svg') as dbg_traces: + with self.viz('mesh_cells.svg') as dbg_cells,\ + self.viz('mesh_composite.svg') as dbg_composite,\ + self.viz('mesh_tiles.svg') as dbg_tiles,\ + self.viz('mesh_traces.svg') as dbg_traces: dbg_cells.add(mask, color='#00000020') dbg_composite.add(mask, color='#00000020') dbg_traces.add(mask, color='#00000020') @@ -425,7 +498,7 @@ class MeshPluginMainDialog(mesh_plugin_dialog.MainDialog): i = 0 past_tiles = {} def dump_output(i): - with DebugOutput(f'per-tile/step{i}.svg') as dbg_per_tile: + with self.viz(f'per-tile/step{i}.svg') as dbg_per_tile: dbg_per_tile.add(mask, color='#00000020') for foo in anchor_outlines: dbg_per_tile.add(foo, color='#00000080', stroke_width=0.05, stroke_color='#00000000') @@ -607,13 +680,6 @@ def virihex(val, max=1.0, alpha=1.0): r, g, b, a = [ int(round(0xff*c)) for c in [r, g, b, alpha] ] return f'#{r:02x}{g:02x}{b:02x}{a:02x}' -@contextmanager -def DebugOutput(filename): - with open(filename, 'w') as f: - wrapper = DebugOutputWrapper(f) - yield wrapper - wrapper.save() - class DebugOutputWrapper: def __init__(self, f): self.f = f diff --git a/mesh_plugin_dialog.py b/mesh_plugin_dialog.py index 6223481..790caa8 100644 --- a/mesh_plugin_dialog.py +++ b/mesh_plugin_dialog.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- ########################################################################### -## Python code generated with wxFormBuilder (version 3.10.1-367-gf0e67a69) +## Python code generated with wxFormBuilder (version 3.10.1-380-gf48f2659) ## http://www.wxformbuilder.org/ ## ## PLEASE DO *NOT* EDIT THIS FILE! @@ -17,12 +17,18 @@ import wx.xrc class MainDialog ( wx.Dialog ): def __init__( self, parent ): - wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Security Mesh Generator Plugin", pos = wx.DefaultPosition, size = wx.Size( 632,458 ), style = wx.CLOSE_BOX|wx.DEFAULT_DIALOG_STYLE|wx.MINIMIZE_BOX|wx.RESIZE_BORDER|wx.STAY_ON_TOP ) + wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Security Mesh Generator Plugin", pos = wx.DefaultPosition, size = wx.Size( 632,580 ), style = wx.CLOSE_BOX|wx.DEFAULT_DIALOG_STYLE|wx.MINIMIZE_BOX|wx.RESIZE_BORDER|wx.STAY_ON_TOP ) self.SetSizeHints( wx.DefaultSize, wx.DefaultSize ) bSizer1 = wx.BoxSizer( wx.VERTICAL ) + self.m_warningLabel = wx.StaticText( self, wx.ID_ANY, u"<font color=\"red\"><b>Warning: Board outline not found</b></font>", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTER_HORIZONTAL ) + self.m_warningLabel.SetLabelMarkup( u"<font color=\"red\"><b>Warning: Board outline not found</b></font>" ) + self.m_warningLabel.Wrap( -1 ) + + bSizer1.Add( self.m_warningLabel, 0, wx.ALL|wx.EXPAND, 5 ) + fgSizer1 = wx.FlexGridSizer( 0, 2, 0, 0 ) fgSizer1.AddGrowableCol( 1 ) fgSizer1.SetFlexibleDirection( wx.BOTH ) @@ -138,6 +144,35 @@ class MainDialog ( wx.Dialog ): fgSizer1.Add( bSizer12, 1, wx.EXPAND, 5 ) + fgSizer1.Add( ( 0, 0), 1, wx.EXPAND, 5 ) + + self.m_useKeepoutCheckbox = wx.CheckBox( self, wx.ID_ANY, u"Respect zone keepouts", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.m_useKeepoutCheckbox.SetValue(True) + fgSizer1.Add( self.m_useKeepoutCheckbox, 0, wx.ALL, 5 ) + + + fgSizer1.Add( ( 0, 0), 1, wx.EXPAND, 5 ) + + self.m_useOutlineCheckbox = wx.CheckBox( self, wx.ID_ANY, u"Respect board outline", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.m_useOutlineCheckbox.SetValue(True) + fgSizer1.Add( self.m_useOutlineCheckbox, 0, wx.ALL, 5 ) + + + fgSizer1.Add( ( 0, 0), 1, wx.EXPAND, 5 ) + + self.m_vizCheckbox = wx.CheckBox( self, wx.ID_ANY, u"Save layout visualizations", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.m_vizCheckbox.SetValue(True) + fgSizer1.Add( self.m_vizCheckbox, 0, wx.ALL, 5 ) + + self.m_staticText14 = wx.StaticText( self, wx.ID_ANY, u"Visualization output directory", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.m_staticText14.Wrap( -1 ) + + fgSizer1.Add( self.m_staticText14, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 5 ) + + self.m_vizTextfield = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ) + fgSizer1.Add( self.m_vizTextfield, 0, wx.ALL|wx.EXPAND, 5 ) + + bSizer1.Add( fgSizer1, 1, wx.EXPAND, 5 ) bSizer99 = wx.BoxSizer( wx.HORIZONTAL ) |