From 70eaa1a7dfd6aa5b2b9c67d7ff80c7c92021906a Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 12 Jun 2023 11:54:17 +0500 Subject: [PATCH] prioritize external styles on ifc import also found a way to switch shade graph for two materials without juggling active materials and active objects - it was necessary to make it work on import without adding temporary active object --- src/blenderbim/blenderbim/bim/import_ifc.py | 21 ++++----------- .../blenderbim/bim/module/style/operator.py | 9 +++++-- .../blenderbim/bim/module/style/prop.py | 9 ++++--- src/blenderbim/blenderbim/tool/blender.py | 27 +++++++++---------- src/blenderbim/blenderbim/tool/style.py | 10 ++++--- 5 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index e85357c6b1..def8c6e939 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -1485,22 +1485,11 @@ class IfcImporter: blender_material.BIMMaterialProperties.ifc_style_id = style.id() self.material_creator.styles[style.id()] = blender_material - rendering_style = None - texture_style = None - - for surface_style in style.Styles: - if surface_style.is_a() == "IfcSurfaceStyleShading": - tool.Loader.create_surface_style_shading(blender_material, surface_style) - elif surface_style.is_a("IfcSurfaceStyleRendering"): - rendering_style = surface_style - tool.Loader.create_surface_style_rendering(blender_material, surface_style) - elif surface_style.is_a("IfcSurfaceStyleWithTextures"): - texture_style = surface_style - - if rendering_style and texture_style: - tool.Loader.create_surface_style_with_textures(blender_material, rendering_style, texture_style) - - tool.Style.record_shading(blender_material) + style_elements = tool.Style.get_style_elements(blender_material) + if tool.Style.has_blender_external_style(style_elements): + blender_material.BIMStyleProperties.active_style_type = "External" + else: + blender_material.BIMStyleProperties.active_style_type = "Shading" def place_objects_in_collections(self): for ifc_definition_id, obj in self.added_data.items(): diff --git a/src/blenderbim/blenderbim/bim/module/style/operator.py b/src/blenderbim/blenderbim/bim/module/style/operator.py index 976016e6af..1aebd3d97c 100644 --- a/src/blenderbim/blenderbim/bim/module/style/operator.py +++ b/src/blenderbim/blenderbim/bim/module/style/operator.py @@ -267,8 +267,13 @@ class ActivateExternalStyle(bpy.types.Operator, tool.Ifc.Operator): bl_label = "Activate External Style" bl_options = {"REGISTER", "UNDO", "INTERNAL"} + material_name: bpy.props.StringProperty(name="Material Name", default="") + def _execute(self, context): - material = context.active_object.active_material + if not self.material_name: + material = context.active_object.active_material + else: + material = bpy.data.materials[self.material_name] external_style = tool.Style.get_style_elements(material)["IfcExternallyDefinedSurfaceStyle"] data_block_type, data_block = external_style.Identification.split("/") style_path = Path(tool.Ifc.resolve_uri(external_style.Location)) @@ -297,7 +302,7 @@ class ActivateExternalStyle(bpy.types.Operator, tool.Ifc.Operator): setattr(material, prop_name, getattr(db["data_block"], prop_name)) if material.use_nodes: - tool.Blender.copy_node_graph_to_active_object(context, db["data_block"]) + tool.Blender.copy_node_graph(material, db["data_block"]) bpy.data.materials.remove(db["data_block"]) diff --git a/src/blenderbim/blenderbim/bim/module/style/prop.py b/src/blenderbim/blenderbim/bim/module/style/prop.py index a44bb91919..266a2d56d8 100644 --- a/src/blenderbim/blenderbim/bim/module/style/prop.py +++ b/src/blenderbim/blenderbim/bim/module/style/prop.py @@ -61,7 +61,7 @@ def update_shading_styles(self, context): materials_to_objects[blender_material] = obj for mat, obj in materials_to_objects.items(): - tool.Style.change_current_style_type(context, obj, mat, self.active_style_type) + tool.Style.change_current_style_type(mat, self.active_style_type) class BIMStylesProperties(PropertyGroup): @@ -79,11 +79,11 @@ class BIMStylesProperties(PropertyGroup): def update_shading_style(self, context): - blender_material = context.active_object.active_material + blender_material = self.id_data style_elements = tool.Style.get_style_elements(blender_material) if self.active_style_type == "External": - if "IfcExternallyDefinedSurfaceStyle" in style_elements: - bpy.ops.bim.activate_external_style() + if tool.Style.has_blender_external_style(style_elements): + bpy.ops.bim.activate_external_style(material_name=blender_material.name) elif self.active_style_type == "Shading": style_elements = tool.Style.get_style_elements(blender_material) @@ -101,6 +101,7 @@ def update_shading_style(self, context): if rendering_style and texture_style: tool.Loader.create_surface_style_with_textures(blender_material, rendering_style, texture_style) + tool.Style.record_shading(blender_material) class BIMStyleProperties(PropertyGroup): diff --git a/src/blenderbim/blenderbim/tool/blender.py b/src/blenderbim/blenderbim/tool/blender.py index 44aca1ceab..ea0aca78d7 100644 --- a/src/blenderbim/blenderbim/tool/blender.py +++ b/src/blenderbim/blenderbim/tool/blender.py @@ -118,32 +118,31 @@ class Blender: return context_override @classmethod - def copy_node_graph_to_active_object(cls, context, material): - """make sure to override `context.active_object` - to you want change node graph for the object that's not actually active - """ + def copy_node_graph(cls, material_to, material_from): temp_override = cls.get_shader_editor_context() - old_material = context.active_object.active_material - new_material = material + shader_editor = temp_override["space"] # remove all nodes from the current material - for n in old_material.node_tree.nodes[:]: - old_material.node_tree.nodes.remove(n) + for n in material_to.node_tree.nodes[:]: + material_to.node_tree.nodes.remove(n) - # change current material and make other window's shader editor is updated - context.active_object.active_material = new_material - temp_override["space"].node_tree = new_material.node_tree + previous_pin_setting = shader_editor.pin + # required to be able to change material to something else + shader_editor.pin = True + shader_editor.node_tree = material_from.node_tree # select all nodes and copy them to clipboard - for node in new_material.node_tree.nodes: + for node in material_from.node_tree.nodes: node.select = True bpy.ops.node.clipboard_copy(temp_override) # back to original material - context.active_object.active_material = old_material - temp_override["space"].node_tree = old_material.node_tree + shader_editor.node_tree = material_to.node_tree bpy.ops.node.clipboard_paste(temp_override, offset=(0, 0)) + # restore shader editor settings + shader_editor.pin = previous_pin_setting + @classmethod def update_screen(cls): bpy.ops.wm.redraw_timer(type="DRAW_WIN_SWAP", iterations=1) diff --git a/src/blenderbim/blenderbim/tool/style.py b/src/blenderbim/blenderbim/tool/style.py index cf2e58b0fa..8dfd6bf2a1 100644 --- a/src/blenderbim/blenderbim/tool/style.py +++ b/src/blenderbim/blenderbim/tool/style.py @@ -227,6 +227,11 @@ class Style(blenderbim.core.tool.Style): attributes.clear() blenderbim.bim.helper.import_attributes2(style, attributes) + @classmethod + def has_blender_external_style(cls, style_elements): + external_style = style_elements.get("IfcExternallyDefinedSurfaceStyle", None) + return bool(external_style and external_style.Location.endswith(".blend")) + @classmethod def is_editing_styles(cls): return bpy.context.scene.BIMStylesProperties.is_editing @@ -243,6 +248,5 @@ class Style(blenderbim.core.tool.Style): obj.select_set(True) @classmethod - def change_current_style_type(cls, context, obj, blender_material, style_type): - with context.temp_override(active_object=obj): - blender_material.BIMStyleProperties.active_style_type = style_type + def change_current_style_type(cls, blender_material, style_type): + blender_material.BIMStyleProperties.active_style_type = style_type