mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-31 07:29:49 +00:00
Added more options to the Rotate Image dialog
Now all of the image effects (except those related to resizing) have the same affect options.
This commit is contained in:
parent
b3aa4a6343
commit
cce4fa4cbb
|
@ -62,146 +62,163 @@ func scale3X(sprite : Image, tol : float = 50) -> Image:
|
||||||
return scaled
|
return scaled
|
||||||
|
|
||||||
|
|
||||||
func rotxel(sprite : Image, angle : float) -> void:
|
func rotxel(sprite : Image, angle : float, pixels : Array) -> void:
|
||||||
# If angle is simple, then nn rotation is the best
|
# If angle is simple, then nn rotation is the best
|
||||||
|
|
||||||
if angle == 0 || angle == PI/2 || angle == PI || angle == 2*PI:
|
if angle == 0 || angle == PI/2 || angle == PI || angle == 2*PI:
|
||||||
nn_rotate(sprite, angle)
|
nn_rotate(sprite, angle, pixels)
|
||||||
return
|
return
|
||||||
|
|
||||||
var aux : Image = Image.new()
|
var aux : Image = Image.new()
|
||||||
aux.copy_from(sprite)
|
aux.copy_from(sprite)
|
||||||
# warning-ignore:integer_division
|
var selection_rectangle := Rect2(pixels[0].x, pixels[0].y, pixels[-1].x - pixels[0].x + 1, pixels[-1].y - pixels[0].y + 1)
|
||||||
# warning-ignore:integer_division
|
var center : Vector2 = selection_rectangle.position + ((selection_rectangle.end - selection_rectangle.position) / 2)
|
||||||
var center : Vector2 = Vector2(sprite.get_width() / 2, sprite.get_height() / 2)
|
|
||||||
var ox : int
|
var ox : int
|
||||||
var oy : int
|
var oy : int
|
||||||
var p : Color
|
var p : Color
|
||||||
aux.lock()
|
aux.lock()
|
||||||
sprite.lock()
|
sprite.lock()
|
||||||
for x in range(sprite.get_width()):
|
for pix in pixels:
|
||||||
for y in range(sprite.get_height()):
|
var x = pix.x
|
||||||
var dx = 3*(x - center.x)
|
var y = pix.y
|
||||||
var dy = 3*(y - center.y)
|
var dx = 3*(x - center.x)
|
||||||
var found_pixel : bool = false
|
var dy = 3*(y - center.y)
|
||||||
for k in range(9):
|
var found_pixel : bool = false
|
||||||
var i = -1 + k % 3
|
for k in range(9):
|
||||||
|
var i = -1 + k % 3
|
||||||
# warning-ignore:integer_division
|
# warning-ignore:integer_division
|
||||||
var j = -1 + int(k / 3)
|
var j = -1 + int(k / 3)
|
||||||
var dir = atan2(dy + j, dx + i)
|
var dir = atan2(dy + j, dx + i)
|
||||||
var mag = sqrt(pow(dx + i, 2) + pow(dy + j, 2))
|
var mag = sqrt(pow(dx + i, 2) + pow(dy + j, 2))
|
||||||
dir -= angle
|
dir -= angle
|
||||||
ox = round(center.x*3 + 1 + mag*cos(dir))
|
ox = round(center.x*3 + 1 + mag*cos(dir))
|
||||||
oy = round(center.y*3 + 1 + mag*sin(dir))
|
oy = round(center.y*3 + 1 + mag*sin(dir))
|
||||||
|
|
||||||
if (sprite.get_width() % 2 != 0):
|
if (sprite.get_width() % 2 != 0):
|
||||||
ox += 1
|
ox += 1
|
||||||
oy += 1
|
oy += 1
|
||||||
|
|
||||||
if (ox >= 0 && ox < sprite.get_width()*3
|
if (ox >= 0 && ox < sprite.get_width()*3
|
||||||
&& oy >= 0 && oy < sprite.get_height()*3):
|
&& oy >= 0 && oy < sprite.get_height()*3):
|
||||||
found_pixel = true
|
found_pixel = true
|
||||||
break
|
break
|
||||||
|
|
||||||
if !found_pixel:
|
if !found_pixel:
|
||||||
sprite.set_pixel(x, y, Color(0,0,0,0))
|
sprite.set_pixel(x, y, Color(0,0,0,0))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
var fil : int = oy % 3
|
var fil : int = oy % 3
|
||||||
var col : int = ox % 3
|
var col : int = ox % 3
|
||||||
var index : int = col + 3*fil
|
var index : int = col + 3*fil
|
||||||
|
|
||||||
ox = round((ox - 1)/3.0);
|
ox = round((ox - 1)/3.0);
|
||||||
oy = round((oy - 1)/3.0);
|
oy = round((oy - 1)/3.0);
|
||||||
var a : Color
|
var a : Color
|
||||||
var b : Color
|
var b : Color
|
||||||
var c : Color
|
var c : Color
|
||||||
var d : Color
|
var d : Color
|
||||||
var e : Color
|
var e : Color
|
||||||
var f : Color
|
var f : Color
|
||||||
var g : Color
|
var g : Color
|
||||||
var h : Color
|
var h : Color
|
||||||
var i : Color
|
var i : Color
|
||||||
if (ox == 0 || ox == sprite.get_width() - 1 ||
|
if (ox == 0 || ox == sprite.get_width() - 1 ||
|
||||||
oy == 0 || oy == sprite.get_height() - 1):
|
oy == 0 || oy == sprite.get_height() - 1):
|
||||||
p = aux.get_pixel(ox, oy)
|
p = aux.get_pixel(ox, oy)
|
||||||
else:
|
else:
|
||||||
a = aux.get_pixel(ox-1,oy-1);
|
a = aux.get_pixel(ox-1,oy-1);
|
||||||
b = aux.get_pixel(ox,oy-1);
|
b = aux.get_pixel(ox,oy-1);
|
||||||
c = aux.get_pixel(ox+1,oy-1);
|
c = aux.get_pixel(ox+1,oy-1);
|
||||||
d = aux.get_pixel(ox-1,oy);
|
d = aux.get_pixel(ox-1,oy);
|
||||||
e = aux.get_pixel(ox,oy);
|
e = aux.get_pixel(ox,oy);
|
||||||
f = aux.get_pixel(ox+1,oy);
|
f = aux.get_pixel(ox+1,oy);
|
||||||
g = aux.get_pixel(ox-1,oy+1);
|
g = aux.get_pixel(ox-1,oy+1);
|
||||||
h = aux.get_pixel(ox,oy+1);
|
h = aux.get_pixel(ox,oy+1);
|
||||||
i = aux.get_pixel(ox+1,oy+1);
|
i = aux.get_pixel(ox+1,oy+1);
|
||||||
|
|
||||||
match(index):
|
match(index):
|
||||||
0:
|
0:
|
||||||
p = d if (similarColors(d,b) && !similarColors(d,h)
|
p = d if (similarColors(d,b) && !similarColors(d,h)
|
||||||
&& !similarColors(b,f)) else e;
|
&& !similarColors(b,f)) else e;
|
||||||
1:
|
1:
|
||||||
p = b if ((similarColors(d,b) && !similarColors(d,h) &&
|
p = b if ((similarColors(d,b) && !similarColors(d,h) &&
|
||||||
!similarColors(b,f) && !similarColors(e,c)) ||
|
!similarColors(b,f) && !similarColors(e,c)) ||
|
||||||
(similarColors(b,f) && !similarColors(d,b) &&
|
(similarColors(b,f) && !similarColors(d,b) &&
|
||||||
!similarColors(f,h) && !similarColors(e,a))) else e;
|
!similarColors(f,h) && !similarColors(e,a))) else e;
|
||||||
2:
|
2:
|
||||||
p = f if (similarColors(b,f) && !similarColors(d,b) &&
|
p = f if (similarColors(b,f) && !similarColors(d,b) &&
|
||||||
!similarColors(f,h)) else e;
|
!similarColors(f,h)) else e;
|
||||||
3:
|
3:
|
||||||
p = d if ((similarColors(d,h) && !similarColors(f,h) &&
|
p = d if ((similarColors(d,h) && !similarColors(f,h) &&
|
||||||
!similarColors(d,b) && !similarColors(e,a)) ||
|
!similarColors(d,b) && !similarColors(e,a)) ||
|
||||||
(similarColors(d,b) && !similarColors(d,h) &&
|
(similarColors(d,b) && !similarColors(d,h) &&
|
||||||
!similarColors(b,f) && !similarColors(e,g))) else e;
|
!similarColors(b,f) && !similarColors(e,g))) else e;
|
||||||
4:
|
4:
|
||||||
p = e
|
p = e
|
||||||
5:
|
5:
|
||||||
p = f if((similarColors(b,f) && !similarColors(d,b) &&
|
p = f if((similarColors(b,f) && !similarColors(d,b) &&
|
||||||
!similarColors(f,h) && !similarColors(e,i))
|
!similarColors(f,h) && !similarColors(e,i))
|
||||||
|| (similarColors(f,h) && !similarColors(b,f) &&
|
|| (similarColors(f,h) && !similarColors(b,f) &&
|
||||||
!similarColors(d,h) && !similarColors(e,c))) else e;
|
!similarColors(d,h) && !similarColors(e,c))) else e;
|
||||||
6:
|
6:
|
||||||
p = d if (similarColors(d,h) && !similarColors(f,h) &&
|
p = d if (similarColors(d,h) && !similarColors(f,h) &&
|
||||||
!similarColors(d,b)) else e;
|
!similarColors(d,b)) else e;
|
||||||
7:
|
7:
|
||||||
p = h if ((similarColors(f,h) && !similarColors(f,b) &&
|
p = h if ((similarColors(f,h) && !similarColors(f,b) &&
|
||||||
!similarColors(d,h) && !similarColors(e,g))
|
!similarColors(d,h) && !similarColors(e,g))
|
||||||
|| (similarColors(d,h) && !similarColors(f,h) &&
|
|| (similarColors(d,h) && !similarColors(f,h) &&
|
||||||
!similarColors(d,b) && !similarColors(e,i))) else e;
|
!similarColors(d,b) && !similarColors(e,i))) else e;
|
||||||
8:
|
8:
|
||||||
p = f if (similarColors(f,h) && !similarColors(f,b) &&
|
p = f if (similarColors(f,h) && !similarColors(f,b) &&
|
||||||
!similarColors(d,h)) else e;
|
!similarColors(d,h)) else e;
|
||||||
sprite.set_pixel(x, y, p)
|
sprite.set_pixel(x, y, p)
|
||||||
sprite.unlock()
|
sprite.unlock()
|
||||||
aux.unlock()
|
aux.unlock()
|
||||||
|
|
||||||
|
|
||||||
func fake_rotsprite(sprite : Image, angle : float) -> void:
|
func fake_rotsprite(sprite : Image, angle : float, pixels : Array) -> void:
|
||||||
sprite.copy_from(scale3X(sprite))
|
var selection_rectangle := Rect2(pixels[0].x, pixels[0].y, pixels[-1].x - pixels[0].x + 1, pixels[-1].y - pixels[0].y + 1)
|
||||||
nn_rotate(sprite,angle)
|
var selected_sprite := Image.new()
|
||||||
|
selected_sprite = sprite.get_rect(selection_rectangle)
|
||||||
|
selected_sprite.copy_from(scale3X(selected_sprite))
|
||||||
|
nn_rotate(selected_sprite, angle, [])
|
||||||
# warning-ignore:integer_division
|
# warning-ignore:integer_division
|
||||||
# warning-ignore:integer_division
|
# warning-ignore:integer_division
|
||||||
sprite.resize(sprite.get_width() / 3, sprite.get_height() / 3, 0)
|
selected_sprite.resize(selected_sprite.get_width() / 3, selected_sprite.get_height() / 3, 0)
|
||||||
|
sprite.blit_rect(selected_sprite, Rect2(Vector2.ZERO, selected_sprite.get_size()), selection_rectangle.position)
|
||||||
|
|
||||||
|
|
||||||
func nn_rotate(sprite : Image, angle : float) -> void:
|
func nn_rotate(sprite : Image, angle : float, pixels : Array) -> void:
|
||||||
var aux : Image = Image.new()
|
var aux : Image = Image.new()
|
||||||
aux.copy_from(sprite)
|
aux.copy_from(sprite)
|
||||||
sprite.lock()
|
sprite.lock()
|
||||||
aux.lock()
|
aux.lock()
|
||||||
var ox: int
|
var ox: int
|
||||||
var oy: int
|
var oy: int
|
||||||
# warning-ignore:integer_division
|
var center : Vector2
|
||||||
# warning-ignore:integer_division
|
if pixels:
|
||||||
var center : Vector2 = Vector2(sprite.get_width() / 2, sprite.get_height() / 2)
|
var selection_rectangle := Rect2(pixels[0].x, pixels[0].y, pixels[-1].x - pixels[0].x + 1, pixels[-1].y - pixels[0].y + 1)
|
||||||
for x in range(sprite.get_width()):
|
center = selection_rectangle.position + ((selection_rectangle.end - selection_rectangle.position) / 2)
|
||||||
for y in range(sprite.get_height()):
|
for pix in pixels:
|
||||||
|
var x = pix.x
|
||||||
|
var y = pix.y
|
||||||
ox = (x - center.x)*cos(angle) + (y - center.y)*sin(angle) + center.x
|
ox = (x - center.x)*cos(angle) + (y - center.y)*sin(angle) + center.x
|
||||||
oy = -(x - center.x)*sin(angle) + (y - center.y)*cos(angle) + center.y
|
oy = -(x - center.x)*sin(angle) + (y - center.y)*cos(angle) + center.y
|
||||||
if ox >= 0 && ox < sprite.get_width() && oy >= 0 && oy < sprite.get_height():
|
if ox >= 0 && ox < sprite.get_width() && oy >= 0 && oy < sprite.get_height():
|
||||||
sprite.set_pixel(x, y, aux.get_pixel(ox, oy))
|
sprite.set_pixel(x, y, aux.get_pixel(ox, oy))
|
||||||
else:
|
else:
|
||||||
sprite.set_pixel(x, y, Color(0,0,0,0))
|
sprite.set_pixel(x, y, Color(0,0,0,0))
|
||||||
|
else:
|
||||||
|
# warning-ignore:integer_division
|
||||||
|
# warning-ignore:integer_division
|
||||||
|
center = Vector2(sprite.get_width() / 2, sprite.get_height() / 2)
|
||||||
|
for x in range(sprite.get_width()):
|
||||||
|
for y in range(sprite.get_height()):
|
||||||
|
ox = (x - center.x)*cos(angle) + (y - center.y)*sin(angle) + center.x
|
||||||
|
oy = -(x - center.x)*sin(angle) + (y - center.y)*cos(angle) + center.y
|
||||||
|
if ox >= 0 && ox < sprite.get_width() && oy >= 0 && oy < sprite.get_height():
|
||||||
|
sprite.set_pixel(x, y, aux.get_pixel(ox, oy))
|
||||||
|
else:
|
||||||
|
sprite.set_pixel(x, y, Color(0,0,0,0))
|
||||||
sprite.unlock()
|
sprite.unlock()
|
||||||
aux.unlock()
|
aux.unlock()
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ func _ready() -> void:
|
||||||
|
|
||||||
func set_nodes() -> void:
|
func set_nodes() -> void:
|
||||||
preview = $VBoxContainer/Preview
|
preview = $VBoxContainer/Preview
|
||||||
|
selection_checkbox = $VBoxContainer/OptionsContainer/SelectionCheckBox
|
||||||
|
affect_option_button = $VBoxContainer/OptionsContainer/AffectOptionButton
|
||||||
|
|
||||||
|
|
||||||
func _about_to_show() -> void:
|
func _about_to_show() -> void:
|
||||||
|
@ -22,13 +24,14 @@ func _about_to_show() -> void:
|
||||||
|
|
||||||
|
|
||||||
func commit_action(_cel : Image, _pixels : Array, _project : Project = Global.current_project) -> void:
|
func commit_action(_cel : Image, _pixels : Array, _project : Project = Global.current_project) -> void:
|
||||||
|
var angle : float = deg2rad(angle_hslider.value)
|
||||||
match type_option_button.text:
|
match type_option_button.text:
|
||||||
"Rotxel":
|
"Rotxel":
|
||||||
DrawingAlgos.rotxel(_cel,angle_hslider.value*PI/180)
|
DrawingAlgos.rotxel(_cel, angle, _pixels)
|
||||||
"Nearest neighbour":
|
"Nearest neighbour":
|
||||||
DrawingAlgos.nn_rotate(_cel,angle_hslider.value*PI/180)
|
DrawingAlgos.nn_rotate(_cel, angle, _pixels)
|
||||||
"Upscale, Rotate and Downscale":
|
"Upscale, Rotate and Downscale":
|
||||||
DrawingAlgos.fake_rotsprite(_cel,angle_hslider.value*PI/180)
|
DrawingAlgos.fake_rotsprite(_cel, angle, _pixels)
|
||||||
|
|
||||||
|
|
||||||
func _confirmed() -> void:
|
func _confirmed() -> void:
|
||||||
|
|
|
@ -25,8 +25,8 @@ __meta__ = {
|
||||||
}
|
}
|
||||||
|
|
||||||
[node name="Preview" type="TextureRect" parent="VBoxContainer"]
|
[node name="Preview" type="TextureRect" parent="VBoxContainer"]
|
||||||
margin_left = 14.0
|
margin_left = 31.0
|
||||||
margin_right = 214.0
|
margin_right = 231.0
|
||||||
margin_bottom = 200.0
|
margin_bottom = 200.0
|
||||||
rect_min_size = Vector2( 200, 200 )
|
rect_min_size = Vector2( 200, 200 )
|
||||||
size_flags_horizontal = 4
|
size_flags_horizontal = 4
|
||||||
|
@ -39,7 +39,7 @@ show_behind_parent = true
|
||||||
|
|
||||||
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
|
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
|
||||||
margin_top = 204.0
|
margin_top = 204.0
|
||||||
margin_right = 229.0
|
margin_right = 263.0
|
||||||
margin_bottom = 224.0
|
margin_bottom = 224.0
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer2"]
|
[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer2"]
|
||||||
|
@ -50,7 +50,7 @@ text = "Type:"
|
||||||
|
|
||||||
[node name="TypeOptionButton" type="OptionButton" parent="VBoxContainer/HBoxContainer2"]
|
[node name="TypeOptionButton" type="OptionButton" parent="VBoxContainer/HBoxContainer2"]
|
||||||
margin_left = 38.0
|
margin_left = 38.0
|
||||||
margin_right = 229.0
|
margin_right = 263.0
|
||||||
margin_bottom = 20.0
|
margin_bottom = 20.0
|
||||||
mouse_default_cursor_shape = 2
|
mouse_default_cursor_shape = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
|
@ -58,7 +58,7 @@ size_flags_vertical = 3
|
||||||
|
|
||||||
[node name="AngleOptions" type="HBoxContainer" parent="VBoxContainer"]
|
[node name="AngleOptions" type="HBoxContainer" parent="VBoxContainer"]
|
||||||
margin_top = 228.0
|
margin_top = 228.0
|
||||||
margin_right = 229.0
|
margin_right = 263.0
|
||||||
margin_bottom = 252.0
|
margin_bottom = 252.0
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="VBoxContainer/AngleOptions"]
|
[node name="Label" type="Label" parent="VBoxContainer/AngleOptions"]
|
||||||
|
@ -69,7 +69,7 @@ text = "Angle:"
|
||||||
|
|
||||||
[node name="AngleHSlider" type="HSlider" parent="VBoxContainer/AngleOptions"]
|
[node name="AngleHSlider" type="HSlider" parent="VBoxContainer/AngleOptions"]
|
||||||
margin_left = 44.0
|
margin_left = 44.0
|
||||||
margin_right = 151.0
|
margin_right = 185.0
|
||||||
margin_bottom = 24.0
|
margin_bottom = 24.0
|
||||||
mouse_default_cursor_shape = 2
|
mouse_default_cursor_shape = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
|
@ -80,12 +80,33 @@ __meta__ = {
|
||||||
}
|
}
|
||||||
|
|
||||||
[node name="AngleSpinBox" type="SpinBox" parent="VBoxContainer/AngleOptions"]
|
[node name="AngleSpinBox" type="SpinBox" parent="VBoxContainer/AngleOptions"]
|
||||||
margin_left = 155.0
|
margin_left = 189.0
|
||||||
margin_right = 229.0
|
margin_right = 263.0
|
||||||
margin_bottom = 24.0
|
margin_bottom = 24.0
|
||||||
mouse_default_cursor_shape = 2
|
mouse_default_cursor_shape = 2
|
||||||
max_value = 359.0
|
max_value = 359.0
|
||||||
suffix = "°"
|
suffix = "°"
|
||||||
|
|
||||||
|
[node name="OptionsContainer" type="HBoxContainer" parent="VBoxContainer"]
|
||||||
|
margin_top = 256.0
|
||||||
|
margin_right = 263.0
|
||||||
|
margin_bottom = 280.0
|
||||||
|
|
||||||
|
[node name="SelectionCheckBox" type="CheckBox" parent="VBoxContainer/OptionsContainer"]
|
||||||
|
margin_right = 160.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
mouse_default_cursor_shape = 2
|
||||||
|
pressed = true
|
||||||
|
text = "Only affect selection"
|
||||||
|
|
||||||
|
[node name="AffectOptionButton" type="OptionButton" parent="VBoxContainer/OptionsContainer"]
|
||||||
|
margin_left = 164.0
|
||||||
|
margin_right = 263.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
mouse_default_cursor_shape = 2
|
||||||
|
text = "Current cel"
|
||||||
|
items = [ "Current cel", null, false, 0, null, "Current frame", null, false, 1, null, "All frames", null, false, 2, null, "All projects", null, false, 3, null ]
|
||||||
|
selected = 0
|
||||||
[connection signal="item_selected" from="VBoxContainer/HBoxContainer2/TypeOptionButton" to="." method="_on_TypeOptionButton_item_selected"]
|
[connection signal="item_selected" from="VBoxContainer/HBoxContainer2/TypeOptionButton" to="." method="_on_TypeOptionButton_item_selected"]
|
||||||
[connection signal="value_changed" from="VBoxContainer/AngleOptions/AngleHSlider" to="." method="_on_HSlider_value_changed"]
|
[connection signal="value_changed" from="VBoxContainer/AngleOptions/AngleHSlider" to="." method="_on_HSlider_value_changed"]
|
||||||
[connection signal="value_changed" from="VBoxContainer/AngleOptions/AngleSpinBox" to="." method="_on_SpinBox_value_changed"]
|
[connection signal="value_changed" from="VBoxContainer/AngleOptions/AngleSpinBox" to="." method="_on_SpinBox_value_changed"]
|
||||||
|
|
Loading…
Reference in a new issue