From 0da30c015c0f973ee23f6dec591ab9d4fe6ff4c7 Mon Sep 17 00:00:00 2001 From: Variable <77773850+Variable-ind@users.noreply.github.com> Date: Sat, 18 Feb 2023 05:33:46 +0500 Subject: [PATCH] Move perspective lines with mouse (plus code improvements) (#821) * Code Improvements to Perspective editor * formatting * fixed a bug * Some drastic changes * Delete src/UI/Tools directory * Delete src/UI/UI/PerspectiveEditor directory * Some drastic changes * i messed up so here's the fix * Added easy movement and rotation * formatting * useless script * fix some things and add tracker disabler * formatting * fix incorrect length on redo * remove useless code --- src/Classes/Project.gd | 2 +- src/Tools/BaseTool.gd | 21 +- src/UI/PerspectiveEditor/LineButton.gd | 9 - src/UI/PerspectiveEditor/LineButton.tscn | 2 + src/UI/PerspectiveEditor/PerspectiveEditor.gd | 36 ++- .../PerspectiveEditor/PerspectiveEditor.tscn | 20 +- src/UI/PerspectiveEditor/PerspectiveLine.gd | 173 ++++++++----- src/UI/PerspectiveEditor/VanishingPoint.gd | 239 ++++++++++-------- 8 files changed, 304 insertions(+), 198 deletions(-) delete mode 100644 src/UI/PerspectiveEditor/LineButton.gd diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 92b6f031e..403c56f3a 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -193,7 +193,7 @@ func change_project() -> void: Global.horizontal_ruler.update() Global.vertical_ruler.update() Global.references_panel.project_changed() - Global.perspective_editor.update() + Global.perspective_editor.update_points() Global.cursor_position_label.text = "[%s×%s]" % [size.x, size.y] Global.window_title = "%s - Pixelorama %s" % [name, Global.current_version] diff --git a/src/Tools/BaseTool.gd b/src/Tools/BaseTool.gd index 0f6dc82e8..a706f696d 100644 --- a/src/Tools/BaseTool.gd +++ b/src/Tools/BaseTool.gd @@ -162,15 +162,18 @@ func snap_position(position: Vector2) -> Vector2: if Global.snap_to_perspective_guides: for point in Global.current_project.vanishing_points: - for i in point.angles.size(): - var angle: float = -deg2rad(point.angles[i]) - var length: float = point.lengths[i] - var s1 := Vector2(point.position_x, point.position_y) - var s2 := s1 + Vector2(length * cos(angle), length * sin(angle)) - var snap := _snap_to_guide(snap_to, position, snap_distance, s1, s2) - if snap == Vector2.INF: - continue - snap_to = snap + if point.has("pos_x") and point.has("pos_y"): # Sanity check + for i in point.lines.size(): + if point.lines[i].has("angle") and point.lines[i].has("length"): # Sanity check + var angle: float = deg2rad(point.lines[i].angle) + var length: float = point.lines[i].length + var start = Vector2(point.pos_x, point.pos_y) + var s1: Vector2 = start + var s2 := s1 + Vector2(length * cos(angle), length * sin(angle)) + var snap := _snap_to_guide(snap_to, position, snap_distance, s1, s2) + if snap == Vector2.INF: + continue + snap_to = snap if snap_to != Vector2.INF: position = snap_to.floor() diff --git a/src/UI/PerspectiveEditor/LineButton.gd b/src/UI/PerspectiveEditor/LineButton.gd deleted file mode 100644 index a6288dad6..000000000 --- a/src/UI/PerspectiveEditor/LineButton.gd +++ /dev/null @@ -1,9 +0,0 @@ -extends Button - -onready var length_slider = $"%LengthSlider" - - -func _ready(): - var p_size = Global.current_project.size - var suitable_length = sqrt(pow(p_size.x, 2) + pow(p_size.y, 2)) - length_slider.max_value = suitable_length diff --git a/src/UI/PerspectiveEditor/LineButton.tscn b/src/UI/PerspectiveEditor/LineButton.tscn index 51ef1a4da..9da19d7e5 100644 --- a/src/UI/PerspectiveEditor/LineButton.tscn +++ b/src/UI/PerspectiveEditor/LineButton.tscn @@ -35,6 +35,7 @@ size_flags_horizontal = 3 margin_right = 51.0 max_value = 359.999 step = 0.001 +allow_greater = true prefix = "Angle:" suffix = "°" @@ -43,6 +44,7 @@ unique_name_in_owner = true margin_top = 28.0 margin_right = 51.0 margin_bottom = 52.0 +min_value = 1.0 max_value = 19999.0 value = 19999.0 allow_greater = true diff --git a/src/UI/PerspectiveEditor/PerspectiveEditor.gd b/src/UI/PerspectiveEditor/PerspectiveEditor.gd index 9fa8367e3..833490474 100644 --- a/src/UI/PerspectiveEditor/PerspectiveEditor.gd +++ b/src/UI/PerspectiveEditor/PerspectiveEditor.gd @@ -4,12 +4,12 @@ var axes: Node2D var do_pool = [] # A pool that stores data of points removed by undo var delete_pool = [] # A pool that containg deleted data and their index var vanishing_point_res := preload("res://src/UI/PerspectiveEditor/VanishingPoint.tscn") - +var tracker_disabled := false onready var vanishing_point_container = $"%VanishingPointContainer" func _on_AddPoint_pressed() -> void: - do_pool.clear() # Reset + do_pool.clear() # Reset (clears Redo history of vanishing points) var project = Global.current_project project.undos += 1 project.undo_redo.create_action("Add Vanishing Point") @@ -18,20 +18,16 @@ func _on_AddPoint_pressed() -> void: project.undo_redo.commit_action() -func update(): - for c in vanishing_point_container.get_children(): - c.queue_free() - for idx in Global.current_project.vanishing_points.size(): - var point_data = Global.current_project.vanishing_points[idx] - var vanishing_point := vanishing_point_res.instance() - vanishing_point_container.add_child(vanishing_point) - vanishing_point.initiate(point_data, idx) +func _on_TrackerLines_toggled(button_pressed): + for point in vanishing_point_container.get_children(): + tracker_disabled = !button_pressed func add_vanishing_point(is_redo := false): var vanishing_point := vanishing_point_res.instance() vanishing_point_container.add_child(vanishing_point) if is_redo and !do_pool.empty(): + # if it's a redo then initialize it with the redo data vanishing_point.initiate(do_pool.pop_back()) vanishing_point.update_data_to_project() else: @@ -41,7 +37,7 @@ func add_vanishing_point(is_redo := false): func undo_add_vanishing_point(): var point = vanishing_point_container.get_child(vanishing_point_container.get_child_count() - 1) point.queue_free() - do_pool.append(point.data.duplicate()) + do_pool.append(point.serialize()) point.update_data_to_project(true) @@ -56,7 +52,7 @@ func delete_point(idx): func do_delete_point(idx): var point = vanishing_point_container.get_child(idx) - delete_pool.append(point.data) + delete_pool.append(point.serialize()) point.queue_free() point.update_data_to_project(true) @@ -64,4 +60,18 @@ func do_delete_point(idx): func undo_delete_point(idx): var point = delete_pool.pop_back() Global.current_project.vanishing_points.insert(idx, point) - update() + update_points() + + +func update_points(): + # Delete old vanishing points + for c in vanishing_point_container.get_children(): + c.queue_free() + # Add the "updated" vanising points from the current_project + for idx in Global.current_project.vanishing_points.size(): + # Create the point + var vanishing_point := vanishing_point_res.instance() + vanishing_point_container.add_child(vanishing_point) + # Initialize it + var point_data = Global.current_project.vanishing_points[idx] + vanishing_point.initiate(point_data, idx) diff --git a/src/UI/PerspectiveEditor/PerspectiveEditor.tscn b/src/UI/PerspectiveEditor/PerspectiveEditor.tscn index ccf31ac7b..bb4bb9bfa 100644 --- a/src/UI/PerspectiveEditor/PerspectiveEditor.tscn +++ b/src/UI/PerspectiveEditor/PerspectiveEditor.tscn @@ -45,18 +45,25 @@ rect_min_size = Vector2( 30, 30 ) text = "+" clip_text = true -[node name="HSeparator" type="HSeparator" parent="VBoxContainer"] +[node name="TrackerLines" type="CheckButton" parent="VBoxContainer"] margin_top = 34.0 margin_right = 262.0 -margin_bottom = 38.0 +margin_bottom = 74.0 +pressed = true +text = "Tracker Lines" + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer"] +margin_top = 78.0 +margin_right = 262.0 +margin_bottom = 82.0 [node name="HSeparator2" type="HSeparator" parent="VBoxContainer"] -margin_top = 42.0 +margin_top = 86.0 margin_right = 262.0 -margin_bottom = 46.0 +margin_bottom = 90.0 [node name="Content" type="ScrollContainer" parent="VBoxContainer"] -margin_top = 50.0 +margin_top = 94.0 margin_right = 262.0 margin_bottom = 210.0 size_flags_vertical = 3 @@ -64,9 +71,10 @@ size_flags_vertical = 3 [node name="VanishingPointContainer" type="VBoxContainer" parent="VBoxContainer/Content"] unique_name_in_owner = true margin_right = 262.0 -margin_bottom = 160.0 +margin_bottom = 116.0 size_flags_horizontal = 3 size_flags_vertical = 3 custom_constants/separation = 5 [connection signal="pressed" from="VBoxContainer/Header/AddPoint" to="." method="_on_AddPoint_pressed"] +[connection signal="toggled" from="VBoxContainer/TrackerLines" to="." method="_on_TrackerLines_toggled"] diff --git a/src/UI/PerspectiveEditor/PerspectiveLine.gd b/src/UI/PerspectiveEditor/PerspectiveLine.gd index dafb807fa..476b889a9 100644 --- a/src/UI/PerspectiveEditor/PerspectiveLine.gd +++ b/src/UI/PerspectiveEditor/PerspectiveLine.gd @@ -1,101 +1,156 @@ class_name PerspectiveLine extends Line2D -const INPUT_WIDTH := 4 +const LINE_WIDTH := 2 +const CIRCLE_RAD := 4 + +var angle := 0 +var length := 19999 + var hidden = false +var has_focus := false var track_mouse := false -var _data = {"start": Vector2.ZERO, "angle": 0, "length": 19999, "color": Color.black} +var change_length = false + +var line_button: Node +var _vanishing_point: Node -func initiate(data: Dictionary): - width = Global.camera.zoom.x * 2 +func serialize() -> Dictionary: + var data = {"angle": angle, "length": length} + return data + + +func deserialize(data: Dictionary): + if data.has("angle"): + angle = data.angle + if data.has("length"): + length = data.length + + +func initiate(data: Dictionary, vanishing_point: Node): + _vanishing_point = vanishing_point + width = Global.camera.zoom.x * LINE_WIDTH Global.canvas.add_child(self) - refresh(data) + deserialize(data) + refresh() -func refresh(data: Dictionary): - _data = data - default_color = data.color +func refresh(): + default_color = _vanishing_point.color draw_perspective_line() func draw_perspective_line(): - var angle = -_data.angle - points[0] = _data.start + var start = Vector2(_vanishing_point.pos_x.value, _vanishing_point.pos_y.value) + points[0] = start if hidden: - points[1] = _data.start + points[1] = start else: - points[1] = ( - _data.start - + Vector2(_data.length * cos(deg2rad(angle)), _data.length * sin(deg2rad(angle))) - ) + points[1] = (start + Vector2(length * cos(deg2rad(angle)), length * sin(deg2rad(angle)))) func hide_perspective_line(): - points[1] = _data.start + var start = Vector2(_vanishing_point.pos_x.value, _vanishing_point.pos_y.value) + points[1] = start hidden = true func _input(event: InputEvent) -> void: if event is InputEventMouse: + var mouse_point = Global.canvas.current_pixel + var project_size = Global.current_project.size + if track_mouse: - if !Global.can_draw or !Global.has_focus: + if !Global.can_draw or !Global.has_focus or Global.perspective_editor.tracker_disabled: hide_perspective_line() return default_color.a = 0.5 - var tmp_transform = get_canvas_transform().affine_inverse() - var tmp_position = Global.main_viewport.get_local_mouse_position() - var mouse_point = tmp_transform.basis_xform(tmp_position) + tmp_transform.origin - var project_size = Global.current_project.size if Rect2(Vector2.ZERO, project_size).has_point(mouse_point): + var start = Vector2(_vanishing_point.pos_x.value, _vanishing_point.pos_y.value) hidden = false draw_perspective_line() - var rel_vector = mouse_point - _data.start - var test_vector = Vector2(_data.start.x, 0) - if sign(test_vector.x) == 0: - test_vector.x += 0.5 - - _data.angle = rad2deg(test_vector.angle_to(rel_vector)) - if sign(test_vector.x) == -1: - _data.angle += 180 + angle = rad2deg(mouse_point.angle_to_point(points[0])) + if angle < 0: + angle += 360 points[1] = ( - _data.start - + Vector2( - _data.length * cos(deg2rad(_data.angle)), - _data.length * sin(deg2rad(_data.angle)) - ) + start + + Vector2(length * cos(deg2rad(angle)), length * sin(deg2rad(angle))) ) else: hide_perspective_line() + else: + try_rotate_scale() update() +func try_rotate_scale(): + var mouse_point = Global.canvas.current_pixel + var project_size = Global.current_project.size + var test_line := (points[1] - points[0]).rotated(deg2rad(90)).normalized() + var from_a = mouse_point - test_line * Global.camera.zoom.x * LINE_WIDTH * 2 + var from_b = mouse_point + test_line * Global.camera.zoom.x * LINE_WIDTH * 2 + if Input.is_action_just_pressed("left_mouse") and Global.can_draw and Global.has_focus: + if ( + Geometry.segment_intersects_segment_2d(from_a, from_b, points[0], points[1]) + or mouse_point.distance_to(points[1]) < Global.camera.zoom.x * CIRCLE_RAD * 2 + ): + if ( + !Rect2(Vector2.ZERO, project_size).has_point(mouse_point) + or Global.move_guides_on_canvas + ): + if mouse_point.distance_to(points[1]) < Global.camera.zoom.x * CIRCLE_RAD * 2: + change_length = true + has_focus = true + Global.has_focus = false + update() + if has_focus: + if Input.is_action_pressed("left_mouse"): + # rotation code here + if line_button: + var new_angle = rad2deg(mouse_point.angle_to_point(points[0])) + if new_angle < 0: + new_angle += 360 + _vanishing_point.angle_changed(new_angle, line_button) + if change_length: + var new_length = mouse_point.distance_to(points[0]) + _vanishing_point.length_changed(new_length, line_button) + + elif Input.is_action_just_released("left_mouse"): + Global.has_focus = true + has_focus = false + change_length = false + update() + + func _draw() -> void: - draw_circle(_data.start, Global.camera.zoom.x * 5, default_color) - width = Global.camera.zoom.x * 2 + var mouse_point = Global.canvas.current_pixel + var arc_points = [] + draw_circle(points[0], Global.camera.zoom.x * CIRCLE_RAD, default_color) # Starting circle + if !track_mouse and mouse_point.distance_to(points[0]) < Global.camera.zoom.x * CIRCLE_RAD * 2: + if ( + !Rect2(Vector2.ZERO, Global.current_project.size).has_point(mouse_point) + or Global.move_guides_on_canvas + or has_focus + ): + arc_points.append(points[0]) + if ( + mouse_point.distance_to(points[1]) < Global.camera.zoom.x * CIRCLE_RAD * 2 + or (has_focus and Input.is_action_pressed("left_mouse")) + ): + if ( + !Rect2(Vector2.ZERO, Global.current_project.size).has_point(mouse_point) + or Global.move_guides_on_canvas + or has_focus + ): + if !arc_points.has(points[0]): + arc_points.append(points[0]) + arc_points.append(points[1]) + + for point in arc_points: + draw_arc(point, Global.camera.zoom.x * CIRCLE_RAD * 2, 0, 360, 360, default_color, 0.5) + + width = Global.camera.zoom.x * LINE_WIDTH if hidden: # Hidden line return - var viewport_size: Vector2 = Global.main_viewport.rect_size - var zoom: Vector2 = Global.camera.zoom - # viewport_poly is an array of the points that make up the corners of the viewport - var viewport_poly := [ - Vector2.ZERO, Vector2(viewport_size.x, 0), viewport_size, Vector2(0, viewport_size.y) - ] - # Adjusting viewport_poly to take into account the camera offset, zoom, and rotation - for p in range(viewport_poly.size()): - viewport_poly[p] = ( - viewport_poly[p].rotated(Global.camera.rotation) * zoom - + Vector2( - ( - Global.camera.offset.x - - (viewport_size.rotated(Global.camera.rotation).x / 2) * zoom.x - ), - ( - Global.camera.offset.y - - (viewport_size.rotated(Global.camera.rotation).y / 2) * zoom.y - ) - ) - ) - # If there's no intersection with a viewport edge, show string in top left corner - draw_set_transform(viewport_poly[0], Global.camera.rotation, zoom * 2) diff --git a/src/UI/PerspectiveEditor/VanishingPoint.gd b/src/UI/PerspectiveEditor/VanishingPoint.gd index b5b58fa06..adca274f3 100644 --- a/src/UI/PerspectiveEditor/VanishingPoint.gd +++ b/src/UI/PerspectiveEditor/VanishingPoint.gd @@ -1,53 +1,66 @@ extends VBoxContainer +var has_focus := false var perspective_lines = [] +var color := Color(randf(), randf(), randf(), 1) + var tracker_line: PerspectiveLine -var data = { - "position_x": 0, - "position_y": 0, - "angles": [], - "lengths": [], - "color": Color(randf(), randf(), randf(), 1).to_html(), -} - onready var color_picker_button = $"%ColorPickerButton" -onready var title = $"%PointCollapseContainer" -onready var pos_x = $"%X" -onready var pos_y = $"%Y" -onready var line_buttons_container = $"%LinesContainer" -onready var boundary_l = $Content/BoundaryL -onready var boundary_r = $Content/BoundaryR -onready var boundary_b = $Content/VBoxContainer/BoundaryB +onready var title := $"%PointCollapseContainer" +onready var pos_x := $"%X" +onready var pos_y := $"%Y" +onready var line_buttons_container := $"%LinesContainer" +onready var boundary_l := $Content/BoundaryL +onready var boundary_r := $Content/BoundaryR +onready var boundary_b := $Content/VBoxContainer/BoundaryB -func initiate(start_data = null, idx = -1) -> void: - if start_data: - data = start_data.duplicate() - add_line(null, true) - for i in data.angles.size(): - var loaded_line_data = { - "start": Vector2(data.position_x, data.position_y), - "angle": data.angles[i], - "length": data.lengths[i], - "color": Color(data.color) - } - add_line(loaded_line_data) - if idx != -1: +func serialize() -> Dictionary: + var lines_data := [] + for line in perspective_lines: + lines_data.append(line.serialize()) + var data = { + "pos_x": pos_x.value, + "pos_y": pos_y.value, + "lines": lines_data, + "color": color.to_html(), + } + return data + + +func deserialize(start_data: Dictionary): + if start_data: # Data is not {} means the project knows about this point + if start_data.has("pos_x") and start_data.has("pos_y"): + pos_x.value = start_data.pos_x + pos_y.value = start_data.pos_y + if start_data.has("color"): + color = Color(start_data.color) + # Add lines if their data is provided + if start_data.has("lines"): + for line_data in start_data["lines"]: + add_line(line_data) + else: # If the project doesn't know about this point + update_data_to_project() + + add_line({}, true) # This is a tracker line (Always follows mouse) + color_picker_button.color = color + update_boundary_color() + + +func initiate(start_data: Dictionary = {}, idx = -1) -> void: + deserialize(start_data) + # Title of Vanishing point button + if idx != -1: # If the initialization is part of a Redo title.point_text = str("Point: ", idx + 1) else: title.point_text = str("Point: ", get_parent().get_child_count()) - pos_x.value = data.position_x - pos_y.value = data.position_y - color_picker_button.color = Color(data.color) - update_boundary_color(color_picker_button.color) + # connect signals color_picker_button.connect("color_changed", self, "_on_color_changed") - pos_x.connect("value_changed", self, "_on_X_value_changed") - pos_y.connect("value_changed", self, "_on_Y_value_changed") - if !start_data: - update_data_to_project() + pos_x.connect("value_changed", self, "_on_pos_value_changed") + pos_y.connect("value_changed", self, "_on_pos_value_changed") -func update_boundary_color(color: Color): +func update_boundary_color(): var luminance = (0.2126 * color.r) + (0.7152 * color.g) + (0.0722 * color.b) color.a = 0.9 - luminance * 0.4 # Interpolates between 0.5 to 0.9 boundary_l.color = color @@ -55,6 +68,33 @@ func update_boundary_color(color: Color): boundary_b.color = color +func _input(_event): + var mouse_point = Global.canvas.current_pixel + var project_size = Global.current_project.size + var start = Vector2(pos_x.value, pos_y.value) + if ( + Input.is_action_just_pressed("left_mouse") + and Global.can_draw + and Global.has_focus + and mouse_point.distance_to(start) < Global.camera.zoom.x * 8 + ): + if ( + !Rect2(Vector2.ZERO, project_size).has_point(Global.canvas.current_pixel) + or Global.move_guides_on_canvas + ): + has_focus = true + Global.has_focus = false + if has_focus: + if Input.is_action_pressed("left_mouse"): + # rotation code here + pos_x.value = mouse_point.x + pos_y.value = mouse_point.y + + elif Input.is_action_just_released("left_mouse"): + Global.has_focus = true + has_focus = false + + # Signals func _on_AddLine_pressed() -> void: add_line() @@ -66,35 +106,38 @@ func _on_Delete_pressed() -> void: func _on_color_changed(_color: Color): - update_boundary_color(_color) - data.color = _color.to_html() + update_boundary_color() + color = _color refresh(-1) update_data_to_project() -func _on_X_value_changed(value: float) -> void: - data.position_x = value +func _on_pos_value_changed(_value: float) -> void: refresh(-1) update_data_to_project() -func _on_Y_value_changed(value): - data.position_y = value - refresh(-1) +func angle_changed(value: float, line_button): + # check if the properties are changing the line or is the line changing properties + var angle_slider = line_button.find_node("AngleSlider") + if angle_slider.value != value: # the line is changing the properties + angle_slider.value = value + else: + var line_index = line_button.get_index() + perspective_lines[line_index].angle = value + refresh(line_index) update_data_to_project() -func _angle_changed(value: float, line_button): - var line_index = line_button.get_index() - data.angles[line_index] = value - refresh(line_index) - update_data_to_project() - - -func _length_changed(value: float, line_button): - var line_index = line_button.get_index() - data.lengths[line_index] = value - refresh(line_index) +func length_changed(value: float, line_button): + # check if the properties are changing the line or is the line changing properties + var length_slider = line_button.find_node("LengthSlider") + if length_slider.value != value: # the line is changing the properties + length_slider.value = value + else: + var line_index = line_button.get_index() + perspective_lines[line_index].length = value + refresh(line_index) update_data_to_project() @@ -106,34 +149,39 @@ func _remove_line_pressed(line_button): # Methods -func add_line(loaded_line_data = null, is_tracker := false): - var p_size = Global.current_project.size - var default_line_data = { - "start": Vector2(data.position_x, data.position_y), - "angle": 0, - "length": 19999, - "color": Color(data.color) - } - if default_line_data.start.x > p_size.x / 2: - # If new line is created ahed of half project distance then - # reverse it's angle (for beautification) - default_line_data.angle = 180 +func generate_line_data(initial_data: Dictionary = {}) -> Dictionary: + # The default data + var line_data = {"angle": 0, "length": 19999} + # If any data needs to be changed by initial_data from project (or possibly by redo data) + if initial_data.has("angle"): + line_data.angle = initial_data["angle"] + if initial_data.has("length"): + line_data.length = initial_data["length"] + return line_data - # Check if we have loading data instead of creating line - # Then THAT should be our data - if loaded_line_data: - default_line_data = loaded_line_data + +func add_line(loaded_line_data := {}, is_tracker := false): + var p_size = Global.current_project.size # for use later in function + + # Note: line_data will automatically get default values if loaded_line_data = {} + var line_data = generate_line_data(loaded_line_data) + + # This code in if block is purely for beautification + if pos_x.value > p_size.x / 2 and !loaded_line_data: + # If new line is created ahed of half project distance then + # reverse it's angle + line_data.angle = 180 if is_tracker: # if we are creating tracker line then length adjustment is not required if tracker_line != null: # Also if the tracker line already exists then cancel creation return else: # If we are not creating a perspective line then adjust it's length - var suitable_length = sqrt(pow(p_size.x, 2) + pow(p_size.y, 2)) - default_line_data.length = suitable_length + if !loaded_line_data: + line_data.length = p_size.x # Create the visual line var line = preload("res://src/UI/PerspectiveEditor/PerspectiveLine.tscn").instance() - line.initiate(default_line_data) + line.initiate(line_data, self) # Set it's mode accordingly if is_tracker: # Settings for Tracker mode @@ -147,7 +195,7 @@ func add_line(loaded_line_data = null, is_tracker := false): line_button.get_parent().move_child(line_button, index) var line_name = str( - "Line", line_button.get_index() + 1, " (", int(default_line_data.angle), "°)" + "Line", line_button.get_index() + 1, " (", int(abs(line_data.angle)), "°)" ) line_button.text = line_name @@ -155,14 +203,12 @@ func add_line(loaded_line_data = null, is_tracker := false): var angle_slider = line_button.find_node("AngleSlider") var length_slider = line_button.find_node("LengthSlider") - angle_slider.value = default_line_data.angle - length_slider.value = default_line_data.length - if !loaded_line_data: - data.angles.append(angle_slider.value) - data.lengths.append(length_slider.value) + angle_slider.value = abs(line_data.angle) + length_slider.value = line_data.length - angle_slider.connect("value_changed", self, "_angle_changed", [line_button]) - length_slider.connect("value_changed", self, "_length_changed", [line_button]) + line.line_button = line_button # In case we need to change properties from line + angle_slider.connect("value_changed", self, "angle_changed", [line_button]) + length_slider.connect("value_changed", self, "length_changed", [line_button]) remove_button.connect("pressed", self, "_remove_line_pressed", [line_button]) perspective_lines.append(line) @@ -170,54 +216,45 @@ func add_line(loaded_line_data = null, is_tracker := false): func remove_line(line_index): var line_to_remove = perspective_lines[line_index] perspective_lines.remove(line_index) - data.angles.remove(line_index) - data.lengths.remove(line_index) line_to_remove.queue_free() func update_data_to_project(removal := false): var project = Global.current_project var idx = get_index() + # If deletion is requested if removal: project.vanishing_points.remove(idx) return + # If project knows about this vanishing point then update it + var data = serialize() if idx < project.vanishing_points.size(): project.vanishing_points[idx] = data + # If project doesn't know about this vanishing point then NOW it knows else: project.vanishing_points.append(data) Global.current_project.has_changed = true func refresh(index: int): - if index == -1: # means all lines should be refreshed + if index == -1: # means all lines should be refreshed (including the tracker line) refresh_tracker() - for i in data.angles.size(): + for i in perspective_lines.size(): refresh_line(i) else: refresh_line(index) func refresh_line(index: int): - var line_data = { - "start": Vector2(data.position_x, data.position_y), - "angle": data.angles[index], - "length": data.lengths[index], - "color": Color(data.color) - } var line_button = line_buttons_container.get_child(index) - var line_name = str("Line", line_button.get_index() + 1, " (", int(line_data.angle), "°)") + var line_data = perspective_lines[index].serialize() + var line_name = str("Line", line_button.get_index() + 1, " (", int(abs(line_data.angle)), "°)") line_button.text = line_name - perspective_lines[index].refresh(line_data) + perspective_lines[index].refresh() func refresh_tracker(): - var line_data = { - "start": Vector2(data.position_x, data.position_y), - "angle": tracker_line._data.angle, - "length": tracker_line._data.length, - "color": Color(data.color) - } - tracker_line.refresh(line_data) + tracker_line.refresh() func _exit_tree() -> void: