From 2cea9925d5a2228b70a7f49c5183fe2a7bde7485 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Sat, 3 Dec 2022 18:38:28 -0300 Subject: [PATCH] [Panelize] Added preview option - Enabled for quick start --- README.md | 8 +++-- docs/samples/generic_plot.kibot.yaml | 8 +++-- kibot/globals.py | 3 +- kibot/gs.py | 10 ++++++ kibot/out_panelize.py | 33 ++++++++++++++++--- kibot/out_pcbdraw.py | 14 ++++---- kibot/pre_set_text_variables.py | 6 ++-- .../panelize/panel_4x4.kibot.yaml | 1 + 8 files changed, 61 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index f8f6afad..180c88f0 100644 --- a/README.md +++ b/README.md @@ -787,7 +787,8 @@ global: - `time_format`: [string='%H-%M-%S'] Format used for the time we started the script. Uses the `strftime` format. - `time_reformat`: [boolean=true] Tries to reformat the PCB/SCH date using the `date_format`. This assumes you let KiCad fill this value and hence the time is in ISO format (YY-MM-DD). - - `units`: [string=''] [millimeters,inches,mils] Default units. Affects `position` and `bom` outputs. Also KiCad 6 dimensions. + - `units`: [string=''] [millimeters,inches,mils] Default units. Affects `position`, `bom` and `panelize` outputs. + Also KiCad 6 dimensions. - `use_dir_for_preflights`: [boolean=true] Use the global `dir` as subdir for the preflights. - `variant`: [string=''] Default variant to apply to all outputs. @@ -2467,7 +2468,7 @@ Notes: KiKit 1.0.5 (the last to support KiCad 5) shown some incompatibilities. Note that you don't need to specify the units for all distances. - If they are omitted they are assumed to be `default_units`. + If they are omitted they are assumed to be `units`. The same is valid for angles, using `default_angles` * Valid keys: - **`comment`**: [string=''] A comment for documentation purposes. @@ -2764,14 +2765,15 @@ Notes: - `voffset`: [number|string] Specify the vertical offset from anchor. Respects KiCAD coordinate system. - `width`: [number|string] Width of the characters (the same parameters as KiCAD uses). - **`output`**: [string='%f-%i%I%v.%x'] Filename for the output (%i=panel, %x=kicad_pcb). Affected by global options. + - `create_preview`: [boolean=false] Use PcbDraw to create a preview of the panel. - `default_angles`: [string='deg'] [deg,°,rad] Angles used when omitted. - - `default_units`: [string='mm'] [mm,cm,dm,m,mil,inch,in] Units used when omitted. - `dnf_filter`: [string|list(string)='_none'] Name of the filter to mark components as not fitted. A short-cut to use for simple cases where a variant is an overkill. - `pre_transform`: [string|list(string)='_none'] Name of the filter to transform fields before applying other filters. A short-cut to use for simple cases where a variant is an overkill. - `title`: [string=''] Text used to replace the sheet title. %VALUE expansions are allowed. If it starts with `+` the text is concatenated. + - `units`: [string='mm'] [millimeters,inches,mils,mm,cm,dm,m,mil,inch,in] Units used when omitted. - `variant`: [string=''] Board variant to apply. - `category`: [string|list(string)=''] The category for this output. If not specified an internally defined category is used. Categories looks like file system paths, i.e. PCB/fabrication/gerber. diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 9ccf403a..4589978c 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -1214,7 +1214,7 @@ outputs: # KiKit 1.0.5 (the last to support KiCad 5) shown some # incompatibilities. # Note that you don't need to specify the units for all distances. - # If they are omitted they are assumed to be `default_units`. + # If they are omitted they are assumed to be `units`. # The same is valid for angles, using `default_angles` - name: 'panelize_example' comment: 'Creates a panel to fabricate various copies of the PCB at once.' @@ -1662,10 +1662,10 @@ outputs: type: 'none' # [number|string] Vertical offset from panel edges voffset: 0 + # [boolean=false] Use PcbDraw to create a preview of the panel + create_preview: false # [string='deg'] [deg,°,rad] Angles used when omitted default_angles: 'deg' - # [string='mm'] [mm,cm,dm,m,mil,inch,in] Units used when omitted - default_units: 'mm' # [string|list(string)='_none'] Name of the filter to mark components as not fitted. # A short-cut to use for simple cases where a variant is an overkill dnf_filter: '_none' @@ -1677,6 +1677,8 @@ outputs: # [string=''] Text used to replace the sheet title. %VALUE expansions are allowed. # If it starts with `+` the text is concatenated title: '' + # [string='mm'] [millimeters,inches,mils,mm,cm,dm,m,mil,inch,in] Units used when omitted + units: 'mm' # [string=''] Board variant to apply variant: '' # PCB Print: diff --git a/kibot/globals.py b/kibot/globals.py index 20b3e787..be55c558 100644 --- a/kibot/globals.py +++ b/kibot/globals.py @@ -226,7 +226,8 @@ class Globals(FiltersOptions): """ Tries to reformat the PCB/SCH date using the `date_format`. This assumes you let KiCad fill this value and hence the time is in ISO format (YY-MM-DD) """ self.units = '' - """ [millimeters,inches,mils] Default units. Affects `position` and `bom` outputs. Also KiCad 6 dimensions """ + """ [millimeters,inches,mils] Default units. Affects `position`, `bom` and `panelize` outputs. + Also KiCad 6 dimensions """ self.use_dir_for_preflights = True """ Use the global `dir` as subdir for the preflights """ self.variant = '' diff --git a/kibot/gs.py b/kibot/gs.py index df894f93..5b5ee222 100644 --- a/kibot/gs.py +++ b/kibot/gs.py @@ -395,6 +395,10 @@ class GS(object): """ Will be repplaced by kiplot.py """ raise AssertionError() + @staticmethod + def load_board_low_level(file): + return pcbnew.LoadBoard(file) + @staticmethod def load_sch(): """ Will be repplaced by kiplot.py """ @@ -423,6 +427,12 @@ class GS(object): """ Looks for a dependency """ return GS.check_tool_dep(context, name, fatal=False) + @staticmethod + def reload_project(pro_name): + sm = pcbnew.GetSettingsManager() + sm.UnloadProject(GS.board.GetProject(), False) + assert sm.LoadProject(pro_name) + @staticmethod def get_resource_path(name): # Try relative to the script diff --git a/kibot/out_panelize.py b/kibot/out_panelize.py index ac009bc0..d674265b 100644 --- a/kibot/out_panelize.py +++ b/kibot/out_panelize.py @@ -16,7 +16,8 @@ import json from tempfile import NamedTemporaryFile from .error import KiPlotConfigurationError from .gs import GS -from .kiplot import run_command +from .kiplot import run_command, config_output + from .layer import Layer from .misc import W_PANELEMPTY from .optionable import BaseOptions @@ -49,7 +50,7 @@ class PanelOptions(BaseOptions): if val is None: continue if isinstance(val, (int, float)): - setattr(self, op, str(val)+self._parent._parent.default_units) + setattr(self, op, str(val)+self._parent._parent.units) else: m = PanelOptions._num_regex.match(val) if m is None: @@ -583,6 +584,7 @@ class PanelizeConfig(PanelOptions): class PanelizeOptions(VariantOptions): _extends_regex = re.compile(r'(.+)\[(.+)\]') + _unit_alias = {'millimeters': 'mm', 'inches': 'inch', 'mils': 'mil'} def __init__(self): with document: @@ -596,10 +598,12 @@ class PanelizeOptions(VariantOptions): self.title = '' """ Text used to replace the sheet title. %VALUE expansions are allowed. If it starts with `+` the text is concatenated """ - self.default_units = 'mm' - """ [mm,cm,dm,m,mil,inch,in] Units used when omitted """ + self.units = 'mm' + """ [millimeters,inches,mils,mm,cm,dm,m,mil,inch,in] Units used when omitted """ self.default_angles = 'deg' """ [deg,°,rad] Angles used when omitted """ + self.create_preview = False + """ Use PcbDraw to create a preview of the panel """ super().__init__() self._expand_id = 'panel' self._expand_ext = 'kicad_pcb' @@ -684,6 +688,7 @@ class PanelizeOptions(VariantOptions): if configs: list(map(self.solve_extends, filter(lambda x: 'extends' in x, configs))) super().config(parent) + self.units = PanelizeOptions._unit_alias.get(self.units, self.units) if isinstance(self.configs, type): logger.warning(W_PANELEMPTY+'Generating a panel with default options, not very useful') self.configs = [] @@ -705,6 +710,23 @@ class PanelizeOptions(VariantOptions): f.write(js) return f.name + def create_preview_file(self, name): + if not self.create_preview or not os.path.isfile(name): + return + img_name = os.path.splitext(name)[0]+'.png' + tree = {'name': '_temporal_pcbdraw_preview', + 'type': 'pcbdraw', + 'comment': 'Internally created for panel preview', + 'options': {'output': img_name, 'variant': '', 'format': 'png'}} + out = RegOutput.get_class_for('pcbdraw')() + out.set_tree(tree) + config_output(out) + logger.debug('Loading PCB panel ...') + board = GS.load_board_low_level(name) + logger.debug('Creating preview image ...') + out.options.create_image(img_name, board) + GS.reload_project(GS.pro_file) + def run(self, output): cmd_kikit, version = self.ensure_tool_get_ver('KiKit') if GS.ki5 and version >= (1, 1, 0): @@ -742,6 +764,7 @@ class PanelizeOptions(VariantOptions): cmd.append(output) try: run_command(cmd) + self.create_preview_file(output) finally: # Remove temporals for f in to_remove: @@ -763,7 +786,7 @@ class Panelize(BaseOutput): # noqa: F821 KiKit 1.0.5 (the last to support KiCad 5) shown some incompatibilities. Note that you don't need to specify the units for all distances. - If they are omitted they are assumed to be `default_units`. + If they are omitted they are assumed to be `units`. The same is valid for angles, using `default_angles` """ def __init__(self): super().__init__() diff --git a/kibot/out_pcbdraw.py b/kibot/out_pcbdraw.py index 5fc67605..5d1d7f08 100644 --- a/kibot/out_pcbdraw.py +++ b/kibot/out_pcbdraw.py @@ -431,8 +431,7 @@ class PcbDrawOptions(VariantOptions): plot_components.highlight = lambda ref: ref in highlight_set return plot_components - def run(self, name): - super().run(name) + def create_image(self, name, board): self.ensure_tool('LXML') from .PcbDraw.plot import PcbPlotter, PlotPaste, PlotPlaceholders, PlotSubstrate, PlotVCuts # Select a name and format that PcbDraw can handle @@ -449,11 +448,8 @@ class PcbDrawOptions(VariantOptions): self.convert_command = self.ensure_tool('ImageMagick') save_output_name = _get_tmp_name('.png') - # Apply any variant - self.filter_pcb_components(GS.board, do_3D=True) - try: - plotter = PcbPlotter(GS.board) + plotter = PcbPlotter(board) # Read libs from KiBot resources plotter.setup_arbitrary_data_path(GS.get_resource_path('pcbdraw')) # Libs indicated by PCBDRAW_LIB_PATH @@ -522,6 +518,12 @@ class PcbDrawOptions(VariantOptions): _run_command(cmd) os.remove(save_output_name) + def run(self, name): + super().run(name) + # Apply any variant + self.filter_pcb_components(GS.board, do_3D=True) + # Create the image + self.create_image(name, GS.board) # Undo the variant self.unfilter_pcb_components(GS.board, do_3D=True) diff --git a/kibot/pre_set_text_variables.py b/kibot/pre_set_text_variables.py index 0a5d05b3..11c8307c 100644 --- a/kibot/pre_set_text_variables.py +++ b/kibot/pre_set_text_variables.py @@ -10,7 +10,6 @@ Dependencies: """ import json import os -import pcbnew import re from subprocess import run, PIPE import sys @@ -150,8 +149,7 @@ class Set_Text_Variables(BasePreFlight): # noqa: F821 f.write(json.dumps(data, sort_keys=True, indent=2)) if GS.board: # Force a project reload - sm = pcbnew.GetSettingsManager() - sm.UnloadProject(GS.board.GetProject(), False) - assert sm.LoadProject(pro_name) + GS.reload_project(pro_name) + # TODO: Do we really need to reload the PCB? # Force the PCB reload (will reload the project file) GS.board = None diff --git a/kibot/resources/config_templates/panelize/panel_4x4.kibot.yaml b/kibot/resources/config_templates/panelize/panel_4x4.kibot.yaml index 275718e4..60c3cfc6 100644 --- a/kibot/resources/config_templates/panelize/panel_4x4.kibot.yaml +++ b/kibot/resources/config_templates/panelize/panel_4x4.kibot.yaml @@ -10,6 +10,7 @@ outputs: options: title: '+ (Panel)' default_units: mm + create_preview: true configs: - layout: rows: 4