mirror of
https://github.com/tonytins/CozyPixelStudio.git
synced 2025-05-05 16:14:50 -04:00
More experiments I may or may not need
Trying to generate a polygon from the individual selected pixels
This commit is contained in:
parent
1e469ddf89
commit
d8c78331f0
4 changed files with 247 additions and 29 deletions
|
@ -84,11 +84,6 @@ _global_script_classes=[ {
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://src/Classes/Project.gd"
|
"path": "res://src/Classes/Project.gd"
|
||||||
}, {
|
}, {
|
||||||
"base": "Reference",
|
|
||||||
"class": "Selection",
|
|
||||||
"language": "GDScript",
|
|
||||||
"path": "res://src/Classes/Selection.gd"
|
|
||||||
}, {
|
|
||||||
"base": "Polygon2D",
|
"base": "Polygon2D",
|
||||||
"class": "SelectionShape",
|
"class": "SelectionShape",
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
|
@ -115,7 +110,6 @@ _global_script_class_icons={
|
||||||
"PaletteColor": "",
|
"PaletteColor": "",
|
||||||
"Patterns": "",
|
"Patterns": "",
|
||||||
"Project": "",
|
"Project": "",
|
||||||
"Selection": "",
|
|
||||||
"SelectionShape": "",
|
"SelectionShape": "",
|
||||||
"SymmetryGuide": ""
|
"SymmetryGuide": ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
class_name Selection extends Reference
|
|
||||||
|
|
||||||
|
|
||||||
var selected_area := [] # Selected pixels for each selection
|
|
||||||
var borders : PoolVector2Array
|
|
||||||
var node : SelectionShape
|
|
||||||
|
|
||||||
|
|
||||||
func _init(_node : SelectionShape) -> void:
|
|
||||||
node = _node
|
|
||||||
Global.canvas.add_child(node)
|
|
|
@ -23,7 +23,6 @@ func _ready() -> void:
|
||||||
tween.start()
|
tween.start()
|
||||||
_clear_image.create(1, 1, false, Image.FORMAT_RGBA8)
|
_clear_image.create(1, 1, false, Image.FORMAT_RGBA8)
|
||||||
_clear_image.fill(Color(0, 0, 0, 0))
|
_clear_image.fill(Color(0, 0, 0, 0))
|
||||||
# set_rect(Rect2(16, 20, 4, 4))
|
|
||||||
|
|
||||||
|
|
||||||
func _offset_tween_completed(_object, _key) -> void:
|
func _offset_tween_completed(_object, _key) -> void:
|
||||||
|
@ -57,17 +56,18 @@ func _draw() -> void:
|
||||||
|
|
||||||
if !local_selected_pixels:
|
if !local_selected_pixels:
|
||||||
return
|
return
|
||||||
var rect_pos := _selected_rect.position
|
# draw_polygon(Global.current_project.get_selection_polygon(), [Color(1, 1, 1, 0.5)])
|
||||||
var rect_end := _selected_rect.end
|
# var rect_pos := _selected_rect.position
|
||||||
draw_circle(rect_pos, 1, Color.gray)
|
# var rect_end := _selected_rect.end
|
||||||
draw_circle(Vector2((rect_end.x + rect_pos.x) / 2, rect_pos.y), 1, Color.gray)
|
# draw_circle(rect_pos, 1, Color.gray)
|
||||||
draw_circle(Vector2(rect_end.x, rect_pos.y), 1, Color.gray)
|
# draw_circle(Vector2((rect_end.x + rect_pos.x) / 2, rect_pos.y), 1, Color.gray)
|
||||||
draw_circle(Vector2(rect_end.x, (rect_end.y + rect_pos.y) / 2), 1, Color.gray)
|
# draw_circle(Vector2(rect_end.x, rect_pos.y), 1, Color.gray)
|
||||||
draw_circle(rect_end, 1, Color.gray)
|
# draw_circle(Vector2(rect_end.x, (rect_end.y + rect_pos.y) / 2), 1, Color.gray)
|
||||||
draw_circle(Vector2(rect_end.x, rect_end.y), 1, Color.gray)
|
# draw_circle(rect_end, 1, Color.gray)
|
||||||
draw_circle(Vector2((rect_end.x + rect_pos.x) / 2, rect_end.y), 1, Color.gray)
|
# draw_circle(Vector2(rect_end.x, rect_end.y), 1, Color.gray)
|
||||||
draw_circle(Vector2(rect_pos.x, rect_end.y), 1, Color.gray)
|
# draw_circle(Vector2((rect_end.x + rect_pos.x) / 2, rect_end.y), 1, Color.gray)
|
||||||
draw_circle(Vector2(rect_pos.x, (rect_end.y + rect_pos.y) / 2), 1, Color.gray)
|
# draw_circle(Vector2(rect_pos.x, rect_end.y), 1, Color.gray)
|
||||||
|
# draw_circle(Vector2(rect_pos.x, (rect_end.y + rect_pos.y) / 2), 1, Color.gray)
|
||||||
|
|
||||||
if _move_pixel:
|
if _move_pixel:
|
||||||
draw_texture(_move_texture, _clipped_rect.position, Color(1, 1, 1, 0.5))
|
draw_texture(_move_texture, _clipped_rect.position, Color(1, 1, 1, 0.5))
|
||||||
|
@ -143,6 +143,9 @@ func _local_selected_pixels_changed(value : Array) -> void:
|
||||||
else:
|
else:
|
||||||
Global.current_project.selected_pixels.append(pixel)
|
Global.current_project.selected_pixels.append(pixel)
|
||||||
|
|
||||||
|
# if value:
|
||||||
|
# Global.canvas.get_node("Selection").generate_polygons()
|
||||||
|
|
||||||
|
|
||||||
func has_point(position : Vector2) -> bool:
|
func has_point(position : Vector2) -> bool:
|
||||||
return Geometry.is_point_in_polygon(position, polygon)
|
return Geometry.is_point_in_polygon(position, polygon)
|
||||||
|
|
232
src/UI/Canvas/Selection.gd
Normal file
232
src/UI/Canvas/Selection.gd
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
|
||||||
|
class SelectionPolygon:
|
||||||
|
# var project : Project
|
||||||
|
var border := PoolVector2Array()
|
||||||
|
var rect_outline : Rect2
|
||||||
|
var rects := [] # Array of Rect2s
|
||||||
|
var selected_pixels := [] # Array of Vector2s - the selected pixels
|
||||||
|
|
||||||
|
|
||||||
|
var line_offset := Vector2.ZERO setget _offset_changed
|
||||||
|
var tween : Tween
|
||||||
|
var selection_polygons := [] # Array of SelectionPolygons
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
tween = Tween.new()
|
||||||
|
tween.connect("tween_completed", self, "_offset_tween_completed")
|
||||||
|
add_child(tween)
|
||||||
|
tween.interpolate_property(self, "line_offset", Vector2.ZERO, Vector2(2, 2), 1)
|
||||||
|
tween.start()
|
||||||
|
|
||||||
|
|
||||||
|
func generate_polygons():
|
||||||
|
# selection_polygons.clear()
|
||||||
|
# selection_polygons.append(SelectionPolygon.new())
|
||||||
|
# for pixel in Global.current_project.selected_pixels:
|
||||||
|
# var current_polygon : SelectionPolygon = selection_polygons[0]
|
||||||
|
# var rect = Rect2(pixel, Vector2.ONE)
|
||||||
|
# var pixel_border = get_rect_border(rect)
|
||||||
|
# var arr = Geometry.merge_polygons_2d(pixel_border, current_polygon.border)
|
||||||
|
## print("Arr ", arr)
|
||||||
|
# if arr.size() == 1: # if the selections intersect
|
||||||
|
## current_polygon.rects.append(rect)
|
||||||
|
# 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)
|
||||||
|
# print("e ", selected_pixels_copy)
|
||||||
|
|
||||||
|
if !rects:
|
||||||
|
return
|
||||||
|
# var polygons := [SelectionPolygon.new()]
|
||||||
|
selection_polygons.clear()
|
||||||
|
var polygons := [SelectionPolygon.new()]
|
||||||
|
var curr_polyg := 0
|
||||||
|
|
||||||
|
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:
|
||||||
|
if !pixels:
|
||||||
|
return Rect2()
|
||||||
|
var rect := Rect2()
|
||||||
|
rect.position = pixels[0]
|
||||||
|
var reached_bottom := false
|
||||||
|
var bottom_right_corner
|
||||||
|
var p = pixels[0]
|
||||||
|
while p + Vector2.DOWN in pixels:
|
||||||
|
p += Vector2.DOWN
|
||||||
|
# while p + Vector2.RIGHT in pixels:
|
||||||
|
# p += Vector2.RIGHT
|
||||||
|
bottom_right_corner = p
|
||||||
|
# for p in pixels:
|
||||||
|
# if p + Vector2.DOWN in pixels:
|
||||||
|
# continue
|
||||||
|
# reached_bottom = true
|
||||||
|
# if p + Vector2.RIGHT in pixels:
|
||||||
|
# continue
|
||||||
|
# if reached_bottom and !bottom_right_corner:
|
||||||
|
# bottom_right_corner = p
|
||||||
|
rect.end = bottom_right_corner + Vector2.ONE
|
||||||
|
return rect
|
||||||
|
|
||||||
|
|
||||||
|
func get_rect_border(rect : Rect2) -> PoolVector2Array:
|
||||||
|
var border := PoolVector2Array()
|
||||||
|
border.append(rect.position)
|
||||||
|
border.append(Vector2(rect.end.x, rect.position.y))
|
||||||
|
border.append(rect.end)
|
||||||
|
border.append(Vector2(rect.position.x, rect.end.y))
|
||||||
|
return border
|
||||||
|
|
||||||
|
|
||||||
|
func _offset_tween_completed(_object, _key) -> void:
|
||||||
|
self.line_offset = Vector2.ZERO
|
||||||
|
tween.interpolate_property(self, "line_offset", Vector2.ZERO, Vector2(2, 2), 1)
|
||||||
|
tween.start()
|
||||||
|
|
||||||
|
|
||||||
|
func _offset_changed(value : Vector2) -> void:
|
||||||
|
line_offset = value
|
||||||
|
update()
|
||||||
|
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
for polygon in selection_polygons:
|
||||||
|
var points : PoolVector2Array = polygon.border
|
||||||
|
# print(points)
|
||||||
|
for i in range(1, points.size() + 1):
|
||||||
|
var point0 = points[i - 1]
|
||||||
|
var point1
|
||||||
|
if i >= points.size():
|
||||||
|
point1 = points[0]
|
||||||
|
else:
|
||||||
|
point1 = points[i]
|
||||||
|
var start_x = min(point0.x, point1.x)
|
||||||
|
var start_y = min(point0.y, point1.y)
|
||||||
|
var end_x = max(point0.x, point1.x)
|
||||||
|
var end_y = max(point0.y, point1.y)
|
||||||
|
|
||||||
|
var start := Vector2(start_x, start_y)
|
||||||
|
var end := Vector2(end_x, end_y)
|
||||||
|
draw_dashed_line(start, end, Color.white, Color.black, 1.0, 1.0, false)
|
||||||
|
|
||||||
|
if !polygon.selected_pixels:
|
||||||
|
return
|
||||||
|
# draw_polygon(Global.current_project.get_selection_polygon(), [Color(1, 1, 1, 0.5)])
|
||||||
|
# var rect_pos := _selected_rect.position
|
||||||
|
# var rect_end := _selected_rect.end
|
||||||
|
# draw_circle(rect_pos, 1, Color.gray)
|
||||||
|
# draw_circle(Vector2((rect_end.x + rect_pos.x) / 2, rect_pos.y), 1, Color.gray)
|
||||||
|
# draw_circle(Vector2(rect_end.x, rect_pos.y), 1, Color.gray)
|
||||||
|
# draw_circle(Vector2(rect_end.x, (rect_end.y + rect_pos.y) / 2), 1, Color.gray)
|
||||||
|
# draw_circle(rect_end, 1, Color.gray)
|
||||||
|
# draw_circle(Vector2(rect_end.x, rect_end.y), 1, Color.gray)
|
||||||
|
# draw_circle(Vector2((rect_end.x + rect_pos.x) / 2, rect_end.y), 1, Color.gray)
|
||||||
|
# draw_circle(Vector2(rect_pos.x, rect_end.y), 1, Color.gray)
|
||||||
|
# draw_circle(Vector2(rect_pos.x, (rect_end.y + rect_pos.y) / 2), 1, Color.gray)
|
||||||
|
|
||||||
|
# if _move_pixel:
|
||||||
|
# draw_texture(_move_texture, _clipped_rect.position, Color(1, 1, 1, 0.5))
|
||||||
|
|
||||||
|
|
||||||
|
# Taken and modified from https://github.com/juddrgledhill/godot-dashed-line
|
||||||
|
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 length = (to - from).length()
|
||||||
|
var normal = (to - from).normalized()
|
||||||
|
var dash_step = normal * dash_length
|
||||||
|
|
||||||
|
var horizontal : bool = from.y == to.y
|
||||||
|
var _offset : Vector2
|
||||||
|
if horizontal:
|
||||||
|
_offset = Vector2(line_offset.x, 0)
|
||||||
|
else:
|
||||||
|
_offset = Vector2(0, line_offset.y)
|
||||||
|
|
||||||
|
if length < dash_length: # not long enough to dash
|
||||||
|
draw_line(from, to, color, width, antialiased)
|
||||||
|
return
|
||||||
|
|
||||||
|
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)
|
Loading…
Add table
Reference in a new issue