Moved sub-PCB specific stuff to var_base (from out_base)
- To allow more than one mechanism - Also changed the order in which sub-PCBs are applied, will make things faster - Also removed board as parameter for un/filter_pcb* Isn't really supported and the sub-PCBs clearly breaks it
This commit is contained in:
parent
bae5e91c7a
commit
1dbe58aab1
|
|
@ -159,7 +159,7 @@ class AnyDrill(VariantOptions):
|
|||
|
||||
def run(self, output_dir):
|
||||
super().run(output_dir)
|
||||
self.filter_pcb_components(GS.board)
|
||||
self.filter_pcb_components()
|
||||
if self.output:
|
||||
output_dir = os.path.dirname(output_dir)
|
||||
# dialog_gendrill.cpp:357
|
||||
|
|
@ -187,7 +187,7 @@ class AnyDrill(VariantOptions):
|
|||
drill_report_file = self.expand_filename(output_dir, self.report, 'drill_report', 'txt')
|
||||
logger.debug("Generating drill report: "+drill_report_file)
|
||||
drill_writer.GenDrillReportFile(drill_report_file)
|
||||
self.unfilter_pcb_components(GS.board)
|
||||
self.unfilter_pcb_components()
|
||||
|
||||
def get_targets(self, out_dir):
|
||||
targets = []
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ class AnyLayerOptions(VariantOptions):
|
|||
def run(self, output_dir, layers):
|
||||
super().run(output_dir)
|
||||
# Apply the variants and filters
|
||||
exclude = self.filter_pcb_components(GS.board)
|
||||
exclude = self.filter_pcb_components()
|
||||
# fresh plot controller
|
||||
plot_ctrl = PLOT_CONTROLLER(GS.board)
|
||||
# set up plot options for the whole output
|
||||
|
|
@ -185,7 +185,7 @@ class AnyLayerOptions(VariantOptions):
|
|||
f.write(content)
|
||||
# Restore the eliminated layers
|
||||
if exclude:
|
||||
self.unfilter_pcb_components(GS.board)
|
||||
self.unfilter_pcb_components()
|
||||
|
||||
def solve_extension(self, layer):
|
||||
if self._plot_format == PLOT_FORMAT_GERBER and self.use_protel_extensions:
|
||||
|
|
|
|||
|
|
@ -57,12 +57,12 @@ class Any_PCB_PrintOptions(VariantOptions):
|
|||
def filter_components(self):
|
||||
if not self.will_filter_pcb_components() and self.title == '':
|
||||
return GS.pcb_file, None
|
||||
self.filter_pcb_components(GS.board)
|
||||
self.filter_pcb_components()
|
||||
self.set_title(self.title)
|
||||
# Save the PCB to a temporal dir
|
||||
fname, pcb_dir = self.save_tmp_dir_board('pdf_pcb_print')
|
||||
self.restore_title()
|
||||
self.unfilter_pcb_components(GS.board)
|
||||
self.unfilter_pcb_components()
|
||||
return fname, pcb_dir
|
||||
|
||||
def get_targets(self, out_dir):
|
||||
|
|
|
|||
|
|
@ -105,14 +105,14 @@ class Stencil_Options(VariantOptions):
|
|||
self.ensure_tool('Xvfb')
|
||||
super().run(output)
|
||||
# Apply variants and filters
|
||||
filtered = self.filter_pcb_components(GS.board)
|
||||
filtered = self.filter_pcb_components()
|
||||
if self.side == 'auto':
|
||||
detected_top, detected_bottom = self.detect_solder_paste(GS.board)
|
||||
else:
|
||||
detected_top = detected_bottom = False
|
||||
fname = self.save_tmp_board() if filtered else GS.pcb_file
|
||||
if filtered:
|
||||
self.unfilter_pcb_components(GS.board)
|
||||
self.unfilter_pcb_components()
|
||||
# Avoid running the tool if we will generate useless models
|
||||
if self.side == 'auto' and not detected_top and not detected_bottom:
|
||||
logger.warning(W_AUTONONE+'No solder paste detected, skipping stencil generation')
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ from glob import glob
|
|||
import math
|
||||
import os
|
||||
import re
|
||||
from tempfile import NamedTemporaryFile, mkdtemp, TemporaryDirectory
|
||||
from tempfile import NamedTemporaryFile, mkdtemp
|
||||
from .gs import GS
|
||||
from .kiplot import load_sch, get_board_comps_data, load_board
|
||||
from .kiplot import load_sch, get_board_comps_data
|
||||
from .misc import Rect, W_WRONGPASTE, DISABLE_3D_MODEL_TEXT, W_NOCRTYD
|
||||
if not GS.kicad_version_n:
|
||||
# When running the regression tests we need it
|
||||
|
|
@ -366,6 +366,7 @@ class VariantOptions(BaseOptions):
|
|||
""" Remove from solder paste layers the filtered components. """
|
||||
if comps_hash is None or not (GS.global_remove_solder_paste_for_dnp or GS.global_remove_adhesive_for_dnp):
|
||||
return
|
||||
logger.debug('Removing paste and glue')
|
||||
exclude = LSET()
|
||||
fpaste = board.GetLayerID('F.Paste')
|
||||
bpaste = board.GetLayerID('B.Paste')
|
||||
|
|
@ -398,16 +399,22 @@ class VariantOptions(BaseOptions):
|
|||
logger.warning(W_WRONGPASTE+'Pad with solder paste, but no copper or solder mask aperture in '+ref)
|
||||
p.SetLayerSet(pad_layers)
|
||||
old_layers.append(old_c_layers)
|
||||
logger.debugl(3, '- Removed paste from '+ref)
|
||||
# Remove any graphical item in the *.Adhes layers
|
||||
if GS.global_remove_adhesive_for_dnp:
|
||||
found = False
|
||||
for gi in m.GraphicalItems():
|
||||
l_gi = gi.GetLayer()
|
||||
if l_gi == fadhes:
|
||||
gi.SetLayer(rescue)
|
||||
old_fadhes.append(gi)
|
||||
found = True
|
||||
if l_gi == badhes:
|
||||
gi.SetLayer(rescue)
|
||||
old_badhes.append(gi)
|
||||
found = True
|
||||
if found:
|
||||
logger.debugl(3, '- Removed adhesive from '+ref)
|
||||
# Store the data to undo the above actions
|
||||
self.old_layers = old_layers
|
||||
self.old_fadhes = old_fadhes
|
||||
|
|
@ -419,11 +426,13 @@ class VariantOptions(BaseOptions):
|
|||
def restore_paste_and_glue(self, board, comps_hash):
|
||||
if comps_hash is None:
|
||||
return
|
||||
logger.debug('Restoring paste and glue')
|
||||
if GS.global_remove_solder_paste_for_dnp:
|
||||
for m in GS.get_modules_board(board):
|
||||
ref = m.GetReference()
|
||||
c = comps_hash.get(ref, None)
|
||||
if c and c.included and not c.fitted:
|
||||
logger.debugl(3, '- Restoring paste for '+ref)
|
||||
restore = self.old_layers.pop(0)
|
||||
for p in m.Pads():
|
||||
pad_layers = p.GetLayerSet()
|
||||
|
|
@ -714,91 +723,54 @@ class VariantOptions(BaseOptions):
|
|||
m.Models().pop()
|
||||
self._highlighted_3D_components = None
|
||||
|
||||
def apply_sub_pcb(self):
|
||||
with TemporaryDirectory(prefix='kibot-separate') as d:
|
||||
dest = os.path.join(d, os.path.basename(GS.pcb_file))
|
||||
# Save the current PCB, with any changes applied
|
||||
with NamedTemporaryFile(mode='w', suffix='.kicad_pcb', delete=False) as f:
|
||||
pcb_file = f.name
|
||||
GS.board.Save(pcb_file)
|
||||
if self._comps:
|
||||
# Memorize the used modules
|
||||
old_modules = {m.GetReference() for m in GS.get_modules()}
|
||||
# Now do the separation
|
||||
self._sub_pcb.load_board(pcb_file, dest)
|
||||
# Remove the temporal PCB
|
||||
os.remove(pcb_file)
|
||||
# Compute the modules we removed
|
||||
self._excl_by_sub_pcb = set()
|
||||
# Now reflect it in the list of components
|
||||
if self._comps:
|
||||
logger.debug('Removing components outside the sub-PCB')
|
||||
# Memorize the used modules
|
||||
new_modules = {m.GetReference() for m in GS.get_modules()}
|
||||
diff = old_modules - new_modules
|
||||
logger.debugl(3, diff)
|
||||
# Exclude them from _comps
|
||||
for c in diff:
|
||||
cmp = self.comps_hash[c]
|
||||
if cmp.included:
|
||||
cmp.included = False
|
||||
self._excl_by_sub_pcb.add(c)
|
||||
logger.debugl(2, '- Removing '+c)
|
||||
|
||||
def will_filter_pcb_components(self):
|
||||
""" True if we will apply filters/variants """
|
||||
return self._comps or self._sub_pcb
|
||||
|
||||
def filter_pcb_components(self, board, do_3D=False, do_2D=True, highlight=None):
|
||||
def filter_pcb_components(self, do_3D=False, do_2D=True, highlight=None):
|
||||
if not self.will_filter_pcb_components():
|
||||
return False
|
||||
self.comps_hash = self.get_refs_hash()
|
||||
if self._sub_pcb:
|
||||
self._sub_pcb.apply(self.comps_hash)
|
||||
if self._comps:
|
||||
self.comps_hash = self.get_refs_hash()
|
||||
if do_2D:
|
||||
self.cross_modules(board, self.comps_hash)
|
||||
self.remove_paste_and_glue(board, self.comps_hash)
|
||||
self.cross_modules(GS.board, self.comps_hash)
|
||||
self.remove_paste_and_glue(GS.board, self.comps_hash)
|
||||
if hasattr(self, 'hide_excluded') and self.hide_excluded:
|
||||
self.remove_fab(board, self.comps_hash)
|
||||
self.remove_fab(GS.board, self.comps_hash)
|
||||
# Copy any change in the schematic fields to the PCB properties
|
||||
# I.e. the value of a component so it gets updated in the *.Fab layer
|
||||
# Also useful for iBoM that can read the sch fields from the PCB
|
||||
self.sch_fields_to_pcb(board, self.comps_hash)
|
||||
self.sch_fields_to_pcb(GS.board, self.comps_hash)
|
||||
if do_3D:
|
||||
# Disable the models that aren't for this variant
|
||||
self.apply_3D_variant_aspect(board)
|
||||
self.apply_3D_variant_aspect(GS.board)
|
||||
# Remove the 3D models for not fitted components (also rename)
|
||||
self.remove_3D_models(board, self.comps_hash)
|
||||
self.remove_3D_models(GS.board, self.comps_hash)
|
||||
# Highlight selected components
|
||||
self.highlight_3D_models(board, highlight)
|
||||
if self._sub_pcb:
|
||||
# Current implementation isn't efficient
|
||||
self.apply_sub_pcb()
|
||||
self.highlight_3D_models(GS.board, highlight)
|
||||
return True
|
||||
|
||||
def unfilter_pcb_components(self, board, do_3D=False, do_2D=True):
|
||||
def unfilter_pcb_components(self, do_3D=False, do_2D=True):
|
||||
if not self.will_filter_pcb_components():
|
||||
return
|
||||
if self._sub_pcb:
|
||||
# Undo the sub-PCB: just reload the PCB
|
||||
GS.board = None
|
||||
load_board()
|
||||
for c in self._excl_by_sub_pcb:
|
||||
self.comps_hash[c].included = True
|
||||
return
|
||||
if do_2D:
|
||||
self.uncross_modules(board, self.comps_hash)
|
||||
self.restore_paste_and_glue(board, self.comps_hash)
|
||||
if do_2D and self.comps_hash:
|
||||
self.uncross_modules(GS.board, self.comps_hash)
|
||||
self.restore_paste_and_glue(GS.board, self.comps_hash)
|
||||
if hasattr(self, 'hide_excluded') and self.hide_excluded:
|
||||
self.restore_fab(board, self.comps_hash)
|
||||
self.restore_fab(GS.board, self.comps_hash)
|
||||
# Restore the PCB properties and values
|
||||
self.restore_sch_fields_to_pcb(board)
|
||||
if do_3D:
|
||||
self.restore_sch_fields_to_pcb(GS.board)
|
||||
if do_3D and self.comps_hash:
|
||||
# Undo the removing (also rename)
|
||||
self.restore_3D_models(board, self.comps_hash)
|
||||
self.restore_3D_models(GS.board, self.comps_hash)
|
||||
# Re-enable the modules that aren't for this variant
|
||||
self.apply_3D_variant_aspect(board, enable=True)
|
||||
self.apply_3D_variant_aspect(GS.board, enable=True)
|
||||
# Remove the highlight 3D object
|
||||
self.unhighlight_3D_models(board)
|
||||
self.unhighlight_3D_models(GS.board)
|
||||
if self._sub_pcb:
|
||||
self._sub_pcb.revert(self.comps_hash)
|
||||
|
||||
def remove_highlight_3D_file(self):
|
||||
# Remove the highlight 3D file if it was created
|
||||
|
|
@ -894,11 +866,11 @@ class VariantOptions(BaseOptions):
|
|||
if not self.will_filter_pcb_components() and not new_title:
|
||||
return GS.pcb_file
|
||||
logger.debug('Creating modified PCB')
|
||||
self.filter_pcb_components(GS.board, do_3D=do_3D)
|
||||
self.filter_pcb_components(do_3D=do_3D)
|
||||
self.set_title(new_title)
|
||||
fname = self.save_tmp_board()
|
||||
self.restore_title()
|
||||
self.unfilter_pcb_components(GS.board, do_3D=do_3D)
|
||||
self.unfilter_pcb_components(do_3D=do_3D)
|
||||
to_remove.extend(GS.get_pcb_and_pro_names(fname))
|
||||
logger.debug('- Modified PCB: '+fname)
|
||||
return fname
|
||||
|
|
|
|||
|
|
@ -201,10 +201,10 @@ class Base3DOptions(VariantOptions):
|
|||
self.undo_3d_models_rename(GS.board)
|
||||
return ret
|
||||
return GS.pcb_file
|
||||
self.filter_pcb_components(GS.board, do_3D=True, do_2D=True, highlight=highlight)
|
||||
self.filter_pcb_components(do_3D=True, do_2D=True, highlight=highlight)
|
||||
self.download_models()
|
||||
fname = self.save_tmp_board()
|
||||
self.unfilter_pcb_components(GS.board, do_3D=True, do_2D=True)
|
||||
self.unfilter_pcb_components(do_3D=True, do_2D=True)
|
||||
return fname
|
||||
|
||||
def get_targets(self, out_dir):
|
||||
|
|
|
|||
|
|
@ -162,10 +162,10 @@ class BoardViewOptions(VariantOptions):
|
|||
|
||||
def run(self, output):
|
||||
super().run(output)
|
||||
self.filter_pcb_components(GS.board)
|
||||
self.filter_pcb_components()
|
||||
with open(output, 'wt') as f:
|
||||
convert(GS.board, f)
|
||||
self.unfilter_pcb_components(GS.board)
|
||||
self.unfilter_pcb_components()
|
||||
|
||||
def get_targets(self, out_dir):
|
||||
return [self._parent.expand_filename(out_dir, self.output)]
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class Copy_FilesOptions(Base3DOptions):
|
|||
dest_dir = dest_dir[:-1]
|
||||
f.output_dir = dest_dir
|
||||
# Apply any variant
|
||||
self.filter_pcb_components(GS.board, do_3D=True, do_2D=True)
|
||||
self.filter_pcb_components(do_3D=True, do_2D=True)
|
||||
# Download missing models and rename all collect 3D models (renamed)
|
||||
f.rel_dirs = self.rel_dirs
|
||||
files_list = self.download_models(rename_filter=f.source, rename_function=FilesList.apply_rename, rename_data=f)
|
||||
|
|
@ -139,7 +139,7 @@ class Copy_FilesOptions(Base3DOptions):
|
|||
# We must undo the download/rename
|
||||
self.undo_3d_models_rename(GS.board)
|
||||
else:
|
||||
self.unfilter_pcb_components(GS.board, do_3D=True, do_2D=True)
|
||||
self.unfilter_pcb_components(do_3D=True, do_2D=True)
|
||||
# Also include the step/wrl counterpart
|
||||
new_list = []
|
||||
for fn in files_list:
|
||||
|
|
|
|||
|
|
@ -184,9 +184,9 @@ class IBoMOptions(VariantOptions):
|
|||
with open(netlist, 'wb') as f:
|
||||
GS.sch.save_netlist(f, self._comps)
|
||||
# Write a board with the filtered values applied
|
||||
self.filter_pcb_components(GS.board)
|
||||
self.filter_pcb_components()
|
||||
pcb_name, _ = self.save_tmp_dir_board('ibom', force_dir=net_dir)
|
||||
self.unfilter_pcb_components(GS.board)
|
||||
self.unfilter_pcb_components()
|
||||
else:
|
||||
# Check if the user wants extra_fields but there is no data about them (#68)
|
||||
if self.need_extra_fields() and not os.path.isfile(self.extra_data_file):
|
||||
|
|
|
|||
|
|
@ -1142,9 +1142,9 @@ class PCB_PrintOptions(VariantOptions):
|
|||
svgutils = importlib.import_module('.svgutils.transform', package=__package__)
|
||||
global kicad_worksheet
|
||||
kicad_worksheet = importlib.import_module('.kicad.worksheet', package=__package__)
|
||||
self.filter_pcb_components(GS.board)
|
||||
self.filter_pcb_components()
|
||||
self.generate_output(output)
|
||||
self.unfilter_pcb_components(GS.board)
|
||||
self.unfilter_pcb_components()
|
||||
|
||||
|
||||
@output_class
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ class PCB_Variant_Options(VariantOptions):
|
|||
|
||||
def run(self, output):
|
||||
super().run(output)
|
||||
self.filter_pcb_components(GS.board, do_3D=True)
|
||||
self.filter_pcb_components(do_3D=True)
|
||||
self.set_title(self.title)
|
||||
logger.debug('Saving PCB to '+output)
|
||||
GS.board.Save(output)
|
||||
if self.copy_project:
|
||||
GS.copy_project(output)
|
||||
self.restore_title()
|
||||
self.unfilter_pcb_components(GS.board, do_3D=True)
|
||||
self.unfilter_pcb_components(do_3D=True)
|
||||
|
||||
|
||||
@output_class
|
||||
|
|
|
|||
|
|
@ -521,11 +521,11 @@ class PcbDrawOptions(VariantOptions):
|
|||
def run(self, name):
|
||||
super().run(name)
|
||||
# Apply any variant
|
||||
self.filter_pcb_components(GS.board, do_3D=True)
|
||||
self.filter_pcb_components(do_3D=True)
|
||||
# Create the image
|
||||
self.create_image(name, GS.board)
|
||||
# Undo the variant
|
||||
self.unfilter_pcb_components(GS.board, do_3D=True)
|
||||
self.unfilter_pcb_components(do_3D=True)
|
||||
|
||||
|
||||
@output_class
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ class PositionOptions(VariantOptions):
|
|||
|
||||
def run(self, fname):
|
||||
super().run(fname)
|
||||
self.filter_pcb_components(GS.board)
|
||||
self.filter_pcb_components()
|
||||
output_dir = os.path.dirname(fname)
|
||||
columns = self.columns.values()
|
||||
conv = GS.unit_name_to_scale_factor(self.units)
|
||||
|
|
@ -304,7 +304,7 @@ class PositionOptions(VariantOptions):
|
|||
self._do_position_plot_ascii(output_dir, columns, modules, maxlengths, modules_side)
|
||||
else: # if self.format == 'CSV':
|
||||
self._do_position_plot_csv(output_dir, columns, modules, modules_side)
|
||||
self.unfilter_pcb_components(GS.board)
|
||||
self.unfilter_pcb_components()
|
||||
|
||||
|
||||
@output_class
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
|
||||
# License: GPL-3.0
|
||||
# Project: KiBot (formerly KiPlot)
|
||||
import os
|
||||
from tempfile import NamedTemporaryFile, TemporaryDirectory
|
||||
from .registrable import RegVariant
|
||||
from .optionable import Optionable, PanelOptions
|
||||
from .fil_base import apply_exclude_filter, apply_fitted_filter, apply_fixed_filter, apply_pre_transform
|
||||
|
|
@ -11,6 +13,9 @@ from .misc import KIKIT_UNIT_ALIASES
|
|||
from .gs import GS
|
||||
from .kiplot import load_board, run_command
|
||||
from .macros import macros, document # noqa: F401
|
||||
from . import log
|
||||
|
||||
logger = log.get_logger()
|
||||
|
||||
|
||||
class SubPCBOptions(PanelOptions):
|
||||
|
|
@ -66,15 +71,59 @@ class SubPCBOptions(PanelOptions):
|
|||
return "annotation; ref: {}".format(self.reference)
|
||||
return "rectangle; tlx: {}; tly: {}; brx: {}; bry: {}".format(self.tlx, self.tly, self.brx, self.bry)
|
||||
|
||||
def load_board(self, pcb_file, dest):
|
||||
def load_board(self, comps_hash):
|
||||
""" Apply the sub-PCB using an external tool and load it into memory """
|
||||
# Make sure kikit is available
|
||||
command = GS.ensure_tool('global', 'KiKit')
|
||||
# Execute the separate
|
||||
cmd = [command, 'separate', '-s', self.get_separate_source(), pcb_file, dest]
|
||||
run_command(cmd)
|
||||
# Load this board
|
||||
with TemporaryDirectory(prefix='kibot-separate') as d:
|
||||
dest = os.path.join(d, os.path.basename(GS.pcb_file))
|
||||
# Save the current PCB, with any changes applied
|
||||
with NamedTemporaryFile(mode='w', suffix='.kicad_pcb', delete=False) as f:
|
||||
pcb_file = f.name
|
||||
GS.board.Save(pcb_file)
|
||||
if comps_hash:
|
||||
# Memorize the used modules
|
||||
old_modules = {m.GetReference() for m in GS.get_modules()}
|
||||
# Now do the separation
|
||||
cmd = [command, 'separate', '-s', self.get_separate_source(), pcb_file, dest]
|
||||
# Execute the separate
|
||||
run_command(cmd)
|
||||
# Load this board
|
||||
GS.board = None
|
||||
load_board(dest)
|
||||
# Remove the temporal PCB
|
||||
os.remove(pcb_file)
|
||||
self._excl_by_sub_pcb = set()
|
||||
# Now reflect the changes in the list of components
|
||||
if comps_hash:
|
||||
logger.debug('Removing components outside the sub-PCB')
|
||||
# Memorize the used modules
|
||||
new_modules = {m.GetReference() for m in GS.get_modules()}
|
||||
# Compute the modules we removed
|
||||
diff = old_modules - new_modules
|
||||
logger.debugl(3, diff)
|
||||
# Exclude them from _comps
|
||||
for c in diff:
|
||||
cmp = comps_hash[c]
|
||||
if cmp.included:
|
||||
cmp.included = False
|
||||
self._excl_by_sub_pcb.add(c)
|
||||
logger.debugl(2, '- Removing '+c)
|
||||
|
||||
def apply(self, comps_hash):
|
||||
if True:
|
||||
self.load_board(comps_hash)
|
||||
|
||||
def unload_board(self, comps_hash):
|
||||
# Undo the sub-PCB: just reload the PCB
|
||||
GS.board = None
|
||||
load_board(dest)
|
||||
load_board()
|
||||
for c in self._excl_by_sub_pcb:
|
||||
comps_hash[c].included = True
|
||||
|
||||
def revert(self, comps_hash):
|
||||
if True:
|
||||
self.unload_board(comps_hash)
|
||||
|
||||
|
||||
class BaseVariant(RegVariant):
|
||||
|
|
|
|||
|
|
@ -71,4 +71,5 @@ outputs:
|
|||
dir: PopulateWithFilter
|
||||
options:
|
||||
renderer: KiCad_3D
|
||||
# renderer: PcbDraw
|
||||
input: tests/data/with_filter_html.md
|
||||
|
|
|
|||
Loading…
Reference in New Issue