diff --git a/src/blenderbim/blenderbim/bim/module/model/__init__.py b/src/blenderbim/blenderbim/bim/module/model/__init__.py index d23386d63f..802d4b7a20 100644 --- a/src/blenderbim/blenderbim/bim/module/model/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/model/__init__.py @@ -9,6 +9,7 @@ classes = ( wall.AlignWall, wall.FlipWall, wall.SplitWall, + wall.AddWallOpening, prop.BIMModelProperties, ui.BIM_PT_authoring, ui.BIM_PT_authoring_architectural, diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py index 25ec66c86b..92ad70346b 100644 --- a/src/blenderbim/blenderbim/bim/module/model/wall.py +++ b/src/blenderbim/blenderbim/bim/module/model/wall.py @@ -36,6 +36,41 @@ def mode_callback(obj, data): IfcStore.edited_objs.add(obj) +class AddWallOpening(bpy.types.Operator): + bl_idname = "bim.add_wall_opening" + bl_label = "Add Wall Opening" + bl_options = {"REGISTER", "UNDO"} + + 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) + if not wall.is_a("IfcWall"): + return {"FINISHED"} + 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 f14eaf5c35..edc51476ec 100644 --- a/src/blenderbim/blenderbim/bim/module/model/workspace.py +++ b/src/blenderbim/blenderbim/bim/module/model/workspace.py @@ -26,6 +26,7 @@ class BimTool(WorkSpaceTool): ("bim.hotkey", {"type": "X", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "X")]}), ("bim.hotkey", {"type": "C", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "C")]}), ("bim.hotkey", {"type": "V", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "V")]}), + ("bim.hotkey", {"type": "O", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "O")]}), ) def draw_settings(context, layout, tool): @@ -45,6 +46,10 @@ class BimTool(WorkSpaceTool): row.label(text="Mitre", icon="EVENT_Y") row.label(text="Flip", icon="EVENT_F") row.label(text="Split", icon="EVENT_S") + row.label(text="Opening", icon="EVENT_O") + + if props.ifc_class == "IfcSlabType": + row.label(text="Opening", icon="EVENT_O") row.label(text="", icon="EVENT_X") row.label(text="", icon="EVENT_C") @@ -87,3 +92,9 @@ class Hotkey(bpy.types.Operator): bpy.ops.bim.align_wall(align_type="EXTERIOR") else: bpy.ops.bim.align_product(align_type="NEGATIVE") + + def hotkey_O(self): + if self.props.ifc_class == "IfcWallType": + bpy.ops.bim.add_wall_opening() + elif self.props.ifc_class == "IfcSlabType": + pass