From a47c57c22c2d89e23fef0f45e91705533de25c9e Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 13 Oct 2023 17:38:55 +1100 Subject: [PATCH] First draft of style manager panel --- .../blenderbim/bim/module/style/__init__.py | 27 ++-- .../blenderbim/bim/module/style/operator.py | 143 +++++++++++++++++- .../blenderbim/bim/module/style/prop.py | 31 +++- .../blenderbim/bim/module/style/ui.py | 109 +++++++++++-- src/blenderbim/blenderbim/tool/style.py | 10 +- 5 files changed, 289 insertions(+), 31 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/style/__init__.py b/src/blenderbim/blenderbim/bim/module/style/__init__.py index 8d37b57ee1..7aa30f52f4 100644 --- a/src/blenderbim/blenderbim/bim/module/style/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/style/__init__.py @@ -20,24 +20,29 @@ import bpy from . import ui, prop, operator classes = ( - operator.AddStyle, - operator.EnableEditingStyle, - operator.DisableEditingStyle, - operator.EditStyle, - operator.UpdateCurrentStyle, - operator.EnableEditingExternalStyle, - operator.DisableEditingExternalStyle, - operator.EditExternalStyle, - operator.DisableEditingStyles, - operator.BrowseExternalStyle, operator.ActivateExternalStyle, + operator.AddPresentationStyle, + operator.AddStyle, + operator.BrowseExternalStyle, + operator.ClearTextureMapPath, + operator.DisableAddPresentationStyle, + operator.DisableEditingExternalStyle, + operator.DisableEditingStyle, + operator.DisableEditingStyles, + operator.EditExternalStyle, + operator.EditStyle, + operator.EditSurfaceStyle, + operator.EnableAddPresentationStyle, + operator.EnableEditingExternalStyle, + operator.EnableEditingStyle, + operator.EnableEditingSurfaceStyle, operator.LoadStyles, operator.RemoveStyle, operator.SelectByStyle, operator.UnlinkStyle, + operator.UpdateCurrentStyle, operator.UpdateStyleColours, operator.UpdateStyleTextures, - operator.ClearTextureMapPath, prop.Style, prop.BIMStylesProperties, prop.BIMStyleProperties, diff --git a/src/blenderbim/blenderbim/bim/module/style/operator.py b/src/blenderbim/blenderbim/bim/module/style/operator.py index 3fbfde90c1..dff00b5081 100644 --- a/src/blenderbim/blenderbim/bim/module/style/operator.py +++ b/src/blenderbim/blenderbim/bim/module/style/operator.py @@ -16,15 +16,16 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . +import os import bpy +import blenderbim.bim.helper import blenderbim.bim.handler import blenderbim.tool as tool import blenderbim.core.style as core import ifcopenshell.util.representation +from pathlib import Path from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.style.data import StylesData, StyleAttributesData -from pathlib import Path -import os class UpdateStyleColours(bpy.types.Operator, tool.Ifc.Operator): @@ -99,9 +100,16 @@ class EnableEditingStyle(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.enable_editing_style" bl_label = "Enable Editing Style" bl_options = {"REGISTER", "UNDO"} + style: bpy.props.IntProperty(default=0) def _execute(self, context): - core.enable_editing_style(tool.Style, obj=context.active_object.active_material) + props = bpy.context.scene.BIMStylesProperties + style = tool.Ifc.get().by_id(self.style) + props.is_editing_style = style.id() + props.is_editing_class = "IfcSurfaceStyle" + attributes = props.attributes + attributes.clear() + blenderbim.bim.helper.import_attributes2(style, attributes) class DisableEditingStyle(bpy.types.Operator, tool.Ifc.Operator): @@ -110,7 +118,8 @@ class DisableEditingStyle(bpy.types.Operator, tool.Ifc.Operator): bl_label = "Disable Editing Style" def _execute(self, context): - core.disable_editing_style(tool.Style, obj=context.active_object.active_material) + props = bpy.context.scene.BIMStylesProperties + props.is_editing_style = 0 class EditStyle(bpy.types.Operator, tool.Ifc.Operator): @@ -119,7 +128,12 @@ class EditStyle(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - core.edit_style(tool.Ifc, tool.Style, obj=context.active_object.active_material) + props = bpy.context.scene.BIMStylesProperties + style = tool.Ifc.get().by_id(props.is_editing_style) + attributes = blenderbim.bim.helper.export_attributes(props.attributes) + ifcopenshell.api.run("style.edit_presentation_style", tool.Ifc.get(), style=style, attributes=attributes) + props.is_editing_style = 0 + core.load_styles(tool.Style, style_type=props.style_type) class UpdateCurrentStyle(bpy.types.Operator): @@ -415,3 +429,122 @@ class ClearTextureMapPath(bpy.types.Operator): props = context.material.BIMStyleProperties setattr(props, self.texture_map_prop, "") return {"FINISHED"} + + +class EnableAddPresentationStyle(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.enable_add_presentation_style" + bl_label = "Enable Add Presentation Style" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + props = bpy.context.scene.BIMStylesProperties + props.is_adding = True + + +class DisableAddPresentationStyle(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.disable_add_presentation_style" + bl_label = "Disable Add Presentation Style" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + props = bpy.context.scene.BIMStylesProperties + props.is_adding = False + + +class AddPresentationStyle(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.add_presentation_style" + bl_label = "Add Presentation Style" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + props = bpy.context.scene.BIMStylesProperties + if props.style_type == "IfcSurfaceStyle": + style = ifcopenshell.api.run("style.add_style", tool.Ifc.get(), name=props.style_name) + if props.surface_style_class in ("IfcSurfaceStyleShading", "IfcSurfaceStyleRendering"): + surface_style = ifcopenshell.api.run( + "style.add_surface_style", + tool.Ifc.get(), + style=style, + ifc_class=props.surface_style_class, + attributes={ + "SurfaceColour": { + "Name": None, + "Red": props.surface_colour[0], + "Green": props.surface_colour[1], + "Blue": props.surface_colour[2], + } + }, + ) + if props.surface_style_class == "IfcSurfaceStyleRendering": + surface_style.ReflectanceMethod = "NOTDEFINED" + props.is_adding = False + core.load_styles(tool.Style, style_type=props.style_type) + + +class EnableEditingSurfaceStyle(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.enable_editing_surface_style" + bl_label = "Enable Editing Surface Style" + bl_options = {"REGISTER", "UNDO"} + style: bpy.props.IntProperty(default=0) + ifc_class: bpy.props.StringProperty(default="") + + def _execute(self, context): + props = bpy.context.scene.BIMStylesProperties + style = tool.Ifc.get().by_id(self.style) + + surface_style = None + for style2 in style.Styles: + if style2.is_a() == self.ifc_class: + surface_style = style2 + break + + if surface_style: + color_to_tuple = lambda x: (x.Red, x.Green, x.Blue) + if self.ifc_class == "IfcSurfaceStyleShading": + props.surface_colour = color_to_tuple(surface_style.SurfaceColour) + props.transparency = surface_style.Transparency or 0. + elif self.ifc_class == "IfcSurfaceStyleRendering": + props.surface_colour = color_to_tuple(surface_style.SurfaceColour) + props.transparency = surface_style.Transparency or 0. + + props.is_editing_style = self.style + props.is_editing_class = self.ifc_class + + +class EditSurfaceStyle(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.edit_surface_style" + bl_label = "Edit Surface Style" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + self.props = bpy.context.scene.BIMStylesProperties + style = tool.Ifc.get().by_id(self.props.is_editing_style) + + self.surface_style = None + self.shading_style = None + self.rendering_style = None + for style2 in style.Styles: + if style2.is_a() == self.props.is_editing_class: + self.surface_style = style2 + if style2.is_a() == "IfcSurfaceStyleShading": + self.shading_style = style2 + if style2.is_a() == "IfcSurfaceStyleRendering": + self.rendering_style = style2 + + if self.surface_style: + self.edit_existing_style() + else: + self.add_new_style() + + self.props.is_editing_style = 0 + core.load_styles(tool.Style, style_type=self.props.style_type) + + def edit_existing_style(self): + if self.surface_style.is_a() == "IfcSurfaceStyleShading": + self.surface_style.SurfaceColour.Red = self.props.surface_colour[0] + self.surface_style.SurfaceColour.Green = self.props.surface_colour[1] + self.surface_style.SurfaceColour.Blue = self.props.surface_colour[2] + self.surface_style.Transparency = self.props.transparency or None + + def add_new_style(self): + pass diff --git a/src/blenderbim/blenderbim/bim/module/style/prop.py b/src/blenderbim/blenderbim/bim/module/style/prop.py index 111b36a5fd..88ffdf47fd 100644 --- a/src/blenderbim/blenderbim/bim/module/style/prop.py +++ b/src/blenderbim/blenderbim/bim/module/style/prop.py @@ -44,6 +44,11 @@ class Style(PropertyGroup): name: StringProperty(name="Name") ifc_definition_id: IntProperty(name="IFC Definition ID") total_elements: IntProperty(name="Total Elements") + style_classes: CollectionProperty(name="Style Classes", type=StrProperty) + has_surface_colour: BoolProperty(name="Has Surface Colour", default=False) + surface_colour: bpy.props.FloatVectorProperty( + name="Surface Colour", subtype="COLOR", default=(1, 1, 1), min=0.0, max=1.0, size=3 + ) STYLE_TYPES = [ @@ -60,8 +65,32 @@ def update_shading_styles(self, context): class BIMStylesProperties(PropertyGroup): + is_adding: BoolProperty(name="Is Adding") is_editing: BoolProperty(name="Is Editing") - style_type: EnumProperty(items=get_style_types, name="Style Type") + is_editing_style: IntProperty(name="Is Editing Style") + is_editing_class: StringProperty(name="Is Editing Class") + attributes: CollectionProperty(name="Attributes", type=Attribute) + style_type: EnumProperty(items=get_style_types, default=2, name="Style Type") + style_name: StringProperty(name="Style Name") + surface_style_class: EnumProperty( + items=[ + (x, x, "") + for x in ( + "IfcSurfaceStyleShading", + "IfcSurfaceStyleRendering", + "IfcSurfaceStyleWithTextures", + "IfcSurfaceStyleLighting", + "IfcSurfaceStyleRefraction", + "IfcExternallyDefinedSurfaceStyle", + ) + ], + name="Surface Style Class", + default="IfcSurfaceStyleShading", + ) + surface_colour: bpy.props.FloatVectorProperty( + name="Surface Colour", subtype="COLOR", default=(1, 1, 1), min=0.0, max=1.0, size=3 + ) + transparency: bpy.props.FloatProperty(name="Transparency", default=0.0, min=0.0, max=1.0) styles: CollectionProperty(name="Styles", type=Style) active_style_index: IntProperty(name="Active Style Index") active_style_type: EnumProperty( diff --git a/src/blenderbim/blenderbim/bim/module/style/ui.py b/src/blenderbim/blenderbim/bim/module/style/ui.py index bb266d9542..348550e779 100644 --- a/src/blenderbim/blenderbim/bim/module/style/ui.py +++ b/src/blenderbim/blenderbim/bim/module/style/ui.py @@ -28,11 +28,11 @@ from blenderbim.tool.style import TEXTURE_MAPS_BY_METHODS, STYLE_TEXTURE_PROPS_M class BIM_PT_styles(Panel): bl_label = "Styles" bl_idname = "BIM_PT_styles" - bl_options = {"DEFAULT_CLOSED"} + bl_options = {"HIDE_HEADER"} bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "scene" - bl_parent_id = "BIM_PT_geometry" + bl_parent_id = "BIM_PT_tab_styles" @classmethod def poll(cls, context): @@ -44,28 +44,97 @@ class BIM_PT_styles(Panel): self.props = context.scene.BIMStylesProperties - row = self.layout.row(align=True) - row.label(text="{} Styles Found".format(StylesData.data["total_styles"]), icon="MATERIAL") - row = self.layout.row(align=True) if self.props.is_editing: + row = self.layout.row(align=True) + row.label(text="{} {}s".format(len(self.props.styles), self.props.style_type), icon="SHADING_RENDERED") + if not self.props.is_adding: + row.operator("bim.enable_add_presentation_style", text="", icon="ADD") row.operator("bim.disable_editing_styles", text="", icon="CANCEL") else: + row = self.layout.row(align=True) + row.label(text="{} Styles".format(StylesData.data["total_styles"]), icon="SHADING_RENDERED") blenderbim.bim.helper.prop_with_search(row, self.props, "style_type", text="") row.operator("bim.load_styles", text="", icon="IMPORT").style_type = self.props.style_type return - row = self.layout.row(align=True) - row.alignment = "RIGHT" + if self.props.is_adding: + box = self.layout.box() + row = box.row() + row.prop(self.props, "style_name", text="Name") + if self.props.style_type == "IfcSurfaceStyle": + row = box.row() + row.prop(self.props, "surface_style_class", text="Class") + if self.props.surface_style_class in ("IfcSurfaceStyleShading", "IfcSurfaceStyleRendering"): + row = box.row() + row.prop(self.props, "surface_colour", text="Colour") + row = box.row(align=True) + row.operator("bim.add_presentation_style", text="Save New Style", icon="CHECKMARK") + row.operator("bim.disable_add_presentation_style", text="", icon="CANCEL") - # row.operator("bim.add_presentation_style", text="", icon="ADD") if self.props.styles and self.props.active_style_index < len(self.props.styles): + row = self.layout.row(align=True) style = self.props.styles[self.props.active_style_index] - op = row.operator("bim.select_by_style", text="", icon="RESTRICT_SELECT_OFF") + op = row.operator("bim.enable_editing_style", text="Edit Style", icon="GREASEPENCIL") op.style = style.ifc_definition_id + row.operator("bim.select_by_style", text="", icon="RESTRICT_SELECT_OFF").style = style.ifc_definition_id row.operator("bim.remove_style", text="", icon="X").style = style.ifc_definition_id + if self.props.style_type == "IfcSurfaceStyle": + col = self.layout.column(align=True) + + row = col.row(align=True) + op = row.operator("bim.enable_editing_surface_style", text="Shade", icon="SHADING_SOLID") + op.ifc_class = "IfcSurfaceStyleShading" + op.style = style.ifc_definition_id + op = row.operator("bim.enable_editing_surface_style", text="Render", icon="SHADING_RENDERED") + op.ifc_class = "IfcSurfaceStyleRendering" + op.style = style.ifc_definition_id + op = row.operator("bim.enable_editing_surface_style", text="Texture", icon="SHADING_TEXTURE") + op.ifc_class = "IfcSurfaceStyleWithTextures" + op.style = style.ifc_definition_id + + row = col.row(align=True) + op = row.operator("bim.enable_editing_surface_style", text="Lighting", icon="LIGHT_SUN") + op.ifc_class = "IfcSurfaceStyleLighting" + op.style = style.ifc_definition_id + op = row.operator("bim.enable_editing_surface_style", text="Refract", icon="LIGHT_POINT") + op.ifc_class = "IfcSurfaceStyleRefraction" + op.style = style.ifc_definition_id + op = row.operator("bim.enable_editing_surface_style", text="External", icon="APPEND_BLEND") + op.ifc_class = "IfcExternallyDefinedSurfaceStyle" + op.style = style.ifc_definition_id + self.layout.template_list("BIM_UL_styles", "", self.props, "styles", self.props, "active_style_index") + if self.props.is_editing_style: + if self.props.is_editing_class == "IfcSurfaceStyle": + blenderbim.bim.helper.draw_attributes(self.props.attributes, self.layout) + row = self.layout.row(align=True) + row.operator("bim.edit_style", text="Save Attributes", icon="CHECKMARK") + row.operator("bim.disable_editing_style", text="", icon="CANCEL") + elif self.props.is_editing_class == "IfcSurfaceStyleShading": + self.draw_surface_style_shading() + elif self.props.is_editing_class == "IfcSurfaceStyleRendering": + self.draw_surface_style_rendering() + + def draw_surface_style_shading(self): + row = self.layout.row() + row.prop(self.props, "surface_colour") + row = self.layout.row() + row.prop(self.props, "transparency") + row = self.layout.row(align=True) + row.operator("bim.edit_surface_style", text="Save Shading Style", icon="CHECKMARK") + row.operator("bim.disable_editing_style", text="", icon="CANCEL") + + def draw_surface_style_rendering(self): + row = self.layout.row() + row.prop(self.props, "surface_colour") + row = self.layout.row() + row.prop(self.props, "transparency") + row = self.layout.row(align=True) + row.operator("bim.edit_surface_style", text="Save Rendering Style", icon="CHECKMARK") + row.operator("bim.disable_editing_style", text="", icon="CANCEL") + def draw_style_ui(self, context): mat = context.material @@ -145,9 +214,6 @@ class BIM_PT_style_attributes(Panel): row.operator("bim.disable_editing_style", icon="CANCEL", text="") blenderbim.bim.helper.draw_attributes(props.attributes, self.layout) else: - row = self.layout.row() - row.operator("bim.enable_editing_style", icon="GREASEPENCIL", text="Edit") - row = self.layout.row(align=True) row.label(text="STEP ID") row.label(text=str(mprops.ifc_style_id)) @@ -218,9 +284,26 @@ class BIM_UL_styles(UIList): if item: row = layout.row(align=True) row.label(text=item.name) + if item.has_surface_colour: + row = row.row() + row.enabled = False + row.prop(item, "surface_colour", text="") row2 = row.row() row2.alignment = "RIGHT" row2.label(text=str(item.total_elements)) + for style in item.style_classes: + if style.name == "IfcSurfaceStyleShading": + row2.label(text="", icon="SHADING_SOLID") + elif style.name == "IfcSurfaceStyleRendering": + row2.label(text="", icon="SHADING_RENDERED") + elif style.name == "IfcSurfaceStyleWithTextures": + row2.label(text="", icon="SHADING_TEXTURE") + elif style.name == "IfcSurfaceStyleLighting": + row2.label(text="", icon="LIGHT_SUN") + elif style.name == "IfcSurfaceStyleRefraction": + row2.label(text="", icon="LIGHT_POINT") + elif style.name == "IfcExternallyDefinedSurfaceStyle": + row2.label(text="", icon="APPEND_BLEND") class BIM_PT_STYLE_GRAPH(Panel): @@ -273,7 +356,7 @@ class BIM_PT_STYLE_GRAPH(Panel): row.prop(props, path_name) op = row.operator("bim.clear_texture_map_path", text="", icon="X") op.texture_map_prop = path_name - + layout.separator() texture_maps = TEXTURE_MAPS_BY_METHODS.get(props.reflectance_method, []) if not texture_maps: diff --git a/src/blenderbim/blenderbim/tool/style.py b/src/blenderbim/blenderbim/tool/style.py index 3b52333d42..344999276e 100644 --- a/src/blenderbim/blenderbim/tool/style.py +++ b/src/blenderbim/blenderbim/tool/style.py @@ -26,7 +26,7 @@ import os.path # fmt: off TEXTURE_MAPS_BY_METHODS = { - "PHYSICAL": ("NORMAL", "EMISSIVE", "METALLICROUGHNESS", "DIFFUSE", "OCCLUSION"), + "PHYSICAL": ("NORMAL", "EMISSIVE", "METALLICROUGHNESS", "DIFFUSE", "OCCLUSION"), "FLAT": ("EMISSIVE",) } # fmt: on @@ -430,6 +430,14 @@ class Style(blenderbim.core.tool.Style): new = props.styles.add() new.ifc_definition_id = style.id() new.name = style.Name or "Unnamed" + new.ifc_class = style.is_a() + for surface_style in getattr(style, "Styles", []): + new2 = new.style_classes.add() + new2.name = surface_style.is_a() + if surface_style.is_a("IfcSurfaceStyleShading"): + color_to_tuple = lambda x: (x.Red, x.Green, x.Blue) + new.has_surface_colour = True + new.surface_colour = color_to_tuple(surface_style.SurfaceColour) new.total_elements = len(ifcopenshell.util.element.get_elements_by_style(tool.Ifc.get(), style)) @classmethod