Experimental mechanism to change 3D models according to the variant.
This commit is contained in:
parent
7c3f273684
commit
7961209b0f
|
|
@ -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
|
- `skip_if_no_field` and `invert` options to the regex used in the generic
|
||||||
filter.
|
filter.
|
||||||
- Basic KiCost support.
|
- Basic KiCost support.
|
||||||
|
- Experimental mechanism to change 3D models according to the variant.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Errors and warnings from KiAuto now are printed as errors and warnings.
|
- Errors and warnings from KiAuto now are printed as errors and warnings.
|
||||||
|
|
|
||||||
|
|
@ -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.
|
This filter implements the VARIANT:FIELD=VALUE renamer to get FIELD=VALUE when VARIANT is in use.
|
||||||
* Valid keys:
|
* Valid keys:
|
||||||
- `comment`: [string=''] A comment for documentation purposes.
|
- `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.
|
- `name`: [string=''] Used to identify this particular filter definition.
|
||||||
- `separator`: [string=':'] Separator used between the variant and the field name.
|
- `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.
|
- `variant_to_value`: [boolean=false] Rename fields matching the variant to the value of the component.
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ class Var_Rename(BaseFilter): # noqa: F821
|
||||||
""" Separator used between the variant and the field name """
|
""" Separator used between the variant and the field name """
|
||||||
self.variant_to_value = False
|
self.variant_to_value = False
|
||||||
""" Rename fields matching the variant to the value of the component """
|
""" 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):
|
def config(self, parent):
|
||||||
super().config(parent)
|
super().config(parent)
|
||||||
|
|
@ -33,10 +35,14 @@ class Var_Rename(BaseFilter): # noqa: F821
|
||||||
|
|
||||||
def filter(self, comp):
|
def filter(self, comp):
|
||||||
""" Look for fields containing VARIANT:FIELD used to change fields according to the variant """
|
""" Look for fields containing VARIANT:FIELD used to change fields according to the variant """
|
||||||
if not GS.variant:
|
if self.force_variant:
|
||||||
# No variant in use, nothing to do
|
variants = [self.force_variant]
|
||||||
return
|
else:
|
||||||
for variant in GS.variant:
|
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():
|
for name, value in comp.get_user_fields():
|
||||||
res = name.strip().split(self.separator)
|
res = name.strip().split(self.separator)
|
||||||
if len(res) == 2:
|
if len(res) == 2:
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ class GS(object):
|
||||||
global_kiauto_wait_start = None
|
global_kiauto_wait_start = None
|
||||||
global_kiauto_time_out_scale = None
|
global_kiauto_time_out_scale = None
|
||||||
global_opts_class = None
|
global_opts_class = None
|
||||||
|
global_3D_model_field = '_3D_model'
|
||||||
test_boolean = True
|
test_boolean = True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
||||||
|
|
@ -81,13 +81,43 @@ class STEPOptions(VariantOptions):
|
||||||
while not models.empty():
|
while not models.empty():
|
||||||
models_l.append(models.pop())
|
models_l.append(models.pop())
|
||||||
# Fix any changed path
|
# 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:
|
if m3d.m_Filename in self.undo_3d_models:
|
||||||
m3d.m_Filename = self.undo_3d_models[m3d.m_Filename]
|
m3d.m_Filename = self.undo_3d_models[m3d.m_Filename]
|
||||||
|
if replaced:
|
||||||
|
m3d.m_Filename = replaced[i]
|
||||||
# Push the models back
|
# Push the models back
|
||||||
for model in models_l:
|
for model in models_l:
|
||||||
models.push_front(model)
|
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):
|
def download_models(self):
|
||||||
""" Check we have the 3D models.
|
""" Check we have the 3D models.
|
||||||
Inform missing models.
|
Inform missing models.
|
||||||
|
|
@ -165,6 +195,7 @@ class STEPOptions(VariantOptions):
|
||||||
|
|
||||||
def filter_components(self, dir):
|
def filter_components(self, dir):
|
||||||
if not self._comps:
|
if not self._comps:
|
||||||
|
# No variant/filter to apply
|
||||||
if self.download_models():
|
if self.download_models():
|
||||||
# Some missing components found and we downloaded them
|
# Some missing components found and we downloaded them
|
||||||
# Save the fixed board
|
# Save the fixed board
|
||||||
|
|
@ -176,15 +207,25 @@ class STEPOptions(VariantOptions):
|
||||||
comps_hash = self.get_refs_hash()
|
comps_hash = self.get_refs_hash()
|
||||||
# Remove the 3D models for not fitted components
|
# Remove the 3D models for not fitted components
|
||||||
rem_models = []
|
rem_models = []
|
||||||
|
self.undo_3d_models_rep = {}
|
||||||
for m in GS.board.GetModules():
|
for m in GS.board.GetModules():
|
||||||
ref = m.GetReference()
|
ref = m.GetReference()
|
||||||
c = comps_hash.get(ref, None)
|
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()
|
models = m.Models()
|
||||||
rem_m_models = []
|
if c.included and not c.fitted:
|
||||||
while not models.empty():
|
# Not fitted, remove the 3D model
|
||||||
rem_m_models.append(models.pop())
|
rem_m_models = []
|
||||||
rem_models.append(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()
|
self.download_models()
|
||||||
fname = self.save_board(dir)
|
fname = self.save_board(dir)
|
||||||
self.undo_3d_models_rename()
|
self.undo_3d_models_rename()
|
||||||
|
|
|
||||||
|
|
@ -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 2 "Resistor_SMD:R_0805_2012Metric" V 2430 1700 50 0001 C CNN
|
||||||
F 3 "~" H 2500 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 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 2500 1700
|
||||||
1 0 0 -1
|
1 0 0 -1
|
||||||
$EndComp
|
$EndComp
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ def test_step_3(test_dir):
|
||||||
def test_step_variant_1(test_dir):
|
def test_step_variant_1(test_dir):
|
||||||
prj = 'kibom-variant_3'
|
prj = 'kibom-variant_3'
|
||||||
ctx = context.TestContext(test_dir, 'test_step_variant_1', prj, 'step_variant_1', '')
|
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
|
# Check all outputs are there
|
||||||
ctx.expect_out_file(prj+'-3D.step')
|
ctx.expect_out_file(prj+'-3D.step')
|
||||||
ctx.clean_up(keep_project=True)
|
ctx.clean_up(keep_project=True)
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,18 @@
|
||||||
kibot:
|
kibot:
|
||||||
version: 1
|
version: 1
|
||||||
|
|
||||||
|
filters:
|
||||||
|
- name: '3D change'
|
||||||
|
comment: 'Changes R2 3D model'
|
||||||
|
type: var_rename
|
||||||
|
force_variant: 'default'
|
||||||
|
|
||||||
variants:
|
variants:
|
||||||
- name: 'default'
|
- name: 'default'
|
||||||
comment: 'Default variant'
|
comment: 'Default variant'
|
||||||
type: ibom
|
type: ibom
|
||||||
variants_blacklist: T2,T3
|
variants_blacklist: T2,T3
|
||||||
|
pre_transform: '3D change'
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
- name: 'step_default'
|
- name: 'step_default'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue