diff --git a/src/blenderbim/blenderbim/bim/module/style/data.py b/src/blenderbim/blenderbim/bim/module/style/data.py index f4fcbb56b5..d11b766246 100644 --- a/src/blenderbim/blenderbim/bim/module/style/data.py +++ b/src/blenderbim/blenderbim/bim/module/style/data.py @@ -18,8 +18,8 @@ import bpy import ifcopenshell -from ifcopenshell.util.doc import get_entity_doc import blenderbim.tool as tool +from ifcopenshell.util.doc import get_entity_doc def refresh(): @@ -33,9 +33,18 @@ class StylesData: @classmethod def load(cls): - cls.data = {"style_types": cls.style_types(), "total_styles": cls.total_styles()} + cls.data = { + "style_types": cls.style_types(), + "total_styles": cls.total_styles(), + "reflectance_methods": cls.reflectance_methods(), + } cls.is_loaded = True + @classmethod + def reflectance_methods(cls): + declaration = tool.Ifc.schema().declaration_by_name("IfcReflectanceMethodEnum") + return [(i, i, "") for i in declaration.enumeration_items()] + @classmethod def style_types(cls): declaration = tool.Ifc.schema().declaration_by_name("IfcPresentationStyle") diff --git a/src/blenderbim/blenderbim/bim/module/style/operator.py b/src/blenderbim/blenderbim/bim/module/style/operator.py index dff00b5081..4d7cd1ed0a 100644 --- a/src/blenderbim/blenderbim/bim/module/style/operator.py +++ b/src/blenderbim/blenderbim/bim/module/style/operator.py @@ -492,20 +492,60 @@ class EnableEditingSurfaceStyle(bpy.types.Operator, tool.Ifc.Operator): props = bpy.context.scene.BIMStylesProperties style = tool.Ifc.get().by_id(self.style) + shading = None + surface_style = None for style2 in style.Styles: if style2.is_a() == self.ifc_class: surface_style = style2 - break + if style2.is_a() == "IfcSurfaceStyleShading": + shading = style2 + + color_to_tuple = lambda x: (x.Red, x.Green, x.Blue) 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. + props.transparency = surface_style.Transparency or 0.0 elif self.ifc_class == "IfcSurfaceStyleRendering": props.surface_colour = color_to_tuple(surface_style.SurfaceColour) - props.transparency = surface_style.Transparency or 0. + props.transparency = surface_style.Transparency or 0.0 + + if surface_style.DiffuseColour: + props.is_diffuse_colour_null = False + if surface_style.DiffuseColour.is_a("IfcColourRgb"): + props.diffuse_colour_class = "IfcColourRgb" + props.diffuse_colour = color_to_tuple(surface_style.DiffuseColour) + else: + props.diffuse_colour_class = "IfcNormalisedRatioMeasure" + props.diffuse_colour_ratio = surface_style.DiffuseColour.wrappedValue + else: + props.is_diffuse_colour_null = False + + if surface_style.SpecularColour: + props.is_specular_colour_null = False + if surface_style.SpecularColour.is_a("IfcColourRgb"): + props.specular_colour_class = "IfcColourRgb" + props.specular_colour = color_to_tuple(surface_style.SpecularColour) + else: + props.specular_colour_class = "IfcNormalisedRatioMeasure" + props.specular_colour_ratio = surface_style.SpecularColour.wrappedValue + else: + props.is_specular_colour_null = False + + if surface_style.SpecularHighlight: + props.is_specular_highlight_null = False + if surface_style.SpecularHighlight.is_a("IfcSpecularRoughness"): + props.specular_highlight = surface_style.SpecularHighlight.wrappedValue + else: + props.is_specular_highlight_null = False # Exponent is meaningless + else: + props.is_specular_highlight_null = True + + props.reflectance_method = surface_style.ReflectanceMethod + elif shading: + props.surface_colour = color_to_tuple(shading.SurfaceColour) + props.transparency = shading.Transparency or 0.0 props.is_editing_style = self.style props.is_editing_class = self.ifc_class @@ -518,12 +558,12 @@ class EditSurfaceStyle(bpy.types.Operator, tool.Ifc.Operator): def _execute(self, context): self.props = bpy.context.scene.BIMStylesProperties - style = tool.Ifc.get().by_id(self.props.is_editing_style) + self.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: + for style2 in self.style.Styles: if style2.is_a() == self.props.is_editing_class: self.surface_style = style2 if style2.is_a() == "IfcSurfaceStyleShading": @@ -541,10 +581,75 @@ class EditSurfaceStyle(bpy.types.Operator, tool.Ifc.Operator): 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 + ifcopenshell.api.run( + "style.edit_surface_style", + tool.Ifc.get(), + style=self.surface_style, + attributes={ + "SurfaceColour": self.color_to_dict(self.props.surface_colour), + "Transparency": self.props.transparency or None, + }, + ) + elif self.surface_style.is_a() == "IfcSurfaceStyleRendering": + ifcopenshell.api.run( + "style.edit_surface_style", + tool.Ifc.get(), + style=self.surface_style, + attributes=self.get_rendering_attributes(), + ) def add_new_style(self): - pass + if self.props.is_editing_class == "IfcSurfaceStyleShading": + ifcopenshell.api.run( + "style.add_surface_style", + tool.Ifc.get(), + style=self.style, + ifc_class="IfcSurfaceStyleShading", + attributes=self.get_shading_attributes(), + ) + elif self.props.is_editing_class == "IfcSurfaceStyleRendering": + ifcopenshell.api.run( + "style.add_surface_style", + tool.Ifc.get(), + style=self.style, + ifc_class="IfcSurfaceStyleRendering", + attributes=self.get_rendering_attributes(), + ) + + def get_shading_attributes(self): + return { + "SurfaceColour": self.color_to_dict(self.props.surface_colour), + "Transparency": self.props.transparency or None, + } + + def get_rendering_attributes(self): + if self.props.is_diffuse_colour_null: + diffuse_colour = None + elif self.props.diffuse_colour_class == "IfcColourRgb": + diffuse_colour = self.color_to_dict(self.props.diffuse_colour) + elif self.props.diffuse_colour_class == "IfcNormalisedRatioMeasure": + diffuse_colour = self.props.diffuse_colour_ratio + + if self.props.is_specular_colour_null: + specular_colour = None + elif self.props.specular_colour_class == "IfcColourRgb": + specular_colour = self.color_to_dict(self.props.specular_colour) + elif self.props.specular_colour_class == "IfcNormalisedRatioMeasure": + specular_colour = self.props.specular_colour_ratio + + if self.props.is_specular_highlight_null: + specular_highlight = None + else: + specular_highlight = {"SpecularRoughness": self.props.specular_highlight} + + return { + "SurfaceColour": self.color_to_dict(self.props.surface_colour), + "Transparency": self.props.transparency or None, + "ReflectanceMethod": self.props.reflectance_method, + "DiffuseColour": diffuse_colour, + "SpecularColour": specular_colour, + "SpecularHighlight": specular_highlight, + } + + def color_to_dict(self, x): + return {"Red": x[0], "Green": x[1], "Blue": x[2]} diff --git a/src/blenderbim/blenderbim/bim/module/style/prop.py b/src/blenderbim/blenderbim/bim/module/style/prop.py index 88ffdf47fd..fdb787ea1e 100644 --- a/src/blenderbim/blenderbim/bim/module/style/prop.py +++ b/src/blenderbim/blenderbim/bim/module/style/prop.py @@ -40,6 +40,12 @@ def get_style_types(self, context): return StylesData.data["style_types"] +def get_reflectance_methods(self, context): + if not StylesData.is_loaded: + StylesData.load() + return StylesData.data["reflectance_methods"] + + class Style(PropertyGroup): name: StringProperty(name="Name") ifc_definition_id: IntProperty(name="IFC Definition ID") @@ -49,6 +55,10 @@ class Style(PropertyGroup): surface_colour: bpy.props.FloatVectorProperty( name="Surface Colour", subtype="COLOR", default=(1, 1, 1), min=0.0, max=1.0, size=3 ) + has_diffuse_colour: BoolProperty(name="Has Diffuse Colour", default=False) + diffuse_colour: bpy.props.FloatVectorProperty( + name="Diffuse Colour", subtype="COLOR", default=(1, 1, 1), min=0.0, max=1.0, size=3 + ) STYLE_TYPES = [ @@ -91,6 +101,27 @@ class BIMStylesProperties(PropertyGroup): 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) + is_diffuse_colour_null: BoolProperty(name="Is Null") + diffuse_colour_class: EnumProperty( + items=[(x, x, "") for x in ("IfcColourRgb", "IfcNormalisedRatioMeasure")], + name="Diffuse Colour Class", + ) + diffuse_colour: bpy.props.FloatVectorProperty( + name="Diffuse Colour", subtype="COLOR", default=(1, 1, 1), min=0.0, max=1.0, size=3 + ) + diffuse_colour_ratio: bpy.props.FloatProperty(name="Diffuse Ratio", default=0.0, min=0.0, max=1.0) + is_specular_colour_null: BoolProperty(name="Is Null") + specular_colour_class: EnumProperty( + items=[(x, x, "") for x in ("IfcColourRgb", "IfcNormalisedRatioMeasure")], + name="Specular Colour Class", + ) + specular_colour: bpy.props.FloatVectorProperty( + name="Specular Colour", subtype="COLOR", default=(1, 1, 1), min=0.0, max=1.0, size=3 + ) + specular_colour_ratio: bpy.props.FloatProperty(name="Specular Ratio", default=0.0, min=0.0, max=1.0) + is_specular_highlight_null: BoolProperty(name="Is Null") + specular_highlight: bpy.props.FloatProperty(name="Specular Highlight", default=0.0, min=0.0, max=1.0) + reflectance_method: EnumProperty(name="Reflectance Method", items=get_reflectance_methods) 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 348550e779..0289eaab65 100644 --- a/src/blenderbim/blenderbim/bim/module/style/ui.py +++ b/src/blenderbim/blenderbim/bim/module/style/ui.py @@ -131,6 +131,55 @@ class BIM_PT_styles(Panel): row.prop(self.props, "surface_colour") row = self.layout.row() row.prop(self.props, "transparency") + row = self.layout.row() + row.prop(self.props, "reflectance_method") + + row = self.layout.row(align=True) + row.label(text="Diffuse") + row.prop(self.props, "diffuse_colour_class", text="") + if self.props.diffuse_colour_class == "IfcColourRgb": + row.prop(self.props, "diffuse_colour", text="") + else: + row.prop(self.props, "diffuse_colour_ratio", text="") + row.prop( + self.props, + "is_diffuse_colour_null", + text="", + icon="RADIOBUT_OFF" if self.props.is_diffuse_colour_null else "RADIOBUT_ON", + ) + + row = self.layout.row(align=True) + if self.props.reflectance_method in ("PHYSICAL", "NOTDEFINED"): + row.label(text="Metallic") + else: + row.label(text="Specular") + row.prop(self.props, "specular_colour_class", text="") + if self.props.specular_colour_class == "IfcColourRgb": + row.prop(self.props, "specular_colour", text="") + else: + row.prop(self.props, "specular_colour_ratio", text="") + row.prop( + self.props, + "is_specular_colour_null", + text="", + icon="RADIOBUT_OFF" if self.props.is_specular_colour_null else "RADIOBUT_ON", + ) + + row = self.layout.row(align=True) + if self.props.reflectance_method in ("PHYSICAL", "NOTDEFINED"): + row.label(text="Roughness") + elif self.props.reflectance_method in ("PHONG"): + row.label(text="Shininess") + else: + row.label(text="Highlight") + row.prop(self.props, "specular_highlight", text="") + row.prop( + self.props, + "is_specular_highlight_null", + text="", + icon="RADIOBUT_OFF" if self.props.is_specular_highlight_null else "RADIOBUT_ON", + ) + 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") @@ -285,9 +334,11 @@ class BIM_UL_styles(UIList): row = layout.row(align=True) row.label(text=item.name) if item.has_surface_colour: - row = row.row() + row = row.row(align=True) row.enabled = False row.prop(item, "surface_colour", text="") + if item.has_diffuse_colour: + row.prop(item, "diffuse_colour", text="") row2 = row.row() row2.alignment = "RIGHT" row2.label(text=str(item.total_elements)) diff --git a/src/blenderbim/blenderbim/tool/style.py b/src/blenderbim/blenderbim/tool/style.py index 344999276e..4cdb694638 100644 --- a/src/blenderbim/blenderbim/tool/style.py +++ b/src/blenderbim/blenderbim/tool/style.py @@ -423,6 +423,7 @@ class Style(blenderbim.core.tool.Style): @classmethod def import_presentation_styles(cls, style_type): + color_to_tuple = lambda x: (x.Red, x.Green, x.Blue) props = bpy.context.scene.BIMStylesProperties props.styles.clear() styles = sorted(tool.Ifc.get().by_type(style_type), key=lambda x: x.Name or "Unnamed") @@ -435,9 +436,12 @@ class Style(blenderbim.core.tool.Style): 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) + if surface_style.is_a("IfcSurfaceStyleRendering"): + if surface_style.DiffuseColour and surface_style.DiffuseColour.is_a("IfcColourRgb"): + new.has_diffuse_colour = True + new.diffuse_colour = color_to_tuple(surface_style.DiffuseColour) new.total_elements = len(ifcopenshell.util.element.get_elements_by_style(tool.Ifc.get(), style)) @classmethod diff --git a/src/ifcpatch/ifcpatch/recipes/ExtractElements.py b/src/ifcpatch/ifcpatch/recipes/ExtractElements.py index fe1ced106e..ec85a5798e 100644 --- a/src/ifcpatch/ifcpatch/recipes/ExtractElements.py +++ b/src/ifcpatch/ifcpatch/recipes/ExtractElements.py @@ -22,7 +22,7 @@ import ifcopenshell.util.selector class Patcher: - def __init__(self, src, file, logger, query: str = ".IfcWall"): + def __init__(self, src, file, logger, query: str = "IfcWall"): """Extract certain elements into a new model Extract a subset of elements from an existing IFC data set and save it