diff --git a/src/blenderbim/blenderbim/bim/module/style/__init__.py b/src/blenderbim/blenderbim/bim/module/style/__init__.py index 159b919712..c7ecdab9e3 100644 --- a/src/blenderbim/blenderbim/bim/module/style/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/style/__init__.py @@ -21,22 +21,30 @@ from . import ui, prop, operator classes = ( operator.AddStyle, - operator.EnableEditingStyle, operator.DisableEditingStyle, + operator.DisableEditingStyles, operator.EditStyle, + operator.EnableEditingStyle, + operator.LoadStyles, operator.RemoveStyle, + operator.UnlinkStyle, operator.UpdateStyleColours, operator.UpdateStyleTextures, - operator.UnlinkStyle, + prop.Style, + prop.BIMStylesProperties, prop.BIMStyleProperties, + ui.BIM_PT_styles, ui.BIM_PT_style, ui.BIM_PT_style_attributes, + ui.BIM_UL_styles, ) def register(): + bpy.types.Scene.BIMStylesProperties = bpy.props.PointerProperty(type=prop.BIMStylesProperties) bpy.types.Material.BIMStyleProperties = bpy.props.PointerProperty(type=prop.BIMStyleProperties) def unregister(): + del bpy.types.Scene.BIMStylesProperties del bpy.types.Material.BIMStyleProperties diff --git a/src/blenderbim/blenderbim/bim/module/style/data.py b/src/blenderbim/blenderbim/bim/module/style/data.py index 78714b7fcd..9f6d768785 100644 --- a/src/blenderbim/blenderbim/bim/module/style/data.py +++ b/src/blenderbim/blenderbim/bim/module/style/data.py @@ -18,12 +18,33 @@ import bpy import blenderbim.tool as tool +import ifcopenshell def refresh(): + StylesData.is_loaded = False StyleAttributesData.is_loaded = False +class StylesData: + data = {} + is_loaded = False + + @classmethod + def load(cls): + cls.data = {"style_types": cls.style_types(), "total_styles": cls.total_styles()} + + @classmethod + def style_types(cls): + declaration = tool.Ifc.schema().declaration_by_name("IfcPresentationStyle") + declarations = ifcopenshell.util.schema.get_subtypes(declaration) + return [(c, c, "") for c in sorted([d.name() for d in declarations])] + + @classmethod + def total_styles(cls): + return len(tool.Ifc.get().by_type("IfcPresentationStyle")) + + class StyleAttributesData: data = {} is_loaded = False diff --git a/src/blenderbim/blenderbim/bim/module/style/operator.py b/src/blenderbim/blenderbim/bim/module/style/operator.py index 174f7e16d5..44e9504d22 100644 --- a/src/blenderbim/blenderbim/bim/module/style/operator.py +++ b/src/blenderbim/blenderbim/bim/module/style/operator.py @@ -107,3 +107,22 @@ class EditStyle(bpy.types.Operator, Operator): def _execute(self, context): core.edit_style(tool.Ifc, tool.Style, obj=context.active_object.active_material) + + +class DisableEditingStyles(bpy.types.Operator, Operator): + bl_idname = "bim.disable_editing_styles" + bl_options = {"REGISTER", "UNDO"} + bl_label = "Disable Editing Styles" + + def _execute(self, context): + core.disable_editing_styles(tool.Style) + + +class LoadStyles(bpy.types.Operator, Operator): + bl_idname = "bim.load_styles" + bl_label = "Load Styles" + bl_options = {"REGISTER", "UNDO"} + style_type: bpy.props.StringProperty() + + def _execute(self, context): + core.load_styles(tool.Style, style_type=self.style_type) diff --git a/src/blenderbim/blenderbim/bim/module/style/prop.py b/src/blenderbim/blenderbim/bim/module/style/prop.py index b5ae846627..f8666f8793 100644 --- a/src/blenderbim/blenderbim/bim/module/style/prop.py +++ b/src/blenderbim/blenderbim/bim/module/style/prop.py @@ -19,6 +19,7 @@ import bpy from blenderbim.bim.ifc import IfcStore from blenderbim.bim.prop import StrProperty, Attribute +from blenderbim.bim.module.style.data import StylesData from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, @@ -32,6 +33,25 @@ from bpy.props import ( ) +def get_style_types(self, context): + if not StylesData.is_loaded: + StylesData.load() + return StylesData.data["style_types"] + + +class Style(PropertyGroup): + name: StringProperty(name="Name") + ifc_definition_id: IntProperty(name="IFC Definition ID") + total_elements: IntProperty(name="Total Elements") + + +class BIMStylesProperties(PropertyGroup): + is_editing: BoolProperty(name="Is Editing") + style_type: EnumProperty(items=get_style_types, name="Style Type") + styles: CollectionProperty(name="Styles", type=Style) + active_style_index: IntProperty(name="Active Style Index") + + class BIMStyleProperties(PropertyGroup): attributes: CollectionProperty(name="Attributes", type=Attribute) is_editing: BoolProperty(name="Is Editing") diff --git a/src/blenderbim/blenderbim/bim/module/style/ui.py b/src/blenderbim/blenderbim/bim/module/style/ui.py index abd2ce812c..dcb2b35bd2 100644 --- a/src/blenderbim/blenderbim/bim/module/style/ui.py +++ b/src/blenderbim/blenderbim/bim/module/style/ui.py @@ -17,9 +17,51 @@ # along with BlenderBIM Add-on. If not, see . import blenderbim.bim.helper -from bpy.types import Panel +from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore -from blenderbim.bim.module.style.data import StyleAttributesData +from blenderbim.bim.module.style.data import StylesData, StyleAttributesData + + +class BIM_PT_styles(Panel): + bl_label = "IFC Styles" + bl_idname = "BIM_PT_styles" + bl_options = {"DEFAULT_CLOSED"} + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "scene" + bl_parent_id = "BIM_PT_geometry" + + @classmethod + def poll(cls, context): + return IfcStore.get_file() + + def draw(self, context): + if not StylesData.is_loaded: + StylesData.load() + + 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.operator("bim.disable_editing_styles", text="", icon="CANCEL") + else: + row.prop(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" + + #row.operator("bim.add_presentation_style", text="", icon="ADD") + #if self.props.styles and self.props.active_style_index < len(self.props.styles): + # style = self.props.styles[self.props.active_style_index] + # op = row.operator("bim.select_by_style", text="", icon="RESTRICT_SELECT_OFF") + # op.style = style.ifc_definition_id + # row.operator("bim.remove_style", text="", icon="X").style = style.ifc_definition_id + + self.layout.template_list("BIM_UL_styles", "", self.props, "styles", self.props, "active_style_index") class BIM_PT_style(Panel): @@ -89,3 +131,13 @@ class BIM_PT_style_attributes(Panel): row = self.layout.row(align=True) row.label(text=attribute["name"]) row.label(text=attribute["value"]) + + +class BIM_UL_styles(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + if item: + row = layout.row(align=True) + row.label(text=item.name) + #row2 = row.row() + #row2.alignment = "RIGHT" + #row2.label(text=str(item.total_elements)) diff --git a/src/blenderbim/blenderbim/core/material.py b/src/blenderbim/blenderbim/core/material.py index 48a9136ca8..e0835f92f8 100644 --- a/src/blenderbim/blenderbim/core/material.py +++ b/src/blenderbim/blenderbim/core/material.py @@ -59,7 +59,7 @@ def remove_material_set(ifc, material_tool, material=None): material_tool.import_material_definitions(material_tool.get_active_material_type()) -def load_materials(material, material_type): +def load_materials(material, material_type=None): material.import_material_definitions(material_type) material.enable_editing_materials() diff --git a/src/blenderbim/blenderbim/core/style.py b/src/blenderbim/blenderbim/core/style.py index e3a26dfc65..038e029bdf 100644 --- a/src/blenderbim/blenderbim/core/style.py +++ b/src/blenderbim/blenderbim/core/style.py @@ -97,3 +97,12 @@ def edit_style(ifc, style, obj=None): attributes = style.export_surface_attributes(obj) ifc.run("style.edit_presentation_style", style=style.get_style(obj), attributes=attributes) style.disable_editing(obj) + + +def load_styles(style, style_type=None): + style.import_presentation_styles(style_type) + style.enable_editing_styles() + + +def disable_editing_styles(style): + style.disable_editing_styles() diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index b18e73000a..74e1d47572 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -432,7 +432,9 @@ class Structural: class Style: def can_support_rendering_style(cls, obj): pass def disable_editing(cls, obj): pass + def disable_editing_styles(cls): pass def enable_editing(cls, obj): pass + def enable_editing_styles(cls): pass def export_surface_attributes(cls, obj): pass def get_context(cls, obj): pass def get_name(cls, obj): pass @@ -443,6 +445,7 @@ class Style: def get_surface_shading_style(cls, obj): pass def get_surface_texture_style(cls, obj): pass def get_uv_maps(cls, representation): pass + def import_presentation_styles(cls, style_type): pass def import_surface_attributes(cls, style, obj): pass diff --git a/src/blenderbim/blenderbim/tool/style.py b/src/blenderbim/blenderbim/tool/style.py index 80f7248d5d..1e14785a61 100644 --- a/src/blenderbim/blenderbim/tool/style.py +++ b/src/blenderbim/blenderbim/tool/style.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . +import bpy import ifcopenshell import blenderbim.core.tool import blenderbim.tool as tool @@ -31,10 +32,18 @@ class Style(blenderbim.core.tool.Style): def disable_editing(cls, obj): obj.BIMStyleProperties.is_editing = False + @classmethod + def disable_editing_styles(cls): + bpy.context.scene.BIMStylesProperties.is_editing = False + @classmethod def enable_editing(cls, obj): obj.BIMStyleProperties.is_editing = True + @classmethod + def enable_editing_styles(cls): + bpy.context.scene.BIMStylesProperties.is_editing = True + @classmethod def export_surface_attributes(cls, obj): return blenderbim.bim.helper.export_attributes(obj.BIMStyleProperties.attributes) @@ -166,6 +175,15 @@ class Style(blenderbim.core.tool.Style): results.append(uv_map) return results + @classmethod + def import_presentation_styles(cls, style_type): + props = bpy.context.scene.BIMStylesProperties + props.styles.clear() + for style in tool.Ifc.get().by_type(style_type): + new = props.styles.add() + new.ifc_definition_id = style.id() + new.name = style.Name or "Unnamed" + @classmethod def import_surface_attributes(cls, style, obj): obj.BIMStyleProperties.attributes.clear() diff --git a/src/blenderbim/test/bim/feature/geometry.feature b/src/blenderbim/test/bim/feature/geometry.feature index 793f499503..dae44cff62 100644 --- a/src/blenderbim/test/bim/feature/geometry.feature +++ b/src/blenderbim/test/bim/feature/geometry.feature @@ -195,7 +195,7 @@ Scenario: Update representation - updating a layered extrusion And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType" And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType" And I press "bim.assign_class" - And I press "bim.add_default_material" + And I press "bim.add_material(obj='')" And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet" And I press "bim.assign_material" And I press "bim.enable_editing_assigned_material" @@ -222,7 +222,7 @@ Scenario: Update representation - updating a profiled extrusion And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType" And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType" And I press "bim.assign_class" - And I press "bim.add_default_material" + And I press "bim.add_material(obj='')" And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet" And I press "bim.assign_material" And I press "bim.enable_editing_assigned_material" @@ -357,7 +357,7 @@ Scenario: Override duplicate move - copying a layered extrusion And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType" And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType" And I press "bim.assign_class" - And I press "bim.add_default_material" + And I press "bim.add_material(obj='')" And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet" And I press "bim.assign_material" And I press "bim.enable_editing_assigned_material" @@ -386,7 +386,7 @@ Scenario: Override duplicate move - copying a profiled extrusion And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType" And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType" And I press "bim.assign_class" - And I press "bim.add_default_material" + And I press "bim.add_material(obj='')" And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet" And I press "bim.assign_material" And I press "bim.enable_editing_assigned_material" diff --git a/src/blenderbim/test/bim/feature/sequence.feature b/src/blenderbim/test/bim/feature/sequence.feature index 5f1a2925d6..f2f12e8a2d 100644 --- a/src/blenderbim/test/bim/feature/sequence.feature +++ b/src/blenderbim/test/bim/feature/sequence.feature @@ -79,7 +79,7 @@ Scenario: Animate the construction of a wall Then "scene.objects.get('IfcWall/Cube').hide_viewport" is "False" And "scene.objects.get('IfcWall/Cube').hide_render" is "False" And "scene.objects.get('IfcWall/Cube').color" is "[0.0, 1.0, 0.0, 1]" - When I am on frame "6" + When I am on frame "7" Then "scene.objects.get('IfcWall/Cube').color" is "[1.0, 1.0, 1.0, 1]" Scenario: Animate the demolition of a wall @@ -116,7 +116,7 @@ Scenario: Animate the demolition of a wall Then "scene.objects.get('IfcWall/Cube').hide_viewport" is "False" And "scene.objects.get('IfcWall/Cube').hide_render" is "False" And "scene.objects.get('IfcWall/Cube').color" is "[1.0, 0.0, 0.0, 1]" - When I am on frame "6" + When I am on frame "7" Then "scene.objects.get('IfcWall/Cube').hide_viewport" is "True" And "scene.objects.get('IfcWall/Cube').hide_render" is "True" And "scene.objects.get('IfcWall/Cube').color" is "[0.0, 0.0, 0.0, 1]" @@ -151,7 +151,7 @@ Scenario: Animate the operation of a wall Then "scene.objects.get('IfcWall/Cube').color" is "[1.0, 1.0, 1.0, 1]" When I am on frame "2" Then "scene.objects.get('IfcWall/Cube').color" is "[0.0, 0.0, 1.0, 1]" - When I am on frame "6" + When I am on frame "7" Then "scene.objects.get('IfcWall/Cube').color" is "[1.0, 1.0, 1.0, 1]" Scenario: Animate the movement of a wall @@ -200,7 +200,7 @@ Scenario: Animate the movement of a wall And "scene.objects.get('IfcWall/ToObject').color" is "[1.0, 1.0, 0.0, 1]" And "scene.objects.get('IfcWall/ToObject').hide_viewport" is "False" And "scene.objects.get('IfcWall/ToObject').hide_render" is "False" - When I am on frame "6" + When I am on frame "7" Then "scene.objects.get('IfcWall/FromObject').color" is "[0.0, 0.0, 0.0, 1]" Then "scene.objects.get('IfcWall/FromObject').hide_viewport" is "True" Then "scene.objects.get('IfcWall/FromObject').hide_render" is "True" @@ -239,7 +239,7 @@ Scenario: Animate the consumption of a wall Then "scene.objects.get('IfcWall/Cube').color" is "[0.0, 1.0, 1.0, 1]" And "scene.objects.get('IfcWall/Cube').hide_viewport" is "False" And "scene.objects.get('IfcWall/Cube').hide_render" is "False" - When I am on frame "6" + When I am on frame "7" Then "scene.objects.get('IfcWall/Cube').color" is "[0.0, 0.0, 0.0, 1]" Then "scene.objects.get('IfcWall/Cube').hide_viewport" is "True" Then "scene.objects.get('IfcWall/Cube').hide_render" is "True" diff --git a/src/blenderbim/test/bim/feature/style.feature b/src/blenderbim/test/bim/feature/style.feature index 2c861f6003..480854663f 100644 --- a/src/blenderbim/test/bim/feature/style.feature +++ b/src/blenderbim/test/bim/feature/style.feature @@ -57,3 +57,20 @@ Scenario: Edit style And I press "bim.enable_editing_style" When I press "bim.edit_style" Then nothing happens + +Scenario: Load styles + Given an empty IFC project + And I add a cube + And I add a material + And I press "bim.add_style" + When I press "bim.load_styles(style_type='IfcSurfaceStyle')" + Then nothing happens + +Scenario: Disable editing styles + Given an empty IFC project + And I add a cube + And I add a material + And I press "bim.add_style" + And I press "bim.load_styles(style_type='IfcSurfaceStyle')" + When I press "bim.disable_editing_style" + Then nothing happens diff --git a/src/blenderbim/test/bim/feature/type.feature b/src/blenderbim/test/bim/feature/type.feature index 2161090f26..bcde86e305 100644 --- a/src/blenderbim/test/bim/feature/type.feature +++ b/src/blenderbim/test/bim/feature/type.feature @@ -42,7 +42,7 @@ Scenario: Assign type - assign to a type with a material layer set And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType" And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType" And I press "bim.assign_class" - And I press "bim.add_default_material" + And I press "bim.add_material(obj='')" And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialLayerSet" And I press "bim.assign_material" And I press "bim.enable_editing_assigned_material" @@ -68,7 +68,7 @@ Scenario: Assign type - assign to a type with a material profile set And I set "scene.BIMRootProperties.ifc_product" to "IfcElementType" And I set "scene.BIMRootProperties.ifc_class" to "IfcWallType" And I press "bim.assign_class" - And I press "bim.add_default_material" + And I press "bim.add_material(obj='')" And I set "active_object.BIMObjectMaterialProperties.material_type" to "IfcMaterialProfileSet" And I press "bim.assign_material" And I press "bim.enable_editing_assigned_material" diff --git a/src/blenderbim/test/core/test_style.py b/src/blenderbim/test/core/test_style.py index 25e761a3dd..a282b73a80 100644 --- a/src/blenderbim/test/core/test_style.py +++ b/src/blenderbim/test/core/test_style.py @@ -174,3 +174,16 @@ class TestEditStyle: ifc.run("style.edit_presentation_style", style="style", attributes="attributes").should_be_called() style.disable_editing("obj").should_be_called() subject.edit_style(ifc, style, obj="obj") + + +class TestLoadStyles: + def test_run(self, style): + style.import_presentation_styles("style_type").should_be_called() + style.enable_editing_styles().should_be_called() + subject.load_styles(style, style_type="style_type") + + +class TestDisableEditingStyles: + def test_run(self, style): + style.disable_editing_styles().should_be_called() + subject.disable_editing_styles(style) diff --git a/src/blenderbim/test/tool/test_style.py b/src/blenderbim/test/tool/test_style.py index 977f9d4fe3..c61150a046 100644 --- a/src/blenderbim/test/tool/test_style.py +++ b/src/blenderbim/test/tool/test_style.py @@ -50,6 +50,13 @@ class TestDisableEditing(NewFile): assert obj.BIMStyleProperties.is_editing is False +class TestDisableEditingStyles(NewFile): + def test_run(self): + bpy.context.scene.BIMStylesProperties.is_editing = True + subject.disable_editing_styles() + assert bpy.context.scene.BIMStylesProperties.is_editing is False + + class TestEnableEditing(NewFile): def test_run(self): obj = bpy.data.materials.new("Material") @@ -57,6 +64,13 @@ class TestEnableEditing(NewFile): assert obj.BIMStyleProperties.is_editing is True +class TestEnableEditingStyles(NewFile): + def test_run(self): + bpy.context.scene.BIMStylesProperties.is_editing = False + subject.enable_editing_styles() + assert bpy.context.scene.BIMStylesProperties.is_editing is True + + class TestExportSurfaceAttributes(NewFile): def test_run(self): TestImportSurfaceAttributes().test_run() @@ -352,3 +366,45 @@ class TestImportSurfaceAttributes(NewFile): assert len(obj.BIMStyleProperties.attributes) == 2 assert obj.BIMStyleProperties.attributes.get("Name").string_value == "Name" assert obj.BIMStyleProperties.attributes.get("Side").enum_value == "BOTH" + + +class TestImportPresentationStyles(NewFile): + def test_import_curve_styles(self): + ifc = ifcopenshell.file() + tool.Ifc.set(ifc) + style = ifc.createIfcCurveStyle(Name="Name") + subject.import_presentation_styles("IfcCurveStyle") + props = bpy.context.scene.BIMStylesProperties + assert props.styles[0].ifc_definition_id == style.id() + assert props.styles[0].name == "Name" + assert props.styles[0].total_elements == 0 + + def test_import_fillarea_styles(self): + ifc = ifcopenshell.file() + tool.Ifc.set(ifc) + style = ifc.createIfcFillAreaStyle(Name="Name") + subject.import_presentation_styles("IfcFillAreaStyle") + props = bpy.context.scene.BIMStylesProperties + assert props.styles[0].ifc_definition_id == style.id() + assert props.styles[0].name == "Name" + assert props.styles[0].total_elements == 0 + + def test_import_surface_styles(self): + ifc = ifcopenshell.file() + tool.Ifc.set(ifc) + style = ifc.createIfcSurfaceStyle(Name="Name") + subject.import_presentation_styles("IfcSurfaceStyle") + props = bpy.context.scene.BIMStylesProperties + assert props.styles[0].ifc_definition_id == style.id() + assert props.styles[0].name == "Name" + assert props.styles[0].total_elements == 0 + + def test_import_text_styles(self): + ifc = ifcopenshell.file() + tool.Ifc.set(ifc) + style = ifc.createIfcTextStyle(Name="Name") + subject.import_presentation_styles("IfcTextStyle") + props = bpy.context.scene.BIMStylesProperties + assert props.styles[0].ifc_definition_id == style.id() + assert props.styles[0].name == "Name" + assert props.styles[0].total_elements == 0