Experimental mechanism to change 3D models according to the variant.

This commit is contained in:
Salvador E. Tropea 2021-03-31 18:00:43 -03:00
parent 7c3f273684
commit 7961209b0f
8 changed files with 69 additions and 11 deletions

View File

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `skip_if_no_field` and `invert` options to the regex used in the generic
filter.
- Basic KiCost support.
- Experimental mechanism to change 3D models according to the variant.
### Changed
- Errors and warnings from KiAuto now are printed as errors and warnings.

View File

@ -369,6 +369,7 @@ Currently the only type available is `generic`.
This filter implements the VARIANT:FIELD=VALUE renamer to get FIELD=VALUE when VARIANT is in use.
* Valid keys:
- `comment`: [string=''] A comment for documentation purposes.
- `force_variant`: [string=''] Use this variant instead of the current variant. Usefull for IBoM variants.
- `name`: [string=''] Used to identify this particular filter definition.
- `separator`: [string=':'] Separator used between the variant and the field name.
- `variant_to_value`: [boolean=false] Rename fields matching the variant to the value of the component.

View File

@ -25,6 +25,8 @@ class Var_Rename(BaseFilter): # noqa: F821
""" Separator used between the variant and the field name """
self.variant_to_value = False
""" Rename fields matching the variant to the value of the component """
self.force_variant = ''
""" Use this variant instead of the current variant. Usefull for IBoM variants """
def config(self, parent):
super().config(parent)
@ -33,10 +35,14 @@ class Var_Rename(BaseFilter): # noqa: F821
def filter(self, comp):
""" Look for fields containing VARIANT:FIELD used to change fields according to the variant """
if not GS.variant:
# No variant in use, nothing to do
return
for variant in GS.variant:
if self.force_variant:
variants = [self.force_variant]
else:
variants = GS.variant
if not variants:
# No variant in use, nothing to do
return
for variant in variants:
for name, value in comp.get_user_fields():
res = name.strip().split(self.separator)
if len(res) == 2:

View File

@ -74,6 +74,7 @@ class GS(object):
global_kiauto_wait_start = None
global_kiauto_time_out_scale = None
global_opts_class = None
global_3D_model_field = '_3D_model'
test_boolean = True
@staticmethod

View File

@ -81,13 +81,43 @@ class STEPOptions(VariantOptions):
while not models.empty():
models_l.append(models.pop())
# Fix any changed path
for m3d in models_l:
replaced = self.undo_3d_models_rep.get(m.GetReference())
for i, m3d in enumerate(models_l):
if m3d.m_Filename in self.undo_3d_models:
m3d.m_Filename = self.undo_3d_models[m3d.m_Filename]
if replaced:
m3d.m_Filename = replaced[i]
# Push the models back
for model in models_l:
models.push_front(model)
def replace_models(self, models, new_model, c):
""" Changes the 3D model using a provided model """
logger.debug('Changing 3D models for '+c.ref)
# Get the model references
models_l = []
while not models.empty():
models_l.append(models.pop())
# Check if we have more than one model
c_models = len(models_l)
if c_models > 1:
new_model = new_model.split(',')
c_replace = len(new_model)
if c_models != c_replace:
raise KiPlotConfigurationError('Found {} models in component {}, but {} replacements provided'.
format(c_models, c, c_replace))
else:
new_model = [new_model]
# Change the models
replaced = []
for i, m3d in enumerate(models_l):
replaced.append(m3d.m_Filename)
m3d.m_Filename = new_model[i]
self.undo_3d_models_rep[c.ref] = replaced
# Push the models back
for model in models_l:
models.push_front(model)
def download_models(self):
""" Check we have the 3D models.
Inform missing models.
@ -165,6 +195,7 @@ class STEPOptions(VariantOptions):
def filter_components(self, dir):
if not self._comps:
# No variant/filter to apply
if self.download_models():
# Some missing components found and we downloaded them
# Save the fixed board
@ -176,15 +207,25 @@ class STEPOptions(VariantOptions):
comps_hash = self.get_refs_hash()
# Remove the 3D models for not fitted components
rem_models = []
self.undo_3d_models_rep = {}
for m in GS.board.GetModules():
ref = m.GetReference()
c = comps_hash.get(ref, None)
if c and c.included and not c.fitted:
if c:
# The filter/variant knows about this component
models = m.Models()
rem_m_models = []
while not models.empty():
rem_m_models.append(models.pop())
rem_models.append(rem_m_models)
if c.included and not c.fitted:
# Not fitted, remove the 3D model
rem_m_models = []
while not models.empty():
rem_m_models.append(models.pop())
rem_models.append(rem_m_models)
else:
# Fitted
new_model = c.get_field_value(GS.global_3D_model_field)
if new_model:
# We will change the 3D model
self.replace_models(models, new_model, c)
self.download_models()
fname = self.save_board(dir)
self.undo_3d_models_rename()

View File

@ -60,6 +60,7 @@ F 1 "1000" H 2570 1655 50 0000 L CNN
F 2 "Resistor_SMD:R_0805_2012Metric" V 2430 1700 50 0001 C CNN
F 3 "~" H 2500 1700 50 0001 C CNN
F 4 "T1" H 2500 1700 50 0001 C CNN "Config"
F 5 "${KISYS3DMOD}/Resistor_SMD.3dshapes/R_2010_5025Metric.wrl" H 2500 1700 50 0001 C CNN "default:_3D_model"
1 2500 1700
1 0 0 -1
$EndComp

View File

@ -57,7 +57,7 @@ def test_step_3(test_dir):
def test_step_variant_1(test_dir):
prj = 'kibom-variant_3'
ctx = context.TestContext(test_dir, 'test_step_variant_1', prj, 'step_variant_1', '')
ctx.run()
ctx.run(extra_debug=True)
# Check all outputs are there
ctx.expect_out_file(prj+'-3D.step')
ctx.clean_up(keep_project=True)

View File

@ -2,11 +2,18 @@
kibot:
version: 1
filters:
- name: '3D change'
comment: 'Changes R2 3D model'
type: var_rename
force_variant: 'default'
variants:
- name: 'default'
comment: 'Default variant'
type: ibom
variants_blacklist: T2,T3
pre_transform: '3D change'
outputs:
- name: 'step_default'