diff --git a/src/bonsai/bonsai/bim/module/model/polyline.py b/src/bonsai/bonsai/bim/module/model/polyline.py index daac2c2ed2..030ba0de77 100644 --- a/src/bonsai/bonsai/bim/module/model/polyline.py +++ b/src/bonsai/bonsai/bim/module/model/polyline.py @@ -170,6 +170,25 @@ class PolylineOperator: """ context.workspace.status_text_set(self.instructions + self.snap_info) + def handle_lock_axis(self, context, event): + if event.value == "RELEASE" and event.type == "L": + self.tool_state.lock_axis = False if self.tool_state.lock_axis else True + self.tool_state.snap_angle = self.input_ui.get_number_value("WORLD_ANGLE") + # Round to the closest 5 + self.tool_state.snap_angle = round(self.tool_state.snap_angle / 5) * 5 + + if event.shift and event.type in {"WHEELUPMOUSE", "WHEELDOWNMOUSE"}: + if event.type in {"WHEELUPMOUSE"}: + self.tool_state.snap_angle += 5 + else: + self.tool_state.snap_angle -= 5 + self.handle_mouse_move(context, event) + 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, 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() + def handle_keyboard_input(self, context, event): if self.tool_state.is_input_on and event.value == "PRESS" and event.type == "TAB": diff --git a/src/bonsai/bonsai/bim/module/model/wall.py b/src/bonsai/bonsai/bim/module/model/wall.py index 578dc9f978..728004f126 100644 --- a/src/bonsai/bonsai/bim/module/model/wall.py +++ b/src/bonsai/bonsai/bim/module/model/wall.py @@ -324,7 +324,7 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator): PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() - if event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}: + if not event.shift and event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}: self.handle_mouse_move(context, event) return {"PASS_THROUGH"} @@ -334,6 +334,8 @@ class DrawPolylineWall(bpy.types.Operator, PolylineOperator): self.choose_axis(event) + self.handle_lock_axis(context, event) + self.handle_snap_selection(context, event) if ( diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index e75fdb3e0f..e558e6d388 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -2401,7 +2401,7 @@ class MeasureTool(bpy.types.Operator, PolylineOperator): PolylineDecorator.update(event, self.tool_state, self.input_ui, self.snapping_points[0]) tool.Blender.update_viewport() - if event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}: + if not event.shift and event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}: self.handle_mouse_move(context, event) return {"PASS_THROUGH"} @@ -2411,6 +2411,8 @@ class MeasureTool(bpy.types.Operator, PolylineOperator): self.choose_axis(event, z=True) + self.handle_lock_axis(context, event) + self.choose_plane(event) self.handle_snap_selection(context, event) diff --git a/src/bonsai/bonsai/tool/polyline.py b/src/bonsai/bonsai/tool/polyline.py index 5499944cde..4856b027f1 100644 --- a/src/bonsai/bonsai/tool/polyline.py +++ b/src/bonsai/bonsai/tool/polyline.py @@ -33,7 +33,8 @@ class Polyline(bonsai.core.tool.Polyline): @dataclass class PolylineUI: _D: str = "" - _A: str = "" + _A: str = "" # Relative to previous polyline points + _WORLD_ANGLE: str = "" # Relative to World Origin. Only used for specific operation. Not used on the UI. _X: str = "" _Y: str = "" _Z: Optional[str] = None @@ -78,6 +79,7 @@ class Polyline(bonsai.core.tool.Polyline): use_default_container: bool = None snap_angle: float = None is_input_on: bool = None + lock_axis: bool = False # angle_axis_start: Vector # angle_axis_end: Vector axis_method: str = None @@ -147,6 +149,8 @@ class Polyline(bonsai.core.tool.Polyline): # this allows to calculate the angle relative to x axis when there is only one point second_to_last_point = Vector((last_point.x + 1000, last_point.y, last_point.z)) + world_second_to_last_point = Vector((last_point.x + 1000, last_point.y, last_point.z)) + distance = (snap_vector - last_point).length if distance < 0: return @@ -158,8 +162,16 @@ class Polyline(bonsai.core.tool.Polyline): # Round angle to the nearest 0.05 angle = round(angle / 0.05) * 0.05 + orientation_angle = tool.Cad.angle_3_vectors( + world_second_to_last_point, last_point, snap_vector, new_angle=None, degrees=True + ) + + # Round angle to the nearest 0.05 + orientation_angle = round(orientation_angle / 0.05) * 0.05 + if distance == 0: angle = 0 + orientation_angle = 0 if input_ui: input_ui.set_value("X", snap_vector.x) input_ui.set_value("Y", snap_vector.y) @@ -168,6 +180,7 @@ class Polyline(bonsai.core.tool.Polyline): input_ui.set_value("D", distance) input_ui.set_value("A", angle) + input_ui.set_value("WORLD_ANGLE", orientation_angle) return return @@ -571,7 +584,6 @@ class Polyline(bonsai.core.tool.Polyline): total_length = tool.Polyline.format_input_ui_units(total_length) polyline_data.total_length = total_length - @classmethod def close_polyline(cls): polyline_data = bpy.context.scene.BIMPolylineProperties.insertion_polyline diff --git a/src/bonsai/bonsai/tool/snap.py b/src/bonsai/bonsai/tool/snap.py index e8ff572ff5..4e980c2eb7 100644 --- a/src/bonsai/bonsai/tool/snap.py +++ b/src/bonsai/bonsai/tool/snap.py @@ -396,7 +396,7 @@ class Snap(bonsai.core.tool.Snap): tool_state.snap_angle = 180 if tool_state.plane_method in {"XZ"} and tool_state.axis_method == "Z": tool_state.snap_angle = 90 - if event.shift or tool_state.axis_method: + if tool_state.lock_axis 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, True) else: @@ -468,7 +468,7 @@ class Snap(bonsai.core.tool.Snap): snapping_points.append((intersection, "Plane")) # Make Axis first priority - if event.shift or tool_state.axis_method in {"X", "Y", "Z"}: + if tool_state.lock_axis 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":