Move some methods from SelectionShape.gd to Selection.gd

The purpose of this is to generalize some selection code, so that it applies to all polygons, the entire selection. More will follow.
This commit is contained in:
Manolis Papadeas 2021-02-23 04:05:56 +02:00
parent ac5d492298
commit 4574c9b60d
6 changed files with 124 additions and 250 deletions

View file

@ -9,15 +9,13 @@ func draw_start(position : Vector2) -> void:
starting_pos = position starting_pos = position
offset = position offset = position
if Global.current_project.selected_pixels: if Global.current_project.selected_pixels:
for selection in Global.current_project.selections: Global.canvas.selection.move_content_start()
selection.move_content_start()
# Global.selection_rectangl.move_start(true) # Global.selection_rectangl.move_start(true)
func draw_move(position : Vector2) -> void: func draw_move(position : Vector2) -> void:
if Global.current_project.selected_pixels: if Global.current_project.selected_pixels:
for selection in Global.current_project.selections: Global.canvas.selection.move_borders(position - offset)
selection.move_polygon(position - offset)
offset = position offset = position
# Global.selection_rectangl.move_rect(position - offset) # Global.selection_rectangl.move_rect(position - offset)
else: else:
@ -34,9 +32,8 @@ func draw_end(position : Vector2) -> void:
if project.selected_pixels: if project.selected_pixels:
pass pass
# for selection in Global.current_project.selections: # Global.canvas.selection.move_content_end()
# selection.move_content_end() # Global.canvas.selection.move_borders_end(position, starting_pos)
# selection.move_polygon_end(position, starting_pos)
else: else:
Global.canvas.move_preview_location = Vector2.ZERO Global.canvas.move_preview_location = Vector2.ZERO
var image_copy := Image.new() var image_copy := Image.new()

View file

@ -25,7 +25,7 @@ func draw_start(position : Vector2) -> void:
current_selection_id = Global.current_project.selections.size() current_selection_id = Global.current_project.selections.size()
var selection_shape := preload("res://src/Tools/SelectionShape.tscn").instance() var selection_shape := preload("res://src/Tools/SelectionShape.tscn").instance()
Global.current_project.selections.append(selection_shape) Global.current_project.selections.append(selection_shape)
Global.canvas.add_child(selection_shape) Global.canvas.selection.add_child(selection_shape)
_start = Rect2(position, Vector2.ZERO) _start = Rect2(position, Vector2.ZERO)
selection_shape.set_rect(_start) selection_shape.set_rect(_start)
else: else:
@ -49,8 +49,7 @@ func draw_move(position : Vector2) -> void:
var selection : SelectionShape = Global.current_project.selections[current_selection_id] var selection : SelectionShape = Global.current_project.selections[current_selection_id]
if _move: if _move:
for _selection in Global.current_project.selections: Global.canvas.selection.move_borders(position - _offset)
_selection.move_polygon(position - _offset)
_offset = position _offset = position
_set_cursor_text(selection.get_rect()) _set_cursor_text(selection.get_rect())
else: else:
@ -58,21 +57,11 @@ func draw_move(position : Vector2) -> void:
rect = rect.grow_individual(0, 0, 1, 1) rect = rect.grow_individual(0, 0, 1, 1)
selection.set_rect(rect) selection.set_rect(rect)
_set_cursor_text(rect) _set_cursor_text(rect)
# if _move:
# Global.selection_rectangle.move_rect(position - _offset)
# _offset = position
# _set_cursor_text(Global.selection_rectangle.get_rect())
# else:
# var rect := _start.expand(position).abs()
# rect = rect.grow_individual(0, 0, 1, 1)
# Global.selection_rectangle.set_rect(rect)
# _set_cursor_text(rect)
func draw_end(position : Vector2) -> void: func draw_end(position : Vector2) -> void:
if _move: if _move:
for _selection in Global.current_project.selections: Global.canvas.selection.move_borders_end(position, start_position)
_selection.move_polygon_end(position, start_position)
else: else:
var selection : SelectionShape = Global.current_project.selections[current_selection_id] var selection : SelectionShape = Global.current_project.selections[current_selection_id]
selection.select_rect(!Tools.control) selection.select_rect(!Tools.control)

View file

