From a3cc0245ca7dc49baf91926bcd410456b0cd16a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Perdig=C3=A3o?= Date: Thu, 8 Aug 2024 20:03:28 -0300 Subject: [PATCH] Started a system to lock on axis --- .../blenderbim/bim/module/model/decorator.py | 35 +++---------- .../blenderbim/bim/module/model/wall.py | 30 ++++++++++- src/blenderbim/blenderbim/tool/snaping.py | 51 +++++++++++++------ 3 files changed, 71 insertions(+), 45 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/model/decorator.py b/src/blenderbim/blenderbim/bim/module/model/decorator.py index caf1f74be8..491aab3f1e 100644 --- a/src/blenderbim/blenderbim/bim/module/model/decorator.py +++ b/src/blenderbim/blenderbim/bim/module/model/decorator.py @@ -332,9 +332,9 @@ class WallPolylineDecorator: cls.input_type = input_type @classmethod - def set_angle_axis_line(cls, angle_snap_mat, angle_snap_loc): - cls.angle_snap_mat = angle_snap_mat - cls.angle_snap_loc = angle_snap_loc + def set_angle_axis_line(cls, start, end): + cls.axis_start = start + cls.axis_end = end @classmethod def calculate_distance_and_angle(cls, context, is_input_on): @@ -349,13 +349,7 @@ class WallPolylineDecorator: if last_point_data: last_point = Vector((last_point_data.x, last_point_data.y, last_point_data.z)) else: - last_point = Vector( - ( - 0, - 0, - 0, - ) - ) + last_point = Vector((0, 0, 0)) if is_input_on: snap_vector = Vector((float(cls.input_panel["X"]), float(cls.input_panel["Y"]), 0)) @@ -364,18 +358,8 @@ class WallPolylineDecorator: distance = (snap_vector - last_point).length # TODO get height from default container x_axis_edge = ( - Vector( - ( - 0, - 0, - ) - ), - Vector( - ( - 1, - 0, - ) - ), + Vector((0, 0)), + Vector((1, 0)), ) current_axis = ( Vector((last_point.x, last_point.y)), @@ -506,10 +490,5 @@ class WallPolylineDecorator: # Line for angle axis snap if snap_prop.snap_type == "Axis": - length = 1000 - direction = Vector((1, 0, 0)) - rot_dir = self.angle_snap_mat.inverted() @ direction - start = self.angle_snap_loc + rot_dir * length - end = self.angle_snap_loc - rot_dir * length self.line_shader.uniform_float("lineWidth", 0.75) - self.draw_batch("LINES", [start, end], decorator_color_unselected, [(0, 1)]) + self.draw_batch("LINES", [self.axis_start, self.axis_end], decorator_color_unselected, [(0, 1)]) diff --git a/src/blenderbim/blenderbim/bim/module/model/wall.py b/src/blenderbim/blenderbim/bim/module/model/wall.py index f165b8f103..a8f178c1fb 100644 --- a/src/blenderbim/blenderbim/bim/module/model/wall.py +++ b/src/blenderbim/blenderbim/bim/module/model/wall.py @@ -460,7 +460,13 @@ class DrawPolylineWall(bpy.types.Operator): ray_origin, ray_target, ray_direction = get_viewport_ray_data() obj, hit, face_index = cast_rays_and_get_best_object() intersection = ray_cast_to_plane(context, plane_origin, plane_normal) - rot_intersection = tool.Snaping.snap_on_axis(intersection) + + # Locks snap into an angle axis + if event.shift: + rot_intersection, _, axis_start, axis_end = tool.Snaping.snap_on_axis(intersection, self.snap_angle) + else: + self.snap_angle = None + rot_intersection, self.snap_angle, _, _ = tool.Snaping.snap_on_axis(intersection) if obj is not None: original_obj = obj.original @@ -469,7 +475,27 @@ class DrawPolylineWall(bpy.types.Operator): snap_point = tool.Snaping.select_snap_point(snap_points, hit, snap_threshold) if snap_point: - tool.Snaping.update_snaping_point(snap_point[0], snap_point[1]) + # Creates a mixed snap point between the locked axis and + # the object snap + # TODO Improve alt responsiveness + # TODO Create decorator for this + if event.shift: + snap_point_axis = ( + Vector((snap_point[0].x + 1000, snap_point[0].y, 0)), + Vector((snap_point[0].x - 1000, snap_point[0].y, 0)), + ) + if event.alt: + snap_point_axis = ( + Vector((snap_point[0].x, snap_point[0].y + 1000, 0)), + Vector((snap_point[0].x, snap_point[0].y - 1000, 0)), + ) + snap_angle_axis = (axis_start, axis_end) + results = tool.Cad.intersect_edges(snap_angle_axis, snap_point_axis) + resulting_vector = Vector((results[0].x, results[0].y, 0)) + + tool.Snaping.update_snaping_point(resulting_vector, "Axis") + else: + tool.Snaping.update_snaping_point(snap_point[0], snap_point[1]) else: tool.Snaping.update_snaping_point(hit, "Face") diff --git a/src/blenderbim/blenderbim/tool/snaping.py b/src/blenderbim/blenderbim/tool/snaping.py index dad9dc0825..4ebeaab6dc 100644 --- a/src/blenderbim/blenderbim/tool/snaping.py +++ b/src/blenderbim/blenderbim/tool/snaping.py @@ -113,7 +113,16 @@ class Snaping(blenderbim.core.tool.Snaping): polyline_data = bpy.context.scene.BIMModelProperties.polyline_point polyline_data.remove(len(polyline_data) - 1) - def snap_on_axis(intersection): + def snap_on_axis(intersection, lock_axis=None): + + def create_axis_line(rot_mat, origin): + length = 1000 + direction = Vector((1, 0, 0)) + rot_dir = rot_mat.inverted() @ direction + start = origin + rot_dir * length + end = origin - rot_dir * length + return start, end + polyline_data = bpy.context.scene.BIMModelProperties.polyline_point if polyline_data: last_point_data = polyline_data[-1] @@ -121,19 +130,31 @@ class Snaping(blenderbim.core.tool.Snaping): else: last_point = Vector((0, 0, 0)) - # translates intersection point based on last_point + # Translates intersection point based on last_point translated_intersection = intersection - last_point - for i in range(12): - angle = 30 * i - rot_mat = Matrix.Rotation(math.radians(360 - angle), 3, "Z") - WallPolylineDecorator.set_angle_axis_line(rot_mat, last_point) - rot_intersection = rot_mat @ translated_intersection - is_on_rot_axis = abs(rot_intersection.y) <= 0.60 - if is_on_rot_axis: - # snap to axis - rot_intersection = Vector((rot_intersection.x, 0, rot_intersection.z)) - # convert it back - snap_intersection = rot_mat.inverted() @ rot_intersection + last_point - return snap_intersection + snap_axis = [] + if not lock_axis: + for i in range(1, 13): + angle = 30 * i + snap_axis.append(angle) + else: + snap_axis = [lock_axis] - return None + for axis in snap_axis: + rot_mat = Matrix.Rotation(math.radians(360 - axis), 3, "Z") + start, end = create_axis_line(rot_mat, last_point) + WallPolylineDecorator.set_angle_axis_line(start, end) + rot_intersection = rot_mat @ translated_intersection + if lock_axis: + is_on_rot_axis = True + else: + is_on_rot_axis = abs(rot_intersection.y) <= 0.60 + + if is_on_rot_axis: + # Snap to axis + rot_intersection = Vector((rot_intersection.x, 0, rot_intersection.z)) + # Convert it back + snap_intersection = rot_mat.inverted() @ rot_intersection + last_point + return snap_intersection, axis, start, end + + return None, None, None, None