mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 09:32:37 +00:00
WIP - Polyline tool refactor
This commit is contained in:
committed by
Bruno Perdigão
parent
2e192034f8
commit
be8b325a83
@@ -301,7 +301,8 @@ class ProfileDecorator:
|
|||||||
class PolylineDecorator:
|
class PolylineDecorator:
|
||||||
is_installed = False
|
is_installed = False
|
||||||
handlers = []
|
handlers = []
|
||||||
mouse_pos = None
|
event = None
|
||||||
|
|
||||||
input_type = None
|
input_type = None
|
||||||
input_ui = None
|
input_ui = None
|
||||||
angle_snap_mat = None
|
angle_snap_mat = None
|
||||||
@@ -333,30 +334,27 @@ class PolylineDecorator:
|
|||||||
cls.is_installed = False
|
cls.is_installed = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_mouse_position(cls, event):
|
def update(cls, event, tool_state, input_ui):
|
||||||
cls.mouse_pos = event.mouse_region_x, event.mouse_region_y
|
cls.event = event
|
||||||
|
cls.tool_state = tool_state
|
||||||
|
cls.input_ui = input_ui
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_input_ui(cls, input_ui, input_type):
|
def set_input_ui(cls, input_ui):
|
||||||
cls.input_ui = input_ui
|
cls.input_ui = input_ui
|
||||||
cls.input_type = input_type
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_angle_axis_line(cls, start, end):
|
def set_angle_axis_line(cls, start, end):
|
||||||
cls.axis_start = start
|
cls.axis_start = start
|
||||||
cls.axis_end = end
|
cls.axis_end = end
|
||||||
|
|
||||||
@classmethod
|
# @classmethod
|
||||||
def set_axis_rectangle(cls, corners):
|
# def set_axis_rectangle(cls, corners):
|
||||||
cls.axis_rectangle = [*corners]
|
# cls.axis_rectangle = [*corners]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_use_default_container(cls, value=False):
|
def set_tool_state(cls, tool_state):
|
||||||
cls.use_default_container = value
|
cls.tool_state = tool_state
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_instructions(cls, instructions):
|
|
||||||
cls.instructions = instructions
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_snap_info(cls, snap_info):
|
def set_snap_info(cls, snap_info):
|
||||||
@@ -379,6 +377,8 @@ class PolylineDecorator:
|
|||||||
"Z": "Z coord:",
|
"Z": "Z coord:",
|
||||||
"AREA": "Area: ",
|
"AREA": "Area: ",
|
||||||
}
|
}
|
||||||
|
mouse_pos = self.event.mouse_region_x, self.event.mouse_region_y
|
||||||
|
|
||||||
|
|
||||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||||
self.font_id = 0
|
self.font_id = 0
|
||||||
@@ -392,18 +392,18 @@ class PolylineDecorator:
|
|||||||
new_line = 20
|
new_line = 20
|
||||||
for i, (key, field_name) in enumerate(texts.items()):
|
for i, (key, field_name) in enumerate(texts.items()):
|
||||||
|
|
||||||
if key != self.input_type:
|
if key != self.tool_state.input_type:
|
||||||
formatted_value = self.input_ui.get_formatted_value(key)
|
formatted_value = self.input_ui.get_formatted_value(key)
|
||||||
else:
|
else:
|
||||||
formatted_value = self.input_ui.get_text_value(key)
|
formatted_value = self.input_ui.get_text_value(key)
|
||||||
|
|
||||||
if formatted_value is None:
|
if formatted_value is None:
|
||||||
continue
|
continue
|
||||||
if key == self.input_type:
|
if key == self.tool_state.input_type:
|
||||||
blf.color(self.font_id, *color_highlight)
|
blf.color(self.font_id, *color_highlight)
|
||||||
else:
|
else:
|
||||||
blf.color(self.font_id, *color)
|
blf.color(self.font_id, *color)
|
||||||
blf.position(self.font_id, self.mouse_pos[0] + offset, self.mouse_pos[1] - (new_line * i), 0)
|
blf.position(self.font_id, mouse_pos[0] + offset, mouse_pos[1] - (new_line * i), 0)
|
||||||
blf.draw(self.font_id, field_name + formatted_value)
|
blf.draw(self.font_id, field_name + formatted_value)
|
||||||
|
|
||||||
|
|
||||||
@@ -452,10 +452,10 @@ class PolylineDecorator:
|
|||||||
color = self.addon_prefs.decorations_colour
|
color = self.addon_prefs.decorations_colour
|
||||||
blf.color(self.font_id, *color)
|
blf.color(self.font_id, *color)
|
||||||
|
|
||||||
text_w, text_h = blf.dimensions(0, self.instructions)
|
text_w, text_h = blf.dimensions(0, self.tool_state.instructions)
|
||||||
position = (region.width / 2) - (text_w / 2)
|
position = (region.width / 2) - (text_w / 2)
|
||||||
blf.position(self.font_id, position, 10, 0)
|
blf.position(self.font_id, position, 10, 0)
|
||||||
blf.draw(self.font_id, self.instructions)
|
blf.draw(self.font_id, self.tool_state.instructions)
|
||||||
|
|
||||||
text_w, text_h = blf.dimensions(0, self.snap_info)
|
text_w, text_h = blf.dimensions(0, self.snap_info)
|
||||||
position = (region.width / 2) - (text_w / 2)
|
position = (region.width / 2) - (text_w / 2)
|
||||||
@@ -494,7 +494,7 @@ class PolylineDecorator:
|
|||||||
|
|
||||||
default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
|
default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
|
||||||
projection_point = []
|
projection_point = []
|
||||||
if self.use_default_container:
|
if self.tool_state.use_default_container:
|
||||||
# When a point is above the plane it projects the point
|
# When a point is above the plane it projects the point
|
||||||
# to the plane and creates a line
|
# to the plane and creates a line
|
||||||
if snap_prop.snap_type != "Plane" and snap_prop.z != 0:
|
if snap_prop.snap_type != "Plane" and snap_prop.z != 0:
|
||||||
@@ -520,10 +520,10 @@ class PolylineDecorator:
|
|||||||
self.line_shader.uniform_float("lineWidth", 0.75)
|
self.line_shader.uniform_float("lineWidth", 0.75)
|
||||||
self.draw_batch("LINES", [self.axis_start, self.axis_end], decorator_color_unselected, [(0, 1)])
|
self.draw_batch("LINES", [self.axis_start, self.axis_end], decorator_color_unselected, [(0, 1)])
|
||||||
|
|
||||||
try:
|
# try:
|
||||||
self.draw_batch("TRIS", self.axis_rectangle, (1, 1, 1, 0.1), [(0, 1, 3), (0, 2, 3)])
|
# self.draw_batch("TRIS", self.axis_rectangle, (1, 1, 1, 0.1), [(0, 1, 3), (0, 2, 3)])
|
||||||
except:
|
# except:
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
# Area highlight
|
# Area highlight
|
||||||
# if "AREA" in list(self.input_panel.keys()): # TODO Change to input_ui
|
# if "AREA" in list(self.input_panel.keys()): # TODO Change to input_ui
|
||||||
|
|||||||
@@ -325,6 +325,7 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
self.is_input_on = False
|
self.is_input_on = False
|
||||||
self.input_options = ["D", "A", "X", "Y"]
|
self.input_options = ["D", "A", "X", "Y"]
|
||||||
self.input_type = None
|
self.input_type = None
|
||||||
|
self.input_type = None
|
||||||
self.input_value_xy = [None, None]
|
self.input_value_xy = [None, None]
|
||||||
self.input_ui = tool.Polyline.create_input_ui()
|
self.input_ui = tool.Polyline.create_input_ui()
|
||||||
self.is_typing = False
|
self.is_typing = False
|
||||||
@@ -337,6 +338,7 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
X Y: Axis
|
X Y: Axis
|
||||||
Shift: Lock axis
|
Shift: Lock axis
|
||||||
"""
|
"""
|
||||||
|
self.tool_state = tool.Polyline.create_tool_state()
|
||||||
|
|
||||||
def recalculate_inputs(self, context):
|
def recalculate_inputs(self, context):
|
||||||
if self.number_input:
|
if self.number_input:
|
||||||
@@ -347,10 +349,10 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
return is_valid
|
return is_valid
|
||||||
else:
|
else:
|
||||||
if self.input_type in {"X", "Y"}:
|
if self.input_type in {"X", "Y"}:
|
||||||
tool.Polyline.calculate_distance_and_angle(context, self.is_input_on, self.input_ui)
|
tool.Polyline.calculate_distance_and_angle(context, self.input_ui, self.tool_state)
|
||||||
elif self.input_type in {"D", "A"}:
|
elif self.input_type in {"D", "A"}:
|
||||||
tool.Polyline.calculate_x_y_and_z(context, self.input_ui)
|
tool.Polyline.calculate_x_y_and_z(context, self.input_ui, self.tool_state)
|
||||||
tool.Polyline.calculate_distance_and_angle(context, self.is_input_on, self.input_ui)
|
tool.Polyline.calculate_distance_and_angle(context, self.input_ui, self.tool_state)
|
||||||
else:
|
else:
|
||||||
self.input_ui.set_value(self.input_type, self.number_output)
|
self.input_ui.set_value(self.input_type, self.number_output)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
@@ -388,8 +390,10 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
if event.type == "MOUSEMOVE" or event.type == "INBETWEEN_MOUSEMOVE":
|
if event.type == "MOUSEMOVE" or event.type == "INBETWEEN_MOUSEMOVE":
|
||||||
self.mousemove_count += 1
|
self.mousemove_count += 1
|
||||||
self.is_input_on = False
|
self.is_input_on = False
|
||||||
|
self.tool_state.is_input_on = False
|
||||||
self.input_type = None
|
self.input_type = None
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
self.tool_state.input_type = None
|
||||||
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
tool.Snap.clear_snapping_ref()
|
tool.Snap.clear_snapping_ref()
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
else:
|
else:
|
||||||
@@ -401,10 +405,9 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
self.objs_2d_bbox.append(tool.Raycast.get_on_screen_2d_bounding_boxes(context, obj))
|
self.objs_2d_bbox.append(tool.Raycast.get_on_screen_2d_bounding_boxes(context, obj))
|
||||||
|
|
||||||
if self.mousemove_count > 3:
|
if self.mousemove_count > 3:
|
||||||
detected_snaps = tool.Snap.detect_snapping_points(context, event, self.objs_2d_bbox)
|
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, detected_snaps)
|
||||||
PolylineDecorator.set_mouse_position(event)
|
tool.Polyline.calculate_distance_and_angle(context, self.input_ui, self.tool_state)
|
||||||
tool.Polyline.calculate_distance_and_angle(context, self.is_input_on, self.input_ui)
|
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
return {"RUNNING_MODAL"}
|
return {"RUNNING_MODAL"}
|
||||||
|
|
||||||
@@ -426,7 +429,7 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
|
|
||||||
if event.value == "PRESS" and event.type == "C":
|
if event.value == "PRESS" and event.type == "C":
|
||||||
tool.Snap.close_polyline()
|
tool.Snap.close_polyline()
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
|
|
||||||
if self.is_input_on and event.value == "PRESS" and event.type == "TAB":
|
if self.is_input_on and event.value == "PRESS" and event.type == "TAB":
|
||||||
@@ -434,39 +437,48 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
index = self.input_options.index(self.input_type)
|
index = self.input_options.index(self.input_type)
|
||||||
size = len(self.input_options)
|
size = len(self.input_options)
|
||||||
self.input_type = self.input_options[((index + 1) % size)]
|
self.input_type = self.input_options[((index + 1) % size)]
|
||||||
|
self.tool_state.input_type = self.input_options[((index + 1) % size)]
|
||||||
self.is_typing = False
|
self.is_typing = False
|
||||||
self.number_input = self.input_ui.get_formatted_value(self.input_type)
|
self.number_input = self.input_ui.get_formatted_value(self.input_type)
|
||||||
self.number_input = list(self.number_input)
|
self.number_input = list(self.number_input)
|
||||||
self.number_output = "".join(self.number_input)
|
self.number_output = "".join(self.number_input)
|
||||||
self.input_ui.set_value(self.input_type, self.number_output)
|
self.input_ui.set_value(self.input_type, self.number_output)
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
|
|
||||||
if not self.is_input_on and event.value == "RELEASE" and event.type == "TAB":
|
if not self.is_input_on and event.value == "RELEASE" and event.type == "TAB":
|
||||||
self.recalculate_inputs(context)
|
self.recalculate_inputs(context)
|
||||||
self.is_input_on = True
|
self.is_input_on = True
|
||||||
|
self.tool_state.is_input_on = True
|
||||||
self.input_type = "D"
|
self.input_type = "D"
|
||||||
|
self.tool_state.input_type = "D"
|
||||||
self.is_typing = False
|
self.is_typing = False
|
||||||
self.number_input = self.input_ui.get_formatted_value(self.input_type)
|
self.number_input = self.input_ui.get_formatted_value(self.input_type)
|
||||||
self.number_input = list(self.number_input)
|
self.number_input = list(self.number_input)
|
||||||
self.number_output = "".join(self.number_input)
|
self.number_output = "".join(self.number_input)
|
||||||
self.input_ui.set_value(self.input_type, self.number_output)
|
self.input_ui.set_value(self.input_type, self.number_output)
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
|
|
||||||
if not self.is_input_on and event.ascii in self.number_options:
|
if not self.is_input_on and event.ascii in self.number_options:
|
||||||
self.recalculate_inputs(context)
|
self.recalculate_inputs(context)
|
||||||
self.is_input_on = True
|
self.is_input_on = True
|
||||||
|
self.tool_state.is_input_on = True
|
||||||
self.input_type = "D"
|
self.input_type = "D"
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
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)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
|
|
||||||
if event.value == "RELEASE" and event.type in {"D", "A"}:
|
if event.value == "RELEASE" and event.type in {"D", "A"}:
|
||||||
self.recalculate_inputs(context)
|
self.recalculate_inputs(context)
|
||||||
self.is_input_on = True
|
self.is_input_on = True
|
||||||
|
self.tool_state.is_input_on = True
|
||||||
self.input_type = event.type
|
self.input_type = event.type
|
||||||
|
self.tool_state.input_type = event.type
|
||||||
self.input_ui.set_value(self.input_type, "")
|
self.input_ui.set_value(self.input_type, "")
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
|
|
||||||
if self.input_type in self.input_options:
|
if self.input_type in self.input_options:
|
||||||
@@ -493,7 +505,7 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
self.is_typing = True
|
self.is_typing = True
|
||||||
self.number_output = "".join(self.number_input)
|
self.number_output = "".join(self.number_input)
|
||||||
self.input_ui.set_value(self.input_type, self.number_output)
|
self.input_ui.set_value(self.input_type, self.number_output)
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
tool.Blender.update_viewport()
|
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.is_input_on and event.value == "RELEASE" and event.type in {"RET", "NUMPAD_ENTER", "RIGHTMOUSE"}:
|
||||||
@@ -508,16 +520,18 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
if is_valid:
|
if is_valid:
|
||||||
tool.Snap.insert_polyline_point(self.input_ui)
|
tool.Snap.insert_polyline_point(self.input_ui)
|
||||||
self.is_input_on = False
|
self.is_input_on = False
|
||||||
|
self.tool_state.is_input_on = False
|
||||||
self.input_type = None
|
self.input_type = None
|
||||||
|
self.tool_state.input_type = None
|
||||||
self.number_input = []
|
self.number_input = []
|
||||||
self.number_output = ""
|
self.number_output = ""
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
|
|
||||||
if event.value == "PRESS" and event.type == "M":
|
if event.value == "PRESS" and event.type == "M":
|
||||||
self.snapping_points = tool.Snap.modify_snapping_point_selection(self.snapping_points)
|
self.snapping_points = tool.Snap.modify_snapping_point_selection(self.snapping_points)
|
||||||
PolylineDecorator.set_mouse_position(event)
|
tool.Polyline.calculate_distance_and_angle(context, self.input_ui, self.tool_state)
|
||||||
tool.Polyline.calculate_distance_and_angle(context, self.is_input_on, self.input_ui)
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
|
|
||||||
if event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}:
|
if event.type in {"MIDDLEMOUSE", "WHEELUPMOUSE", "WHEELDOWNMOUSE"}:
|
||||||
@@ -527,8 +541,10 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
if event.value == "RELEASE" and event.type in {"ESC"}:
|
if event.value == "RELEASE" and event.type in {"ESC"}:
|
||||||
self.recalculate_inputs(context)
|
self.recalculate_inputs(context)
|
||||||
self.is_input_on = False
|
self.is_input_on = False
|
||||||
|
self.tool_state.is_input_on = False
|
||||||
self.input_type = None
|
self.input_type = None
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
self.tool_state.input_type = None
|
||||||
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
else:
|
else:
|
||||||
if event.value == "RELEASE" and event.type in {"ESC"}:
|
if event.value == "RELEASE" and event.type in {"ESC"}:
|
||||||
@@ -544,21 +560,19 @@ class DrawPolylineWall(bpy.types.Operator):
|
|||||||
if context.space_data.type == "VIEW_3D":
|
if context.space_data.type == "VIEW_3D":
|
||||||
PolylineDecorator.install(context)
|
PolylineDecorator.install(context)
|
||||||
tool.Snap.clear_snapping_point()
|
tool.Snap.clear_snapping_point()
|
||||||
tool.Snap.set_use_default_container(True)
|
|
||||||
tool.Snap.clear_snap_angle()
|
self.tool_state.use_default_container = True
|
||||||
PolylineDecorator.set_use_default_container(True)
|
tool.Snap.set_tool_state(self.tool_state)
|
||||||
tool.Polyline.set_use_default_container(True)
|
|
||||||
tool.Snap.set_snap_axis_method(None)
|
tool.Snap.set_snap_axis_method(None)
|
||||||
tool.Snap.set_snap_plane_method("XY")
|
tool.Snap.set_snap_plane_method("XY")
|
||||||
PolylineDecorator.set_instructions(self.instructions)
|
PolylineDecorator.update(event, self.tool_state, self.input_ui)
|
||||||
PolylineDecorator.set_input_ui(self.input_ui, self.input_type)
|
|
||||||
self.visible_objs = tool.Raycast.get_visible_objects(context)
|
self.visible_objs = tool.Raycast.get_visible_objects(context)
|
||||||
for obj in self.visible_objs:
|
for obj in self.visible_objs:
|
||||||
self.objs_2d_bbox.append(tool.Raycast.get_on_screen_2d_bounding_boxes(context, obj))
|
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)
|
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, detected_snaps)
|
||||||
PolylineDecorator.set_mouse_position(event)
|
tool.Polyline.calculate_distance_and_angle(context, self.input_ui, self.tool_state)
|
||||||
tool.Polyline.calculate_distance_and_angle(context, self.is_input_on, self.input_ui)
|
|
||||||
|
|
||||||
tool.Blender.update_viewport()
|
tool.Blender.update_viewport()
|
||||||
context.window_manager.modal_handler_add(self)
|
context.window_manager.modal_handler_add(self)
|
||||||
|
|||||||
@@ -83,6 +83,26 @@ class PolylineUI:
|
|||||||
|
|
||||||
return format_distance(value * factor, precision=precision, suppress_zero_inches=True, in_unit_length=True)
|
return format_distance(value * factor, precision=precision, suppress_zero_inches=True, in_unit_length=True)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ToolState:
|
||||||
|
use_default_container: bool = None
|
||||||
|
snap_angle: float = None
|
||||||
|
is_input_on: bool = None
|
||||||
|
# angle_axis_start: Vector
|
||||||
|
# angle_axis_end: Vector
|
||||||
|
axis_method: str = None
|
||||||
|
plane_method: str = None
|
||||||
|
instructions: str = """TAB: Cycle Input
|
||||||
|
M: Modify Snap Point
|
||||||
|
C: Close
|
||||||
|
Backspace: Remove
|
||||||
|
X Y: Axis
|
||||||
|
Shift: Lock axis
|
||||||
|
"""
|
||||||
|
snap_info: str = None
|
||||||
|
# input_state: str = None | "Select" | "Edit"
|
||||||
|
input_type: str = None
|
||||||
|
|
||||||
|
|
||||||
class Polyline(bonsai.core.tool.Polyline):
|
class Polyline(bonsai.core.tool.Polyline):
|
||||||
|
|
||||||
@@ -91,37 +111,11 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
return PolylineUI(init_z=init_z, init_area=init_area)
|
return PolylineUI(init_z=init_z, init_area=init_area)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_mouse_position(cls, event):
|
def create_tool_state(cls):
|
||||||
cls.mouse_pos = event.mouse_region_x, event.mouse_region_y
|
return ToolState()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_angle_axis_line(cls, start, end):
|
def calculate_distance_and_angle(cls, context, input_ui, tool_state):
|
||||||
cls.axis_start = start
|
|
||||||
cls.axis_end = end
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_axis_rectangle(cls, corners):
|
|
||||||
cls.axis_rectangle = [*corners]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_use_default_container(cls, value=False):
|
|
||||||
cls.use_default_container = value
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_plane(cls, plane_origin, plane_normal):
|
|
||||||
cls.plane_origin = plane_origin
|
|
||||||
cls.plane_normal = plane_normal
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_instructions(cls, instructions):
|
|
||||||
cls.instructions = instructions
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_snap_info(cls, snap_info):
|
|
||||||
cls.snap_info = snap_info
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def calculate_distance_and_angle(cls, context, is_input_on, input_ui):
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
polyline_data = context.scene.BIMModelProperties.polyline_point
|
polyline_data = context.scene.BIMModelProperties.polyline_point
|
||||||
@@ -138,8 +132,8 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
else:
|
else:
|
||||||
last_point = Vector((0, 0, 0))
|
last_point = Vector((0, 0, 0))
|
||||||
|
|
||||||
if is_input_on:
|
if tool_state.is_input_on:
|
||||||
if cls.use_default_container:
|
if tool_state.use_default_container:
|
||||||
snap_vector = Vector(
|
snap_vector = Vector(
|
||||||
(input_ui.get_number_value("X"), input_ui.get_number_value("Y"), default_container_elevation)
|
(input_ui.get_number_value("X"), input_ui.get_number_value("Y"), default_container_elevation)
|
||||||
)
|
)
|
||||||
@@ -148,7 +142,7 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
(input_ui.get_number_value("X"), input_ui.get_number_value("Y"), input_ui.get_number_value("Z"))
|
(input_ui.get_number_value("X"), input_ui.get_number_value("Y"), input_ui.get_number_value("Z"))
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if cls.use_default_container:
|
if tool_state.use_default_container:
|
||||||
snap_vector = Vector((snap_prop.x, snap_prop.y, default_container_elevation))
|
snap_vector = Vector((snap_prop.x, snap_prop.y, default_container_elevation))
|
||||||
else:
|
else:
|
||||||
snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
|
snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
|
||||||
@@ -229,7 +223,7 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def calculate_x_y_and_z(cls, context, input_ui):
|
def calculate_x_y_and_z(cls, context, input_ui, tool_state):
|
||||||
try:
|
try:
|
||||||
polyline_data = context.scene.BIMModelProperties.polyline_point
|
polyline_data = context.scene.BIMModelProperties.polyline_point
|
||||||
default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
|
default_container_elevation = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
|
||||||
@@ -242,7 +236,7 @@ class Polyline(bonsai.core.tool.Polyline):
|
|||||||
snap_prop = context.scene.BIMModelProperties.snap_mouse_point[0]
|
snap_prop = context.scene.BIMModelProperties.snap_mouse_point[0]
|
||||||
snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
|
snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
|
||||||
|
|
||||||
if cls.use_default_container:
|
if tool_state.use_default_container:
|
||||||
snap_vector = Vector((snap_prop.x, snap_prop.y, default_container_elevation))
|
snap_vector = Vector((snap_prop.x, snap_prop.y, default_container_elevation))
|
||||||
else:
|
else:
|
||||||
snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
|
snap_vector = Vector((snap_prop.x, snap_prop.y, snap_prop.z))
|
||||||
|
|||||||
@@ -27,15 +27,14 @@ from lark import Lark, Transformer
|
|||||||
|
|
||||||
|
|
||||||
class Snap(bonsai.core.tool.Snap):
|
class Snap(bonsai.core.tool.Snap):
|
||||||
mouse_pos = None
|
|
||||||
snap_angle = None
|
snap_angle = None
|
||||||
use_default_container = False
|
tool_state = None
|
||||||
snap_plane_method = None
|
snap_plane_method = None
|
||||||
snap_axis_method = None
|
snap_axis_method = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_use_default_container(cls, value=True):
|
def set_tool_state(cls, tool_state):
|
||||||
cls.use_default_container = value
|
cls.tool_state = tool_state
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_snap_plane_method(cls, value=True):
|
def set_snap_plane_method(cls, value=True):
|
||||||
@@ -145,7 +144,7 @@ class Snap(bonsai.core.tool.Snap):
|
|||||||
a = input_ui.get_formatted_value("A")
|
a = input_ui.get_formatted_value("A")
|
||||||
|
|
||||||
snap_vertex = bpy.context.scene.BIMModelProperties.snap_mouse_point[0]
|
snap_vertex = bpy.context.scene.BIMModelProperties.snap_mouse_point[0]
|
||||||
if cls.use_default_container:
|
if cls.tool_state.use_default_container:
|
||||||
z = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
|
z = tool.Ifc.get_object(tool.Root.get_default_container()).location.z
|
||||||
|
|
||||||
if x is None and y is None:
|
if x is None and y is None:
|
||||||
@@ -289,11 +288,10 @@ class Snap(bonsai.core.tool.Snap):
|
|||||||
return sorted_intersections[0], "Mix"
|
return sorted_intersections[0], "Mix"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def detect_snapping_points(cls, context, event, objs_2d_bbox):
|
def detect_snapping_points(cls, context, event, objs_2d_bbox, tool_state):
|
||||||
region = context.region
|
|
||||||
rv3d = context.region_data
|
rv3d = context.region_data
|
||||||
space = context.space_data
|
space = context.space_data
|
||||||
cls.mouse_pos = event.mouse_region_x, event.mouse_region_y
|
mouse_pos = event.mouse_region_x, event.mouse_region_y
|
||||||
detected_snaps = []
|
detected_snaps = []
|
||||||
|
|
||||||
snap_threshold = 0.3
|
snap_threshold = 0.3
|
||||||
@@ -322,7 +320,7 @@ class Snap(bonsai.core.tool.Snap):
|
|||||||
plane_normal = view_direction.normalized()
|
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 cls.snap_plane_method == "XY" or (not cls.snap_plane_method and cls.snap_axis_method in {"X", "Y"}):
|
||||||
if cls.use_default_container:
|
if cls.tool_state.use_default_container:
|
||||||
plane_origin = Vector((0, 0, elevation))
|
plane_origin = Vector((0, 0, elevation))
|
||||||
elif not last_polyline_point:
|
elif not last_polyline_point:
|
||||||
plane_origin = Vector((0, 0, 0))
|
plane_origin = Vector((0, 0, 0))
|
||||||
@@ -342,7 +340,7 @@ class Snap(bonsai.core.tool.Snap):
|
|||||||
|
|
||||||
return plane_origin, plane_normal
|
return plane_origin, plane_normal
|
||||||
|
|
||||||
def cast_rays_and_get_best_object(objs_to_raycast):
|
def cast_rays_and_get_best_object(objs_to_raycast, mouse_pos):
|
||||||
best_length_squared = 1.0
|
best_length_squared = 1.0
|
||||||
best_obj = None
|
best_obj = None
|
||||||
best_hit = None
|
best_hit = None
|
||||||
@@ -352,13 +350,13 @@ class Snap(bonsai.core.tool.Snap):
|
|||||||
hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj)
|
hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj)
|
||||||
if hit is None:
|
if hit is None:
|
||||||
# Tried original mouse position. Now it will try the offsets.
|
# Tried original mouse position. Now it will try the offsets.
|
||||||
original_mouse_pos = cls.mouse_pos
|
original_mouse_pos = mouse_pos
|
||||||
for value in mouse_offset:
|
for value in mouse_offset:
|
||||||
cls.mouse_pos = tuple(x + y for x, y in zip(original_mouse_pos, value))
|
mouse_pos = tuple(x + y for x, y in zip(original_mouse_pos, value))
|
||||||
hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj, cls.mouse_pos)
|
hit, normal, face_index = tool.Raycast.obj_ray_cast(context, event, obj, mouse_pos)
|
||||||
if hit:
|
if hit:
|
||||||
break
|
break
|
||||||
cls.mouse_pos = original_mouse_pos
|
mouse_pos = original_mouse_pos
|
||||||
|
|
||||||
if hit is not None:
|
if hit is not None:
|
||||||
hit_world = obj.original.matrix_world @ hit
|
hit_world = obj.original.matrix_world @ hit
|
||||||
@@ -380,14 +378,14 @@ class Snap(bonsai.core.tool.Snap):
|
|||||||
objs_to_raycast = []
|
objs_to_raycast = []
|
||||||
for obj, bbox_2d in objs_2d_bbox:
|
for obj, bbox_2d in objs_2d_bbox:
|
||||||
if obj.type == "MESH" and bbox_2d:
|
if obj.type == "MESH" and bbox_2d:
|
||||||
if tool.Raycast.intersect_mouse_2d_bounding_box(cls.mouse_pos, bbox_2d, offset):
|
if tool.Raycast.intersect_mouse_2d_bounding_box(mouse_pos, bbox_2d, offset):
|
||||||
if space.local_view:
|
if space.local_view:
|
||||||
if obj.local_view_get(context.space_data):
|
if obj.local_view_get(context.space_data):
|
||||||
objs_to_raycast.append(obj)
|
objs_to_raycast.append(obj)
|
||||||
else:
|
else:
|
||||||
objs_to_raycast.append(obj)
|
objs_to_raycast.append(obj)
|
||||||
# Obj
|
# Obj
|
||||||
snap_obj, hit, face_index = cast_rays_and_get_best_object(objs_to_raycast)
|
snap_obj, hit, face_index = cast_rays_and_get_best_object(objs_to_raycast, mouse_pos)
|
||||||
if hit is not None:
|
if hit is not None:
|
||||||
detected_snaps.append({"Object": (snap_obj, hit, face_index)})
|
detected_snaps.append({"Object": (snap_obj, hit, face_index)})
|
||||||
|
|
||||||
@@ -423,29 +421,29 @@ class Snap(bonsai.core.tool.Snap):
|
|||||||
rot_intersection = None
|
rot_intersection = None
|
||||||
if not cls.snap_plane_method:
|
if not cls.snap_plane_method:
|
||||||
if cls.snap_axis_method == "X":
|
if cls.snap_axis_method == "X":
|
||||||
cls.snap_angle = 180
|
tool_state.snap_angle = 180
|
||||||
if cls.snap_axis_method == "Y":
|
if cls.snap_axis_method == "Y":
|
||||||
cls.snap_angle = 90
|
tool_state.snap_angle = 90
|
||||||
if cls.snap_axis_method == "Z":
|
if cls.snap_axis_method == "Z":
|
||||||
cls.snap_angle = 90
|
tool_state.snap_angle = 90
|
||||||
if cls.snap_axis_method:
|
if cls.snap_axis_method:
|
||||||
# Doesn't update snap_angle so that it keeps in the same axis
|
# Doesn't update snap_angle so that it keeps in the same axis
|
||||||
rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, cls.snap_angle)
|
rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, tool_state.snap_angle)
|
||||||
|
|
||||||
if cls.snap_plane_method:
|
if cls.snap_plane_method:
|
||||||
if cls.snap_plane_method in {"XY", "XZ"} and cls.snap_axis_method == "X":
|
if cls.snap_plane_method in {"XY", "XZ"} and cls.snap_axis_method == "X":
|
||||||
cls.snap_angle = 180
|
tool_state.snap_angle = 180
|
||||||
if cls.snap_plane_method in {"XY", "YZ"} and cls.snap_axis_method == "Y":
|
if cls.snap_plane_method in {"XY", "YZ"} and cls.snap_axis_method == "Y":
|
||||||
cls.snap_angle = 90
|
tool_state.snap_angle = 90
|
||||||
if cls.snap_plane_method in {"YZ"} and cls.snap_axis_method == "Z":
|
if cls.snap_plane_method in {"YZ"} and cls.snap_axis_method == "Z":
|
||||||
cls.snap_angle = 180
|
tool_state.snap_angle = 180
|
||||||
if cls.snap_plane_method in {"XZ"} and cls.snap_axis_method == "Z":
|
if cls.snap_plane_method in {"XZ"} and cls.snap_axis_method == "Z":
|
||||||
cls.snap_angle = 90
|
tool_state.snap_angle = 90
|
||||||
if event.shift or cls.snap_axis_method:
|
if event.shift or cls.snap_axis_method:
|
||||||
# Doesn't update snap_angle so that it keeps in the same axis
|
# Doesn't update snap_angle so that it keeps in the same axis
|
||||||
rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, cls.snap_angle)
|
rot_intersection, _, axis_start, axis_end = cls.snap_on_axis(intersection, tool_state.snap_angle)
|
||||||
else:
|
else:
|
||||||
rot_intersection, cls.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, None)
|
||||||
if rot_intersection:
|
if rot_intersection:
|
||||||
detected_snaps.append({"Axis": (rot_intersection, axis_start, axis_end)})
|
detected_snaps.append({"Axis": (rot_intersection, axis_start, axis_end)})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user