@ -169,23 +169,6 @@ func set_rect(rect : Rect2) -> void:
# visible = not rect.has_no_area() # visible = not rect.has_no_area()
func move_polygon(move : Vector2) -> void:
_selected_rect.position += move
_clipped_rect.position += move
for i in polygon.size():
polygon[i] += move
# set_rect(_selected_rect)
func move_polygon_end(new_pos : Vector2, old_pos : Vector2) -> void:
var diff := new_pos - old_pos
var selected_pixels_copy = local_selected_pixels.duplicate()
for i in selected_pixels_copy.size():
selected_pixels_copy[i] += diff
self.local_selected_pixels = selected_pixels_copy
func select_rect(merge := true) -> void: func select_rect(merge := true) -> void:
var project : Project = Global.current_project var project : Project = Global.current_project
self.local_selected_pixels = [] self.local_selected_pixels = []
@ -245,7 +228,7 @@ func merge_multiple_selections(merge := true) -> void:
for i in range(1, arr.size()): for i in range(1, arr.size()):
var selection_shape = load("res://src/Tools/SelectionShape.tscn").instance() var selection_shape = load("res://src/Tools/SelectionShape.tscn").instance()
Global.current_project.selections.append(selection_shape) Global.current_project.selections.append(selection_shape)
Global.canvas.add_child(selection_shape) Global.canvas.selection.add_child(selection_shape)
selection_shape.set_polygon(arr[i]) selection_shape.set_polygon(arr[i])
@ -275,29 +258,6 @@ func get_image() -> Image:
return image return image
func move_content_start() -> void:
if !local_image.is_empty():
return
local_image = get_image()
local_image_texture.create_from_image(local_image, 0)
var project : Project = Global.current_project
var cel_image : Image = project.frames[project.current_frame].cels[project.current_layer].image
_clear_image.resize(_selected_rect.size.x, _selected_rect.size.y, Image.INTERPOLATE_NEAREST)
cel_image.blit_rect_mask(_clear_image, local_image, Rect2(Vector2.ZERO, _selected_rect.size), _selected_rect.position)
Global.canvas.update_texture(project.current_layer)
func move_content_end() -> void:
if local_image.is_empty():
return
var project : Project = Global.current_project
var cel_image : Image = project.frames[project.current_frame].cels[project.current_layer].image
cel_image.blit_rect_mask(local_image, local_image, Rect2(Vector2.ZERO, _selected_rect.size), _selected_rect.position)
Global.canvas.update_texture(project.current_layer)
local_image = Image.new()
local_image_texture = ImageTexture.new()
#func move_start(move_pixel : bool) -> void: #func move_start(move_pixel : bool) -> void:
# if not move_pixel: # if not move_pixel:
# return # return
@ -428,7 +388,7 @@ func _get_undo_data(undo_image : bool) -> Dictionary:
func _on_SelectionShape_tree_exiting() -> void: func _on_SelectionShape_tree_exiting() -> void:
move_content_end() get_parent().move_content_end()
Global.current_project.selections.erase(self) Global.current_project.selections.erase(self)
if clear_selection_on_tree_exit: if clear_selection_on_tree_exit:
self.local_selected_pixels = [] self.local_selected_pixels = []

View file

