mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-02-20 12:33:14 +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:
parent
c60675b4e7
commit
0da30c015c
8 changed files with 304 additions and 198 deletions
|
@ -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]
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Reference in a new issue