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 = context.scene.BIMGeoreferenceProperties
props.projected_crs.clear() props.projected_crs.clear()
blenderbim.bim.helper.import_attributes("IfcProjectedCRS", props.projected_crs, Data.projected_crs)
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()]
props.is_map_unit_null = Data.projected_crs["MapUnit"] is None props.is_map_unit_null = Data.projected_crs["MapUnit"] is None
if not props.is_map_unit_null: 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_unit_imperial = Data.projected_crs["MapUnit"]["Name"]
props.map_conversion.clear() props.map_conversion.clear()
blenderbim.bim.helper.import_attributes(
for attribute in IfcStore.get_schema().declaration_by_name("IfcMapConversion").all_attributes(): "IfcMapConversion", props.map_conversion, Data.map_conversion, self.import_map_conversion_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()])
props.has_true_north = bool(Data.true_north) props.has_true_north = bool(Data.true_north)
if Data.true_north: if Data.true_north:
@@ -90,6 +64,12 @@ class EnableEditingGeoreferencing(bpy.types.Operator):
props.is_editing = True props.is_editing = True
return {"FINISHED"} 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): class DisableEditingGeoreferencing(bpy.types.Operator):
bl_idname = "bim.disable_editing_georeferencing" bl_idname = "bim.disable_editing_georeferencing"
@@ -20,6 +20,7 @@
import bpy import bpy
import ifcopenshell.util.attribute import ifcopenshell.util.attribute
import ifcopenshell.api import ifcopenshell.api
import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.group.data import Data from ifcopenshell.api.group.data import Data
@@ -120,17 +121,8 @@ class EnableEditingGroup(bpy.types.Operator):
props = context.scene.BIMGroupProperties props = context.scene.BIMGroupProperties
props.group_attributes.clear() 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 props.active_group_id = self.group
return {"FINISHED"} return {"FINISHED"}
@@ -21,6 +21,7 @@ import bpy
import json import json
import ifcopenshell.util.attribute import ifcopenshell.util.attribute
import ifcopenshell.api import ifcopenshell.api
import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.layer.data import Data from ifcopenshell.api.layer.data import Data
@@ -63,17 +64,10 @@ class EnableEditingLayer(bpy.types.Operator):
props = context.scene.BIMLayerProperties props = context.scene.BIMLayerProperties
props.layer_attributes.clear() 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 props.active_layer_id = self.layer
return {"FINISHED"} return {"FINISHED"}
@@ -429,14 +429,7 @@ class EnableEditingAssignedMaterial(bpy.types.Operator):
props.material_set_attributes.clear() props.material_set_attributes.clear()
for attribute in IfcStore.get_schema().declaration_by_name(material_set_class).all_attributes(): blenderbim.bim.helper.import_attributes(material_set_class, props.material_set_attributes, material_set_data)
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()]
return {"FINISHED"} return {"FINISHED"}
def import_attributes(self, name, prop, data): def import_attributes(self, name, prop, data):
@@ -508,10 +501,7 @@ class EditAssignedMaterial(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
material_set = self.file.by_id(self.material_set) material_set = self.file.by_id(self.material_set)
attributes = blenderbim.bim.helper.export_attributes(props.material_set_attributes)
attributes = {}
for attribute in props.material_set_attributes:
attributes[attribute.name] = None if attribute.is_null else attribute.string_value
ifcopenshell.api.run( ifcopenshell.api.run(
"material.edit_assigned_material", "material.edit_assigned_material",
self.file, self.file,
@@ -610,35 +600,15 @@ class EnableEditingMaterialSetItem(bpy.types.Operator):
profile = self.file.by_id(material_set_item_data["Profile"]) profile = self.file.by_id(material_set_item_data["Profile"])
profile_data = ProfileData.profiles[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(): blenderbim.bim.helper.import_attributes(profile.is_a(), props, profile_data)
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute) for prop in props:
if data_type == "entity": # Force null to be false if the attribute is mandatory because when we first assign a profile, all of
continue # its fields are null (which is illegal).
if attribute.name() in profile_data: # TODO: find a better solution.
new = self.props.material_set_item_profile_attributes.add() if not prop.is_optional:
new.name = attribute.name() prop.is_null = False
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
class DisableEditingMaterialSetItem(bpy.types.Operator): class DisableEditingMaterialSetItem(bpy.types.Operator):
@@ -20,6 +20,7 @@
import bpy import bpy
import ifcopenshell.util.attribute import ifcopenshell.util.attribute
import ifcopenshell.api import ifcopenshell.api
import blenderbim.bim.helper
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.system.data import Data from ifcopenshell.api.system.data import Data
@@ -120,17 +121,7 @@ class EnableEditingSystem(bpy.types.Operator):
props = context.scene.BIMSystemProperties props = context.scene.BIMSystemProperties
props.system_attributes.clear() props.system_attributes.clear()
data = Data.systems[self.system] blenderbim.bim.helper.import_attributes("IfcSystem", props.system_attributes, 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()]
props.active_system_id = self.system props.active_system_id = self.system
return {"FINISHED"} return {"FINISHED"}