@ -11,9 +11,10 @@ var move_preview_location := Vector2.ZERO
onready var currently_visible_frame : Viewport = $CurrentlyVisibleFrame onready var currently_visible_frame : Viewport = $CurrentlyVisibleFrame
onready var current_frame_drawer = $CurrentlyVisibleFrame/CurrentFrameDrawer onready var current_frame_drawer = $CurrentlyVisibleFrame/CurrentFrameDrawer
onready var tile_mode = $TileMode
onready var pixel_grid = $PixelGrid onready var pixel_grid = $PixelGrid
onready var grid = $Grid onready var grid = $Grid
onready var tile_mode = $TileMode onready var selection = $Selection
onready var indicators = $Indicators onready var indicators = $Indicators

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=8 format=2] [gd_scene load_steps=9 format=2]
[ext_resource path="res://src/UI/Canvas/Canvas.gd" type="Script" id=1] [ext_resource path="res://src/UI/Canvas/Canvas.gd" type="Script" id=1]
[ext_resource path="res://src/UI/Canvas/Grid.gd" type="Script" id=2] [ext_resource path="res://src/UI/Canvas/Grid.gd" type="Script" id=2]
@ -6,6 +6,7 @@
[ext_resource path="res://src/UI/Canvas/TileMode.gd" type="Script" id=4] [ext_resource path="res://src/UI/Canvas/TileMode.gd" type="Script" id=4]
[ext_resource path="res://src/UI/Canvas/CurrentFrameDrawer.gd" type="Script" id=5] [ext_resource path="res://src/UI/Canvas/CurrentFrameDrawer.gd" type="Script" id=5]
[ext_resource path="res://src/UI/Canvas/PixelGrid.gd" type="Script" id=6] [ext_resource path="res://src/UI/Canvas/PixelGrid.gd" type="Script" id=6]
[ext_resource path="res://src/UI/Canvas/Selection.gd" type="Script" id=7]
[sub_resource type="CanvasItemMaterial" id=1] [sub_resource type="CanvasItemMaterial" id=1]
blend_mode = 4 blend_mode = 4
@ -35,5 +36,8 @@ script = ExtResource( 6 )
[node name="Grid" type="Node2D" parent="."] [node name="Grid" type="Node2D" parent="."]
script = ExtResource( 2 ) script = ExtResource( 2 )
[node name="Selection" type="Node2D" parent="."]
script = ExtResource( 7 )
[node name="Indicators" type="Node2D" parent="."] [node name="Indicators" type="Node2D" parent="."]
script = ExtResource( 3 ) script = ExtResource( 3 )

View file

