1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-21 13:03:13 +00:00

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
This commit is contained in:
Variable 2023-02-18 05:33:46 +05:00 committed by GitHub
parent c60675b4e7
commit 0da30c015c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 304 additions and 198 deletions

View file

@ -193,7 +193,7 @@ func change_project() -> void:
Global.horizontal_ruler.update() Global.horizontal_ruler.update()
Global.vertical_ruler.update() Global.vertical_ruler.update()
Global.references_panel.project_changed() 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.cursor_position_label.text = "[%s×%s]" % [size.x, size.y]
Global.window_title = "%s - Pixelorama %s" % [name, Global.current_version] Global.window_title = "%s - Pixelorama %s" % [name, Global.current_version]

View file

@ -162,15 +162,18 @@ func snap_position(position: Vector2) -> Vector2:
if Global.snap_to_perspective_guides: if Global.snap_to_perspective_guides:
for point in Global.current_project.vanishing_points: for point in Global.current_project.vanishing_points:
for i in point.angles.size(): if point.has("pos_x") and point.has("pos_y"): # Sanity check
var angle: float = -deg2rad(point.angles[i]) for i in point.lines.size():
var length: float = point.lengths[i] if point.lines[i].has("angle") and point.lines[i].has("length"): # Sanity check
var s1 := Vector2(point.position_x, point.position_y) var angle: float = deg2rad(point.lines[i].angle)
var s2 := s1 + Vector2(length * cos(angle), length * sin(angle)) var length: float = point.lines[i].length
var snap := _snap_to_guide(snap_to, position, snap_distance, s1, s2) var start = Vector2(point.pos_x, point.pos_y)
if snap == Vector2.INF: var s1: Vector2 = start
continue var s2 := s1 + Vector2(length * cos(angle), length * sin(angle))
snap_to = snap 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: if snap_to != Vector2.INF:
position = snap_to.floor() position = snap_to.floor()

View file

@ -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

View file

@ -35,6 +35,7 @@ size_flags_horizontal = 3
margin_right = 51.0 margin_right = 51.0
max_value = 359.999 max_value = 359.999
step = 0.001 step = 0.001
allow_greater = true
prefix = "Angle:" prefix = "Angle:"
suffix = "°" suffix = "°"
@ -43,6 +44,7 @@ unique_name_in_owner = true
margin_top = 28.0 margin_top = 28.0
margin_right = 51.0 margin_right = 51.0
margin_bottom = 52.0 margin_bottom = 52.0
min_value = 1.0
max_value = 19999.0 max_value = 19999.0
value = 19999.0 value = 19999.0
allow_greater = true allow_greater = true

View file

@ -4,12 +4,12 @@ var axes: Node2D
var do_pool = [] # A pool that stores data of points removed by undo 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 delete_pool = [] # A pool that containg deleted data and their index
var vanishing_point_res := preload("res://src/UI/PerspectiveEditor/VanishingPoint.tscn") var vanishing_point_res := preload("res://src/UI/PerspectiveEditor/VanishingPoint.tscn")
var tracker_disabled := false
onready var vanishing_point_container = $"%VanishingPointContainer" onready var vanishing_point_container = $"%VanishingPointContainer"
func _on_AddPoint_pressed() -> void: func _on_AddPoint_pressed() -> void:
do_pool.clear() # Reset do_pool.clear() # Reset (clears Redo history of vanishing points)
var project = Global.current_project var project = Global.current_project
project.undos += 1 project.undos += 1
project.undo_redo.create_action("Add Vanishing Point") project.undo_redo.create_action("Add Vanishing Point")
@ -18,20 +18,16 @@ func _on_AddPoint_pressed() -> void:
project.undo_redo.commit_action() project.undo_redo.commit_action()
func update(): func _on_TrackerLines_toggled(button_pressed):
for c in vanishing_point_container.get_children(): for point in vanishing_point_container.get_children():
c.queue_free() tracker_disabled = !button_pressed
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 add_vanishing_point(is_redo := false): func add_vanishing_point(is_redo := false):
var vanishing_point := vanishing_point_res.instance() var vanishing_point := vanishing_point_res.instance()
vanishing_point_container.add_child(vanishing_point) vanishing_point_container.add_child(vanishing_point)
if is_redo and !do_pool.empty(): 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.initiate(do_pool.pop_back())
vanishing_point.update_data_to_project() vanishing_point.update_data_to_project()
else: else:
@ -41,7 +37,7 @@ func add_vanishing_point(is_redo := false):
func undo_add_vanishing_point(): func undo_add_vanishing_point():
var point = vanishing_point_container.get_child(vanishing_point_container.get_child_count() - 1) var point = vanishing_point_container.get_child(vanishing_point_container.get_child_count() - 1)
point.queue_free() point.queue_free()
do_pool.append(point.data.duplicate()) do_pool.append(point.serialize())
point.update_data_to_project(true) point.update_data_to_project(true)
@ -56,7 +52,7 @@ func delete_point(idx):
func do_delete_point(idx): func do_delete_point(idx):
var point = vanishing_point_container.get_child(idx) var point = vanishing_point_container.get_child(idx)
delete_pool.append(point.data) delete_pool.append(point.serialize())
point.queue_free() point.queue_free()
point.update_data_to_project(true) point.update_data_to_project(true)
@ -64,4 +60,18 @@ func do_delete_point(idx):
func undo_delete_point(idx): func undo_delete_point(idx):
var point = delete_pool.pop_back() var point = delete_pool.pop_back()
Global.current_project.vanishing_points.insert(idx, point) 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)

