diff --git a/src/blenderbim/blenderbim/bim/module/attribute/ui.py b/src/blenderbim/blenderbim/bim/module/attribute/ui.py index 68573cb3ee..243b25353f 100644 --- a/src/blenderbim/blenderbim/bim/module/attribute/ui.py +++ b/src/blenderbim/blenderbim/bim/module/attribute/ui.py @@ -83,7 +83,7 @@ class BIM_PT_object_attributes(Panel): class BIM_PT_material_attributes(Panel): - bl_label = "IFC Attributes" + bl_label = "IFC Material Attributes" bl_idname = "BIM_PT_material_attributes" bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" diff --git a/src/blenderbim/blenderbim/bim/module/style/__init__.py b/src/blenderbim/blenderbim/bim/module/style/__init__.py index e9d7bf9e4b..e161508777 100644 --- a/src/blenderbim/blenderbim/bim/module/style/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/style/__init__.py @@ -1,18 +1,23 @@ import bpy -from . import ui, operator +from . import ui, prop, operator classes = ( operator.AddStyle, + operator.EnableEditingStyle, + operator.DisableEditingStyle, operator.EditStyle, operator.RemoveStyle, + operator.UpdateStyleColours, operator.UnlinkStyle, + prop.BIMStyleProperties, ui.BIM_PT_style, + ui.BIM_PT_style_attributes, ) def register(): - pass + bpy.types.Material.BIMStyleProperties = bpy.props.PointerProperty(type=prop.BIMStyleProperties) def unregister(): - pass + del bpy.types.Material.BIMStyleProperties diff --git a/src/blenderbim/blenderbim/bim/module/style/operator.py b/src/blenderbim/blenderbim/bim/module/style/operator.py index 0e53ab57bb..43ef806e56 100644 --- a/src/blenderbim/blenderbim/bim/module/style/operator.py +++ b/src/blenderbim/blenderbim/bim/module/style/operator.py @@ -1,6 +1,8 @@ import bpy import ifcopenshell.api +import blenderbim.bim.helper from blenderbim.bim.ifc import IfcStore +from ifcopenshell.api.style.data import Data def get_colour_settings(material): @@ -18,9 +20,9 @@ def get_colour_settings(material): } -class EditStyle(bpy.types.Operator): - bl_idname = "bim.edit_style" - bl_label = "Edit Style" +class UpdateStyleColours(bpy.types.Operator): + bl_idname = "bim.update_style_colours" + bl_label = "Update Style Colours" bl_options = {"REGISTER", "UNDO"} material: bpy.props.StringProperty() @@ -32,7 +34,7 @@ class EditStyle(bpy.types.Operator): material = bpy.data.materials.get(self.material) if self.material else bpy.context.active_object.active_material settings = get_colour_settings(material) settings["style"] = self.file.by_id(material.BIMMaterialProperties.ifc_style_id) - ifcopenshell.api.run("style.edit_style", self.file, **settings) + ifcopenshell.api.run("style.edit_style_colours", self.file, **settings) return {"FINISHED"} @@ -88,3 +90,54 @@ class UnlinkStyle(bpy.types.Operator): if "Ifc" in material.name and "/" in material.name: material.name = "/".join(material.name.split("/")[1:]) return {"FINISHED"} + + +class EnableEditingStyle(bpy.types.Operator): + bl_idname = "bim.enable_editing_style" + bl_label = "Enable Editing Style" + bl_options = {"REGISTER", "UNDO"} + material: bpy.props.StringProperty() + + def execute(self, context): + material = bpy.data.materials.get(self.material) if self.material else bpy.context.active_object.active_material + props = material.BIMStyleProperties + while len(props.attributes) > 0: + props.attributes.remove(0) + + data = Data.styles[material.BIMMaterialProperties.ifc_style_id] + blenderbim.bim.helper.import_attributes("IfcSurfaceStyle", props.attributes, data) + props.is_editing_attributes = True + return {"FINISHED"} + + +class DisableEditingStyle(bpy.types.Operator): + bl_idname = "bim.disable_editing_style" + bl_options = {"REGISTER", "UNDO"} + bl_label = "Disable Editing Style" + material: bpy.props.StringProperty() + + def execute(self, context): + material = bpy.data.materials.get(self.material) if self.material else bpy.context.active_object.active_material + props = material.BIMStyleProperties + props.is_editing_attributes = False + return {"FINISHED"} + + +class EditStyle(bpy.types.Operator): + bl_idname = "bim.edit_style" + bl_label = "Edit Style" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + return IfcStore.execute_ifc_operator(self, context) + + def _execute(self, context): + material = bpy.context.active_object.active_material + props = material.BIMStyleProperties + attributes = blenderbim.bim.helper.export_attributes(props.attributes) + self.file = IfcStore.get_file() + style = self.file.by_id(material.BIMMaterialProperties.ifc_style_id) + ifcopenshell.api.run("style.edit_style", self.file, **{"style": style, "attributes": attributes}) + Data.load(IfcStore.get_file(), material.BIMMaterialProperties.ifc_style_id) + bpy.ops.bim.disable_editing_style() + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/style/prop.py b/src/blenderbim/blenderbim/bim/module/style/prop.py new file mode 100644 index 0000000000..11fec121cd --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/style/prop.py @@ -0,0 +1,18 @@ +import bpy +from blenderbim.bim.ifc import IfcStore +from blenderbim.bim.prop import StrProperty, Attribute +from bpy.types import PropertyGroup +from bpy.props import ( + PointerProperty, + StringProperty, + EnumProperty, + BoolProperty, + IntProperty, + FloatProperty, + FloatVectorProperty, + CollectionProperty, +) + +class BIMStyleProperties(PropertyGroup): + attributes: CollectionProperty(name="Attributes", type=Attribute) + is_editing_attributes: BoolProperty(name="Is Editing Attributes") diff --git a/src/blenderbim/blenderbim/bim/module/style/ui.py b/src/blenderbim/blenderbim/bim/module/style/ui.py index a56705a751..325e2c6178 100644 --- a/src/blenderbim/blenderbim/bim/module/style/ui.py +++ b/src/blenderbim/blenderbim/bim/module/style/ui.py @@ -1,5 +1,7 @@ +import blenderbim.bim.helper from bpy.types import Panel from blenderbim.bim.ifc import IfcStore +from ifcopenshell.api.style.data import Data class BIM_PT_style(Panel): @@ -21,10 +23,51 @@ class BIM_PT_style(Panel): props = context.active_object.active_material.BIMMaterialProperties row = self.layout.row(align=True) if props.ifc_style_id: - row.operator("bim.edit_style", icon="GREASEPENCIL") + row.operator("bim.update_style_colours", icon="GREASEPENCIL") op = row.operator("bim.unlink_style", icon="UNLINKED", text="") op.material = context.active_object.active_material.name op = row.operator("bim.remove_style", icon="X", text="") op.material = context.active_object.active_material.name else: row.operator("bim.add_style", icon="ADD") + + +class BIM_PT_style_attributes(Panel): + bl_label = "IFC Style Attributes" + bl_idname = "BIM_PT_style_attributes" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "material" + + @classmethod + def poll(cls, context): + try: + return bool(context.active_object.active_material.BIMMaterialProperties.ifc_style_id) + except: + return False + + def draw(self, context): + obj = context.active_object.active_material + mprops = obj.BIMMaterialProperties + props = obj.BIMStyleProperties + if mprops.ifc_style_id not in Data.styles: + Data.load(IfcStore.get_file(), mprops.ifc_style_id) + if props.is_editing_attributes: + row = self.layout.row(align=True) + row.operator("bim.edit_style", icon="CHECKMARK") + 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)) + + for name, value in Data.styles[mprops.ifc_style_id].items(): + if name in ["id", "type", "Styles"]: + continue + row = self.layout.row(align=True) + row.label(text=name) + row.label(text=str(value)) diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/data.py b/src/ifcopenshell-python/ifcopenshell/api/style/data.py new file mode 100644 index 0000000000..dd4a932a2b --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/style/data.py @@ -0,0 +1,14 @@ +class Data: + styles = {} + + @classmethod + def purge(cls): + cls.styles = {} + + @classmethod + def load(cls, file, style_id): + if not file: + return + data = file.by_id(style_id).get_info() + data["Styles"] = [s.id() for s in data["Styles"]] + cls.styles[style_id] = data diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/edit_style.py b/src/ifcopenshell-python/ifcopenshell/api/style/edit_style.py index e5083ff97f..7a98032435 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/style/edit_style.py +++ b/src/ifcopenshell-python/ifcopenshell/api/style/edit_style.py @@ -1,67 +1,10 @@ class Usecase: def __init__(self, file, **settings): self.file = file - self.settings = { - "style": None, - "surface_colour": [], # RGB - "diffuse_colour": [], # RGB - "transparency": 0, - "external_definition": { - "location": None, - "identification": None, - "name": "Name" - }, - } + self.settings = {"style": None, "attributes": {}} for key, value in settings.items(): self.settings[key] = value def execute(self): - #has_external_definition = None - for element in self.file.traverse(self.settings["style"]): - if element.is_a("IfcSurfaceStyleShading"): - if element.SurfaceColour: - self.update_colour_rgb(element.SurfaceColour, self.settings["surface_colour"]) - else: - element.SurfaceColour = self.create_colour_rgb(self.settings["surface_colour"]) - element.Transparency = (self.settings["transparency"] - 1) * -1 - if element.is_a("IfcSurfaceStyleRendering"): - if element.DiffuseColour: - self.update_colour_rgb(element.DiffuseColour, self.settings["diffuse_colour"]) - else: - element.DiffuseColour = self.create_colour_rgb(self.settings["diffuse_colour"]) - # TODO: Move to separate usecase - #if element.is_a("IfcExternallyDefinedSurfaceStyle"): - # element.Location = self.settings["location"] - # element.Identification = self.settings["identification"] - # element.Name = self.settings["name"] - # has_external_definition = True - #if not has_external_definition: - # styles = list(self.settings["style"].Styles) - # styles.append(self.create_externally_defined_surface_style()) - # self.settings["style"].Styles = styles - return self.settings["style"] - - def create_surface_style_rendering(self): - return self.file.create_entity("IfcSurfaceStyleRendering", **{ - "SurfaceColour": self.create_colour_rgb(self.settings["surface_colour"]), - "Transparency": (self.settings["transparency"] - 1) * -1, - "ReflectanceMethod": "NOTDEFINED", - "DiffuseColour": self.create_colour_rgb(self.settings["diffuse_colour"]) - }) - - def create_externally_defined_surface_style(self): - self.file.create_entity( - "IfcExternallyDefinedSurfaceStyle", **{ - "Location": self.settings["location"], - "Identification": self.settings["identification"], - "Name": self.settings["name"], - } - ) - - def create_colour_rgb(self, colour): - return self.file.createIfcColourRgb(None, colour[0], colour[1], colour[2]) - - def update_colour_rgb(self, element, colour): - element[1] = colour[0] - element[2] = colour[1] - element[3] = colour[2] + for name, value in self.settings["attributes"].items(): + setattr(self.settings["style"], name, value) diff --git a/src/ifcopenshell-python/ifcopenshell/api/style/edit_style_colours.py b/src/ifcopenshell-python/ifcopenshell/api/style/edit_style_colours.py new file mode 100644 index 0000000000..e5083ff97f --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/style/edit_style_colours.py @@ -0,0 +1,67 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = { + "style": None, + "surface_colour": [], # RGB + "diffuse_colour": [], # RGB + "transparency": 0, + "external_definition": { + "location": None, + "identification": None, + "name": "Name" + }, + } + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + #has_external_definition = None + for element in self.file.traverse(self.settings["style"]): + if element.is_a("IfcSurfaceStyleShading"): + if element.SurfaceColour: + self.update_colour_rgb(element.SurfaceColour, self.settings["surface_colour"]) + else: + element.SurfaceColour = self.create_colour_rgb(self.settings["surface_colour"]) + element.Transparency = (self.settings["transparency"] - 1) * -1 + if element.is_a("IfcSurfaceStyleRendering"): + if element.DiffuseColour: + self.update_colour_rgb(element.DiffuseColour, self.settings["diffuse_colour"]) + else: + element.DiffuseColour = self.create_colour_rgb(self.settings["diffuse_colour"]) + # TODO: Move to separate usecase + #if element.is_a("IfcExternallyDefinedSurfaceStyle"): + # element.Location = self.settings["location"] + # element.Identification = self.settings["identification"] + # element.Name = self.settings["name"] + # has_external_definition = True + #if not has_external_definition: + # styles = list(self.settings["style"].Styles) + # styles.append(self.create_externally_defined_surface_style()) + # self.settings["style"].Styles = styles + return self.settings["style"] + + def create_surface_style_rendering(self): + return self.file.create_entity("IfcSurfaceStyleRendering", **{ + "SurfaceColour": self.create_colour_rgb(self.settings["surface_colour"]), + "Transparency": (self.settings["transparency"] - 1) * -1, + "ReflectanceMethod": "NOTDEFINED", + "DiffuseColour": self.create_colour_rgb(self.settings["diffuse_colour"]) + }) + + def create_externally_defined_surface_style(self): + self.file.create_entity( + "IfcExternallyDefinedSurfaceStyle", **{ + "Location": self.settings["location"], + "Identification": self.settings["identification"], + "Name": self.settings["name"], + } + ) + + def create_colour_rgb(self, colour): + return self.file.createIfcColourRgb(None, colour[0], colour[1], colour[2]) + + def update_colour_rgb(self, element, colour): + element[1] = colour[0] + element[2] = colour[1] + element[3] = colour[2]