From d532aee550ab548d990637154dacdf2b8c3213ea Mon Sep 17 00:00:00 2001 From: Variable <77773850+Variable-ind@users.noreply.github.com> Date: Tue, 21 Nov 2023 19:54:03 +0500 Subject: [PATCH] Added Measurements to move tool (and other fixes) (#932) * fixed mouse guide, added measurements * typo * code improvements * change width * fixed accidental uneven indentation * minor fixes * formatting * formatting * fixed ui of canvas preview container * centered labels of tool names * changed text overrun behaviour of Mode to Ellipsis * use grid container * Revert "use grid container" This reverts commit 8ac9ac2aaec437c41b31f186c2dc4fbb009e89a5. * Revert "changed text overrun behaviour of Mode to Ellipsis" This reverts commit eec1482e5fe3c2d4181f8d4f3a995eefd88a842b. * Revert "centered labels of tool names" This reverts commit 9720e37ef8c04240cfc6a5bce452ae0331e7e63b. * Revert "fixed ui of canvas preview container" This reverts commit 9809fa333601b1e1b73721055bb8388ba3006292. --- src/Autoload/Global.gd | 1 + src/Tools/Move.gd | 3 + src/UI/Canvas/Canvas.gd | 1 + src/UI/Canvas/Canvas.tscn | 6 +- src/UI/Canvas/Measurements.gd | 135 +++++++++++++++++++++++++ src/UI/Canvas/MouseGuide.gd | 16 +-- src/UI/Canvas/MouseGuideContainer.tscn | 11 +- 7 files changed, 156 insertions(+), 17 deletions(-) create mode 100644 src/UI/Canvas/Measurements.gd diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 71b421e63..3aa252654 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -17,6 +17,7 @@ enum GridTypes { CARTESIAN, ISOMETRIC, ALL } ## or if it is a custom color. enum ColorFrom { THEME, CUSTOM } enum ButtonSize { SMALL, BIG } +enum MeasurementMode { NONE, MOVE } ## Enumeration of items present in the File Menu. enum FileMenu { NEW, OPEN, OPEN_LAST_PROJECT, RECENT, SAVE, SAVE_AS, EXPORT, EXPORT_AS, QUIT } diff --git a/src/Tools/Move.gd b/src/Tools/Move.gd index 7e199dbf6..c0945982c 100644 --- a/src/Tools/Move.gd +++ b/src/Tools/Move.gd @@ -44,6 +44,7 @@ func draw_start(pos: Vector2i) -> void: selection_node.transform_content_start() _content_transformation_check = selection_node.is_moving_content Global.canvas.sprite_changed_this_frame = true + Global.canvas.measurements.update_measurement(Global.MeasurementMode.MOVE) func draw_move(pos: Vector2i) -> void: @@ -62,6 +63,7 @@ func draw_move(pos: Vector2i) -> void: Global.canvas.move_preview_location = pos - _start_pos _offset = pos Global.canvas.sprite_changed_this_frame = true + Global.canvas.measurements.update_measurement(Global.MeasurementMode.MOVE) func draw_end(pos: Vector2i) -> void: @@ -86,6 +88,7 @@ func draw_end(pos: Vector2i) -> void: _start_pos = Vector2.INF _snap_to_grid = false Global.canvas.sprite_changed_this_frame = true + Global.canvas.measurements.update_measurement(Global.MeasurementMode.NONE) func _snap_position(pos: Vector2) -> Vector2: diff --git a/src/UI/Canvas/Canvas.gd b/src/UI/Canvas/Canvas.gd index 7bb4b66ff..598a7a904 100644 --- a/src/UI/Canvas/Canvas.gd +++ b/src/UI/Canvas/Canvas.gd @@ -21,6 +21,7 @@ var move_preview_location := Vector2i.ZERO @onready var previews := $Previews as Node2D @onready var mouse_guide_container := $MouseGuideContainer as Node2D @onready var gizmos_3d := $Gizmos3D as Node2D +@onready var measurements := $Measurements as Node2D func _ready() -> void: diff --git a/src/UI/Canvas/Canvas.tscn b/src/UI/Canvas/Canvas.tscn index b2ae851c6..642d45f7a 100644 --- a/src/UI/Canvas/Canvas.tscn +++ b/src/UI/Canvas/Canvas.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=20 format=3 uid="uid://ba24iuv55m4l3"] +[gd_scene load_steps=21 format=3 uid="uid://ba24iuv55m4l3"] [ext_resource type="Script" path="res://src/UI/Canvas/Canvas.gd" id="1"] [ext_resource type="Shader" path="res://src/Shaders/BlendLayers.gdshader" id="1_253dh"] @@ -15,6 +15,7 @@ [ext_resource type="Script" path="res://src/UI/Canvas/OnionSkinning.gd" id="12"] [ext_resource type="Script" path="res://src/UI/Canvas/CropRect.gd" id="13"] [ext_resource type="Script" path="res://src/UI/Canvas/Gizmos3D.gd" id="14"] +[ext_resource type="Script" path="res://src/UI/Canvas/Measurements.gd" id="16_nxilb"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_6b0ox"] shader = ExtResource("1_253dh") @@ -90,3 +91,6 @@ script = ExtResource("12") [node name="Gizmos3D" type="Node2D" parent="."] script = ExtResource("14") + +[node name="Measurements" type="Node2D" parent="."] +script = ExtResource("16_nxilb") diff --git a/src/UI/Canvas/Measurements.gd b/src/UI/Canvas/Measurements.gd new file mode 100644 index 000000000..652cd2691 --- /dev/null +++ b/src/UI/Canvas/Measurements.gd @@ -0,0 +1,135 @@ +extends Node2D + +const WIDTH = 2 + +var font: Font +var line_color = Global.guide_color +var mode = Global.MeasurementMode.NONE +var apparent_width = WIDTH +var rect_bounds: Rect2i + + +func _ready() -> void: + font = Global.control.theme.default_font + + +func update_measurement(mode_idx := Global.MeasurementMode.NONE): + mode = mode_idx + queue_redraw() + + +func _draw() -> void: + match mode: + Global.MeasurementMode.MOVE: + _prepare_movement_rect() + _draw_move_measurement() + _: + rect_bounds = Rect2i() + + +func _input(_event: InputEvent) -> void: + apparent_width = WIDTH / Global.camera.zoom.x + + +func _prepare_movement_rect(): + var project := Global.current_project + if project.has_selection: + rect_bounds = Global.canvas.selection.preview_image.get_used_rect() + rect_bounds.position += Vector2i(Global.canvas.selection.big_bounding_rectangle.position) + if !rect_bounds.has_area(): + rect_bounds = Global.canvas.selection.big_bounding_rectangle + return + if rect_bounds.has_area(): + return + var selected_cels = Global.current_project.selected_cels + var frames = [] + for selected_cel in selected_cels: + if not selected_cel[0] in frames: + frames.append(selected_cel[0]) + for frame in frames: + # Find used rect of the current frame (across all of the layers) + var used_rect := Rect2i() + for cel_idx in project.frames[frame].cels.size(): + if not [frame, cel_idx] in selected_cels: + continue + var cel = project.frames[frame].cels[cel_idx] + if not cel is PixelCel: + continue + var cel_rect := cel.get_image().get_used_rect() + if cel_rect.has_area(): + used_rect = used_rect.merge(cel_rect) if used_rect.has_area() else cel_rect + if not used_rect.has_area(): + continue + if !rect_bounds.has_area(): + rect_bounds = used_rect + else: + rect_bounds = rect_bounds.merge(used_rect) + if not rect_bounds.has_area(): + rect_bounds = Rect2(Vector2.ZERO, project.size) + + +func _draw_move_measurement(): + var p_size = Global.current_project.size + var dashed_color = line_color + dashed_color.a = 0.5 + # Draw boundary + var boundary = Rect2i(rect_bounds) + boundary.position += Global.canvas.move_preview_location + draw_rect(boundary, line_color, false, apparent_width) + # calculate lines + var top = Vector2(boundary.get_center().x, boundary.position.y) + var bottom = Vector2(boundary.get_center().x, boundary.end.y) + var left = Vector2(boundary.position.x, boundary.get_center().y) + var right = Vector2(boundary.end.x, boundary.get_center().y) + var p_vertical = [Vector2(top.x, 0), Vector2(bottom.x, p_size.y)] # top, bottom + var p_horizontal = [Vector2(0, left.y), Vector2(p_size.x, right.y)] # left, right + var lines = [] + if left.x > -boundary.size.x: # left side + if left.x < p_size.x: + lines.append([left, p_horizontal[0]]) + else: + lines.append([left, p_horizontal[1]]) + if right.x < p_size.x + boundary.size.x: # right side + if right.x > 0: + lines.append([right, p_horizontal[1]]) + else: + lines.append([right, p_horizontal[0]]) + if top.y > -boundary.size.y: # top side + if top.y < p_size.y: + lines.append([top, p_vertical[0]]) + else: + lines.append([top, p_vertical[1]]) + if bottom.y < p_size.y + boundary.size.y: # bottom side + if bottom.y > 0: + lines.append([bottom, p_vertical[1]]) + else: + lines.append([bottom, p_vertical[0]]) + for line in lines: + if !Rect2i(Vector2.ZERO, p_size + Vector2i.ONE).has_point(line[1]): + var point_a := Vector2.ZERO + var point_b := Vector2.ZERO + # project lines if needed + if line[1] == p_vertical[0]: # upper horizontal projection + point_a = Vector2(p_size.x / 2, 0) + point_b = Vector2(top.x, 0) + elif line[1] == p_vertical[1]: # lower horizontal projection + point_a = Vector2(p_size.x / 2, p_size.y) + point_b = Vector2(bottom.x, p_size.y) + elif line[1] == p_horizontal[0]: # left vertical projection + point_a = Vector2(0, p_size.y / 2) + point_b = Vector2(0, left.y) + elif line[1] == p_horizontal[1]: # right vertical projection + point_a = Vector2(p_size.x, p_size.y / 2) + point_b = Vector2(p_size.x, right.y) + var offset = (point_b - point_a).normalized() * (boundary.size / 2.0) + draw_dashed_line(point_a + offset, point_b + offset, dashed_color, apparent_width) + draw_line(line[0], line[1], line_color, apparent_width) + var string_vec = line[0] + (line[1] - line[0]) / 2 + draw_set_transform(Vector2.ZERO, Global.camera.rotation, Vector2.ONE / Global.camera.zoom) + draw_string( + font, + string_vec * Global.camera.zoom, + str(line[0].distance_to(line[1]), "px"), + HORIZONTAL_ALIGNMENT_LEFT + ) + draw_set_transform(Vector2.ZERO, Global.camera.rotation, Vector2.ONE) diff --git a/src/UI/Canvas/MouseGuide.gd b/src/UI/Canvas/MouseGuide.gd index 6e88a4683..e1982b3cc 100644 --- a/src/UI/Canvas/MouseGuide.gd +++ b/src/UI/Canvas/MouseGuide.gd @@ -4,12 +4,18 @@ enum Types { VERTICAL, HORIZONTAL } const INPUT_WIDTH := 4 @export var type := 0 var track_mouse := true +var _texture := preload("res://assets/graphics/dotted_line.png") func _ready() -> void: # Add a subtle difference to the normal guide color by mixing in some green default_color = Global.guide_color.lerp(Color(0.2, 0.92, 0.2), .6) - width = Global.camera.zoom.x * 2 + texture = _texture + texture_repeat = CanvasItem.TEXTURE_REPEAT_ENABLED + texture_mode = Line2D.LINE_TEXTURE_TILE + await get_tree().process_frame + await get_tree().process_frame + width = 2.0 / Global.camera.zoom.x draw_guide_line() @@ -50,7 +56,7 @@ func _input(event: InputEvent) -> void: func _draw() -> void: - width = Global.camera.zoom.x * 2 + width = 2.0 / Global.camera.zoom.x var viewport_size := Global.main_viewport.size var zoom := Global.camera.zoom @@ -65,13 +71,11 @@ func _draw() -> void: + Vector2( ( Global.camera.offset.x - - (viewport_size.rotated(Global.camera.rotation).x / 2) * zoom.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 + - (viewport_size.rotated(Global.camera.rotation).y / 2) / zoom.y ) ) ) - - draw_set_transform(viewport_poly[0], Global.camera.rotation, zoom * 2) diff --git a/src/UI/Canvas/MouseGuideContainer.tscn b/src/UI/Canvas/MouseGuideContainer.tscn index 67a5ccaf3..9ace410ce 100644 --- a/src/UI/Canvas/MouseGuideContainer.tscn +++ b/src/UI/Canvas/MouseGuideContainer.tscn @@ -1,25 +1,16 @@ -[gd_scene load_steps=4 format=3 uid="uid://no3w7e2264u4"] +[gd_scene load_steps=2 format=3 uid="uid://no3w7e2264u4"] -[ext_resource type="Texture2D" uid="uid://xnqvppcpt7jb" path="res://assets/graphics/dotted_line.png" id="1"] [ext_resource type="Script" path="res://src/UI/Canvas/MouseGuide.gd" id="2"] -[sub_resource type="AtlasTexture" id="1"] -atlas = ExtResource("1") -region = Rect2(0, 0, 8, 1) - [node name="MouseGuideContainer" type="Node2D"] [node name="Vertical" type="Line2D" parent="."] visible = false points = PackedVector2Array(0, 19999, 0, -19999) -texture = SubResource("1") -texture_mode = 1 script = ExtResource("2") [node name="Horizontal" type="Line2D" parent="."] visible = false points = PackedVector2Array(-19999, 0, 19999, 0) -texture = SubResource("1") -texture_mode = 1 script = ExtResource("2") type = 1