diff --git a/kibot/out_any_layer.py b/kibot/out_any_layer.py index 9da0ea11..6f65216a 100644 --- a/kibot/out_any_layer.py +++ b/kibot/out_any_layer.py @@ -69,21 +69,7 @@ class AnyLayerOptions(BaseOptions): # We'll come back to this on a per-layer basis po.SetSkipPlotNPTH_Pads(False) - def run(self, output_dir, board, layers): - # fresh plot controller - plot_ctrl = PLOT_CONTROLLER(board) - # set up plot options for the whole output - po = plot_ctrl.GetPlotOptions() - self._configure_plot_ctrl(po, output_dir) - - # Gerber Job files aren't automagically created - # We need to assist KiCad - create_job = po.GetCreateGerberJobFile() - if create_job: - jobfile_writer = GERBER_JOBFILE_WRITER(board) - - plot_ctrl.SetColorMode(True) - + def filter_components(self, board): # Apply the variants and filters exclude = None if hasattr(self, 'variant') and (self.dnf_filter or self.variant): @@ -102,13 +88,15 @@ class AnyLayerOptions(BaseOptions): exclude.addLayer(board.GetLayerID('F.Paste')) exclude.addLayer(board.GetLayerID('B.Paste')) old_layers = [] + fadhes = board.GetLayerID('F.Adhes') + badhes = board.GetLayerID('B.Adhes') + old_fadhes = [] + old_badhes = [] for m in board.GetModules(): ref = m.GetReference() - # logger.debug('Ref {}'.format(ref)) c = comps_hash.get(ref, None) - # logger.debug('Component {}'.format(c)) if (c and not c.fitted) or m.GetAttributes() == UI_VIRTUAL: - # logger.debug('Removing') + # Remove all pads from *.Paste old_c_layers = [] for p in m.Pads(): pad_layers = p.GetLayerSet() @@ -116,9 +104,57 @@ class AnyLayerOptions(BaseOptions): pad_layers.removeLayerSet(exclude) p.SetLayerSet(pad_layers) old_layers.append(old_c_layers) + # Remove any graphical item in the *.Adhes layers + for gi in m.GraphicalItems(): + l_gi = gi.GetLayer() + if l_gi == fadhes: + gi.SetLayer(-1) + old_fadhes.append(gi) + if l_gi == badhes: + gi.SetLayer(-1) + old_badhes.append(gi) + # if gi.GetClass() == 'MGRAPHIC': + # logger.debug(gi.GetShapeStr()) + self.comps_hash = comps_hash + self.old_layers = old_layers + self.old_fadhes = old_fadhes + self.old_badhes = old_badhes + return exclude + def unfilter_components(self, board): + for m in board.GetModules(): + ref = m.GetReference() + c = self.comps_hash.get(ref, None) + if (c and not c.fitted) or m.GetAttributes() == UI_VIRTUAL: + restore = self.old_layers.pop(0) + for p in m.Pads(): + pad_layers = p.GetLayerSet() + res = restore.pop(0) + pad_layers.ParseHex(res, len(res)) + p.SetLayerSet(pad_layers) + fadhes = board.GetLayerID('F.Adhes') + for gi in self.old_fadhes: + gi.SetLayer(fadhes) + badhes = board.GetLayerID('B.Adhes') + for gi in self.old_badhes: + gi.SetLayer(badhes) + + def run(self, output_dir, board, layers): + # fresh plot controller + plot_ctrl = PLOT_CONTROLLER(board) + # set up plot options for the whole output + po = plot_ctrl.GetPlotOptions() + self._configure_plot_ctrl(po, output_dir) + # Gerber Job files aren't automagically created + # We need to assist KiCad + create_job = po.GetCreateGerberJobFile() + if create_job: + jobfile_writer = GERBER_JOBFILE_WRITER(board) + plot_ctrl.SetColorMode(True) + # Apply the variants and filters + exclude = self.filter_components(board) + # Plot every layer in the output layers = Layer.solve(layers) - # plot every layer in the output for la in layers: suffix = la.suffix desc = la.description @@ -129,13 +165,12 @@ class AnyLayerOptions(BaseOptions): # a copper layer is_cu = IsCopperLayer(id) po.SetSkipPlotNPTH_Pads(is_cu) - # Plot single layer to file logger.debug("Opening plot file for layer `{}` format `{}`".format(la, self._plot_format)) if not plot_ctrl.OpenPlotfile(suffix, self._plot_format, desc): # Shouldn't happen raise PlotError("OpenPlotfile failed!") # pragma: no cover - + # Compute the current file name and the one we want k_filename = plot_ctrl.GetPlotFileName() if self.output: filename = self.expand_filename(output_dir, self.output, suffix, os.path.splitext(k_filename)[1][1:]) @@ -148,21 +183,12 @@ class AnyLayerOptions(BaseOptions): os.rename(k_filename, filename) if create_job: jobfile_writer.AddGbrFile(id, os.path.basename(filename)) - + # Create the job file if create_job: jobfile_writer.CreateJobFile(self.expand_filename(output_dir, po.gerber_job_file, 'job', 'gbrjob')) # Restore the eliminated layers if exclude: - for m in board.GetModules(): - ref = m.GetReference() - c = comps_hash.get(ref, None) - if (c and not c.fitted) or m.GetAttributes() == UI_VIRTUAL: - restore = old_layers.pop(0) - for p in m.Pads(): - pad_layers = p.GetLayerSet() - res = restore.pop(0) - pad_layers.ParseHex(res, len(res)) - p.SetLayerSet(pad_layers) + self.unfilter_components(board) def read_vals_from_po(self, po): # excludeedgelayer diff --git a/tests/board_samples/kibom-variant_3.kicad_pcb b/tests/board_samples/kibom-variant_3.kicad_pcb index 09c6d31d..f626dd3f 100644 --- a/tests/board_samples/kibom-variant_3.kicad_pcb +++ b/tests/board_samples/kibom-variant_3.kicad_pcb @@ -172,6 +172,7 @@ (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1)) (fp_text user %R (at 0 0) (layer F.Fab) (effects (font (size 0.5 0.5) (thickness 0.08))) ) @@ -208,6 +209,7 @@ (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1)) (fp_text user %R (at 0 0) (layer F.Fab) (effects (font (size 0.5 0.5) (thickness 0.08))) ) @@ -243,6 +245,7 @@ (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1)) (fp_text user %R (at 0 0) (layer F.Fab) (effects (font (size 0.5 0.5) (thickness 0.08))) ) @@ -279,6 +282,7 @@ (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1)) (fp_text user %R (at 0 0) (layer F.Fab) (effects (font (size 0.5 0.5) (thickness 0.08))) ) diff --git a/tests/test_plot/test_gerber.py b/tests/test_plot/test_gerber.py index 3fa9de13..8bed0e56 100644 --- a/tests/test_plot/test_gerber.py +++ b/tests/test_plot/test_gerber.py @@ -91,12 +91,13 @@ def check_layers_exist(ctx, dir, prefix, layers, suffix): ctx.expect_out_file(compose_fname(dir, prefix, 'job', suffix, 'gbrjob')) -def check_components(ctx, dir, prefix, layer, suffix, exclude, include): - fname = compose_fname(dir, prefix, layer, suffix) - inc = [r'%TO\.C,{}\*%'.format(v) for v in include] - ctx.search_in_file(fname, inc) - exc = [r'%TO\.C,{}\*%'.format(v) for v in exclude] - ctx.search_not_in_file(fname, exc) +def check_components(ctx, dir, prefix, layers, suffix, exclude, include): + for layer in layers: + fname = compose_fname(dir, prefix, layer, suffix) + inc = [r'%TO\.C,{}\*%'.format(v) for v in include] + ctx.search_in_file(fname, inc) + exc = [r'%TO\.C,{}\*%'.format(v) for v in exclude] + ctx.search_not_in_file(fname, exc) def test_gerber_variant_1(): @@ -108,11 +109,11 @@ def test_gerber_variant_1(): # R3 is a component added to the PCB, included in all cases # variant: default directory: gerber components: R1, R2 and R3 check_layers_exist(ctx, 'gerber', prj, ALL_LAYERS, '') - check_components(ctx, 'gerber', prj, 'F_Paste', '', ['C1', 'C2'], ['R1', 'R2', 'R3']) + check_components(ctx, 'gerber', prj, ['F_Paste', 'F_Adhes'], '', ['C1', 'C2'], ['R1', 'R2', 'R3']) # variant: production directory: production components: R1, R2, R3 and C2 check_layers_exist(ctx, 'production', prj, ALL_LAYERS, '_(production)') - check_components(ctx, 'production', prj, 'F_Paste', '_(production)', ['C1'], ['R1', 'R2', 'R3', 'C2']) + check_components(ctx, 'production', prj, ['F_Paste', 'F_Adhes'], '_(production)', ['C1'], ['R1', 'R2', 'R3', 'C2']) # variant: test directory: test components: R1, R3 and C2 check_layers_exist(ctx, 'test', prj, ALL_LAYERS, '_(test)') - check_components(ctx, 'test', prj, 'F_Paste', '_(test)', ['C1', 'R2'], ['R1', 'R3', 'C2']) + check_components(ctx, 'test', prj, ['F_Paste', 'F_Adhes'], '_(test)', ['C1', 'R2'], ['R1', 'R3', 'C2']) ctx.clean_up()