From a13b71abf05c721d94a3bc8b502fc721bc4fcdd6 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 25 May 2021 13:10:26 +1000 Subject: [PATCH] Layer set usages now inherit layer sets from the type. Walls now support material layer set usages. Also minor fixes, thanks s-leger! --- src/blenderbim/blenderbim/bim/handler.py | 10 +++++++- .../blenderbim/bim/module/model/operator.py | 24 ++++++++++++------- .../bim/module/parametric/operator.py | 4 ++-- .../api/material/assign_material.py | 11 ++++++++- .../ifcopenshell/util/element.py | 4 ---- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index c91fb3f410..9720353ce6 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -8,6 +8,9 @@ from ifcopenshell.api.attribute.data import Data as AttributeData from ifcopenshell.api.type.data import Data as TypeData +global_subscription_owner = object() + + def mode_callback(obj, data): for obj in bpy.context.selected_objects + [bpy.context.active_object]: if ( @@ -87,6 +90,8 @@ def purge_module_data(): def loadIfcStore(scene): IfcStore.purge() ifc_file = IfcStore.get_file() + if not ifc_file: + return IfcStore.get_schema() [ IfcStore.link_element(ifc_file.by_id(o.BIMObjectProperties.ifc_definition_id), o) @@ -182,8 +187,11 @@ def active_object_callback(): @persistent def setDefaultProperties(scene): + global global_subscription_owner active_object_key = bpy.types.LayerObjects, "active" - bpy.msgbus.subscribe_rna(key=active_object_key, owner="BlenderBIM", args=(), notify=active_object_callback) + bpy.msgbus.subscribe_rna( + key=active_object_key, owner=global_subscription_owner, args=(), notify=active_object_callback + ) ifcopenshell.api.owner.settings.get_person = ( lambda ifc: ifc.by_id(int(bpy.context.scene.BIMOwnerProperties.user_person)) if bpy.context.scene.BIMOwnerProperties.user_person diff --git a/src/blenderbim/blenderbim/bim/module/model/operator.py b/src/blenderbim/blenderbim/bim/module/model/operator.py index a602b5b839..ac7e97a1d9 100644 --- a/src/blenderbim/blenderbim/bim/module/model/operator.py +++ b/src/blenderbim/blenderbim/bim/module/model/operator.py @@ -6,6 +6,7 @@ import ifcopenshell.util.unit import mathutils.geometry from blenderbim.bim.ifc import IfcStore from mathutils import Vector, Matrix +from ifcopenshell.api.material.data import Data as MaterialData class AddTypeInstance(bpy.types.Operator): @@ -83,6 +84,9 @@ class JoinWall(bpy.types.Operator): joiner.join_L() elif self.join_type == "V": joiner.join_V() + IfcStore.edited_objs.add(obj) + if self.join_type != "T": + IfcStore.edited_objs.add(context.active_object) return {"FINISHED"} @@ -110,7 +114,7 @@ class AlignWall(bpy.types.Operator): def recalculate_dumb_wall_origin(wall): - new_origin = wall.matrix_world @ ((Vector(wall.bound_box[3]) + Vector(wall.bound_box[0])) / 2) + new_origin = wall.matrix_world @ Vector(wall.bound_box[0]) if (wall.matrix_world.translation - new_origin).length > 0.001: wall.data.transform( Matrix.Translation( @@ -524,14 +528,14 @@ class DumbWallGenerator: def create_wall(self): verts = [ - Vector((0, self.width / 2, 0)), - Vector((0, -self.width / 2, 0)), - Vector((0, self.width / 2, self.height)), - Vector((0, -self.width / 2, self.height)), - Vector((self.length, self.width / 2, 0)), - Vector((self.length, -self.width / 2, 0)), - Vector((self.length, self.width / 2, self.height)), - Vector((self.length, -self.width / 2, self.height)), + Vector((0, self.width, 0)), + Vector((0, 0, 0)), + Vector((0, self.width, self.height)), + Vector((0, 0, self.height)), + Vector((self.length, self.width, 0)), + Vector((self.length, 0, 0)), + Vector((self.length, self.width, self.height)), + Vector((self.length, 0, self.height)), ] faces = [ [1, 3, 2, 0], @@ -554,4 +558,6 @@ class DumbWallGenerator: 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.DumbWall"}) + ifcopenshell.api.run("material.assign_material", self.file, product=element, type="IfcMaterialLayerSetUsage") + MaterialData.load(self.file) return obj diff --git a/src/blenderbim/blenderbim/bim/module/parametric/operator.py b/src/blenderbim/blenderbim/bim/module/parametric/operator.py index 43a3b97a4a..e55c1628be 100644 --- a/src/blenderbim/blenderbim/bim/module/parametric/operator.py +++ b/src/blenderbim/blenderbim/bim/module/parametric/operator.py @@ -52,8 +52,8 @@ def generate_dumb_wall_axis(usecase_path, ifc_file, **settings): new_settings["context"] = axis_context mesh = bpy.data.meshes.new("Temporary Axis") - start = (Vector(obj.bound_box[3]) + Vector(obj.bound_box[0])) / 2 - end = (Vector(obj.bound_box[7]) + Vector(obj.bound_box[4])) / 2 + start = Vector(obj.bound_box[0]) + end = Vector(obj.bound_box[4]) mesh.from_pydata([start, end], [(0, 1)], []) new_settings["geometry"] = mesh diff --git a/src/ifcopenshell-python/ifcopenshell/api/material/assign_material.py b/src/ifcopenshell-python/ifcopenshell/api/material/assign_material.py index 8e7147ee67..3a4f751e45 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/material/assign_material.py +++ b/src/ifcopenshell-python/ifcopenshell/api/material/assign_material.py @@ -1,4 +1,5 @@ import ifcopenshell +import ifcopenshell.util.element class Usecase: @@ -18,7 +19,15 @@ class Usecase: material_set = self.file.create_entity(self.settings["type"]) self.create_material_association(material_set) elif self.settings["type"] == "IfcMaterialLayerSetUsage": - material_set = self.file.create_entity("IfcMaterialLayerSet") + element_type = ifcopenshell.util.element.get_type(self.settings["product"]) + if element_type: + element_type_material = ifcopenshell.util.element.get_material(element_type) + if element_type_material and element_type_material.is_a("IfcMaterialLayerSet"): + material_set = element_type_material + else: + material_set = self.file.create_entity("IfcMaterialLayerSet") + else: + material_set = self.file.create_entity("IfcMaterialLayerSet") material_set_usage = self.create_layer_set_usage(material_set) self.create_material_association(material_set_usage) elif self.settings["type"] == "IfcMaterialProfileSet": diff --git a/src/ifcopenshell-python/ifcopenshell/util/element.py b/src/ifcopenshell-python/ifcopenshell/util/element.py index 8fb338e957..0bbcb8cb8f 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/element.py +++ b/src/ifcopenshell-python/ifcopenshell/util/element.py @@ -79,10 +79,6 @@ def get_material(element): if hasattr(relating_type, "HasAssociations") and relating_type.HasAssociations: for relationship in relating_type.HasAssociations: if relationship.is_a("IfcRelAssociatesMaterial"): - if relationship.RelatingMaterial.is_a("IfcMaterialLayerSetUsage"): - return relationship.RelatingMaterial.ForLayerSet - elif relationship.RelatingMaterial.is_a("IfcMaterialProfileSetUsage"): - return relationship.RelatingMaterial.ForProfileSet return relationship.RelatingMaterial