mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 02:23:34 +00:00
Fix #1554. Changing Blender material name now auto updates both IFC material name and surface style name
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"):
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user