View file

@ -45,18 +45,25 @@ rect_min_size = Vector2( 30, 30 )
text = "+" text = "+"
clip_text = true clip_text = true
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"] [node name="TrackerLines" type="CheckButton" parent="VBoxContainer"]
margin_top = 34.0 margin_top = 34.0
margin_right = 262.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"] [node name="HSeparator2" type="HSeparator" parent="VBoxContainer"]
margin_top = 42.0 margin_top = 86.0
margin_right = 262.0 margin_right = 262.0
margin_bottom = 46.0 margin_bottom = 90.0
[node name="Content" type="ScrollContainer" parent="VBoxContainer"] [node name="Content" type="ScrollContainer" parent="VBoxContainer"]
margin_top = 50.0 margin_top = 94.0
margin_right = 262.0 margin_right = 262.0
margin_bottom = 210.0 margin_bottom = 210.0
size_flags_vertical = 3 size_flags_vertical = 3
@ -64,9 +71,10 @@ size_flags_vertical = 3
[node name="VanishingPointContainer" type="VBoxContainer" parent="VBoxContainer/Content"] [node name="VanishingPointContainer" type="VBoxContainer" parent="VBoxContainer/Content"]
unique_name_in_owner = true unique_name_in_owner = true
margin_right = 262.0 margin_right = 262.0
margin_bottom = 160.0 margin_bottom = 116.0
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
custom_constants/separation = 5 custom_constants/separation = 5
[connection signal="pressed" from="VBoxContainer/Header/AddPoint" to="." method="_on_AddPoint_pressed"] [connection signal="pressed" from="VBoxContainer/Header/AddPoint" to="." method="_on_AddPoint_pressed"]
[connection signal="toggled" from="VBoxContainer/TrackerLines" to="." method="_on_TrackerLines_toggled"]

View file

@ -1,101 +1,156 @@
class_name PerspectiveLine class_name PerspectiveLine
extends Line2D extends Line2D
const INPUT_WIDTH := 4 const LINE_WIDTH := 2
const CIRCLE_RAD := 4
var angle := 0
var length := 19999
var hidden = false var hidden = false
var has_focus := false
var track_mouse := 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): func serialize() -> Dictionary:
width = Global.camera.zoom.x * 2 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) Global.canvas.add_child(self)
refresh(data) deserialize(data)
refresh()
func refresh(data: Dictionary): func refresh():
_data = data default_color = _vanishing_point.color
default_color = data.color
draw_perspective_line() draw_perspective_line()
func draw_perspective_line(): func draw_perspective_line():
var angle = -_data.angle var start = Vector2(_vanishing_point.pos_x.value, _vanishing_point.pos_y.value)
points[0] = _data.start points[0] = start
if hidden: if hidden:
points[1] = _data.start points[1] = start
else: else:
points[1] = ( points[1] = (start + Vector2(length * cos(deg2rad(angle)), length * sin(deg2rad(angle))))
_data.start
+ Vector2(_data.length * cos(deg2rad(angle)), _data.length * sin(deg2rad(angle)))
)
func hide_perspective_line(): 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 hidden = true
func _input(event: InputEvent) -> void: func _input(event: InputEvent) -> void:
if event is InputEventMouse: if event is InputEventMouse:
var mouse_point = Global.canvas.current_pixel
var project_size = Global.current_project.size
if track_mouse: 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() hide_perspective_line()
return return
default_color.a = 0.5 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): 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 hidden = false
draw_perspective_line() draw_perspective_line()
var rel_vector = mouse_point - _data.start angle = rad2deg(mouse_point.angle_to_point(points[0]))
var test_vector = Vector2(_data.start.x, 0) if angle < 0:
if sign(test_vector.x) == 0: angle += 360
test_vector.x += 0.5
_data.angle = rad2deg(test_vector.angle_to(rel_vector))
if sign(test_vector.x) == -1:
_data.angle += 180
points[1] = ( points[1] = (
_data.start start
+ Vector2( + Vector2(length * cos(deg2rad(angle)), length * sin(deg2rad(angle)))
_data.length * cos(deg2rad(_data.angle)),
_data.length * sin(deg2rad(_data.angle))
)
) )
else: else:
hide_perspective_line() hide_perspective_line()
else:
try_rotate_scale()
update() 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: func _draw() -> void:
draw_circle(_data.start, Global.camera.zoom.x * 5, default_color) var mouse_point = Global.canvas.current_pixel
width = Global.camera.zoom.x * 2 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 if hidden: # Hidden line
return 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)

