Use attribute helper functions

This commit is contained in:
Gorgious
2021-08-25 17:20:37 +02:00
parent 049e7324fe
commit 88e778374d
5 changed files with 28 additions and 101 deletions
@@ -39,24 +39,7 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
props = context.scene.BIMGeoreferenceProperties
props.projected_crs.clear()
for attribute in IfcStore.get_schema().declaration_by_name("IfcProjectedCRS").all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity":
continue
new = props.projected_crs.add()
new.name = attribute.name()
new.is_null = Data.projected_crs[attribute.name()] is None
new.is_optional = attribute.optional()
new.data_type = data_type
if data_type == "string":
new.string_value = "" if new.is_null else Data.projected_crs[attribute.name()]
elif data_type == "float":
new.float_value = 0.0 if new.is_null else Data.projected_crs[attribute.name()]
elif data_type == "integer":
new.int_value = 0 if new.is_null else Data.projected_crs[attribute.name()]
elif data_type == "boolean":
new.bool_value = False if new.is_null else Data.projected_crs[attribute.name()]
blenderbim.bim.helper.import_attributes("IfcProjectedCRS", props.projected_crs, Data.projected_crs)
props.is_map_unit_null = Data.projected_crs["MapUnit"] is None
if not props.is_map_unit_null:
@@ -69,18 +52,9 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
props.map_unit_imperial = Data.projected_crs["MapUnit"]["Name"]
props.map_conversion.clear()
for attribute in IfcStore.get_schema().declaration_by_name("IfcMapConversion").all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity" or data_type == "select":
continue
new = props.map_conversion.add()
new.name = attribute.name()
new.is_null = Data.map_conversion[attribute.name()] is None
new.is_optional = attribute.optional()
# Enforce a string data type to prevent data loss in single-precision Blender props
new.data_type = "string"
new.string_value = "" if new.is_null else str(Data.map_conversion[attribute.name()])
blenderbim.bim.helper.import_attributes(
"IfcMapConversion", props.map_conversion, Data.map_conversion, self.import_map_conversion_attributes
)
props.has_true_north = bool(Data.true_north)
if Data.true_north:
@@ -90,6 +64,12 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
props.is_editing = True
return {"FINISHED"}
def import_map_conversion_attributes(self, name, prop, data):
if prop is not None:
# Enforce a string data type to prevent data loss in single-precision Blender props
prop.data_type = "string"
prop.string_value = "" if prop.is_null else str(data[name])
return True
class DisableEditingGeoreferencing(bpy.types.Operator):
bl_idname = "bim.disable_editing_georeferencing"
@@ -20,6 +20,7 @@
import bpy
import ifcopenshell.util.attribute
import ifcopenshell.api
import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.group.data import Data
@@ -120,17 +121,8 @@ class EnableEditingGroup(bpy.types.Operator):
props = context.scene.BIMGroupProperties
props.group_attributes.clear()
data = Data.groups[self.group]
blenderbim.bim.helper.import_attributes("IfcGroup", props.group_attributes, Data.groups[self.group])
for attribute in IfcStore.get_schema().declaration_by_name("IfcGroup").all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity":
continue
new = props.group_attributes.add()
new.name = attribute.name()
new.is_null = data[attribute.name()] is None
new.is_optional = attribute.optional()
new.string_value = "" if new.is_null else data[attribute.name()]
props.active_group_id = self.group
return {"FINISHED"}
@@ -21,6 +21,7 @@ import bpy
import json
import ifcopenshell.util.attribute
import ifcopenshell.api
import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.layer.data import Data
@@ -63,17 +64,10 @@ class EnableEditingLayer(bpy.types.Operator):
props = context.scene.BIMLayerProperties
props.layer_attributes.clear()
data = Data.layers[self.layer]
blenderbim.bim.helper.import_attributes(
"IfcPresentationLayerAssignment", props.layer_attributes, Data.layers[self.layer]
)
for attribute in IfcStore.get_schema().declaration_by_name("IfcPresentationLayerAssignment").all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity" or data_type == "select":
continue
new = props.layer_attributes.add()
new.name = attribute.name()
new.is_null = data[attribute.name()] is None
new.is_optional = attribute.optional()
new.string_value = "" if new.is_null else data[attribute.name()]
props.active_layer_id = self.layer
return {"FINISHED"}
@@ -429,14 +429,7 @@ class EnableEditingAssignedMaterial(bpy.types.Operator):
props.material_set_attributes.clear()
for attribute in IfcStore.get_schema().declaration_by_name(material_set_class).all_attributes():
if "<string>" not in str(attribute.type_of_attribute):
continue
if attribute.name() in material_set_data:
new = props.material_set_attributes.add()
new.name = attribute.name()
new.is_null = material_set_data[attribute.name()] is None
new.string_value = "" if new.is_null else material_set_data[attribute.name()]
blenderbim.bim.helper.import_attributes(material_set_class, props.material_set_attributes, material_set_data)
return {"FINISHED"}
def import_attributes(self, name, prop, data):
@@ -508,10 +501,7 @@ class EditAssignedMaterial(bpy.types.Operator):
return {"FINISHED"}
material_set = self.file.by_id(self.material_set)
attributes = {}
for attribute in props.material_set_attributes:
attributes[attribute.name] = None if attribute.is_null else attribute.string_value
attributes = blenderbim.bim.helper.export_attributes(props.material_set_attributes)
ifcopenshell.api.run(
"material.edit_assigned_material",
self.file,
@@ -610,35 +600,15 @@ class EnableEditingMaterialSetItem(bpy.types.Operator):
profile = self.file.by_id(material_set_item_data["Profile"])
profile_data = ProfileData.profiles[material_set_item_data["Profile"]]
props = self.props.material_set_item_profile_attributes
for attribute in IfcStore.get_schema().declaration_by_name(profile.is_a()).all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity":
continue
if attribute.name() in profile_data:
new = self.props.material_set_item_profile_attributes.add()
new.name = attribute.name()
new.is_null = profile_data[attribute.name()] is None
new.is_optional = attribute.optional()
new.data_type = data_type
if data_type == "string":
new.string_value = "" if new.is_null else profile_data[attribute.name()]
elif data_type == "float":
new.float_value = 0.0 if new.is_null else profile_data[attribute.name()]
elif data_type == "integer":
new.int_value = 0 if new.is_null else profile_data[attribute.name()]
elif data_type == "boolean":
new.bool_value = False if new.is_null else profile_data[attribute.name()]
elif data_type == "enum":
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
if profile_data[attribute.name()]:
new.enum_value = profile_data[attribute.name()]
# Force null to be false if the attribute is mandatory because when we first assign a profile, all of
# its fields are null (which is illegal).
# TODO: find a better solution.
if not new.is_optional:
new.is_null = False
blenderbim.bim.helper.import_attributes(profile.is_a(), props, profile_data)
for prop in props:
# Force null to be false if the attribute is mandatory because when we first assign a profile, all of
# its fields are null (which is illegal).
# TODO: find a better solution.
if not prop.is_optional:
prop.is_null = False
class DisableEditingMaterialSetItem(bpy.types.Operator):
@@ -20,6 +20,7 @@
import bpy
import ifcopenshell.util.attribute
import ifcopenshell.api
import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.system.data import Data
@@ -120,17 +121,7 @@ class EnableEditingSystem(bpy.types.Operator):
props = context.scene.BIMSystemProperties
props.system_attributes.clear()
data = Data.systems[self.system]
for attribute in IfcStore.get_schema().declaration_by_name("IfcSystem").all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity":
continue
new = props.system_attributes.add()
new.name = attribute.name()
new.is_null = data[attribute.name()] is None
new.is_optional = attribute.optional()
new.string_value = "" if new.is_null else data[attribute.name()]
blenderbim.bim.helper.import_attributes("IfcSystem", props.system_attributes, Data.systems[self.system])
props.active_system_id = self.system
return {"FINISHED"}