From 519a53dc614d27839b09f95c3448615814538e63 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Thu, 8 Jul 2021 18:59:40 +1000 Subject: [PATCH] Fix #1554. Changing Blender material name now auto updates both IFC material name and surface style name --- src/blenderbim/blenderbim/bim/handler.py | 24 +++++++++++++++---- src/blenderbim/blenderbim/bim/ifc.py | 2 +- src/blenderbim/blenderbim/bim/import_ifc.py | 18 ++++++++++++-- .../blenderbim/bim/module/clash/operator.py | 1 + 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index 65869099e0..6d7ec1f8f7 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -5,6 +5,7 @@ import ifcopenshell.api.owner.settings from bpy.app.handlers import persistent from blenderbim.bim.ifc import IfcStore from ifcopenshell.api.attribute.data import Data as AttributeData +from ifcopenshell.api.material.data import Data as MaterialData from ifcopenshell.api.type.data import Data as TypeData @@ -34,11 +35,23 @@ def mode_callback(obj, data): def name_callback(obj, data): try: - oby.type + obj.name except: return # In case the object RNA is gone during an undo / redo operation - # Blender material names are up to 63 UTF-8 bytes - if not obj.BIMObjectProperties.ifc_definition_id or "/" not in obj.name or len(bytes(obj.name, "utf-8")) >= 63: + # Blender names are up to 63 UTF-8 bytes + if len(bytes(obj.name, "utf-8")) >= 63: + return + + if isinstance(obj, bpy.types.Material): + if obj.BIMObjectProperties.ifc_definition_id: + IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id).Name = obj.name + AttributeData.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) + MaterialData.load_materials() + if obj.BIMMaterialProperties.ifc_style_id: + IfcStore.get_file().by_id(obj.BIMMaterialProperties.ifc_style_id).Name = obj.name + return + + if not obj.BIMObjectProperties.ifc_definition_id or "/" not in obj.name: return element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id) if not element.is_a("IfcRoot"): @@ -73,7 +86,10 @@ def active_object_callback(): def subscribe_to(object, data_path, callback): - subscribe_to = object.path_resolve(data_path, False) + try: + subscribe_to = object.path_resolve(data_path, False) + except: + return bpy.msgbus.subscribe_rna( key=subscribe_to, owner=object, diff --git a/src/blenderbim/blenderbim/bim/ifc.py b/src/blenderbim/blenderbim/bim/ifc.py index 320813844d..10ef0a53f8 100644 --- a/src/blenderbim/blenderbim/bim/ifc.py +++ b/src/blenderbim/blenderbim/bim/ifc.py @@ -62,7 +62,7 @@ class IfcStore: map_object = IfcStore.guid_map try: obj = map_object[id_or_guid] - obj.type # In case the object has been deleted, this triggers an exception + obj.name # In case the object has been deleted, this triggers an exception except: return return obj diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 371cf14843..57fd668de8 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -800,6 +800,8 @@ class IfcImporter: def merge_by_class(self): merge_set = {} for obj in self.added_data.values(): + if not isinstance(obj, bpy.types.Object): + continue if "/" not in obj.name or "IfcRelAggregates" in obj.users_collection[0].name: continue merge_set.setdefault(obj.name.split("/")[0], []).append(obj) @@ -808,6 +810,8 @@ class IfcImporter: def merge_by_material(self): merge_set = {} for obj in self.added_data.values(): + if not isinstance(obj, bpy.types.Object): + continue if "/" not in obj.name or "IfcRelAggregates" in obj.users_collection[0].name: continue if not obj.material_slots: @@ -834,6 +838,8 @@ class IfcImporter: cleaned_material["material"].diffuse_color = cleaned_material["diffuse_color"] for obj in self.added_data.values(): + if not isinstance(obj, bpy.types.Object): + continue if not hasattr(obj, "material_slots") or not obj.material_slots: continue for slot in obj.material_slots: @@ -858,6 +864,8 @@ class IfcImporter: obj = None last_obj = None for obj in self.added_data.values(): + if not isinstance(obj, bpy.types.Object): + continue if obj.type == "MESH": obj.select_set(True) last_obj = obj @@ -1005,7 +1013,7 @@ class IfcImporter: def create_materials(self): for material in self.file.by_type("IfcMaterial"): blender_material = bpy.data.materials.new(material.Name) - blender_material.BIMObjectProperties.ifc_definition_id = material.id() + self.link_element(material, blender_material) self.material_creator.materials[material.id()] = blender_material blender_material.use_fake_user = True @@ -1028,6 +1036,11 @@ class IfcImporter: self.create_style(style, blender_material) def create_style(self, style, blender_material): + old_definition_id = blender_material.BIMObjectProperties.ifc_definition_id + if not old_definition_id: + self.link_element(style, blender_material) + blender_material.BIMObjectProperties.ifc_definition_id = old_definition_id + blender_material.BIMMaterialProperties.ifc_style_id = style.id() self.material_creator.styles[style.id()] = blender_material for surface_style in style.Styles: @@ -1060,7 +1073,8 @@ class IfcImporter: def place_objects_in_spatial_tree(self): for ifc_definition_id, obj in self.added_data.items(): - self.place_object_in_spatial_tree(self.file.by_id(ifc_definition_id), obj) + if isinstance(obj, bpy.types.Object): + self.place_object_in_spatial_tree(self.file.by_id(ifc_definition_id), obj) def place_object_in_spatial_tree(self, element, obj): if element.is_a("IfcProject"): diff --git a/src/blenderbim/blenderbim/bim/module/clash/operator.py b/src/blenderbim/blenderbim/bim/module/clash/operator.py index 9212d2ae77..05fd235d18 100644 --- a/src/blenderbim/blenderbim/bim/module/clash/operator.py +++ b/src/blenderbim/blenderbim/bim/module/clash/operator.py @@ -128,6 +128,7 @@ class SelectClashSource(bpy.types.Operator): bl_label = "Select Clash Source" bl_options = {"REGISTER", "UNDO"} filepath: bpy.props.StringProperty(subtype="FILE_PATH") + filter_glob: bpy.props.StringProperty(default="*.ifc", options={"HIDDEN"}) index: bpy.props.IntProperty() group: bpy.props.StringProperty()