From 4e3ce192cc6627b72b4cb40c0e8eed65912f8970 Mon Sep 17 00:00:00 2001 From: Gorgious56 Date: Thu, 3 Nov 2022 09:54:35 +0100 Subject: [PATCH] Custom property set attributes now show their description when right clicking the field + Add explicit numerical constraint members to attribute class #2562 + Fix error in numerical value callback #2562 + Fix error in setting attribute values because of wrong type cast --- src/blenderbim/blenderbim/bim/helper.py | 21 ++++++++++------ .../bim/module/material/operator.py | 10 ++++---- .../blenderbim/bim/module/pset/operator.py | 10 ++++---- src/blenderbim/blenderbim/bim/prop.py | 25 +++++++------------ src/blenderbim/blenderbim/bim/ui.py | 6 ++++- 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py index 14e2b3fc49..f1705e2ec5 100644 --- a/src/blenderbim/blenderbim/bim/helper.py +++ b/src/blenderbim/blenderbim/bim/helper.py @@ -93,22 +93,22 @@ def import_attribute(attribute, props, data, callback=None): elif is_handled_by_callback is False: props.remove(len(props) - 1) elif data_type == "string": - new.string_value = "" if new.is_null else data[attribute.name()] + new.string_value = "" if new.is_null else str(data[attribute.name()]) if attribute.type_of_attribute().declared_type().name() == "IfcURIReference": new.is_uri = True elif data_type == "boolean": - new.bool_value = False if new.is_null else data[attribute.name()] + new.bool_value = False if new.is_null else bool(data[attribute.name()]) elif data_type == "integer": - new.int_value = 0 if new.is_null else data[attribute.name()] + new.int_value = 0 if new.is_null else int(data[attribute.name()]) elif data_type == "float": - new.float_value = 0.0 if new.is_null else data[attribute.name()] + new.float_value = 0.0 if new.is_null else float(data[attribute.name()]) elif data_type == "enum": enum_items = ifcopenshell.util.attribute.get_enum_items(attribute) new.enum_items = json.dumps(enum_items) add_attribute_enum_items_descriptions(new, enum_items) if data[new.name]: new.enum_value = data[new.name] - add_attribute_description(new) + add_attribute_description(new, data) add_attribute_min_max(new) @@ -120,6 +120,7 @@ def add_attribute_min_max(attribute_blender): constraints = ATTRIBUTE_MIN_MAX_CONSTRAINTS[attribute_blender.ifc_class].get(attribute_blender.name, {}) for constraint, value in constraints.items(): setattr(attribute_blender, constraint, value) + setattr(attribute_blender, constraint + "_constraint", True) def add_attribute_enum_items_descriptions(attribute_blender, enum_items): @@ -136,14 +137,20 @@ def add_attribute_enum_items_descriptions(attribute_blender, enum_items): new_enum_description.name = description -def add_attribute_description(attribute_blender): +def add_attribute_description(attribute_blender, attribute_ifc=None): if not attribute_blender.name: return version = tool.Ifc.get_schema() + description = "" try: description = get_attribute_doc(version, attribute_blender.ifc_class, attribute_blender.name) except RuntimeError: # It's not an Entity Attribute. Let's try a Property Set attribute. - description = get_property_doc(version, attribute_blender.ifc_class, attribute_blender.name).get("description") + doc = get_property_doc(version, attribute_blender.ifc_class, attribute_blender.name) + if doc: + description = doc.get("description", "") + else: # It's a custom property set. Check if this attribute has a description + if attribute_ifc is not None: + description = getattr(attribute_ifc, "Description", "") if description: attribute_blender.description = description diff --git a/src/blenderbim/blenderbim/bim/module/material/operator.py b/src/blenderbim/blenderbim/bim/module/material/operator.py index 4080eae669..2b1cfb20d9 100644 --- a/src/blenderbim/blenderbim/bim/module/material/operator.py +++ b/src/blenderbim/blenderbim/bim/module/material/operator.py @@ -618,14 +618,14 @@ class EnableEditingMaterialSetItem(bpy.types.Operator): new.is_null = material_set_item_data[attribute.name()] is None new.data_type = data_type if data_type == "string": - new.string_value = "" if new.is_null else material_set_item_data[attribute.name()] + new.string_value = "" if new.is_null else str(material_set_item_data[attribute.name()]) elif data_type == "float": - new.float_value = 0.0 if new.is_null else material_set_item_data[attribute.name()] + new.float_value = 0.0 if new.is_null else float(material_set_item_data[attribute.name()]) elif data_type == "integer": - new.int_value = 0 if new.is_null else material_set_item_data[attribute.name()] + new.int_value = 0 if new.is_null else int(material_set_item_data[attribute.name()]) elif data_type == "boolean": - new.bool_value = False if new.is_null else material_set_item_data[attribute.name()] - blenderbim.bim.helper.add_attribute_description(new) + new.bool_value = False if new.is_null else bool(material_set_item_data[attribute.name()]) + blenderbim.bim.helper.add_attribute_description(new, material_set_item_data) blenderbim.bim.helper.add_attribute_min_max(new) diff --git a/src/blenderbim/blenderbim/bim/module/pset/operator.py b/src/blenderbim/blenderbim/bim/module/pset/operator.py index d7ed392c0f..dd17f9483d 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset/operator.py @@ -120,16 +120,16 @@ class EnablePsetEditing(bpy.types.Operator): metadata.data_type = self.get_data_type(prop_template) if metadata.data_type == "string": - metadata.string_value = "" if metadata.is_null else data[prop_template.Name] + metadata.string_value = "" if metadata.is_null else str(data[prop_template.Name]) elif metadata.data_type == "integer": - metadata.int_value = 0 if metadata.is_null else data[prop_template.Name] + metadata.int_value = 0 if metadata.is_null else int(data[prop_template.Name]) elif metadata.data_type == "float": - metadata.float_value = 0.0 if metadata.is_null else data[prop_template.Name] + metadata.float_value = 0.0 if metadata.is_null else float(data[prop_template.Name]) elif metadata.data_type == "boolean": - metadata.bool_value = False if metadata.is_null else data[prop_template.Name] + metadata.bool_value = False if metadata.is_null else bool(data[prop_template.Name]) metadata.ifc_class = pset_template.Name - blenderbim.bim.helper.add_attribute_description(metadata) + blenderbim.bim.helper.add_attribute_description(metadata, prop_template) def get_data_type(self, prop_template): if prop_template.TemplateType in ["Q_LENGTH", "Q_AREA", "Q_VOLUME", "Q_WEIGHT", "Q_TIME"]: diff --git a/src/blenderbim/blenderbim/bim/prop.py b/src/blenderbim/blenderbim/bim/prop.py index fb7e2a134e..f688ee713a 100644 --- a/src/blenderbim/blenderbim/bim/prop.py +++ b/src/blenderbim/blenderbim/bim/prop.py @@ -195,21 +195,12 @@ def update_attribute_value(self, context): self.is_null = False -def get_numerical_value(self): - value_attr = self.get_value_name() - if value_attr == "int_value": - return int(self.get(value_attr) or 0) - elif value_attr == "float_value": - return float(self.get(value_attr) or 0) - - def set_numerical_value(self, new_value): - value_attr = self.get_value_name() - if new_value < self.value_min: + if self.value_min_constraint and new_value < self.value_min: new_value = self.value_min - elif new_value > self.value_max: + elif self.value_max_constraint and new_value > self.value_max: new_value = self.value_max - self[value_attr] = new_value + self[self.get_value_name()] = new_value class Attribute(PropertyGroup): @@ -224,14 +215,14 @@ class Attribute(PropertyGroup): name="Value", description=tooltip, update=update_attribute_value, - get=get_numerical_value, + get=lambda self: int(self.get("int_value", 0)), set=set_numerical_value, ) float_value: FloatProperty( name="Value", description=tooltip, update=update_attribute_value, - get=get_numerical_value, + get=lambda self: float(self.get("float_value", 0.0)), set=set_numerical_value, ) enum_items: StringProperty(name="Value") @@ -242,8 +233,10 @@ class Attribute(PropertyGroup): is_uri: BoolProperty(name="Is Uri", default=False) is_selected: BoolProperty(name="Is Selected", default=False) has_calculator: BoolProperty(name="Has Calculator", default=False) - value_min: FloatProperty(default=-10e20, description="This is used to validate int_value and float_value") - value_max: FloatProperty(default=10e20, description="This is used to validate int_value and float_value") + value_min: FloatProperty(description="This is used to validate int_value and float_value") + value_min_constraint: BoolProperty(default=False, description="True if the numerical value has a lower bound") + value_max: FloatProperty(description="This is used to validate int_value and float_value") + value_max_constraint: BoolProperty(default=False, description="True if the numerical value has an upper bound") def get_value(self): if self.is_optional and self.is_null: diff --git a/src/blenderbim/blenderbim/bim/ui.py b/src/blenderbim/blenderbim/bim/ui.py index c40cb18b9a..1d60e112f4 100644 --- a/src/blenderbim/blenderbim/bim/ui.py +++ b/src/blenderbim/blenderbim/bim/ui.py @@ -413,7 +413,11 @@ def draw_custom_context_menu(self, context): try: url = get_entity_doc(version, context.button_pointer.ifc_class).get("spec_url", "") except RuntimeError: # It's not an Entity Attribute. Let's try a Property Set attribute. - url = get_property_set_doc(version, context.button_pointer.ifc_class).get("spec_url", "") + doc = get_property_set_doc(version, context.button_pointer.ifc_class) + if doc: + url = doc.get("spec_url", "") + else: # It's a custom property set. No URL available + url = "" if description: layout.separator() op_description = layout.operator("bim.show_description", text="IFC Description", icon="INFO")