diff --git a/src/blenderbim/blenderbim/bim/module/material/__init__.py b/src/blenderbim/blenderbim/bim/module/material/__init__.py index cb1794481b..dc45495d16 100644 --- a/src/blenderbim/blenderbim/bim/module/material/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/material/__init__.py @@ -21,6 +21,7 @@ from . import ui, prop, operator classes = ( operator.AddConstituent, + operator.AddDefaultMaterial, operator.AddLayer, operator.AddListItem, operator.AddMaterial, diff --git a/src/blenderbim/blenderbim/bim/module/material/operator.py b/src/blenderbim/blenderbim/bim/module/material/operator.py index 7cc6818c3c..7d455a2b63 100644 --- a/src/blenderbim/blenderbim/bim/module/material/operator.py +++ b/src/blenderbim/blenderbim/bim/module/material/operator.py @@ -68,6 +68,16 @@ class AssignParameterizedProfile(bpy.types.Operator): return {"FINISHED"} +class AddDefaultMaterial(bpy.types.Operator, Operator): + bl_idname = "bim.add_default_material" + bl_label = "Add Default Material" + bl_options = {"REGISTER", "UNDO"} + + def _execute(self, context): + core.add_default_material(tool.Ifc, tool.Material) + Data.load(IfcStore.get_file()) + + class AddMaterial(bpy.types.Operator): bl_idname = "bim.add_material" bl_label = "Add Material" diff --git a/src/blenderbim/blenderbim/bim/module/material/ui.py b/src/blenderbim/blenderbim/bim/module/material/ui.py index f3cb954d33..bd676e42c2 100644 --- a/src/blenderbim/blenderbim/bim/module/material/ui.py +++ b/src/blenderbim/blenderbim/bim/module/material/ui.py @@ -77,8 +77,9 @@ class BIM_PT_object_material(Panel): self.product_data = Data.products[self.oprops.ifc_definition_id] if not Data.materials: - row = self.layout.row() + row = self.layout.row(align=True) row.label(text="No Materials Available") + row.operator("bim.add_default_material", icon="ADD", text="") return if self.product_data: diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py index c50e684823..4331bf68f6 100644 --- a/src/blenderbim/blenderbim/bim/module/model/product.py +++ b/src/blenderbim/blenderbim/bim/module/model/product.py @@ -116,7 +116,6 @@ class AddTypeInstance(bpy.types.Operator): bpy.ops.bim.assign_class(obj=obj.name, ifc_class=instance_class) blenderbim.core.type.assign_type( tool.Ifc, - tool.Geometry, tool.Type, element=tool.Ifc.get_entity(obj), type=tool.Ifc.get().by_id(int(tprops.relating_type)), diff --git a/src/blenderbim/blenderbim/bim/module/model/profile.py b/src/blenderbim/blenderbim/bim/module/model/profile.py index 1890714b04..ee73153521 100644 --- a/src/blenderbim/blenderbim/bim/module/model/profile.py +++ b/src/blenderbim/blenderbim/bim/module/model/profile.py @@ -168,9 +168,7 @@ class DumbProfileGenerator: obj.rotation_euler[2] = math.pi / 2 element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) - blenderbim.core.type.assign_type( - tool.Ifc, tool.Geometry, tool.Type, element=tool.Ifc.get_entity(obj), type=self.relating_type - ) + blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=tool.Ifc.get_entity(obj), type=self.relating_type) profile_set_usage = ifcopenshell.util.element.get_material(element) blenderbim.core.geometry.add_representation( tool.Ifc, diff --git a/src/blenderbim/blenderbim/bim/module/model/slab.py b/src/blenderbim/blenderbim/bim/module/model/slab.py index 94b58b09a0..2a7b294513 100644 --- a/src/blenderbim/blenderbim/bim/module/model/slab.py +++ b/src/blenderbim/blenderbim/bim/module/model/slab.py @@ -307,9 +307,7 @@ class DumbSlabGenerator: ifc_class=ifc_class, ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryProfileDefWithVoids", ) - blenderbim.core.type.assign_type( - tool.Ifc, tool.Geometry, tool.Type, element=tool.Ifc.get_entity(obj), type=self.relating_type - ) + blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=tool.Ifc.get_entity(obj), type=self.relating_type) element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric") ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Engine": "BlenderBIM.DumbLayer3"}) diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py index 9ff3af2b1e..243977ab48 100644 --- a/src/blenderbim/blenderbim/bim/module/model/wall.py +++ b/src/blenderbim/blenderbim/bim/module/model/wall.py @@ -807,9 +807,7 @@ class DumbWallGenerator: ifc_representation_class="IfcExtrudedAreaSolid/IfcArbitraryClosedProfileDef", ) - blenderbim.core.type.assign_type( - tool.Ifc, tool.Geometry, tool.Type, element=tool.Ifc.get_entity(obj), type=self.relating_type - ) + blenderbim.core.type.assign_type(tool.Ifc, tool.Type, element=tool.Ifc.get_entity(obj), type=self.relating_type) element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) pset = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name="EPset_Parametric") ifcopenshell.api.run("pset.edit_pset", self.file, pset=pset, properties={"Engine": "BlenderBIM.DumbLayer2"}) diff --git a/src/blenderbim/blenderbim/core/material.py b/src/blenderbim/blenderbim/core/material.py index 2707616ccc..78516df6ac 100644 --- a/src/blenderbim/blenderbim/core/material.py +++ b/src/blenderbim/blenderbim/core/material.py @@ -19,3 +19,9 @@ def unlink_material(material, obj=None): material.unlink(obj) + + +def add_default_material(ifc, material): + obj = material.add_default_material_object() + material.link(ifc.run("material.add_material", name="Default"), obj) + return obj diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index 9c3b94f216..2cb740e11c 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -90,6 +90,8 @@ class Ifc: @interface class Material: + def add_default_material_object(cls): pass + def link(cls, element, obj): pass def unlink(cls, obj): pass diff --git a/src/blenderbim/blenderbim/tool/material.py b/src/blenderbim/blenderbim/tool/material.py index f4ef4821c2..79620381b9 100644 --- a/src/blenderbim/blenderbim/tool/material.py +++ b/src/blenderbim/blenderbim/tool/material.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 @@ -23,6 +24,10 @@ import blenderbim.bim.helper class Material(blenderbim.core.tool.Material): + @classmethod + def add_default_material_object(cls): + return bpy.data.materials.new("Default") + @classmethod def link(cls, material, obj): obj.BIMObjectProperties.ifc_definition_id = material.id() diff --git a/src/blenderbim/test/bim/feature/material.feature b/src/blenderbim/test/bim/feature/material.feature index 6fc0a3cbaf..9a969862fb 100644 --- a/src/blenderbim/test/bim/feature/material.feature +++ b/src/blenderbim/test/bim/feature/material.feature @@ -1,6 +1,11 @@ @material Feature: Material +Scenario: Add default material + Given an empty IFC project + When I press "bim.add_default_material" + Then the material "Default" exists + Scenario: Unlink object Given an empty IFC project And I add a cube diff --git a/src/blenderbim/test/core/test_material.py b/src/blenderbim/test/core/test_material.py index fdea88b98c..8fa9a9fe5e 100644 --- a/src/blenderbim/test/core/test_material.py +++ b/src/blenderbim/test/core/test_material.py @@ -24,3 +24,11 @@ class TestUnlinkMaterial: def test_run(self, material): material.unlink("obj").should_be_called() subject.unlink_material(material, obj="obj") + + +class TestAddDefaultMaterial: + def test_run(self, ifc, material): + material.add_default_material_object().should_be_called().will_return("obj") + ifc.run("material.add_material", name="Default").should_be_called().will_return("material") + material.link("material", "obj").should_be_called() + assert subject.add_default_material(ifc, material) == "obj" diff --git a/src/blenderbim/test/tool/test_material.py b/src/blenderbim/test/tool/test_material.py index 4fcc0d5755..cb6735797c 100644 --- a/src/blenderbim/test/tool/test_material.py +++ b/src/blenderbim/test/tool/test_material.py @@ -24,6 +24,18 @@ from test.bim.bootstrap import NewFile from blenderbim.tool.material import Material as subject +class TestImplementsTool(NewFile): + def test_run(self): + assert isinstance(subject(), blenderbim.core.tool.Material) + + +class TestAddDefaultMaterialObject(NewFile): + def test_run(self): + material = subject.add_default_material_object() + assert isinstance(material, bpy.types.Material) + assert material.name == "Default" + + class TestLink(NewFile): def test_run(self): obj = bpy.data.materials.new("Material")