View file

@ -1,53 +1,66 @@
extends VBoxContainer extends VBoxContainer
var has_focus := false
var perspective_lines = [] var perspective_lines = []
var color := Color(randf(), randf(), randf(), 1)
var tracker_line: PerspectiveLine 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 color_picker_button = $"%ColorPickerButton"
onready var title = $"%PointCollapseContainer" onready var title := $"%PointCollapseContainer"
onready var pos_x = $"%X" onready var pos_x := $"%X"
onready var pos_y = $"%Y" onready var pos_y := $"%Y"
onready var line_buttons_container = $"%LinesContainer" onready var line_buttons_container := $"%LinesContainer"
onready var boundary_l = $Content/BoundaryL onready var boundary_l := $Content/BoundaryL
onready var boundary_r = $Content/BoundaryR onready var boundary_r := $Content/BoundaryR
onready var boundary_b = $Content/VBoxContainer/BoundaryB onready var boundary_b := $Content/VBoxContainer/BoundaryB
func initiate(start_data = null, idx = -1) -> void: func serialize() -> Dictionary:
if start_data: var lines_data := []
data = start_data.duplicate() for line in perspective_lines:
add_line(null, true) lines_data.append(line.serialize())
for i in data.angles.size(): var data = {
var loaded_line_data = { "pos_x": pos_x.value,
"start": Vector2(data.position_x, data.position_y), "pos_y": pos_y.value,
"angle": data.angles[i], "lines": lines_data,
"length": data.lengths[i], "color": color.to_html(),
"color": Color(data.color) }
} return data
add_line(loaded_line_data)
if idx != -1:
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) title.point_text = str("Point: ", idx + 1)
else: else:
title.point_text = str("Point: ", get_parent().get_child_count()) title.point_text = str("Point: ", get_parent().get_child_count())
pos_x.value = data.position_x # connect signals
pos_y.value = data.position_y
color_picker_button.color = Color(data.color)
update_boundary_color(color_picker_button.color)
color_picker_button.connect("color_changed", self, "_on_color_changed") color_picker_button.connect("color_changed", self, "_on_color_changed")
pos_x.connect("value_changed", self, "_on_X_value_changed") pos_x.connect("value_changed", self, "_on_pos_value_changed")
pos_y.connect("value_changed", self, "_on_Y_value_changed") pos_y.connect("value_changed", self, "_on_pos_value_changed")
if !start_data:
update_data_to_project()
func update_boundary_color(color: Color): func update_boundary_color():
var luminance = (0.2126 * color.r) + (0.7152 * color.g) + (0.0722 * color.b) 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 color.a = 0.9 - luminance * 0.4 # Interpolates between 0.5 to 0.9
boundary_l.color = color boundary_l.color = color
@ -55,6 +68,33 @@ func update_boundary_color(color: Color):
boundary_b.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 # Signals
func _on_AddLine_pressed() -> void: func _on_AddLine_pressed() -> void:
add_line() add_line()
@ -66,35 +106,38 @@ func _on_Delete_pressed() -> void:
func _on_color_changed(_color: Color): func _on_color_changed(_color: Color):
update_boundary_color(_color) update_boundary_color()
data.color = _color.to_html() color = _color
refresh(-1) refresh(-1)
update_data_to_project() update_data_to_project()
func _on_X_value_changed(value: float) -> void: func _on_pos_value_changed(_value: float) -> void:
data.position_x = value
refresh(-1) refresh(-1)
update_data_to_project() update_data_to_project()
func _on_Y_value_changed(value): func angle_changed(value: float, line_button):
data.position_y = value # check if the properties are changing the line or is the line changing properties
refresh(-1) 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() update_data_to_project()
func _angle_changed(value: float, line_button): func length_changed(value: float, line_button):
var line_index = line_button.get_index() # check if the properties are changing the line or is the line changing properties
data.angles[line_index] = value var length_slider = line_button.find_node("LengthSlider")
refresh(line_index) if length_slider.value != value: # the line is changing the properties
update_data_to_project() length_slider.value = value
else:
var line_index = line_button.get_index()
func _length_changed(value: float, line_button): perspective_lines[line_index].length = value
var line_index = line_button.get_index() refresh(line_index)
data.lengths[line_index] = value
refresh(line_index)
update_data_to_project() update_data_to_project()
@ -106,34 +149,39 @@ func _remove_line_pressed(line_button):
# Methods # Methods
func add_line(loaded_line_data = null, is_tracker := false): func generate_line_data(initial_data: Dictionary = {}) -> Dictionary:
var p_size = Global.current_project.size # The default data
var default_line_data = { var line_data = {"angle": 0, "length": 19999}
"start": Vector2(data.position_x, data.position_y), # If any data needs to be changed by initial_data from project (or possibly by redo data)
"angle": 0, if initial_data.has("angle"):
"length": 19999, line_data.angle = initial_data["angle"]
"color": Color(data.color) if initial_data.has("length"):
} line_data.length = initial_data["length"]
if default_line_data.start.x > p_size.x / 2: return line_data
# If new line is created ahed of half project distance then
# reverse it's angle (for beautification)
default_line_data.angle = 180
# Check if we have loading data instead of creating line
# Then THAT should be our data func add_line(loaded_line_data := {}, is_tracker := false):
if loaded_line_data: var p_size = Global.current_project.size # for use later in function
default_line_data = loaded_line_data
# 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 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 if tracker_line != null: # Also if the tracker line already exists then cancel creation
return return
else: # If we are not creating a perspective line then adjust it's length 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)) if !loaded_line_data:
default_line_data.length = suitable_length line_data.length = p_size.x
# Create the visual line # Create the visual line
var line = preload("res://src/UI/PerspectiveEditor/PerspectiveLine.tscn").instance() 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 # Set it's mode accordingly
if is_tracker: # Settings for Tracker mode 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) line_button.get_parent().move_child(line_button, index)
var line_name = str( 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 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 angle_slider = line_button.find_node("AngleSlider")
var length_slider = line_button.find_node("LengthSlider") var length_slider = line_button.find_node("LengthSlider")
angle_slider.value = default_line_data.angle angle_slider.value = abs(line_data.angle)
length_slider.value = default_line_data.length length_slider.value = line_data.length
if !loaded_line_data:
data.angles.append(angle_slider.value)
data.lengths.append(length_slider.value)
angle_slider.connect("value_changed", self, "_angle_changed", [line_button]) line.line_button = line_button # In case we need to change properties from line
length_slider.connect("value_changed", self, "_length_changed", [line_button]) 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]) remove_button.connect("pressed", self, "_remove_line_pressed", [line_button])
perspective_lines.append(line) perspective_lines.append(line)
@ -170,54 +216,45 @@ func add_line(loaded_line_data = null, is_tracker := false):
func remove_line(line_index): func remove_line(line_index):
var line_to_remove = perspective_lines[line_index] var line_to_remove = perspective_lines[line_index]
perspective_lines.remove(line_index) perspective_lines.remove(line_index)
data.angles.remove(line_index)
data.lengths.remove(line_index)
line_to_remove.queue_free() line_to_remove.queue_free()
func update_data_to_project(removal := false): func update_data_to_project(removal := false):
var project = Global.current_project var project = Global.current_project
var idx = get_index() var idx = get_index()
# If deletion is requested
if removal: if removal:
project.vanishing_points.remove(idx) project.vanishing_points.remove(idx)
return return
# If project knows about this vanishing point then update it
var data = serialize()
if idx < project.vanishing_points.size(): if idx < project.vanishing_points.size():
project.vanishing_points[idx] = data project.vanishing_points[idx] = data
# If project doesn't know about this vanishing point then NOW it knows
else: else:
project.vanishing_points.append(data) project.vanishing_points.append(data)
Global.current_project.has_changed = true Global.current_project.has_changed = true
func refresh(index: int): 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() refresh_tracker()
for i in data.angles.size(): for i in perspective_lines.size():
refresh_line(i) refresh_line(i)
else: else:
refresh_line(index) refresh_line(index)
func refresh_line(index: int): 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_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 line_button.text = line_name
perspective_lines[index].refresh(line_data) perspective_lines[index].refresh()
func refresh_tracker(): func refresh_tracker():
var line_data = { tracker_line.refresh()
"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)
func _exit_tree() -> void: func _exit_tree() -> void: