diff --git a/src/blenderbim/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py index b87350482f..3fede4f2ef 100644 --- a/src/blenderbim/blenderbim/bim/module/model/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/model/__init__.py @@ -11,8 +11,7 @@ classes = ( wall.AlignWall, wall.FlipWall, wall.SplitWall, - wall.AddWallOpening, - slab.AddSlabOpening, + opening.AddElementOpening, profile.ExtendProfile, prop.BIMModelProperties, ui.BIM_PT_authoring, diff --git a/src/blenderbim/blenderbim/bim/module/model/opening.py b/src/blenderbim/blenderbim/bim/module/model/opening.py index 4a53b564dc..9c0c482e3c 100644 --- a/src/blenderbim/blenderbim/bim/module/model/opening.py +++ b/src/blenderbim/blenderbim/bim/module/model/opening.py @@ -52,6 +52,46 @@ def mode_callback(obj, data): bm.free() +class AddElementOpening(bpy.types.Operator): + bl_idname = "bim.add_element_opening" + bl_label = "Add Element Opening" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + return IfcStore.execute_ifc_operator(self, context) + + def _execute(self, context): + selected_objs = context.selected_objects + if len(selected_objs) == 0 or not context.active_object: + return {"FINISHED"} + obj = context.active_object + if not obj.BIMObjectProperties.ifc_definition_id: + return {"FINISHED"} + element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id) + local_location = obj.matrix_world.inverted() @ context.scene.cursor.location + raycast = obj.closest_point_on_mesh(local_location, distance=0.01) + if not raycast[0]: + return {"FINISHED"} + + # The opening shall be based on the smallest bounding dimension of the element + dimension = min(obj.dimensions) + bpy.ops.mesh.primitive_cube_add(size=dimension * 2) + opening = context.selected_objects[0] + + # Place the opening in the middle of the element + global_location = obj.matrix_world @ raycast[1] + normal = raycast[2] + normal.negate() + global_normal = obj.matrix_world.to_quaternion() @ normal + opening.location = global_location + (global_normal * (dimension / 2)) + + opening.rotation_euler = obj.rotation_euler + opening.name = "Opening" + bpy.ops.bim.add_opening(opening=opening.name, obj=obj.name) + return {"FINISHED"} + + + def add_object(self, context): bm = bmesh.new() bmesh.ops.create_cube(bm, size=self.size) diff --git a/src/blenderbim/blenderbim/bim/module/model/product.py b/src/blenderbim/blenderbim/bim/module/model/product.py index 55e99c7045..3633783b5b 100644 --- a/src/blenderbim/blenderbim/bim/module/model/product.py +++ b/src/blenderbim/blenderbim/bim/module/model/product.py @@ -244,12 +244,17 @@ def regenerate_profile_usage(usecase_path, ifc_file, settings): def ensure_material_assigned(usecase_path, ifc_file, settings): - elements = [] - for rel in ifc_file.by_type("IfcRelAssociatesMaterial"): - if rel.RelatingMaterial == settings["material"] or [ - e for e in ifc_file.traverse(rel.RelatingMaterial) if e == settings["material"] - ]: - elements.extend(rel.RelatedObjects) + if usecase_path == "material.assign_material": + if not settings.get("Material", None): + return + elements = [self.settings["product"]] + else: + elements = [] + for rel in ifc_file.by_type("IfcRelAssociatesMaterial"): + if rel.RelatingMaterial == settings["material"] or [ + e for e in ifc_file.traverse(rel.RelatingMaterial) if e == settings["material"] + ]: + elements.extend(rel.RelatedObjects) for element in elements: obj = IfcStore.get_element(element.GlobalId) diff --git a/src/blenderbim/blenderbim/bim/module/model/slab.py b/src/blenderbim/blenderbim/bim/module/model/slab.py index 49468f3861..997b2b2463 100644 --- a/src/blenderbim/blenderbim/bim/module/model/slab.py +++ b/src/blenderbim/blenderbim/bim/module/model/slab.py @@ -199,42 +199,6 @@ def calculate_quantities(usecase_path, ifc_file, settings): PsetData.load(ifc_file, obj.BIMObjectProperties.ifc_definition_id) -class AddSlabOpening(bpy.types.Operator): - bl_idname = "bim.add_slab_opening" - bl_label = "Add Slab Opening" - bl_options = {"REGISTER", "UNDO"} - - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - - def _execute(self, context): - selected_objs = context.selected_objects - if len(selected_objs) == 0 or not context.active_object: - return {"FINISHED"} - slab_obj = context.active_object - if not slab_obj.BIMObjectProperties.ifc_definition_id: - return {"FINISHED"} - slab = IfcStore.get_file().by_id(slab_obj.BIMObjectProperties.ifc_definition_id) - local_location = slab_obj.matrix_world.inverted() @ context.scene.cursor.location - raycast = slab_obj.closest_point_on_mesh(local_location, distance=0.01) - if not raycast[0]: - return {"FINISHED"} - bpy.ops.mesh.primitive_cube_add(size=slab_obj.dimensions[2] * 2) - opening = context.selected_objects[0] - - # Place the opening in the middle of the slab - global_location = slab_obj.matrix_world @ raycast[1] - normal = raycast[2] - normal.negate() - global_normal = slab_obj.matrix_world.to_quaternion() @ normal - opening.location = global_location + (global_normal * (slab_obj.dimensions[2] / 2)) - - opening.rotation_euler = slab_obj.rotation_euler - opening.name = "Opening" - bpy.ops.bim.add_opening(opening=opening.name, obj=slab_obj.name) - return {"FINISHED"} - - class DumbSlabGenerator: def __init__(self, relating_type): self.relating_type = relating_type diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py index 019271365f..4cfbe60653 100644 --- a/src/blenderbim/blenderbim/bim/module/model/wall.py +++ b/src/blenderbim/blenderbim/bim/module/model/wall.py @@ -41,42 +41,6 @@ def mode_callback(obj, data): bm.free() -class AddWallOpening(bpy.types.Operator): - bl_idname = "bim.add_wall_opening" - bl_label = "Add Wall Opening" - bl_options = {"REGISTER", "UNDO"} - - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - - def _execute(self, context): - selected_objs = context.selected_objects - if len(selected_objs) == 0 or not context.active_object: - return {"FINISHED"} - wall_obj = context.active_object - if not wall_obj.BIMObjectProperties.ifc_definition_id: - return {"FINISHED"} - wall = IfcStore.get_file().by_id(wall_obj.BIMObjectProperties.ifc_definition_id) - local_location = wall_obj.matrix_world.inverted() @ context.scene.cursor.location - raycast = wall_obj.closest_point_on_mesh(local_location, distance=0.01) - if not raycast[0]: - return {"FINISHED"} - bpy.ops.mesh.primitive_cube_add(size=wall_obj.dimensions[1] * 2) - opening = bpy.context.selected_objects[0] - - # Place the opening in the middle of the wall - global_location = wall_obj.matrix_world @ raycast[1] - normal = raycast[2] - normal.negate() - global_normal = wall_obj.matrix_world.to_quaternion() @ normal - opening.location = global_location + (global_normal * (wall_obj.dimensions[1] / 2)) - - opening.rotation_euler = wall_obj.rotation_euler - opening.name = "Opening" - bpy.ops.bim.add_opening(opening=opening.name, obj=wall_obj.name) - return {"FINISHED"} - - class JoinWall(bpy.types.Operator): bl_idname = "bim.join_wall" bl_label = "Join Wall" diff --git a/src/blenderbim/blenderbim/bim/module/model/workspace.py b/src/blenderbim/blenderbim/bim/module/model/workspace.py index 4b29e5092f..6bf9b0ac2a 100644 --- a/src/blenderbim/blenderbim/bim/module/model/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/model/workspace.py @@ -64,14 +64,6 @@ class BimTool(WorkSpaceTool): row = layout.row(align=True) row.label(text="", icon="EVENT_SHIFT") row.label(text="Split", icon="EVENT_S") - row = layout.row(align=True) - row.label(text="", icon="EVENT_SHIFT") - row.label(text="Opening", icon="EVENT_O") - - if props.ifc_class == "IfcSlabType": - row = layout.row(align=True) - row.label(text="", icon="EVENT_SHIFT") - row.label(text="Opening", icon="EVENT_O") if props.ifc_class in ["IfcColumnType", "IfcBeamType", "IfcMemberType"]: row = layout.row() @@ -80,6 +72,10 @@ class BimTool(WorkSpaceTool): row.label(text="", icon="EVENT_SHIFT") row.label(text="Extend", icon="EVENT_E") + row = layout.row(align=True) + row.label(text="", icon="EVENT_SHIFT") + row.label(text="Opening", icon="EVENT_O") + row = layout.row(align=True) row.label(text="Align") row = layout.row(align=True) @@ -142,10 +138,7 @@ class Hotkey(bpy.types.Operator): bpy.ops.bim.align_product(align_type="NEGATIVE") def hotkey_S_O(self): - if self.props.ifc_class == "IfcWallType": - bpy.ops.bim.add_wall_opening() - elif self.props.ifc_class == "IfcSlabType": - bpy.ops.bim.add_slab_opening() + bpy.ops.bim.add_element_opening() def hotkey_A_D(self): bpy.ops.bim.toggle_decomposition_parenting()