WIP - More refactor

This commit is contained in:
Bruno Perdigão
2024-09-07 17:30:18 -03:00
committed by Bruno Perdigão
parent be8b325a83
commit 55df9a42e6
4 changed files with 75 additions and 90 deletions
@@ -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):
+39 -36
View File
@@ -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"}
+1 -1
View File
@@ -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
+31 -49
View File
@@ -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":