diff --git a/src/bonsai/bonsai/bim/module/model/decorator.py b/src/bonsai/bonsai/bim/module/model/decorator.py index 2ea21af71f..85091a3b2a 100644 --- a/src/bonsai/bonsai/bim/module/model/decorator.py +++ b/src/bonsai/bonsai/bim/module/model/decorator.py @@ -296,7 +296,7 @@ class ProfileDecorator: return points, listEdg -class WallPolylineDecorator: +class PolylineDecorator: is_installed = False handlers = [] mouse_pos = None diff --git a/src/bonsai/bonsai/bim/module/model/wall.py b/src/bonsai/bonsai/bim/module/model/wall.py index bdd2035b42..303d63bb38 100644 --- a/src/bonsai/bonsai/bim/module/model/wall.py +++ b/src/bonsai/bonsai/bim/module/model/wall.py @@ -37,7 +37,7 @@ from bonsai.bim.ifc import IfcStore from math import pi, sin, cos, degrees from mathutils import Vector, Matrix from bonsai.bim.module.model.opening import FilledOpeningGenerator -from bonsai.bim.module.model.decorator import WallPolylineDecorator +from bonsai.bim.module.model.decorator import PolylineDecorator from typing import Optional from lark import Lark, Transformer @@ -487,13 +487,13 @@ class DrawPolylineWall(bpy.types.Operator): self.report({"WARNING"}, "The number typed is not valid.") else: if self.input_type in {"X", "Y"}: - self.input_panel = WallPolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) + self.input_panel = PolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) elif self.input_type in {"D", "A"}: - self.input_panel = WallPolylineDecorator.calculate_x_and_y(context) + self.input_panel = PolylineDecorator.calculate_x_y_and_z(context) self.input_panel[self.input_type] = self.number_output - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() # TODO This is creating a hack in generate function from DumbWallGenerator @@ -527,7 +527,7 @@ class DrawPolylineWall(bpy.types.Operator): self.mousemove_count += 1 self.is_input_on = False self.input_type = "OFF" - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Snap.clear_snaping_ref() tool.Blender.update_viewport() else: @@ -540,32 +540,31 @@ class DrawPolylineWall(bpy.types.Operator): if self.mousemove_count > 3: tool.Snap.snaping_movement(context, event, self.objs_2d_bbox) - WallPolylineDecorator.set_mouse_position(event) - self.input_panel = WallPolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) + PolylineDecorator.set_mouse_position(event) + self.input_panel = PolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) tool.Blender.update_viewport() return {"RUNNING_MODAL"} + if event.value == "RELEASE" and event.type == "BACK_SPACE": + tool.Snap.remove_last_polyline_point() + tool.Blender.update_viewport() + if event.value == "RELEASE" and event.type == "LEFTMOUSE": tool.Snap.insert_polyline_point() tool.Blender.update_viewport() if event.value == "PRESS" and event.type == "C": tool.Snap.close_polyline() - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() - if not self.is_input_on: - if event.value == "RELEASE" and event.type == "BACK_SPACE": - tool.Snap.remove_last_polyline_point() - tool.Blender.update_viewport() - if self.is_input_on and event.value == "PRESS" and event.type == "TAB": self.recalculate_inputs(context) index = self.input_options.index(self.input_type) size = len(self.input_options) self.input_type = self.input_options[((index + 1) % size)] self.number_input = [] - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() if not self.is_input_on and event.value == "RELEASE" and event.type == "TAB": @@ -573,7 +572,7 @@ class DrawPolylineWall(bpy.types.Operator): self.is_input_on = True self.input_type = "X" self.number_input = [] - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() if not self.is_input_on and event.ascii in self.number_options: @@ -581,7 +580,7 @@ class DrawPolylineWall(bpy.types.Operator): self.is_input_on = True self.input_type = "D" self.number_input = [] - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() if event.value == "RELEASE" and event.type in self.input_options: @@ -589,7 +588,7 @@ class DrawPolylineWall(bpy.types.Operator): self.is_input_on = True self.input_type = event.type self.number_input = [] - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() if self.input_type in self.input_options: @@ -603,7 +602,7 @@ class DrawPolylineWall(bpy.types.Operator): self.number_input = self.number_input[:-1] self.number_output = "".join(self.number_input) self.input_panel[self.input_type] = self.number_output - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() else: self.number_input.append(event.ascii) @@ -645,11 +644,11 @@ class DrawPolylineWall(bpy.types.Operator): if event.value == "RELEASE" and event.type in {"RIGHTMOUSE", "ESC"}: self.is_input_on = False self.input_type = "OFF" - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() else: if event.value == "RELEASE" and event.type in {"RIGHTMOUSE", "ESC"}: - WallPolylineDecorator.uninstall() + PolylineDecorator.uninstall() tool.Snap.clear_polyline() tool.Blender.update_viewport() return {"CANCELLED"} @@ -658,17 +657,17 @@ class DrawPolylineWall(bpy.types.Operator): def invoke(self, context, event): if context.space_data.type == "VIEW_3D": - WallPolylineDecorator.install(context) + PolylineDecorator.install(context) tool.Snap.set_use_default_container(True) - WallPolylineDecorator.set_use_default_container(True) + PolylineDecorator.set_use_default_container(True) tool.Snap.set_snap_plane_method("XY") - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) self.visible_objs = tool.Raycast.get_visible_objects(context) for obj in self.visible_objs: self.objs_2d_bbox.append(tool.Raycast.get_objects_2d_bounding_boxes(context, obj)) tool.Snap.snaping_movement(context, event, self.objs_2d_bbox) - WallPolylineDecorator.set_mouse_position(event) - self.input_panel = WallPolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) + PolylineDecorator.set_mouse_position(event) + self.input_panel = PolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) tool.Blender.update_viewport() context.window_manager.modal_handler_add(self) return {"RUNNING_MODAL"} diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index 18b1e6cc69..aa9487ac7b 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -52,7 +52,7 @@ from bpy.app.handlers import persistent from ifcopenshell.geom import ShapeElementType from bonsai.bim.module.project.data import LinksData from bonsai.bim.module.project.decorator import ProjectDecorator, ClippingPlaneDecorator -from bonsai.bim.module.model.decorator import WallPolylineDecorator +from bonsai.bim.module.model.decorator import PolylineDecorator from typing import Union @@ -2311,78 +2311,177 @@ class MeasureTool(bpy.types.Operator): self.input_options = ["X", "Y", "D", "A"] self.input_type = "OFF" self.input_value_xy = [None, None] - self.input_panel = {"X": "", "Y": "", "Z": "", "D": "", "A": ""} + self.input_panel = {"X": "", "Y": "", "Z": "", "D": "", "A": "", "AREA": ""} self.snap_angle = None + def recalculate_inputs(self, context): + if self.number_input: + is_valid, self.number_output = tool.Snap.validate_input(self.number_output) + self.input_panel[self.input_type] = self.number_output + if not is_valid: + self.report({"WARNING"}, "The number typed is not valid.") + else: + if self.input_type in {"X", "Y", "Z"}: + self.input_panel = PolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) + elif self.input_type in {"D", "A"}: + self.input_panel = PolylineDecorator.calculate_x_y_and_z(context) + + self.input_panel[self.input_type] = self.number_output + + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Blender.update_viewport() + def modal(self, context, event): - if event.type == "MOUSEMOVE": - self.mousemove_count += 1 - self.input_type = "OFF" - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) - tool.Blender.update_viewport() - else: - self.mousemove_count = 0 + if not self.is_input_on: + if event.type == "MOUSEMOVE": + self.mousemove_count += 1 + self.is_input_on = False + self.input_type = "OFF" + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Snap.clear_snaping_ref() + tool.Blender.update_viewport() + else: + self.mousemove_count = 0 - if self.mousemove_count == 2: - self.objs_2d_bbox = [] - for obj in self.visible_objs: - self.objs_2d_bbox.append(tool.Raycast.get_objects_2d_bounding_boxes(context, obj)) + if self.mousemove_count == 2: + self.objs_2d_bbox = [] + for obj in self.visible_objs: + self.objs_2d_bbox.append(tool.Raycast.get_objects_2d_bounding_boxes(context, obj)) - if self.mousemove_count > 3: - tool.Snap.snaping_movement(context, event, self.objs_2d_bbox) - WallPolylineDecorator.set_mouse_position(event) - self.input_panel = WallPolylineDecorator.calculate_distance_and_angle(context, False) - tool.Blender.update_viewport() - return {"RUNNING_MODAL"} + if self.mousemove_count > 3: + tool.Snap.snaping_movement(context, event, self.objs_2d_bbox) + PolylineDecorator.set_mouse_position(event) + self.input_panel = PolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + self.input_panel = PolylineDecorator.calculate_area(context) + tool.Blender.update_viewport() + return {"RUNNING_MODAL"} - if event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}: - return {"PASS_THROUGH"} + if event.value == "RELEASE" and event.type == "BACK_SPACE": + tool.Snap.remove_last_polyline_point() + tool.Blender.update_viewport() if event.value == "RELEASE" and event.type == "LEFTMOUSE": tool.Snap.insert_polyline_point() tool.Blender.update_viewport() - if event.value == "RELEASE" and event.type == "BACK_SPACE": - tool.Snap.remove_last_polyline_point() + if event.value == "PRESS" and event.type == "C": + tool.Snap.close_polyline() + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Blender.update_viewport() + + if self.is_input_on and event.value == "PRESS" and event.type == "TAB": + self.recalculate_inputs(context) + index = self.input_options.index(self.input_type) + size = len(self.input_options) + self.input_type = self.input_options[((index + 1) % size)] + self.number_input = [] + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Blender.update_viewport() + + if not self.is_input_on and event.value == "RELEASE" and event.type == "TAB": + self.recalculate_inputs(context) + self.is_input_on = True + self.input_type = "X" + self.number_input = [] + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Blender.update_viewport() + + if not self.is_input_on and event.ascii in self.number_options: + self.recalculate_inputs(context) + self.is_input_on = True + self.input_type = "D" + self.number_input = [] + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Blender.update_viewport() + + if event.value == "RELEASE" and event.type in self.input_options: + self.recalculate_inputs(context) + self.is_input_on = True + self.input_type = event.type + self.number_input = [] + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Blender.update_viewport() + + if self.input_type in self.input_options: + if (event.ascii in self.number_options) or (event.value == "RELEASE" and event.type == "BACK_SPACE"): + if event.type == "BACK_SPACE": + if len(self.number_input) <= 1: + self.number_input = [] + else: + self.number_input = self.number_input[:-1] + self.number_output = "".join(self.number_input) + self.input_panel[self.input_type] = self.number_output + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Blender.update_viewport() + else: + self.number_input.append(event.ascii) + self.number_output = "".join(self.number_input) + + if self.number_input: + self.input_panel[self.input_type] = self.number_output + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Blender.update_viewport() + + if self.is_input_on and event.value == "RELEASE" and event.type in {"RET", "NUMPAD_ENTER"}: + self.recalculate_inputs(context) + tool.Snap.insert_polyline_point( + float(self.input_panel["X"]), float(self.input_panel["Y"]), float(self.input_panel["Z"]) + ) + self.is_input_on = False + self.input_type = "OFF" + self.number_input = [] + self.number_output = "" + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) tool.Blender.update_viewport() if event.shift and event.type == "X": tool.Snap.set_use_default_container(False) - WallPolylineDecorator.set_use_default_container(False) + PolylineDecorator.set_use_default_container(False) tool.Snap.set_snap_plane_method("YZ") if event.shift and event.type == "Y": tool.Snap.set_use_default_container(False) - WallPolylineDecorator.set_use_default_container(False) + PolylineDecorator.set_use_default_container(False) tool.Snap.set_snap_plane_method("XZ") if event.shift and event.type == "Z": tool.Snap.set_use_default_container(False) - WallPolylineDecorator.set_use_default_container(False) + PolylineDecorator.set_use_default_container(False) tool.Snap.set_snap_plane_method("XY") - if event.value == "RELEASE" and event.type in {"RIGHTMOUSE", "ESC"}: - WallPolylineDecorator.uninstall() - tool.Snap.clear_polyline() - tool.Blender.update_viewport() - return {"FINISHED"} + if event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}: + return {"PASS_THROUGH"} + + if self.is_input_on: + if event.value == "RELEASE" and event.type in {"RIGHTMOUSE", "ESC"}: + self.is_input_on = False + self.input_type = "OFF" + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) + tool.Blender.update_viewport() + else: + if event.value == "RELEASE" and event.type in {"RIGHTMOUSE", "ESC"}: + PolylineDecorator.uninstall() + tool.Snap.clear_polyline() + tool.Blender.update_viewport() + return {"CANCELLED"} return {"RUNNING_MODAL"} def invoke(self, context, event): if context.space_data.type == "VIEW_3D": - WallPolylineDecorator.install(context) + PolylineDecorator.install(context) tool.Snap.set_use_default_container(False) - WallPolylineDecorator.set_use_default_container(False) + PolylineDecorator.set_use_default_container(False) tool.Snap.set_snap_plane_method("No Plane") - WallPolylineDecorator.set_input_panel(self.input_panel, self.input_type) + PolylineDecorator.set_input_panel(self.input_panel, self.input_type) self.visible_objs = tool.Raycast.get_visible_objects(context) for obj in self.visible_objs: self.objs_2d_bbox.append(tool.Raycast.get_objects_2d_bounding_boxes(context, obj)) tool.Snap.snaping_movement(context, event, self.objs_2d_bbox) - WallPolylineDecorator.set_mouse_position(event) - self.input_panel = WallPolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) + PolylineDecorator.set_mouse_position(event) + self.input_panel = PolylineDecorator.calculate_distance_and_angle(context, self.is_input_on) tool.Blender.update_viewport() context.window_manager.modal_handler_add(self) return {"RUNNING_MODAL"} diff --git a/src/bonsai/bonsai/tool/snap.py b/src/bonsai/bonsai/tool/snap.py index 47a284c139..143703175c 100644 --- a/src/bonsai/bonsai/tool/snap.py +++ b/src/bonsai/bonsai/tool/snap.py @@ -19,7 +19,7 @@ import bpy import bonsai.core.tool import bonsai.tool as tool -from bonsai.bim.module.model.decorator import WallPolylineDecorator +from bonsai.bim.module.model.decorator import PolylineDecorator import math import mathutils from mathutils import Matrix, Vector @@ -222,7 +222,7 @@ class Snap(bonsai.core.tool.Snap): pivot_axis = "X" rectangle_data = create_axis_rectangle_data(last_point) - WallPolylineDecorator.set_axis_rectangle(rectangle_data) + PolylineDecorator.set_axis_rectangle(rectangle_data) for axis in snap_axis: rot_mat = Matrix.Rotation(math.radians(360 - axis), 3, pivot_axis) start, end = create_axis_line_data(rot_mat, last_point) @@ -230,7 +230,7 @@ class Snap(bonsai.core.tool.Snap): proximity = rot_intersection.y if cls.snap_plane_method == "XZ": proximity = rot_intersection.z - WallPolylineDecorator.set_angle_axis_line(start, end) + PolylineDecorator.set_angle_axis_line(start, end) if lock_axis: is_on_rot_axis = True else: @@ -379,7 +379,7 @@ class Snap(bonsai.core.tool.Snap): elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z plane_origin, plane_normal = select_plane_method() - WallPolylineDecorator.set_plane(plane_origin, plane_normal) + PolylineDecorator.set_plane(plane_origin, plane_normal) intersection = tool.Raycast.ray_cast_to_plane(context, event, plane_origin, plane_normal) if cls.snap_plane_method in {"XY", "XZ", "YZ"}: