Fix #1554. Changing Blender material name now auto updates both IFC material name and surface style name

This commit is contained in:
Dion Moult
2021-07-08 18:59:40 +10:00
parent 21c4433c75
commit 519a53dc61
4 changed files with 38 additions and 7 deletions
+20 -4
View File
@@ -5,6 +5,7 @@ import ifcopenshell.api.owner.settings
from bpy.app.handlers import persistent from bpy.app.handlers import persistent
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.attribute.data import Data as AttributeData 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 from ifcopenshell.api.type.data import Data as TypeData
@@ -34,11 +35,23 @@ def mode_callback(obj, data):
def name_callback(obj, data): def name_callback(obj, data):
try: try:
oby.type obj.name
except: except:
return # In case the object RNA is gone during an undo / redo operation return # In case the object RNA is gone during an undo / redo operation
# Blender material names are up to 63 UTF-8 bytes # Blender 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: 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 return
element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id) element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
if not element.is_a("IfcRoot"): if not element.is_a("IfcRoot"):
@@ -73,7 +86,10 @@ def active_object_callback():
def subscribe_to(object, data_path, 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( bpy.msgbus.subscribe_rna(
key=subscribe_to, key=subscribe_to,
owner=object, owner=object,
+1 -1
View File
@@ -62,7 +62,7 @@ class IfcStore:
map_object = IfcStore.guid_map map_object = IfcStore.guid_map
try: try:
obj = map_object[id_or_guid] 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: except:
return return
return obj return obj
+16 -2
View File
@@ -800,6 +800,8 @@ class IfcImporter:
def merge_by_class(self): def merge_by_class(self):
merge_set = {} merge_set = {}
for obj in self.added_data.values(): 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: if "/" not in obj.name or "IfcRelAggregates" in obj.users_collection[0].name:
continue continue
merge_set.setdefault(obj.name.split("/")[0], []).append(obj) merge_set.setdefault(obj.name.split("/")[0], []).append(obj)
@@ -808,6 +810,8 @@ class IfcImporter:
def merge_by_material(self): def merge_by_material(self):
merge_set = {} merge_set = {}
for obj in self.added_data.values(): 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: if "/" not in obj.name or "IfcRelAggregates" in obj.users_collection[0].name:
continue continue
if not obj.material_slots: if not obj.material_slots:
@@ -834,6 +838,8 @@ class IfcImporter:
cleaned_material["material"].diffuse_color = cleaned_material["diffuse_color"] cleaned_material["material"].diffuse_color = cleaned_material["diffuse_color"]
for obj in self.added_data.values(): 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: if not hasattr(obj, "material_slots") or not obj.material_slots:
continue continue
for slot in obj.material_slots: for slot in obj.material_slots:
@@ -858,6 +864,8 @@ class IfcImporter:
obj = None obj = None
last_obj = None last_obj = None
for obj in self.added_data.values(): for obj in self.added_data.values():
if not isinstance(obj, bpy.types.Object):
continue
if obj.type == "MESH": if obj.type == "MESH":
obj.select_set(True) obj.select_set(True)
last_obj = obj last_obj = obj
@@ -1005,7 +1013,7 @@ class IfcImporter:
def create_materials(self): def create_materials(self):
for material in self.file.by_type("IfcMaterial"): for material in self.file.by_type("IfcMaterial"):
blender_material = bpy.data.materials.new(material.Name) 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 self.material_creator.materials[material.id()] = blender_material
blender_material.use_fake_user = True blender_material.use_fake_user = True
@@ -1028,6 +1036,11 @@ class IfcImporter:
self.create_style(style, blender_material) self.create_style(style, blender_material)
def create_style(self, 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() blender_material.BIMMaterialProperties.ifc_style_id = style.id()
self.material_creator.styles[style.id()] = blender_material self.material_creator.styles[style.id()] = blender_material
for surface_style in style.Styles: for surface_style in style.Styles:
@@ -1060,7 +1073,8 @@ class IfcImporter:
def place_objects_in_spatial_tree(self): def place_objects_in_spatial_tree(self):
for ifc_definition_id, obj in self.added_data.items(): 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): def place_object_in_spatial_tree(self, element, obj):
if element.is_a("IfcProject"): if element.is_a("IfcProject"):
@@ -128,6 +128,7 @@ class SelectClashSource(bpy.types.Operator):
bl_label = "Select Clash Source" bl_label = "Select Clash Source"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
filepath: bpy.props.StringProperty(subtype="FILE_PATH") filepath: bpy.props.StringProperty(subtype="FILE_PATH")
filter_glob: bpy.props.StringProperty(default="*.ifc", options={"HIDDEN"})
index: bpy.props.IntProperty() index: bpy.props.IntProperty()
group: bpy.props.StringProperty() group: bpy.props.StringProperty()