[Variants] Added some limited support for `kikit separate`
This commit is contained in:
parent
fafd5d2f6d
commit
da2d5f1001
|
|
@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Fixed
|
||||
- New output:
|
||||
- `vrml` export the 3D model in Virtual Reality Modeling Language (#349)
|
||||
- Variants:
|
||||
- Added some limited support for `kikit separate`
|
||||
- PCB_Print:
|
||||
- Images not showing in custom frames. (#352)
|
||||
|
||||
|
|
|
|||
67
README.md
67
README.md
|
|
@ -146,6 +146,7 @@ Notes:
|
|||
|
||||
[**KiKit**](https://github.com/yaqwsx/KiKit) [](https://github.com/yaqwsx/KiKit) 
|
||||
- Mandatory for: `panelize`, `stencil_3d`, `stencil_for_jig`
|
||||
- Optional to separate multiboard projects for general use
|
||||
|
||||
[**LXML**](https://pypi.org/project/LXML/) [](https://pypi.org/project/LXML/) [](https://packages.debian.org/bullseye/python3-lxml) 
|
||||
- Mandatory for: `pcb_print`, `pcbdraw`
|
||||
|
|
@ -1038,6 +1039,28 @@ Note that the **_kibom_...** filters uses a field named `Config`, but you can cu
|
|||
Use '_var_rename' to transform VARIANT:FIELD fields.
|
||||
Use '_var_rename_kicost' to transform kicost.VARIANT:FIELD fields.
|
||||
Use '_kicost_rename' to apply KiCost field rename rules.
|
||||
- `sub_pcbs`: [list(dict)] Used for multi-board workflows as defined by KiKit.
|
||||
I don't recommend using it, for detail read
|
||||
[this](https://github.com/INTI-CMNB/KiBot/tree/master/docs/1_SCH_2_part_PCBs).
|
||||
But if you really need it you can define the sub-PCBs here.
|
||||
Then you just use *VARIANT[SUB_PCB_NAME]* instead of just *VARIANT*.
|
||||
* Valid keys:
|
||||
- **`name`**: [string=''] Name for this sub-pcb.
|
||||
- *ref*: Alias for reference.
|
||||
- **`reference`**: [string=''] Use it for the annotations method.
|
||||
This is the reference for the `kikit:Board` footprint used to identify the sub-PCB.
|
||||
When empty the sub-PCB is specified using a rectangle.
|
||||
- *bottom_right_x*: Alias for brx.
|
||||
- *bottom_right_y*: Alias for bry.
|
||||
- `brx`: [number|string] The X position of the bottom right corner for the rectangle that contains the sub-PCB.
|
||||
- `bry`: [number|string] The Y position of the bottom right corner for the rectangle that contains the sub-PCB.
|
||||
- `file_id`: [string=''] Text to use as the replacement for %v expansion.
|
||||
When empty we use the parent `file_id` plus the `name` of the sub-PCB.
|
||||
- `tlx`: [number|string] The X position of the top left corner for the rectangle that contains the sub-PCB.
|
||||
- `tly`: [number|string] The Y position of the top left corner for the rectangle that contains the sub-PCB.
|
||||
- *top_left_x*: Alias for tlx.
|
||||
- *top_left_y*: Alias for tly.
|
||||
- `units`: [string='mm'] [millimeters,inches,mils,mm,cm,dm,m,mil,inch,in] Units used when omitted.
|
||||
- `variant_field`: [string='Config'] Name of the field that stores board variant for component.
|
||||
- `variants_blacklist`: [string|list(string)=''] List of board variants to exclude from the BOM.
|
||||
- `variants_whitelist`: [string|list(string)=''] List of board variants to include in the BOM.
|
||||
|
|
@ -1061,6 +1084,28 @@ Note that the **_kibom_...** filters uses a field named `Config`, but you can cu
|
|||
Use '_var_rename' to transform VARIANT:FIELD fields.
|
||||
Use '_var_rename_kicost' to transform kicost.VARIANT:FIELD fields.
|
||||
Use '_kicost_rename' to apply KiCost field rename rules.
|
||||
- `sub_pcbs`: [list(dict)] Used for multi-board workflows as defined by KiKit.
|
||||
I don't recommend using it, for detail read
|
||||
[this](https://github.com/INTI-CMNB/KiBot/tree/master/docs/1_SCH_2_part_PCBs).
|
||||
But if you really need it you can define the sub-PCBs here.
|
||||
Then you just use *VARIANT[SUB_PCB_NAME]* instead of just *VARIANT*.
|
||||
* Valid keys:
|
||||
- **`name`**: [string=''] Name for this sub-pcb.
|
||||
- *ref*: Alias for reference.
|
||||
- **`reference`**: [string=''] Use it for the annotations method.
|
||||
This is the reference for the `kikit:Board` footprint used to identify the sub-PCB.
|
||||
When empty the sub-PCB is specified using a rectangle.
|
||||
- *bottom_right_x*: Alias for brx.
|
||||
- *bottom_right_y*: Alias for bry.
|
||||
- `brx`: [number|string] The X position of the bottom right corner for the rectangle that contains the sub-PCB.
|
||||
- `bry`: [number|string] The Y position of the bottom right corner for the rectangle that contains the sub-PCB.
|
||||
- `file_id`: [string=''] Text to use as the replacement for %v expansion.
|
||||
When empty we use the parent `file_id` plus the `name` of the sub-PCB.
|
||||
- `tlx`: [number|string] The X position of the top left corner for the rectangle that contains the sub-PCB.
|
||||
- `tly`: [number|string] The Y position of the top left corner for the rectangle that contains the sub-PCB.
|
||||
- *top_left_x*: Alias for tlx.
|
||||
- *top_left_y*: Alias for tly.
|
||||
- `units`: [string='mm'] [millimeters,inches,mils,mm,cm,dm,m,mil,inch,in] Units used when omitted.
|
||||
- `variant`: [string|list(string)=''] Board variant(s).
|
||||
- `kicost`: KiCost variant style
|
||||
The `variant` field (configurable) contains one or more values.
|
||||
|
|
@ -1086,6 +1131,28 @@ Note that the **_kibom_...** filters uses a field named `Config`, but you can cu
|
|||
- `separators`: [string=',;/ '] Valid separators for variants in the variant field.
|
||||
Each character is a valid separator.
|
||||
Only supported internally, don't use it if you plan to use KiCost.
|
||||
- `sub_pcbs`: [list(dict)] Used for multi-board workflows as defined by KiKit.
|
||||
I don't recommend using it, for detail read
|
||||
[this](https://github.com/INTI-CMNB/KiBot/tree/master/docs/1_SCH_2_part_PCBs).
|
||||
But if you really need it you can define the sub-PCBs here.
|
||||
Then you just use *VARIANT[SUB_PCB_NAME]* instead of just *VARIANT*.
|
||||
* Valid keys:
|
||||
- **`name`**: [string=''] Name for this sub-pcb.
|
||||
- *ref*: Alias for reference.
|
||||
- **`reference`**: [string=''] Use it for the annotations method.
|
||||
This is the reference for the `kikit:Board` footprint used to identify the sub-PCB.
|
||||
When empty the sub-PCB is specified using a rectangle.
|
||||
- *bottom_right_x*: Alias for brx.
|
||||
- *bottom_right_y*: Alias for bry.
|
||||
- `brx`: [number|string] The X position of the bottom right corner for the rectangle that contains the sub-PCB.
|
||||
- `bry`: [number|string] The Y position of the bottom right corner for the rectangle that contains the sub-PCB.
|
||||
- `file_id`: [string=''] Text to use as the replacement for %v expansion.
|
||||
When empty we use the parent `file_id` plus the `name` of the sub-PCB.
|
||||
- `tlx`: [number|string] The X position of the top left corner for the rectangle that contains the sub-PCB.
|
||||
- `tly`: [number|string] The Y position of the top left corner for the rectangle that contains the sub-PCB.
|
||||
- *top_left_x*: Alias for tlx.
|
||||
- *top_left_y*: Alias for tly.
|
||||
- `units`: [string='mm'] [millimeters,inches,mils,mm,cm,dm,m,mil,inch,in] Units used when omitted.
|
||||
- `variant`: [string=''] Variants to match (regex).
|
||||
- `variant_field`: [string='variant'] Name of the field that stores board variant/s for component.
|
||||
Only supported internally, don't use it if you plan to use KiCost.
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ Dependencies:
|
|||
github: yaqwsx/KiKit
|
||||
pypi: KiKit
|
||||
downloader: pytool
|
||||
- from: KiKit
|
||||
role: Separate multiboard projects
|
||||
- name: Xvfbwrapper
|
||||
python_module: true
|
||||
debian: python3-xvfbwrapper
|
||||
|
|
|
|||
|
|
@ -268,6 +268,7 @@ USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
|
|||
DISABLE_3D_MODEL_TEXT = '_Disabled_by_KiBot'
|
||||
RENDERERS = ['pcbdraw', 'render_3d']
|
||||
PCB_GENERATORS = ['pcb_variant', 'panelize']
|
||||
KIKIT_UNIT_ALIASES = {'millimeters': 'mm', 'inches': 'inch', 'mils': 'mil'}
|
||||
|
||||
|
||||
class Rect(object):
|
||||
|
|
|
|||
|
|
@ -501,3 +501,49 @@ class BaseOptions(Optionable):
|
|||
self._expand_id = cur_id
|
||||
self._expand_ext = cur_ext
|
||||
return res
|
||||
|
||||
|
||||
class PanelOptions(BaseOptions):
|
||||
""" A class for options that uses KiKit's units """
|
||||
_num_regex = re.compile(r'([\d\.]+)(mm|cm|dm|m|mil|inch|in)')
|
||||
_ang_regex = re.compile(r'([\d\.]+)(deg|°|rad)')
|
||||
|
||||
def add_units(self, ops, def_units=None):
|
||||
if def_units is None:
|
||||
def_units = self._parent._parent.units
|
||||
for op in ops:
|
||||
val = getattr(self, op)
|
||||
if val is None:
|
||||
continue
|
||||
if isinstance(val, (int, float)):
|
||||
setattr(self, op, str(val)+def_units)
|
||||
else:
|
||||
m = PanelOptions._num_regex.match(val)
|
||||
if m is None:
|
||||
raise KiPlotConfigurationError('Malformed value `{}: {}` must be a number and units'.format(op, val))
|
||||
num = m.group(1)
|
||||
try:
|
||||
num_d = float(num)
|
||||
except ValueError:
|
||||
num_d = None
|
||||
if num_d is None:
|
||||
raise KiPlotConfigurationError('Malformed number in `{}` ({})'.format(op, num))
|
||||
|
||||
def add_angle(self, ops, def_units=None):
|
||||
if def_units is None:
|
||||
def_units = self._parent._parent.units
|
||||
for op in ops:
|
||||
val = getattr(self, op)
|
||||
if isinstance(val, (int, float)):
|
||||
setattr(self, op, str(val)+def_units)
|
||||
else:
|
||||
m = PanelOptions._ang_regex.match(val)
|
||||
if m is None:
|
||||
raise KiPlotConfigurationError('Malformed angle `{}: {}` must be a number and its type'.format(op, val))
|
||||
num = m.group(1)
|
||||
try:
|
||||
num_d = float(num)
|
||||
except ValueError:
|
||||
num_d = None
|
||||
if num_d is None:
|
||||
raise KiPlotConfigurationError('Malformed number in `{}` ({})'.format(op, num))
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ from glob import glob
|
|||
import math
|
||||
import os
|
||||
import re
|
||||
from tempfile import NamedTemporaryFile, mkdtemp
|
||||
from tempfile import NamedTemporaryFile, mkdtemp, TemporaryDirectory
|
||||
from .gs import GS
|
||||
from .kiplot import load_sch, get_board_comps_data
|
||||
from .kiplot import load_sch, get_board_comps_data, load_board
|
||||
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
|
||||
|
|
@ -710,27 +710,41 @@ 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))
|
||||
self._sub_pcb.load_board(dest)
|
||||
|
||||
def filter_pcb_components(self, board, do_3D=False, do_2D=True, highlight=None):
|
||||
if not self._comps:
|
||||
if not self._comps and not self._sub_pcb:
|
||||
return False
|
||||
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)
|
||||
if hasattr(self, 'hide_excluded') and self.hide_excluded:
|
||||
self.remove_fab(board, self.comps_hash)
|
||||
if do_3D:
|
||||
# Disable the models that aren't for this variant
|
||||
self.apply_3D_variant_aspect(board)
|
||||
# Remove the 3D models for not fitted components (also rename)
|
||||
self.remove_3D_models(board, self.comps_hash)
|
||||
# Highlight selected components
|
||||
self.highlight_3D_models(board, highlight)
|
||||
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)
|
||||
if hasattr(self, 'hide_excluded') and self.hide_excluded:
|
||||
self.remove_fab(board, self.comps_hash)
|
||||
if do_3D:
|
||||
# Disable the models that aren't for this variant
|
||||
self.apply_3D_variant_aspect(board)
|
||||
# Remove the 3D models for not fitted components (also rename)
|
||||
self.remove_3D_models(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()
|
||||
return True
|
||||
|
||||
def unfilter_pcb_components(self, board, do_3D=False, do_2D=True):
|
||||
if not self._comps:
|
||||
return
|
||||
if self._sub_pcb:
|
||||
# Undo the sub-PCB: just reload the PCB
|
||||
GS.board = None
|
||||
load_board()
|
||||
return
|
||||
if do_2D:
|
||||
self.uncross_modules(board, self.comps_hash)
|
||||
self.restore_paste_and_glue(board, self.comps_hash)
|
||||
|
|
@ -918,4 +932,7 @@ class VariantOptions(BaseOptions):
|
|||
if self.variant:
|
||||
# Apply the variant
|
||||
comps = self.variant.filter(comps)
|
||||
self._sub_pcb = self.variant._sub_pcb
|
||||
else:
|
||||
self._sub_pcb = None
|
||||
self._comps = comps
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@ from tempfile import NamedTemporaryFile
|
|||
from .error import KiPlotConfigurationError
|
||||
from .gs import GS
|
||||
from .kiplot import run_command, config_output
|
||||
|
||||
from .layer import Layer
|
||||
from .misc import W_PANELEMPTY
|
||||
from .optionable import BaseOptions
|
||||
from .misc import W_PANELEMPTY, KIKIT_UNIT_ALIASES
|
||||
from .optionable import PanelOptions
|
||||
from .out_base import VariantOptions
|
||||
from .registrable import RegOutput
|
||||
from .macros import macros, document, output_class # noqa: F401
|
||||
|
|
@ -40,47 +39,6 @@ def update_dict(d, u):
|
|||
return d
|
||||
|
||||
|
||||
class PanelOptions(BaseOptions):
|
||||
_num_regex = re.compile(r'([\d\.]+)(mm|cm|dm|m|mil|inch|in)')
|
||||
_ang_regex = re.compile(r'([\d\.]+)(deg|°|rad)')
|
||||
|
||||
def add_units(self, ops):
|
||||
for op in ops:
|
||||
val = getattr(self, op)
|
||||
if val is None:
|
||||
continue
|
||||
if isinstance(val, (int, float)):
|
||||
setattr(self, op, str(val)+self._parent._parent.units)
|
||||
else:
|
||||
m = PanelOptions._num_regex.match(val)
|
||||
if m is None:
|
||||
raise KiPlotConfigurationError('Malformed value `{}: {}` must be a number and units'.format(op, val))
|
||||
num = m.group(1)
|
||||
try:
|
||||
num_d = float(num)
|
||||
except ValueError:
|
||||
num_d = None
|
||||
if num_d is None:
|
||||
raise KiPlotConfigurationError('Malformed number in `{}` ({})'.format(op, num))
|
||||
|
||||
def add_angle(self, ops):
|
||||
for op in ops:
|
||||
val = getattr(self, op)
|
||||
if isinstance(val, (int, float)):
|
||||
setattr(self, op, str(val)+self._parent._parent.default_angles)
|
||||
else:
|
||||
m = PanelOptions._ang_regex.match(val)
|
||||
if m is None:
|
||||
raise KiPlotConfigurationError('Malformed angle `{}: {}` must be a number and its type'.format(op, val))
|
||||
num = m.group(1)
|
||||
try:
|
||||
num_d = float(num)
|
||||
except ValueError:
|
||||
num_d = None
|
||||
if num_d is None:
|
||||
raise KiPlotConfigurationError('Malformed number in `{}` ({})'.format(op, num))
|
||||
|
||||
|
||||
class PanelOptionsWithPlugin(PanelOptions):
|
||||
def __init__(self):
|
||||
with document:
|
||||
|
|
@ -584,7 +542,6 @@ class PanelizeConfig(PanelOptions):
|
|||
|
||||
class PanelizeOptions(VariantOptions):
|
||||
_extends_regex = re.compile(r'(.+)\[(.+)\]')
|
||||
_unit_alias = {'millimeters': 'mm', 'inches': 'inch', 'mils': 'mil'}
|
||||
|
||||
def __init__(self):
|
||||
with document:
|
||||
|
|
@ -688,7 +645,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)
|
||||
self.units = KIKIT_UNIT_ALIASES.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 = []
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
# License: GPL-3.0
|
||||
# Project: KiBot (formerly KiPlot)
|
||||
from collections import OrderedDict
|
||||
from copy import copy
|
||||
from .optionable import Optionable
|
||||
from .error import KiPlotConfigurationError
|
||||
|
||||
|
|
@ -59,7 +60,21 @@ class RegOutput(Optionable, Registrable):
|
|||
|
||||
@staticmethod
|
||||
def add_variants(variants):
|
||||
RegOutput._def_variants.update(variants)
|
||||
for k, v in variants.items():
|
||||
# Do we have sub-PCBs
|
||||
if v.sub_pcbs:
|
||||
# Add a variant for each sub-PCB
|
||||
for sp in v.sub_pcbs:
|
||||
name = k+'['+sp.name+']'
|
||||
vn = copy(v)
|
||||
vn._sub_pcb = sp
|
||||
if sp.file_id:
|
||||
vn.file_id = sp.file_id
|
||||
else:
|
||||
vn.file_id += '_'+sp.name
|
||||
RegOutput._def_variants[name] = vn
|
||||
else:
|
||||
RegOutput._def_variants[k] = v
|
||||
|
||||
@staticmethod
|
||||
def is_variant(name):
|
||||
|
|
|
|||
|
|
@ -1,14 +1,82 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020-2021 Salvador E. Tropea
|
||||
# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial
|
||||
# Copyright (c) 2020-2022 Salvador E. Tropea
|
||||
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
|
||||
# License: GPL-3.0
|
||||
# Project: KiBot (formerly KiPlot)
|
||||
from .registrable import RegVariant
|
||||
from .optionable import Optionable
|
||||
from .optionable import Optionable, PanelOptions
|
||||
from .fil_base import apply_exclude_filter, apply_fitted_filter, apply_fixed_filter, apply_pre_transform
|
||||
from .error import KiPlotConfigurationError
|
||||
from .misc import KIKIT_UNIT_ALIASES
|
||||
from .gs import GS
|
||||
from .kiplot import load_board, run_command
|
||||
from .macros import macros, document # noqa: F401
|
||||
|
||||
|
||||
class SubPCBOptions(PanelOptions):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._unkown_is_error = True
|
||||
with document:
|
||||
self.name = ''
|
||||
""" *Name for this sub-pcb """
|
||||
self.reference = ''
|
||||
""" *Use it for the annotations method.
|
||||
This is the reference for the `kikit:Board` footprint used to identify the sub-PCB.
|
||||
When empty the sub-PCB is specified using a rectangle """
|
||||
self.ref = None
|
||||
""" {reference} """
|
||||
self.tlx = 0
|
||||
""" [number|string] The X position of the top left corner for the rectangle that contains the sub-PCB """
|
||||
self.top_left_x = None
|
||||
""" {tlx} """
|
||||
self.tly = 0
|
||||
""" [number|string] The Y position of the top left corner for the rectangle that contains the sub-PCB """
|
||||
self.top_left_y = None
|
||||
""" {tly} """
|
||||
self.brx = 0
|
||||
""" [number|string] The X position of the bottom right corner for the rectangle that contains the sub-PCB """
|
||||
self.bottom_right_x = None
|
||||
""" {brx} """
|
||||
self.bry = 0
|
||||
""" [number|string] The Y position of the bottom right corner for the rectangle that contains the sub-PCB """
|
||||
self.bottom_right_y = None
|
||||
""" {bry} """
|
||||
self.units = 'mm'
|
||||
""" [millimeters,inches,mils,mm,cm,dm,m,mil,inch,in] Units used when omitted """
|
||||
self.file_id = ''
|
||||
""" Text to use as the replacement for %v expansion.
|
||||
When empty we use the parent `file_id` plus the `name` of the sub-PCB """
|
||||
|
||||
def is_zero(self, val):
|
||||
return isinstance(val, (int, float)) and val == 0
|
||||
|
||||
def config(self, parent):
|
||||
super().config(parent)
|
||||
if not self.name:
|
||||
raise KiPlotConfigurationError('Sub-PCB without a name')
|
||||
self.units = KIKIT_UNIT_ALIASES.get(self.units, self.units)
|
||||
if (not self.reference and self.is_zero(self.tlx) and self.is_zero(self.tly) and self.is_zero(self.brx) and
|
||||
self.is_zero(self.bry)):
|
||||
raise KiPlotConfigurationError('No reference or rectangle specified for {} sub-PCB'.format(self.name))
|
||||
self.add_units(('tlx', 'tly', 'brx', 'bry'), self.units)
|
||||
|
||||
def get_separate_source(self):
|
||||
if self.reference:
|
||||
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, dest):
|
||||
# Make sure kikit is available
|
||||
command = GS.ensure_tool('global', 'KiKit')
|
||||
# Execute the separate
|
||||
cmd = [command, 'separate', '-s', self.get_separate_source(), GS.pcb_file, dest]
|
||||
run_command(cmd)
|
||||
# Load this board
|
||||
GS.board = None
|
||||
load_board(dest)
|
||||
|
||||
|
||||
class BaseVariant(RegVariant):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
|
@ -38,6 +106,18 @@ class BaseVariant(RegVariant):
|
|||
self.dnc_filter = Optionable
|
||||
""" [string|list(string)=''] Name of the filter to mark components as 'Do Not Change'.
|
||||
Use '_kibom_dnc' for the default KiBoM behavior """
|
||||
self.sub_pcbs = SubPCBOptions
|
||||
""" [list(dict)] Used for multi-board workflows as defined by KiKit.
|
||||
I don't recommend using it, for detail read
|
||||
[this](https://github.com/INTI-CMNB/KiBot/tree/master/docs/1_SCH_2_part_PCBs).
|
||||
But if you really need it you can define the sub-PCBs here.
|
||||
Then you just use *VARIANT[SUB_PCB_NAME]* instead of just *VARIANT* """
|
||||
self._sub_pcb = None
|
||||
|
||||
def config(self, parent):
|
||||
super().config(parent)
|
||||
if isinstance(self.sub_pcbs, type):
|
||||
self.sub_pcbs = []
|
||||
|
||||
def get_variant_field(self):
|
||||
""" Returns the name of the field used to determine if the component belongs to the variant """
|
||||
|
|
|
|||
|
|
@ -576,17 +576,24 @@ deps = '{\
|
|||
"extra_arch": null,\
|
||||
"extra_deb": null,\
|
||||
"help_option": "--version",\
|
||||
"importance": 30000,\
|
||||
"importance": 30100,\
|
||||
"in_debian": false,\
|
||||
"is_kicad_plugin": false,\
|
||||
"is_python": false,\
|
||||
"name": "KiKit",\
|
||||
"no_cmd_line_version": false,\
|
||||
"no_cmd_line_version_old": false,\
|
||||
"output": "panelize",\
|
||||
"output": "global",\
|
||||
"plugin_dirs": null,\
|
||||
"pypi_name": "KiKit",\
|
||||
"roles": [\
|
||||
{\
|
||||
"desc": "Separate multiboard projects",\
|
||||
"mandatory": false,\
|
||||
"max_version": null,\
|
||||
"output": "global",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
|
|
|
|||
|
|
@ -0,0 +1,173 @@
|
|||
(kicad_pcb (version 20171130) (host pcbnew 5.1.9-73d0e3b20d~88~ubuntu20.04.1)
|
||||
|
||||
(general
|
||||
(thickness 1.6)
|
||||
(drawings 18)
|
||||
(tracks 0)
|
||||
(zones 0)
|
||||
(modules 3)
|
||||
(nets 1)
|
||||
)
|
||||
|
||||
(page A4)
|
||||
(layers
|
||||
(0 F.Cu signal)
|
||||
(31 B.Cu signal)
|
||||
(32 B.Adhes user)
|
||||
(33 F.Adhes user)
|
||||
(34 B.Paste user)
|
||||
(35 F.Paste user)
|
||||
(36 B.SilkS user)
|
||||
(37 F.SilkS user)
|
||||
(38 B.Mask user)
|
||||
(39 F.Mask user)
|
||||
(40 Dwgs.User user)
|
||||
(41 Cmts.User user)
|
||||
(42 Eco1.User user)
|
||||
(43 Eco2.User user)
|
||||
(44 Edge.Cuts user)
|
||||
(45 Margin user)
|
||||
(46 B.CrtYd user)
|
||||
(47 F.CrtYd user)
|
||||
(48 B.Fab user)
|
||||
(49 F.Fab user)
|
||||
)
|
||||
|
||||
(setup
|
||||
(last_trace_width 0.25)
|
||||
(trace_clearance 0.2)
|
||||
(zone_clearance 0.508)
|
||||
(zone_45_only no)
|
||||
(trace_min 0.2)
|
||||
(via_size 0.8)
|
||||
(via_drill 0.4)
|
||||
(via_min_size 0.4)
|
||||
(via_min_drill 0.3)
|
||||
(uvia_size 0.3)
|
||||
(uvia_drill 0.1)
|
||||
(uvias_allowed no)
|
||||
(uvia_min_size 0.2)
|
||||
(uvia_min_drill 0.1)
|
||||
(edge_width 0.2)
|
||||
(segment_width 0.2)
|
||||
(pcb_text_width 0.3)
|
||||
(pcb_text_size 1.5 1.5)
|
||||
(mod_edge_width 0.12)
|
||||
(mod_text_size 1 1)
|
||||
(mod_text_width 0.15)
|
||||
(pad_size 1.524 1.524)
|
||||
(pad_drill 0.762)
|
||||
(pad_to_mask_clearance 0)
|
||||
(aux_axis_origin 0 0)
|
||||
(visible_elements FFFFFF7F)
|
||||
(pcbplotparams
|
||||
(layerselection 0x010fc_ffffffff)
|
||||
(usegerberextensions false)
|
||||
(usegerberattributes true)
|
||||
(usegerberadvancedattributes true)
|
||||
(creategerberjobfile true)
|
||||
(excludeedgelayer true)
|
||||
(linewidth 0.150000)
|
||||
(plotframeref false)
|
||||
(viasonmask false)
|
||||
(mode 1)
|
||||
(useauxorigin false)
|
||||
(hpglpennumber 1)
|
||||
(hpglpenspeed 20)
|
||||
(hpglpendiameter 15.000000)
|
||||
(psnegative false)
|
||||
(psa4output false)
|
||||
(plotreference true)
|
||||
(plotvalue true)
|
||||
(plotinvisibletext false)
|
||||
(padsonsilk false)
|
||||
(subtractmaskfromsilk false)
|
||||
(outputformat 1)
|
||||
(mirror false)
|
||||
(drillshape 1)
|
||||
(scaleselection 1)
|
||||
(outputdirectory ""))
|
||||
)
|
||||
|
||||
(net 0 "")
|
||||
|
||||
(net_class Default "This is the default net class."
|
||||
(clearance 0.2)
|
||||
(trace_width 0.25)
|
||||
(via_dia 0.8)
|
||||
(via_drill 0.4)
|
||||
(uvia_dia 0.3)
|
||||
(uvia_drill 0.1)
|
||||
)
|
||||
|
||||
(module kikit:Board (layer F.Cu) (tedit 605A1488) (tstamp 605A707C)
|
||||
(at 185 90)
|
||||
(descr "Mark board for extraction")
|
||||
(fp_text reference B3 (at -4.5 -5) (layer Dwgs.User)
|
||||
(effects (font (size 1 1) (thickness 0.15)) (justify left))
|
||||
)
|
||||
(fp_text value Board (at -7.25 -5) (layer Dwgs.User)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_line (start 0 0) (end -1.25 -4) (layer Dwgs.User) (width 0.2))
|
||||
(fp_line (start -1.25 -4) (end -9.25 -4) (layer Dwgs.User) (width 0.2))
|
||||
(fp_line (start 0 0) (end 0.5 -1) (layer Dwgs.User) (width 0.2))
|
||||
(fp_line (start 0 0) (end -1 -0.5) (layer Dwgs.User) (width 0.2))
|
||||
)
|
||||
|
||||
(module kikit:Board (layer F.Cu) (tedit 605A1488) (tstamp 605A706E)
|
||||
(at 135 90)
|
||||
(descr "Mark board for extraction")
|
||||
(fp_text reference B2 (at -4.5 -5) (layer Dwgs.User)
|
||||
(effects (font (size 1 1) (thickness 0.15)) (justify left))
|
||||
)
|
||||
(fp_text value Board (at -7.25 -5) (layer Dwgs.User)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_line (start 0 0) (end -1 -0.5) (layer Dwgs.User) (width 0.2))
|
||||
(fp_line (start 0 0) (end 0.5 -1) (layer Dwgs.User) (width 0.2))
|
||||
(fp_line (start -1.25 -4) (end -9.25 -4) (layer Dwgs.User) (width 0.2))
|
||||
(fp_line (start 0 0) (end -1.25 -4) (layer Dwgs.User) (width 0.2))
|
||||
)
|
||||
|
||||
(module kikit:Board (layer F.Cu) (tedit 605A1488) (tstamp 605A7057)
|
||||
(at 100 90)
|
||||
(descr "Mark board for extraction")
|
||||
(fp_text reference B1 (at -4.5 -5) (layer Dwgs.User)
|
||||
(effects (font (size 1 1) (thickness 0.15)) (justify left))
|
||||
)
|
||||
(fp_text value Board (at -7.25 -5) (layer Dwgs.User)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_line (start 0 0) (end -1.25 -4) (layer Dwgs.User) (width 0.2))
|
||||
(fp_line (start -1.25 -4) (end -9.25 -4) (layer Dwgs.User) (width 0.2))
|
||||
(fp_line (start 0 0) (end 0.5 -1) (layer Dwgs.User) (width 0.2))
|
||||
(fp_line (start 0 0) (end -1 -0.5) (layer Dwgs.User) (width 0.2))
|
||||
)
|
||||
|
||||
(gr_text C (at 185 100) (layer F.SilkS) (tstamp 605A709F)
|
||||
(effects (font (size 5 5) (thickness 1)))
|
||||
)
|
||||
(gr_text B (at 145 100) (layer F.SilkS) (tstamp 605A709D)
|
||||
(effects (font (size 5 5) (thickness 1)))
|
||||
)
|
||||
(gr_text A (at 100 100) (layer F.SilkS)
|
||||
(effects (font (size 5 5) (thickness 1)))
|
||||
)
|
||||
(gr_line (start 200 100) (end 190 100) (layer Edge.Cuts) (width 0.2) (tstamp 605A142A))
|
||||
(gr_line (start 200 105) (end 200 100) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 190 105) (end 200 105) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 190 100) (end 190 105) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 210 90) (end 180 90) (layer Edge.Cuts) (width 0.2) (tstamp 605A1425))
|
||||
(gr_line (start 210 110) (end 210 90) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 180 110) (end 210 110) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 180 90) (end 180 110) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 150 110) (end 135 110) (layer Edge.Cuts) (width 0.2) (tstamp 605A1415))
|
||||
(gr_line (start 150 100) (end 150 110) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 160 100) (end 150 100) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 160 90) (end 160 100) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 135 90) (end 160 90) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_line (start 135 110) (end 135 90) (layer Edge.Cuts) (width 0.2))
|
||||
(gr_circle (center 100 100) (end 110 100) (layer Edge.Cuts) (width 0.2))
|
||||
|
||||
)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
EESchema Schematic File Version 4
|
||||
EELAYER 30 0
|
||||
EELAYER END
|
||||
$Descr A4 11693 8268
|
||||
encoding utf-8
|
||||
Sheet 1 1
|
||||
Title ""
|
||||
Date ""
|
||||
Rev ""
|
||||
Comp ""
|
||||
Comment1 ""
|
||||
Comment2 ""
|
||||
Comment3 ""
|
||||
Comment4 ""
|
||||
$EndDescr
|
||||
$EndSCHEMATC
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
(kicad_pcb (version 20211014) (generator pcbnew)
|
||||
|
||||
(general
|
||||
(thickness 1.6)
|
||||
)
|
||||
|
||||
(paper "A4")
|
||||
(layers
|
||||
(0 "F.Cu" signal)
|
||||
(31 "B.Cu" signal)
|
||||
(32 "B.Adhes" user "B.Adhesive")
|
||||
(33 "F.Adhes" user "F.Adhesive")
|
||||
(34 "B.Paste" user)
|
||||
(35 "F.Paste" user)
|
||||
(36 "B.SilkS" user "B.Silkscreen")
|
||||
(37 "F.SilkS" user "F.Silkscreen")
|
||||
(38 "B.Mask" user)
|
||||
(39 "F.Mask" user)
|
||||
(40 "Dwgs.User" user "User.Drawings")
|
||||
(41 "Cmts.User" user "User.Comments")
|
||||
(42 "Eco1.User" user "User.Eco1")
|
||||
(43 "Eco2.User" user "User.Eco2")
|
||||
(44 "Edge.Cuts" user)
|
||||
(45 "Margin" user)
|
||||
(46 "B.CrtYd" user "B.Courtyard")
|
||||
(47 "F.CrtYd" user "F.Courtyard")
|
||||
(48 "B.Fab" user)
|
||||
(49 "F.Fab" user)
|
||||
)
|
||||
|
||||
(setup
|
||||
(pad_to_mask_clearance 0)
|
||||
(pcbplotparams
|
||||
(layerselection 0x00010fc_ffffffff)
|
||||
(disableapertmacros false)
|
||||
(usegerberextensions false)
|
||||
(usegerberattributes true)
|
||||
(usegerberadvancedattributes true)
|
||||
(creategerberjobfile true)
|
||||
(svguseinch false)
|
||||
(svgprecision 6)
|
||||
(excludeedgelayer true)
|
||||
(plotframeref false)
|
||||
(viasonmask false)
|
||||
(mode 1)
|
||||
(useauxorigin false)
|
||||
(hpglpennumber 1)
|
||||
(hpglpenspeed 20)
|
||||
(hpglpendiameter 15.000000)
|
||||
(dxfpolygonmode true)
|
||||
(dxfimperialunits true)
|
||||
(dxfusepcbnewfont true)
|
||||
(psnegative false)
|
||||
(psa4output false)
|
||||
(plotreference true)
|
||||
(plotvalue true)
|
||||
(plotinvisibletext false)
|
||||
(sketchpadsonfab false)
|
||||
(subtractmaskfromsilk false)
|
||||
(outputformat 1)
|
||||
(mirror false)
|
||||
(drillshape 1)
|
||||
(scaleselection 1)
|
||||
(outputdirectory "")
|
||||
)
|
||||
)
|
||||
|
||||
(net 0 "")
|
||||
|
||||
(footprint "kikit:Board" (layer "F.Cu")
|
||||
(tedit 605A1488) (tstamp 00000000-0000-0000-0000-0000605a7057)
|
||||
(at 100 90)
|
||||
(descr "Mark board for extraction")
|
||||
(attr through_hole)
|
||||
(fp_text reference "B1" (at -4.5 -5) (layer "Dwgs.User")
|
||||
(effects (font (size 1 1) (thickness 0.15)) (justify left))
|
||||
(tstamp cc934527-b84e-4ca1-ad52-399f8e7bf3df)
|
||||
)
|
||||
(fp_text value "Board" (at -7.25 -5) (layer "Dwgs.User")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 43c89b73-cf56-4390-ad99-0ff92ac35d30)
|
||||
)
|
||||
(fp_line (start 0 0) (end 0.5 -1) (layer "Dwgs.User") (width 0.2) (tstamp 2d675f93-d44f-485c-8207-150c12492452))
|
||||
(fp_line (start 0 0) (end -1.25 -4) (layer "Dwgs.User") (width 0.2) (tstamp 87358536-a504-44ce-8c66-b8b876d8894f))
|
||||
(fp_line (start -1.25 -4) (end -9.25 -4) (layer "Dwgs.User") (width 0.2) (tstamp 982364b6-bcbd-41ff-a125-84aef9991943))
|
||||
(fp_line (start 0 0) (end -1 -0.5) (layer "Dwgs.User") (width 0.2) (tstamp dd80f3b3-31f9-4741-adf5-c81fa1f4c68b))
|
||||
)
|
||||
|
||||
(footprint "kikit:Board" (layer "F.Cu")
|
||||
(tedit 605A1488) (tstamp 00000000-0000-0000-0000-0000605a706e)
|
||||
(at 135 90)
|
||||
(descr "Mark board for extraction")
|
||||
(attr through_hole)
|
||||
(fp_text reference "B2" (at -4.5 -5) (layer "Dwgs.User")
|
||||
(effects (font (size 1 1) (thickness 0.15)) (justify left))
|
||||
(tstamp 5c8f7927-58c0-47ef-854e-3dd8cc0bf312)
|
||||
)
|
||||
(fp_text value "Board" (at -7.25 -5) (layer "Dwgs.User")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp bb77f266-f95c-4d63-b73d-9eb5f6c9f1bc)
|
||||
)
|
||||
(fp_line (start 0 0) (end -1 -0.5) (layer "Dwgs.User") (width 0.2) (tstamp 17e1baca-0f8f-4171-b616-6601bb7efd5b))
|
||||
(fp_line (start -1.25 -4) (end -9.25 -4) (layer "Dwgs.User") (width 0.2) (tstamp 2cc0aca6-d467-4eed-bd95-c60b0cdb0ccc))
|
||||
(fp_line (start 0 0) (end 0.5 -1) (layer "Dwgs.User") (width 0.2) (tstamp 3605dbc5-2619-4e06-bf86-49f1c1817220))
|
||||
(fp_line (start 0 0) (end -1.25 -4) (layer "Dwgs.User") (width 0.2) (tstamp 500b75b0-5ef8-4f0f-8bab-ed9123c39485))
|
||||
)
|
||||
|
||||
(footprint "kikit:Board" (layer "F.Cu")
|
||||
(tedit 605A1488) (tstamp 00000000-0000-0000-0000-0000605a707c)
|
||||
(at 185 90)
|
||||
(descr "Mark board for extraction")
|
||||
(attr through_hole)
|
||||
(fp_text reference "B3" (at -4.5 -5) (layer "Dwgs.User")
|
||||
(effects (font (size 1 1) (thickness 0.15)) (justify left))
|
||||
(tstamp 01bee0de-da40-4390-898d-9738e5a86bcc)
|
||||
)
|
||||
(fp_text value "Board" (at -7.25 -5) (layer "Dwgs.User")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 3f2b141b-7bc9-4979-84f7-000f6c66c53b)
|
||||
)
|
||||
(fp_line (start 0 0) (end 0.5 -1) (layer "Dwgs.User") (width 0.2) (tstamp 0ef8c6c7-83b7-4ec8-8948-2e70fa334d77))
|
||||
(fp_line (start -1.25 -4) (end -9.25 -4) (layer "Dwgs.User") (width 0.2) (tstamp 181c6f00-96c3-4bb7-ba16-c3fde41797ab))
|
||||
(fp_line (start 0 0) (end -1.25 -4) (layer "Dwgs.User") (width 0.2) (tstamp 5e41870a-537a-491e-a56f-ec6759e82e36))
|
||||
(fp_line (start 0 0) (end -1 -0.5) (layer "Dwgs.User") (width 0.2) (tstamp f1ebaa83-56da-4499-929a-773021ade5b3))
|
||||
)
|
||||
|
||||
(gr_line (start 150 110) (end 135 110) (layer "Edge.Cuts") (width 0.2) (tstamp 00000000-0000-0000-0000-0000605a1415))
|
||||
(gr_line (start 210 90) (end 180 90) (layer "Edge.Cuts") (width 0.2) (tstamp 00000000-0000-0000-0000-0000605a1425))
|
||||
(gr_line (start 200 100) (end 190 100) (layer "Edge.Cuts") (width 0.2) (tstamp 00000000-0000-0000-0000-0000605a142a))
|
||||
(gr_line (start 160 100) (end 150 100) (layer "Edge.Cuts") (width 0.2) (tstamp 51ee268f-1cdb-4d7d-9c21-906f097e0468))
|
||||
(gr_line (start 180 90) (end 180 110) (layer "Edge.Cuts") (width 0.2) (tstamp 64c01c4a-0872-44ed-b267-b18d90185def))
|
||||
(gr_line (start 210 110) (end 210 90) (layer "Edge.Cuts") (width 0.2) (tstamp 7197a3a4-13b0-4964-97bb-d3c67b25d3cc))
|
||||
(gr_line (start 160 90) (end 160 100) (layer "Edge.Cuts") (width 0.2) (tstamp 993fe7e0-bb83-477b-b768-ddb19b694f3e))
|
||||
(gr_line (start 135 90) (end 160 90) (layer "Edge.Cuts") (width 0.2) (tstamp a3e28d38-69cd-42a1-b425-f1a15302e858))
|
||||
(gr_line (start 180 110) (end 210 110) (layer "Edge.Cuts") (width 0.2) (tstamp afbb53e6-3063-40ce-bb83-3604be396e1d))
|
||||
(gr_line (start 190 105) (end 200 105) (layer "Edge.Cuts") (width 0.2) (tstamp c0684255-d65e-4027-adfe-519b7fcde519))
|
||||
(gr_line (start 135 110) (end 135 90) (layer "Edge.Cuts") (width 0.2) (tstamp c30d7998-579c-409d-b75a-00fa9f4eed59))
|
||||
(gr_circle (center 100 100) (end 110 100) (layer "Edge.Cuts") (width 0.2) (fill none) (tstamp c817e371-265a-41a5-8be4-97a10008c2fc))
|
||||
(gr_line (start 150 100) (end 150 110) (layer "Edge.Cuts") (width 0.2) (tstamp d2bf3808-d0b7-47de-a1f9-f2e94b771c7b))
|
||||
(gr_line (start 190 100) (end 190 105) (layer "Edge.Cuts") (width 0.2) (tstamp da6b8bc6-f48f-49c2-9e3e-3bb909ccfe9a))
|
||||
(gr_line (start 200 105) (end 200 100) (layer "Edge.Cuts") (width 0.2) (tstamp e6c0520a-00d5-4fde-85e1-681298498d17))
|
||||
(gr_text "B" (at 145 100) (layer "F.SilkS") (tstamp 00000000-0000-0000-0000-0000605a709d)
|
||||
(effects (font (size 5 5) (thickness 1)))
|
||||
)
|
||||
(gr_text "C" (at 185 100) (layer "F.SilkS") (tstamp 00000000-0000-0000-0000-0000605a709f)
|
||||
(effects (font (size 5 5) (thickness 1)))
|
||||
)
|
||||
(gr_text "A" (at 100 100) (layer "F.SilkS") (tstamp eb565a94-7da3-44d3-82d1-76c30d6f561a)
|
||||
(effects (font (size 5 5) (thickness 1)))
|
||||
)
|
||||
|
||||
)
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
(kicad_sch (version 20211123) (generator eeschema)
|
||||
|
||||
(uuid 2e1c5c17-733f-432d-ac13-7421fd62239d)
|
||||
|
||||
(paper "A4")
|
||||
|
||||
(lib_symbols
|
||||
)
|
||||
|
||||
|
||||
(sheet_instances
|
||||
(path "/" (page "1"))
|
||||
)
|
||||
)
|
||||
|
|
@ -8,7 +8,7 @@ outputs:
|
|||
type: panelize
|
||||
options:
|
||||
title: '+ (Panel)'
|
||||
default_units: mm
|
||||
units: mm
|
||||
configs:
|
||||
- layout:
|
||||
rows: 4
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
# Example KiBot config file
|
||||
kibot:
|
||||
version: 1
|
||||
|
||||
global:
|
||||
hide_excluded: true
|
||||
pcb_finish: ENIG
|
||||
solder_mask_color: blue
|
||||
|
||||
variants:
|
||||
- name: 'default'
|
||||
comment: 'Default variant'
|
||||
type: ibom
|
||||
sub_pcbs:
|
||||
- name: A
|
||||
tlx: 89
|
||||
tly: 89
|
||||
brx: 111
|
||||
bry: 111
|
||||
- name: B
|
||||
ref: B2
|
||||
- name: C
|
||||
ref: B3
|
||||
|
||||
outputs:
|
||||
- name: 'pcb_A'
|
||||
comment: "PCB A"
|
||||
type: pcb_variant
|
||||
options:
|
||||
variant: default[A]
|
||||
title: 'Hello %V'
|
||||
|
||||
- name: 'pcb_B'
|
||||
comment: "PCB B"
|
||||
type: pcb_variant
|
||||
options:
|
||||
variant: default[B]
|
||||
title: 'Hello %V'
|
||||
|
||||
- name: 'pcb_C'
|
||||
comment: "PCB C"
|
||||
type: pcb_variant
|
||||
options:
|
||||
variant: default[C]
|
||||
title: 'Hello %V'
|
||||
|
||||
- name: draw_A
|
||||
type: pcbdraw
|
||||
options:
|
||||
variant: default[A]
|
||||
|
||||
- name: draw_B
|
||||
type: pcbdraw
|
||||
options:
|
||||
variant: default[B]
|
||||
|
||||
- name: draw_C
|
||||
type: pcbdraw
|
||||
options:
|
||||
variant: default[C]
|
||||
Loading…
Reference in New Issue