From 55df9a42e65223657726c28246fd65381c62325f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Sat, 7 Sep 2024 17:30:18 -0300 Subject: [PATCH] WIP - More refactor --- .../bonsai/bim/module/model/decorator.py | 8 +- src/bonsai/bonsai/bim/module/model/wall.py | 75 ++++++++--------- src/bonsai/bonsai/tool/polyline.py | 2 +- src/bonsai/bonsai/tool/snap.py | 80 +++++++------------ 4 files changed, 75 insertions(+), 90 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/model/decorator.py b/src/bonsai/bonsai/bim/module/model/decorator.py index 790cd9740b..c330602467 100644 --- a/src/bonsai/bonsai/bim/module/model/decorator.py +++ b/src/bonsai/bonsai/bim/module/model/decorator.py @@ -334,10 +334,13 @@ class PolylineDecorator: cls.is_installed = False @classmethod - def update(cls, event, tool_state, input_ui): + def update(cls, event, tool_state, input_ui, snapping_point): cls.event = event cls.tool_state = tool_state cls.input_ui = input_ui + cls.snap_info = f"""Snap: {snapping_point[1]} + Axis:{tool_state.axis_method} + Plane: {tool_state.plane_method}""" @classmethod def set_input_ui(cls, input_ui): @@ -356,9 +359,6 @@ class PolylineDecorator: def set_tool_state(cls, tool_state): cls.tool_state = tool_state - @classmethod - def set_snap_info(cls, snap_info): - cls.snap_info = snap_info def draw_batch(self, shader_type, content_pos, color, indices=None): diff --git a/src/bonsai/bonsai/bim/module/model/wall.py b/src/bonsai/bonsai/bim/module/model/wall.py index 50cd35de0f..3b6a1d2ee0 100644 --- a/src/bonsai/bonsai/bim/module/model/wall.py +++ b/src/bonsai/bonsai/bim/module/model/wall.py @@ -322,7 +322,6 @@ class DrawPolylineWall(bpy.types.Operator): self.number_input = [] self.number_output = "" self.number_is_negative = False - self.is_input_on = False self.input_options = ["D", "A", "X", "Y"] self.input_type = None self.input_type = None @@ -386,14 +385,14 @@ class DrawPolylineWall(bpy.types.Operator): def modal(self, context, event): - if not self.is_input_on: + if not self.tool_state.is_input_on: if event.type == "MOUSEMOVE" or event.type == "INBETWEEN_MOUSEMOVE": self.mousemove_count += 1 - self.is_input_on = False + self.tool_state.mode = "Mouse" self.tool_state.is_input_on = False self.input_type = None self.tool_state.input_type = None - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Snap.clear_snapping_ref() tool.Blender.update_viewport() else: @@ -406,7 +405,8 @@ class DrawPolylineWall(bpy.types.Operator): if self.mousemove_count > 3: detected_snaps = tool.Snap.detect_snapping_points(context, event, self.objs_2d_bbox, self.tool_state) - self.snapping_points = tool.Snap.select_snapping_points(context, event, detected_snaps) + self.snapping_points = tool.Snap.select_snapping_points(context, event, self.tool_state, detected_snaps) + print(self.snapping_points) tool.Polyline.calculate_distance_and_angle(context, self.input_ui, self.tool_state) tool.Blender.update_viewport() return {"RUNNING_MODAL"} @@ -420,35 +420,38 @@ class DrawPolylineWall(bpy.types.Operator): tool.Blender.update_viewport() if event.value == "PRESS" and event.type == "X": - tool.Snap.set_snap_axis_method("X") + self.tool_state.axis_method = "X" if self.tool_state.axis_method != event.type else None + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() if event.value == "PRESS" and event.type == "Y": - tool.Snap.set_snap_axis_method("Y") + self.tool_state.axis_method = "Y" if self.tool_state.axis_method != event.type else None + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() if event.value == "PRESS" and event.type == "C": tool.Snap.close_polyline() - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() - if self.is_input_on and event.value == "PRESS" and event.type == "TAB": + if self.tool_state.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.tool_state.input_type = self.input_options[((index + 1) % size)] + self.tool_state.mode = "Select" self.is_typing = False self.number_input = self.input_ui.get_formatted_value(self.input_type) self.number_input = list(self.number_input) self.number_output = "".join(self.number_input) self.input_ui.set_value(self.input_type, self.number_output) - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() - if not self.is_input_on and event.value == "RELEASE" and event.type == "TAB": + if not self.tool_state.is_input_on and event.value == "RELEASE" and event.type == "TAB": self.recalculate_inputs(context) - self.is_input_on = True + self.tool_state.mode = "Select" self.tool_state.is_input_on = True self.input_type = "D" self.tool_state.input_type = "D" @@ -457,33 +460,31 @@ class DrawPolylineWall(bpy.types.Operator): self.number_input = list(self.number_input) self.number_output = "".join(self.number_input) self.input_ui.set_value(self.input_type, self.number_output) - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() - if not self.is_input_on and event.ascii in self.number_options: + if not self.tool_state.is_input_on and event.ascii in self.number_options: self.recalculate_inputs(context) - self.is_input_on = True + self.tool_state.mode = "Edit" self.tool_state.is_input_on = True self.input_type = "D" self.tool_state.input_type = "D" - # PolylineDecorator.set_input_ui(self.input_ui) - # PolylineDecorator.set_tool_state(self.tool_state) - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() if event.value == "RELEASE" and event.type in {"D", "A"}: self.recalculate_inputs(context) - self.is_input_on = True + self.tool_state.mode = "Edit" self.tool_state.is_input_on = True self.input_type = event.type self.tool_state.input_type = event.type self.input_ui.set_value(self.input_type, "") - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) 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 not self.is_typing and not (event.ascii == "=" or event.type == "BACK_SPACE"): + if not self.tool_state.mode == "Edit" and not (event.ascii == "=" or event.type == "BACK_SPACE"): self.number_input = [] if event.type == "BACK_SPACE": @@ -502,58 +503,60 @@ class DrawPolylineWall(bpy.types.Operator): if not self.number_input: self.number_output = "0" + self.tool_state.mode = "Edit" self.is_typing = True self.number_output = "".join(self.number_input) self.input_ui.set_value(self.input_type, self.number_output) - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() - if not self.is_input_on and event.value == "RELEASE" and event.type in {"RET", "NUMPAD_ENTER", "RIGHTMOUSE"}: + if not self.tool_state.is_input_on and event.value == "RELEASE" and event.type in {"RET", "NUMPAD_ENTER", "RIGHTMOUSE"}: self.create_walls_from_polyline(context) PolylineDecorator.uninstall() tool.Snap.clear_polyline() tool.Blender.update_viewport() return {"FINISHED"} - if self.is_input_on and event.value == "RELEASE" and event.type in {"RET", "NUMPAD_ENTER", "RIGHTMOUSE"}: + if self.tool_state.is_input_on and event.value == "RELEASE" and event.type in {"RET", "NUMPAD_ENTER", "RIGHTMOUSE"}: is_valid = self.recalculate_inputs(context) if is_valid: tool.Snap.insert_polyline_point(self.input_ui) - self.is_input_on = False + self.tool_state.mode = "Mouse" self.tool_state.is_input_on = False self.input_type = None self.tool_state.input_type = None self.number_input = [] self.number_output = "" - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() if event.value == "PRESS" and event.type == "M": self.snapping_points = tool.Snap.modify_snapping_point_selection(self.snapping_points) tool.Polyline.calculate_distance_and_angle(context, self.input_ui, self.tool_state) - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() if event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}: return {"PASS_THROUGH"} - if self.is_input_on: + if self.tool_state.is_input_on: if event.value == "RELEASE" and event.type in {"ESC"}: self.recalculate_inputs(context) - self.is_input_on = False + self.tool_state.mode = "Mouse" self.tool_state.is_input_on = False self.input_type = None self.tool_state.input_type = None - PolylineDecorator.update(event, self.tool_state, self.input_ui) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() else: if event.value == "RELEASE" and event.type in {"ESC"}: - tool.Snap.set_snap_axis_method(None) + self.tool_state.axis_method = None PolylineDecorator.uninstall() tool.Snap.clear_polyline() tool.Blender.update_viewport() return {"CANCELLED"} + print(">>> ", self.tool_state.mode) return {"RUNNING_MODAL"} def invoke(self, context, event): @@ -562,18 +565,18 @@ class DrawPolylineWall(bpy.types.Operator): tool.Snap.clear_snapping_point() self.tool_state.use_default_container = True + self.tool_state.axis_method = None + self.tool_state.plane_method = "XY" + self.tool_state.mode = "Mouse" tool.Snap.set_tool_state(self.tool_state) - - tool.Snap.set_snap_axis_method(None) - tool.Snap.set_snap_plane_method("XY") - PolylineDecorator.update(event, self.tool_state, self.input_ui) self.visible_objs = tool.Raycast.get_visible_objects(context) for obj in self.visible_objs: self.objs_2d_bbox.append(tool.Raycast.get_on_screen_2d_bounding_boxes(context, obj)) detected_snaps = tool.Snap.detect_snapping_points(context, event, self.objs_2d_bbox, self.tool_state) - self.snapping_points = tool.Snap.select_snapping_points(context, event, detected_snaps) + self.snapping_points = tool.Snap.select_snapping_points(context, event, self.tool_state, detected_snaps) tool.Polyline.calculate_distance_and_angle(context, self.input_ui, self.tool_state) + PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() context.window_manager.modal_handler_add(self) return {"RUNNING_MODAL"} diff --git a/src/bonsai/bonsai/tool/polyline.py b/src/bonsai/bonsai/tool/polyline.py index 5b43a9fd7e..3b3feeaf7b 100644 --- a/src/bonsai/bonsai/tool/polyline.py +++ b/src/bonsai/bonsai/tool/polyline.py @@ -100,7 +100,7 @@ class ToolState: Shift: Lock axis """ snap_info: str = None - # input_state: str = None | "Select" | "Edit" + mode: str = None input_type: str = None diff --git a/src/bonsai/bonsai/tool/snap.py b/src/bonsai/bonsai/tool/snap.py index 3164fccabc..137bad0b52 100644 --- a/src/bonsai/bonsai/tool/snap.py +++ b/src/bonsai/bonsai/tool/snap.py @@ -27,10 +27,8 @@ from lark import Lark, Transformer class Snap(bonsai.core.tool.Snap): - snap_angle = None tool_state = None snap_plane_method = None - snap_axis_method = None @classmethod def set_tool_state(cls, tool_state): @@ -40,10 +38,6 @@ class Snap(bonsai.core.tool.Snap): def set_snap_plane_method(cls, value=True): cls.snap_plane_method = value - @classmethod - def clear_snap_angle(cls): - cls.snap_angle = None - @classmethod def cycle_snap_plane_method(cls, value=True): if cls.snap_plane_method == value: @@ -51,13 +45,6 @@ class Snap(bonsai.core.tool.Snap): return cls.snap_plane_method = value - @classmethod - def set_snap_axis_method(cls, value=True): - if cls.snap_axis_method == value: - cls.snap_axis_method = None - return - cls.snap_axis_method = value - @classmethod def get_snap_points_on_raycasted_face(cls, context, event, obj, face_index): matrix = obj.matrix_world.copy() @@ -102,11 +89,6 @@ class Snap(bonsai.core.tool.Snap): except: snap_vertex = bpy.context.scene.BIMModelProperties.snap_mouse_point.add() - info = f"""Snap: {snap_type} - Axis:{cls.snap_axis_method} - Plane:{cls.snap_plane_method} -""" - PolylineDecorator.set_snap_info(info) snap_vertex.x = snap_point[0] snap_vertex.y = snap_point[1] snap_vertex.z = snap_point[2] @@ -194,12 +176,12 @@ class Snap(bonsai.core.tool.Snap): polyline_measurement.remove(len(polyline_measurement) - 1) @classmethod - def snap_on_axis(cls, intersection, lock_axis=None): + def snap_on_axis(cls, intersection, tool_state, lock_angle=False): def create_axis_line_data(rot_mat, origin): length = 1000 direction = Vector((1, 0, 0)) - if cls.snap_plane_method == "YZ" or (not cls.snap_plane_method and cls.snap_axis_method == "Z"): + if tool_state.plane_method == "YZ" or (not tool_state.plane_method and tool_state.axis_method == "Z"): direction = Vector((0, 0, 1)) rot_dir = rot_mat.inverted() @ direction start = origin + rot_dir * length @@ -210,13 +192,13 @@ class Snap(bonsai.core.tool.Snap): def create_axis_rectangle_data(origin): size = 0.5 direction = Vector((1, 0, 0)) - if cls.snap_plane_method == "YZ": + if tool_state.plane_method == "YZ": direction = Vector((0, 0, 1)) rot_mat = Matrix.Rotation(math.radians(360), 3, pivot_axis) rot_dir = rot_mat.inverted() @ direction v1 = origin + rot_dir * 0 v2 = origin + rot_dir * size - if cls.snap_plane_method == "XY": + if tool_state.plane_method == "XY": angle = 270 else: angle = 90 @@ -238,17 +220,17 @@ class Snap(bonsai.core.tool.Snap): # Translates intersection point based on last_point translated_intersection = intersection - last_point snap_axis = [] - if not lock_axis: + if not tool_state.snap_angle: for i in range(1, 25): angle = 15 * i snap_axis.append(angle) else: - snap_axis = [lock_axis] + snap_axis = [tool_state.snap_angle] pivot_axis = "Z" - if cls.snap_plane_method == "XZ": + if tool_state.plane_method == "XZ": pivot_axis = "Y" - if cls.snap_plane_method == "YZ": + if tool_state.plane_method == "YZ": pivot_axis = "X" for axis in snap_axis: @@ -256,10 +238,10 @@ class Snap(bonsai.core.tool.Snap): start, end = create_axis_line_data(rot_mat, last_point) rot_intersection = rot_mat @ translated_intersection proximity = rot_intersection.y - if cls.snap_plane_method == "XZ": + if tool_state.plane_method == "XZ": proximity = rot_intersection.z PolylineDecorator.set_angle_axis_line(start, end) - if lock_axis: + if lock_angle: is_on_rot_axis = True else: is_on_rot_axis = abs(proximity) <= 0.15 @@ -267,7 +249,7 @@ class Snap(bonsai.core.tool.Snap): if is_on_rot_axis: # Snap to axis rot_intersection = Vector((rot_intersection.x, 0, rot_intersection.z)) - if cls.snap_plane_method == "XZ": + if tool_state.plane_method == "XZ": rot_intersection = Vector((rot_intersection.x, rot_intersection.y, 0)) # Convert it back snap_intersection = rot_mat.inverted() @ rot_intersection + last_point @@ -313,13 +295,13 @@ class Snap(bonsai.core.tool.Snap): plane_origin = Vector((0, 0, 0)) plane_normal = Vector((0, 0, 1)) - if not cls.snap_plane_method: + if not tool_state.plane_method: camera_rotation = rv3d.view_rotation plane_origin = Vector((0, 0, 0)) view_direction = Vector((0, 0, -1)) @ camera_rotation.to_matrix().transposed() plane_normal = view_direction.normalized() - if cls.snap_plane_method == "XY" or (not cls.snap_plane_method and cls.snap_axis_method in {"X", "Y"}): + if tool_state.plane_method == "XY" or (not tool_state.plane_method and tool_state.axis_method in {"X", "Y"}): if cls.tool_state.use_default_container: plane_origin = Vector((0, 0, elevation)) elif not last_polyline_point: @@ -328,12 +310,12 @@ class Snap(bonsai.core.tool.Snap): plane_origin = Vector((last_polyline_point.x, last_polyline_point.y, last_polyline_point.z)) plane_normal = Vector((0, 0, 1)) - elif cls.snap_plane_method == "XZ" or (not cls.snap_plane_method and cls.snap_axis_method == "Z"): + elif tool_state.plane_method == "XZ" or (not tool_state.plane_method and tool_state.axis_method == "Z"): if last_polyline_point: plane_origin = Vector((last_polyline_point.x, last_polyline_point.y, last_polyline_point.z)) plane_normal = Vector((0, 1, 0)) - elif cls.snap_plane_method == "YZ": + elif tool_state.plane_method == "YZ": if last_polyline_point: plane_origin = Vector((last_polyline_point.x, last_polyline_point.y, last_polyline_point.z)) plane_normal = Vector((1, 0, 0)) @@ -419,31 +401,31 @@ class Snap(bonsai.core.tool.Snap): # TODO It only work for XY plane. Make it work also for None plane_method rot_intersection = None - if not cls.snap_plane_method: - if cls.snap_axis_method == "X": + if not tool_state.plane_method: + if tool_state.axis_method == "X": tool_state.snap_angle = 180 - if cls.snap_axis_method == "Y": + if tool_state.axis_method == "Y": tool_state.snap_angle = 90 - if cls.snap_axis_method == "Z": + if tool_state.axis_method == "Z": tool_state.snap_angle = 90 - if cls.snap_axis_method: + if tool_state.axis_method: # Doesn't update snap_angle so that it keeps in the same axis - rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, tool_state.snap_angle) + rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, tool_state, True) - if cls.snap_plane_method: - if cls.snap_plane_method in {"XY", "XZ"} and cls.snap_axis_method == "X": + if tool_state.plane_method: + if tool_state.plane_method in {"XY", "XZ"} and tool_state.axis_method == "X": tool_state.snap_angle = 180 - if cls.snap_plane_method in {"XY", "YZ"} and cls.snap_axis_method == "Y": + if tool_state.plane_method in {"XY", "YZ"} and tool_state.axis_method == "Y": tool_state.snap_angle = 90 - if cls.snap_plane_method in {"YZ"} and cls.snap_axis_method == "Z": + if tool_state.plane_method in {"YZ"} and tool_state.axis_method == "Z": tool_state.snap_angle = 180 - if cls.snap_plane_method in {"XZ"} and cls.snap_axis_method == "Z": + if tool_state.plane_method in {"XZ"} and tool_state.axis_method == "Z": tool_state.snap_angle = 90 - if event.shift or cls.snap_axis_method: + if event.shift or tool_state.axis_method: # Doesn't update snap_angle so that it keeps in the same axis - rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, tool_state.snap_angle) + rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, tool_state, True) else: - rot_intersection, tool_state.snap_angle, axis_start, axis_end = cls.snap_on_axis(intersection, None) + rot_intersection, tool_state.snap_angle, axis_start, axis_end = cls.snap_on_axis(intersection, tool_state, False) if rot_intersection: detected_snaps.append({"Axis": (rot_intersection, axis_start, axis_end)}) @@ -452,7 +434,7 @@ class Snap(bonsai.core.tool.Snap): return detected_snaps @classmethod - def select_snapping_points(cls, context, event, detected_snaps): + def select_snapping_points(cls, context, event, tool_state, detected_snaps): snapping_points = [] for origin in detected_snaps: if "Object" in list(origin.keys()): @@ -497,7 +479,7 @@ class Snap(bonsai.core.tool.Snap): snapping_points.append((intersection, "Plane")) # Make Axis first priority - if event.shift or cls.snap_axis_method in {"X", "Y", "Z"}: + if event.shift or tool_state.axis_method in {"X", "Y", "Z"}: cls.update_snapping_ref(snapping_points[0][0], snapping_points[0][1]) for point in snapping_points: if point[1] == "Axis":