@ -1,94 +1,55 @@
extends Node2D extends Node2D
class SelectionPolygon: #class SelectionPolygon:
# var project : Project ## var project : Project
var border := PoolVector2Array() # var border := PoolVector2Array()
var rect_outline : Rect2 # var rect_outline : Rect2
var rects := [] # Array of Rect2s # var rects := [] # Array of Rect2s
var selected_pixels := [] # Array of Vector2s - the selected pixels # var selected_pixels := [] # Array of Vector2s - the selected pixels
var line_offset := Vector2.ZERO setget _offset_changed func move_borders(move : Vector2) -> void:
var tween : Tween for shape in get_children():
var selection_polygons := [] # Array of SelectionPolygons shape._selected_rect.position += move
shape._clipped_rect.position += move
for i in shape.polygon.size():
shape.polygon[i] += move
func _ready() -> void: func move_borders_end(new_pos : Vector2, old_pos : Vector2) -> void:
tween = Tween.new() for shape in get_children():
tween.connect("tween_completed", self, "_offset_tween_completed") var diff := new_pos - old_pos
add_child(tween) var selected_pixels_copy = shape.local_selected_pixels.duplicate()
tween.interpolate_property(self, "line_offset", Vector2.ZERO, Vector2(2, 2), 1) for i in selected_pixels_copy.size():
tween.start() selected_pixels_copy[i] += diff
shape.local_selected_pixels = selected_pixels_copy
func generate_polygons(): func move_content_start() -> void:
# selection_polygons.clear() for shape in get_children():
# selection_polygons.append(SelectionPolygon.new()) if !shape.local_image.is_empty():
# for pixel in Global.current_project.selected_pixels: return
# var current_polygon : SelectionPolygon = selection_polygons[0] shape.local_image = shape.get_image()
# var rect = Rect2(pixel, Vector2.ONE) shape.local_image_texture.create_from_image(shape.local_image, 0)
# var pixel_border = get_rect_border(rect) var project : Project = Global.current_project
# var arr = Geometry.merge_polygons_2d(pixel_border, current_polygon.border) var cel_image : Image = project.frames[project.current_frame].cels[project.current_layer].image
## print("Arr ", arr) shape._clear_image.resize(shape._selected_rect.size.x, shape._selected_rect.size.y, Image.INTERPOLATE_NEAREST)
# if arr.size() == 1: # if the selections intersect cel_image.blit_rect_mask(shape._clear_image, shape.local_image, Rect2(Vector2.ZERO, shape._selected_rect.size), shape._selected_rect.position)
## current_polygon.rects.append(rect) Global.canvas.update_texture(project.current_layer)
# current_polygon.rect_outline.merge(rect)
# current_polygon.border = arr[0]
#
#
# return
var selected_pixels_copy := Global.current_project.selected_pixels.duplicate()
var rects := []
while selected_pixels_copy.size() > 0:
var rect : Rect2 = generate_rect(selected_pixels_copy)
print("!!!")
if !rect:
break
for pixel in Global.current_project.selected_pixels:
if rect.has_point(pixel):
# print("POINT")
selected_pixels_copy.erase(pixel)
rects.append(rect)
print(rects) func move_content_end() -> void:
# print("e ", selected_pixels_copy) for shape in get_children():
if shape.local_image.is_empty():
if !rects: return
return var project : Project = Global.current_project
# var polygons := [SelectionPolygon.new()] var cel_image : Image = project.frames[project.current_frame].cels[project.current_layer].image
selection_polygons.clear() cel_image.blit_rect_mask(shape.local_image, shape.local_image, Rect2(Vector2.ZERO, shape._selected_rect.size), shape._selected_rect.position)
var polygons := [SelectionPolygon.new()] Global.canvas.update_texture(project.current_layer)
var curr_polyg := 0 shape.local_image = Image.new()
shape.local_image_texture = ImageTexture.new()
if rects.size() == 1:
polygons[0].rects.append(rects[0])
polygons[0].rect_outline = rects[0]
polygons[0].selected_pixels = Global.current_project.selected_pixels.duplicate()
var border : PoolVector2Array = get_rect_border(rects[0])
polygons[0].border = border
selection_polygons = polygons
return
for i in rects.size():
var current_polygon : SelectionPolygon = polygons[curr_polyg]
var rect : Rect2 = rects[i]
var outlines : PoolVector2Array = get_rect_border(rect)
# var rect_prev : Rect2 = rects[i - 1]
# var outlines_prev : PoolVector2Array = get_rect_border(rect_prev)
var arr = Geometry.merge_polygons_2d(outlines, current_polygon.border)
print("Arr ", arr)
if arr.size() == 1: # if the selections intersect
current_polygon.rects.append(rect)
# if not rect_prev in current_polygon.rects:
# current_polygon.rects.append(rect_prev)
current_polygon.rect_outline.merge(rect)
current_polygon.border = arr[0]
selection_polygons = polygons
func generate_rect(pixels : Array) -> Rect2: func generate_rect(pixels : Array) -> Rect2:
@ -125,108 +86,70 @@ func get_rect_border(rect : Rect2) -> PoolVector2Array:
return border return border
func _offset_tween_completed(_object, _key) -> void: #func generate_polygons():
self.line_offset = Vector2.ZERO ## selection_polygons.clear()
tween.interpolate_property(self, "line_offset", Vector2.ZERO, Vector2(2, 2), 1) ## selection_polygons.append(SelectionPolygon.new())
tween.start() ## for pixel in Global.current_project.selected_pixels:
## var current_polygon : SelectionPolygon = selection_polygons[0]
## var rect = Rect2(pixel, Vector2.ONE)
func _offset_changed(value : Vector2) -> void: ## var pixel_border = get_rect_border(rect)
line_offset = value ## var arr = Geometry.merge_polygons_2d(pixel_border, current_polygon.border)
update() ### print("Arr ", arr)
## if arr.size() == 1: # if the selections intersect
### current_polygon.rects.append(rect)
func _draw() -> void: ## current_polygon.rect_outline.merge(rect)
for polygon in selection_polygons: ## current_polygon.border = arr[0]
var points : PoolVector2Array = polygon.border ##
# print(points) ##
for i in range(1, points.size() + 1): ## return
var point0 = points[i - 1] # var selected_pixels_copy := Global.current_project.selected_pixels.duplicate()
var point1 # var rects := []
if i >= points.size(): # while selected_pixels_copy.size() > 0:
point1 = points[0] # var rect : Rect2 = generate_rect(selected_pixels_copy)
else: # print("!!!")
point1 = points[i] # if !rect:
var start_x = min(point0.x, point1.x) # break
var start_y = min(point0.y, point1.y) # for pixel in Global.current_project.selected_pixels:
var end_x = max(point0.x, point1.x) # if rect.has_point(pixel):
var end_y = max(point0.y, point1.y) ## print("POINT")
# selected_pixels_copy.erase(pixel)
var start := Vector2(start_x, start_y) #
var end := Vector2(end_x, end_y) # rects.append(rect)
draw_dashed_line(start, end, Color.white, Color.black, 1.0, 1.0, false) #
# print(rects)
if !polygon.selected_pixels: ## print("e ", selected_pixels_copy)
return #
# draw_polygon(Global.current_project.get_selection_polygon(), [Color(1, 1, 1, 0.5)]) # if !rects:
# var rect_pos := _selected_rect.position # return
# var rect_end := _selected_rect.end ## var polygons := [SelectionPolygon.new()]
# draw_circle(rect_pos, 1, Color.gray) # selection_polygons.clear()
# draw_circle(Vector2((rect_end.x + rect_pos.x) / 2, rect_pos.y), 1, Color.gray) # var polygons := [SelectionPolygon.new()]
# draw_circle(Vector2(rect_end.x, rect_pos.y), 1, Color.gray) # var curr_polyg := 0
# draw_circle(Vector2(rect_end.x, (rect_end.y + rect_pos.y) / 2), 1, Color.gray) #
# draw_circle(rect_end, 1, Color.gray) # if rects.size() == 1:
# draw_circle(Vector2(rect_end.x, rect_end.y), 1, Color.gray) # polygons[0].rects.append(rects[0])
# draw_circle(Vector2((rect_end.x + rect_pos.x) / 2, rect_end.y), 1, Color.gray) # polygons[0].rect_outline = rects[0]
# draw_circle(Vector2(rect_pos.x, rect_end.y), 1, Color.gray) # polygons[0].selected_pixels = Global.current_project.selected_pixels.duplicate()
# draw_circle(Vector2(rect_pos.x, (rect_end.y + rect_pos.y) / 2), 1, Color.gray) # var border : PoolVector2Array = get_rect_border(rects[0])
# polygons[0].border = border
# if _move_pixel: # selection_polygons = polygons
# draw_texture(_move_texture, _clipped_rect.position, Color(1, 1, 1, 0.5)) # return
#
# for i in rects.size():
# Taken and modified from https://github.com/juddrgledhill/godot-dashed-line # var current_polygon : SelectionPolygon = polygons[curr_polyg]
func draw_dashed_line(from : Vector2, to : Vector2, color : Color, color2 : Color, width := 1.0, dash_length := 1.0, cap_end := false, antialiased := false) -> void: # var rect : Rect2 = rects[i]
var length = (to - from).length() # var outlines : PoolVector2Array = get_rect_border(rect)
var normal = (to - from).normalized() #
var dash_step = normal * dash_length ## var rect_prev : Rect2 = rects[i - 1]
## var outlines_prev : PoolVector2Array = get_rect_border(rect_prev)
var horizontal : bool = from.y == to.y #
var _offset : Vector2 # var arr = Geometry.merge_polygons_2d(outlines, current_polygon.border)
if horizontal: # print("Arr ", arr)
_offset = Vector2(line_offset.x, 0) # if arr.size() == 1: # if the selections intersect
else: # current_polygon.rects.append(rect)
_offset = Vector2(0, line_offset.y) ## if not rect_prev in current_polygon.rects:
## current_polygon.rects.append(rect_prev)
if length < dash_length: # not long enough to dash # current_polygon.rect_outline.merge(rect)
draw_line(from, to, color, width, antialiased) # current_polygon.border = arr[0]
return #
# selection_polygons = polygons
else:
var draw_flag = true
var segment_start = from
var steps = length/dash_length
for _start_length in range(0, steps + 1):
var segment_end = segment_start + dash_step
var start = segment_start + _offset
start.x = min(start.x, to.x)
start.y = min(start.y, to.y)
var end = segment_end + _offset
end.x = min(end.x, to.x)
end.y = min(end.y, to.y)
if draw_flag:
draw_line(start, end, color, width, antialiased)
else:
draw_line(start, end, color2, width, antialiased)
if _offset.length() < 1:
draw_line(from, from + _offset, color2, width, antialiased)
else:
var from_offseted : Vector2 = from + _offset
var halfway_point : Vector2 = from_offseted
if horizontal:
halfway_point += Vector2.LEFT
else:
halfway_point += Vector2.UP
from_offseted.x = min(from_offseted.x, to.x)
from_offseted.y = min(from_offseted.y, to.y)
draw_line(halfway_point, from_offseted, color2, width, antialiased)
draw_line(from, halfway_point, color, width, antialiased)
segment_start = segment_end
draw_flag = !draw_flag
if cap_end:
draw_line(segment_start, to, color, width, antialiased)