From d65f2b432b461526c92af828d389d32dafff1c51 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 26 Apr 2020 22:06:27 +1000 Subject: [PATCH] New import workaround for vendors who create a silly amount of materials like DDS-CAD --- .../blenderbim/bim/import_ifc.py | 36 ++++++++++++++++--- .../blenderbim/bim/operator.py | 1 + src/ifcblenderexport/blenderbim/bim/prop.py | 1 + src/ifcblenderexport/blenderbim/bim/ui.py | 2 ++ src/ifcblenderexport/material_cleaner.py | 34 ------------------ 5 files changed, 36 insertions(+), 38 deletions(-) delete mode 100644 src/ifcblenderexport/material_cleaner.py diff --git a/src/ifcblenderexport/blenderbim/bim/import_ifc.py b/src/ifcblenderexport/blenderbim/bim/import_ifc.py index 3abfbe4618..51e2f87c23 100644 --- a/src/ifcblenderexport/blenderbim/bim/import_ifc.py +++ b/src/ifcblenderexport/blenderbim/bim/import_ifc.py @@ -63,10 +63,9 @@ class MaterialCreator(): self.parse_styled_item(styled_item, self.materials[material_name]) if self.ifc_import_settings.should_treat_styled_item_as_material: - # Revit workaround: since Revit exports all material - # assignments as individual object styled items. Treating - # them as reusable materials makes things much more - # efficient in Blender. + # Revit workaround: since Revit/DDS-CAD exports all material + # assignments as individual object styled items. Treating them as + # reusable materials makes things much more efficient in Blender. self.assign_material_to_mesh(self.materials[material_name]) else: # Proper behaviour @@ -233,10 +232,16 @@ class IfcImporter(): self.merge_by_class() elif self.ifc_import_settings.should_merge_by_material: self.merge_by_material() + if self.ifc_import_settings.should_merge_materials_by_colour \ + or (self.ifc_import_settings.should_auto_set_workarounds \ + and len(self.material_creator.materials) > 300): + self.merge_materials_by_colour() if self.ifc_import_settings.should_clean_mesh: self.clean_mesh() def auto_set_workarounds(self): + if 'DDS-CAD' in self.file.wrapped_data.header.file_name.originating_system: + self.ifc_import_settings.should_treat_styled_item_as_material = True applications = self.file.by_type('IfcApplication') if not applications: return @@ -517,6 +522,28 @@ class IfcImporter(): context_override['selected_objects'] = context_override['selected_editable_objects'] = objs bpy.ops.object.join(context_override) + def merge_materials_by_colour(self): + cleaned_materials = {} + for m in bpy.data.materials: + key = '-'.join([str(x) for x in m.diffuse_color]) + cleaned_materials[key] = { 'diffuse_color': m.diffuse_color } + + for cleaned_material in cleaned_materials.values(): + cleaned_material['material'] = bpy.data.materials.new('Merged Material') + cleaned_material['material'].diffuse_color = cleaned_material['diffuse_color'] + + for obj in self.added_data.values(): + if not hasattr(obj, 'material_slots') \ + or not obj.material_slots: + continue + for slot in obj.material_slots: + m = slot.material + key = '-'.join([str(x) for x in m.diffuse_color]) + slot.material = cleaned_materials[key]['material'] + + for material in self.material_creator.materials.values(): + bpy.data.materials.remove(material) + def clean_mesh(self): obj = None last_obj = None @@ -960,6 +987,7 @@ class IfcImportSettings: self.should_ignore_site_coordinates = False self.should_ignore_building_coordinates = False self.should_reset_absolute_coordinates = False + self.should_merge_materials_by_colour = False self.should_import_curves = False self.should_import_opening_elements = False self.should_import_spaces = False diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index d9c531da6d..ac8c6f64ee 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -94,6 +94,7 @@ class ImportIFC(bpy.types.Operator, ImportHelper): ifc_import_settings.should_import_aggregates = bpy.context.scene.BIMProperties.import_should_import_aggregates ifc_import_settings.should_merge_by_class = bpy.context.scene.BIMProperties.import_should_merge_by_class ifc_import_settings.should_merge_by_material = bpy.context.scene.BIMProperties.import_should_merge_by_material + ifc_import_settings.should_merge_materials_by_colour = bpy.context.scene.BIMProperties.import_should_merge_materials_by_colour ifc_import_settings.should_clean_mesh = bpy.context.scene.BIMProperties.import_should_clean_mesh ifc_importer = import_ifc.IfcImporter(ifc_import_settings) ifc_importer.execute() diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index bc315eaa17..b68427caa6 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -813,6 +813,7 @@ class BIMProperties(PropertyGroup): import_should_import_aggregates: BoolProperty(name="Import Aggregates", default=True) import_should_merge_by_class: BoolProperty(name="Import and Merge by Class", default=False) import_should_merge_by_material: BoolProperty(name="Import and Merge by Material", default=False) + import_should_merge_materials_by_colour: BoolProperty(name="Import and Merge Materials by Colour", default=False) import_should_clean_mesh: BoolProperty(name="Import and Clean Mesh", default=True) qa_reject_element_reason: StringProperty(name="Element Rejection Reason") person: EnumProperty(items=getPersons, name="Person") diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 97489c2a51..d3e5a2aeb6 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -940,6 +940,8 @@ class BIM_PT_mvd(Panel): row = layout.row() row.prop(bim_properties, 'import_should_merge_by_material') row = layout.row() + row.prop(bim_properties, 'import_should_merge_materials_by_colour') + row = layout.row() row.prop(bim_properties, 'import_should_clean_mesh') layout.label(text='Vendor Workarounds:') diff --git a/src/ifcblenderexport/material_cleaner.py b/src/ifcblenderexport/material_cleaner.py deleted file mode 100644 index 41c1df14e2..0000000000 --- a/src/ifcblenderexport/material_cleaner.py +++ /dev/null @@ -1,34 +0,0 @@ -import bpy -import pprint -print('# Start') -cleaned_materials = {} -n = 0 -for m in bpy.data.materials: - r = m.diffuse_color[0] - g = m.diffuse_color[1] - b = m.diffuse_color[2] - key = str(r) + '-' + str(g) + '-' + str(b) - cleaned_materials[key] = {'name': 'name{}'.format(n)} - n += 1 - -pprint.pprint(cleaned_materials) -print(len(bpy.data.materials.keys())) -print(len(cleaned_materials.keys())) - -for rgb, data in cleaned_materials.items(): - m = bpy.data.materials.new(data['name']) - print(rgb) - m.diffuse_color = ( - float(rgb.split('-')[0]), - float(rgb.split('-')[1]), - float(rgb.split('-')[2]), - 1) - data['material'] = m - -for o in bpy.context.selected_objects: - m = o.material_slots[0].material - r = m.diffuse_color[0] - g = m.diffuse_color[1] - b = m.diffuse_color[2] - key = str(r) + '-' + str(g) + '-' + str(b) - o.material_slots[0].material = cleaned_materials[key]['material'] \ No newline at end of file