mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-20 23:36:20 +00:00
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
This commit is contained in:
@@ -93,22 +93,22 @@ def import_attribute(attribute, props, data, callback=None):
|
|||||||
elif is_handled_by_callback is False:
|
elif is_handled_by_callback is False:
|
||||||
props.remove(len(props) - 1)
|
props.remove(len(props) - 1)
|
||||||
elif data_type == "string":
|
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":
|
if attribute.type_of_attribute().declared_type().name() == "IfcURIReference":
|
||||||
new.is_uri = True
|
new.is_uri = True
|
||||||
elif data_type == "boolean":
|
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":
|
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":
|
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":
|
elif data_type == "enum":
|
||||||
enum_items = ifcopenshell.util.attribute.get_enum_items(attribute)
|
enum_items = ifcopenshell.util.attribute.get_enum_items(attribute)
|
||||||
new.enum_items = json.dumps(enum_items)
|
new.enum_items = json.dumps(enum_items)
|
||||||
add_attribute_enum_items_descriptions(new, enum_items)
|
add_attribute_enum_items_descriptions(new, enum_items)
|
||||||
if data[new.name]:
|
if data[new.name]:
|
||||||
new.enum_value = data[new.name]
|
new.enum_value = data[new.name]
|
||||||
add_attribute_description(new)
|
add_attribute_description(new, data)
|
||||||
add_attribute_min_max(new)
|
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, {})
|
constraints = ATTRIBUTE_MIN_MAX_CONSTRAINTS[attribute_blender.ifc_class].get(attribute_blender.name, {})
|
||||||
for constraint, value in constraints.items():
|
for constraint, value in constraints.items():
|
||||||
setattr(attribute_blender, constraint, value)
|
setattr(attribute_blender, constraint, value)
|
||||||
|
setattr(attribute_blender, constraint + "_constraint", True)
|
||||||
|
|
||||||
|
|
||||||
def add_attribute_enum_items_descriptions(attribute_blender, enum_items):
|
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
|
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:
|
if not attribute_blender.name:
|
||||||
return
|
return
|
||||||
version = tool.Ifc.get_schema()
|
version = tool.Ifc.get_schema()
|
||||||
|
description = ""
|
||||||
try:
|
try:
|
||||||
description = get_attribute_doc(version, attribute_blender.ifc_class, attribute_blender.name)
|
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.
|
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:
|
if description:
|
||||||
attribute_blender.description = description
|
attribute_blender.description = description
|
||||||
|
|
||||||
|
|||||||
@@ -618,14 +618,14 @@ class EnableEditingMaterialSetItem(bpy.types.Operator):
|
|||||||
new.is_null = material_set_item_data[attribute.name()] is None
|
new.is_null = material_set_item_data[attribute.name()] is None
|
||||||
new.data_type = data_type
|
new.data_type = data_type
|
||||||
if data_type == "string":
|
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":
|
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":
|
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":
|
elif data_type == "boolean":
|
||||||
new.bool_value = False if new.is_null else material_set_item_data[attribute.name()]
|
new.bool_value = False if new.is_null else bool(material_set_item_data[attribute.name()])
|
||||||
blenderbim.bim.helper.add_attribute_description(new)
|
blenderbim.bim.helper.add_attribute_description(new, material_set_item_data)
|
||||||
blenderbim.bim.helper.add_attribute_min_max(new)
|
blenderbim.bim.helper.add_attribute_min_max(new)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -120,16 +120,16 @@ class EnablePsetEditing(bpy.types.Operator):
|
|||||||
metadata.data_type = self.get_data_type(prop_template)
|
metadata.data_type = self.get_data_type(prop_template)
|
||||||
|
|
||||||
if metadata.data_type == "string":
|
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":
|
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":
|
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":
|
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
|
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):
|
def get_data_type(self, prop_template):
|
||||||
if prop_template.TemplateType in ["Q_LENGTH", "Q_AREA", "Q_VOLUME", "Q_WEIGHT", "Q_TIME"]:
|
if prop_template.TemplateType in ["Q_LENGTH", "Q_AREA", "Q_VOLUME", "Q_WEIGHT", "Q_TIME"]:
|
||||||
|
|||||||
@@ -195,21 +195,12 @@ def update_attribute_value(self, context):
|
|||||||
self.is_null = False
|
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):
|
def set_numerical_value(self, new_value):
|
||||||
value_attr = self.get_value_name()
|
if self.value_min_constraint and new_value < self.value_min:
|
||||||
if new_value < self.value_min:
|
|
||||||
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
|
new_value = self.value_max
|
||||||
self[value_attr] = new_value
|
self[self.get_value_name()] = new_value
|
||||||
|
|
||||||
|
|
||||||
class Attribute(PropertyGroup):
|
class Attribute(PropertyGroup):
|
||||||
@@ -224,14 +215,14 @@ class Attribute(PropertyGroup):
|
|||||||
name="Value",
|
name="Value",
|
||||||
description=tooltip,
|
description=tooltip,
|
||||||
update=update_attribute_value,
|
update=update_attribute_value,
|
||||||
get=get_numerical_value,
|
get=lambda self: int(self.get("int_value", 0)),
|
||||||
set=set_numerical_value,
|
set=set_numerical_value,
|
||||||
)
|
)
|
||||||
float_value: FloatProperty(
|
float_value: FloatProperty(
|
||||||
name="Value",
|
name="Value",
|
||||||
description=tooltip,
|
description=tooltip,
|
||||||
update=update_attribute_value,
|
update=update_attribute_value,
|
||||||
get=get_numerical_value,
|
get=lambda self: float(self.get("float_value", 0.0)),
|
||||||
set=set_numerical_value,
|
set=set_numerical_value,
|
||||||
)
|
)
|
||||||
enum_items: StringProperty(name="Value")
|
enum_items: StringProperty(name="Value")
|
||||||
@@ -242,8 +233,10 @@ class Attribute(PropertyGroup):
|
|||||||
is_uri: BoolProperty(name="Is Uri", default=False)
|
is_uri: BoolProperty(name="Is Uri", default=False)
|
||||||
is_selected: BoolProperty(name="Is Selected", default=False)
|
is_selected: BoolProperty(name="Is Selected", default=False)
|
||||||
has_calculator: BoolProperty(name="Has Calculator", 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_min: FloatProperty(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_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):
|
def get_value(self):
|
||||||
if self.is_optional and self.is_null:
|
if self.is_optional and self.is_null:
|
||||||
|
|||||||
@@ -413,7 +413,11 @@ def draw_custom_context_menu(self, context):
|
|||||||
try:
|
try:
|
||||||
url = get_entity_doc(version, context.button_pointer.ifc_class).get("spec_url", "")
|
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.
|
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:
|
if description:
|
||||||
layout.separator()
|
layout.separator()
|
||||||
op_description = layout.operator("bim.show_description", text="IFC Description", icon="INFO")
|
op_description = layout.operator("bim.show_description", text="IFC Description", icon="INFO")
|
||||||
|
|||||||
Reference in New Issue
Block a user