diff --git a/src/bonsai/bonsai/bim/module/pset/ui.py b/src/bonsai/bonsai/bim/module/pset/ui.py index d9c17c7992..ad656a1d4b 100644 --- a/src/bonsai/bonsai/bim/module/pset/ui.py +++ b/src/bonsai/bonsai/bim/module/pset/ui.py @@ -378,8 +378,10 @@ class BIM_PT_object_qtos(Panel): ) layout = self.layout qtoprops = context.scene.BIMQtoProperties - row = layout.row() + row = layout.row(align=True) row.prop(qtoprops, "qto_rule", text="") + # A bit confusing as we typically use this icon for is_null. + row.prop(qtoprops, "fallback", text="", icon="RADIOBUT_ON" if qtoprops.fallback else "RADIOBUT_OFF") row = layout.row() row.operator("bim.perform_quantity_take_off") diff --git a/src/bonsai/bonsai/bim/module/qto/operator.py b/src/bonsai/bonsai/bim/module/qto/operator.py index dfa750bd3d..fe1574d1fa 100644 --- a/src/bonsai/bonsai/bim/module/qto/operator.py +++ b/src/bonsai/bonsai/bim/module/qto/operator.py @@ -176,12 +176,20 @@ class PerformQuantityTakeOff(bpy.types.Operator, tool.Ifc.Operator): else: elements = set(tool.Ifc.get().by_type("IfcElement")) - rules = ifc5d.qto.rules[props.qto_rule] + def run_quantification( + rule: str, elements: set[ifcopenshell.entity_instance] + ) -> set[ifcopenshell.entity_instance]: + rules = ifc5d.qto.rules[rule] + ifc_file = tool.Ifc.get() + results = ifc5d.qto.quantify(ifc_file, elements, rules) + ifc5d.qto.edit_qtos(ifc_file, results) + not_quantified_elements = elements - set(results.keys()) + return not_quantified_elements - ifc_file = tool.Ifc.get() - results = ifc5d.qto.quantify(ifc_file, elements, rules) - not_quantified_elements = elements - set(results.keys()) - ifc5d.qto.edit_qtos(ifc_file, results) + not_quantified_elements = run_quantification(props.qto_rule, elements) + if props.fallback and not_quantified_elements: + alternative_rules = next(rule for rule in ifc5d.qto.rules if rule != props.qto_rule) + not_quantified_elements = run_quantification(alternative_rules, not_quantified_elements) not_quantified_message = "" if not_quantified_elements: diff --git a/src/bonsai/bonsai/bim/module/qto/prop.py b/src/bonsai/bonsai/bim/module/qto/prop.py index cdd52ed414..ec5c60cbc2 100644 --- a/src/bonsai/bonsai/bim/module/qto/prop.py +++ b/src/bonsai/bonsai/bim/module/qto/prop.py @@ -67,3 +67,11 @@ class BIMQtoProperties(PropertyGroup): qto_result: StringProperty(default="", name="Qto Result") qto_name: StringProperty(name="Qto Name", default="My_Qto") prop_name: StringProperty(name="Prop Name", default="MyDimension") + fallback: BoolProperty( + name="Fallback To Other Calculators", + description=( + "If currently selected calculator does not support quantitication " + "of some class/property, to try other available calculators." + ), + default=False, + ) diff --git a/src/bonsai/bonsai/bim/module/qto/ui.py b/src/bonsai/bonsai/bim/module/qto/ui.py index ffd6a4f10a..49840ba4be 100644 --- a/src/bonsai/bonsai/bim/module/qto/ui.py +++ b/src/bonsai/bonsai/bim/module/qto/ui.py @@ -41,6 +41,7 @@ class BIM_PT_qto(bpy.types.Panel): row.label(text="Quantifying All Objects", icon="MOD_EDGESPLIT") row = layout.row() row.prop(props, "qto_rule", text="") + row.prop(props, "fallback", text="", icon="RADIOBUT_ON" if props.fallback else "RADIOBUT_OFF") row = layout.row() row.operator("bim.perform_quantity_take_off")