mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-30 23:19:49 +00:00
Add a transform
method to DrawingAlgos
Can be used as a general method to apply rotation and skewing. It does not handle scaling though, and I am not sure if it should.
This commit is contained in:
parent
0809dc2dcf
commit
e40d507a6a
|
@ -1,5 +1,6 @@
|
|||
extends Node
|
||||
|
||||
enum RotationAlgorithm { ROTXEL_SMEAR, CLEANEDGE, OMNISCALE, NNS, NN, ROTXEL, URD }
|
||||
enum GradientDirection { TOP, BOTTOM, LEFT, RIGHT }
|
||||
## Continuation from Image.Interpolation
|
||||
enum Interpolation { SCALE3X = 5, CLEANEDGE = 6, OMNISCALE = 7 }
|
||||
|
@ -14,6 +15,8 @@ var omniscale_shader: Shader:
|
|||
if omniscale_shader == null:
|
||||
omniscale_shader = load("res://src/Shaders/Effects/Rotation/OmniScale.gdshader")
|
||||
return omniscale_shader
|
||||
var rotxel_shader := preload("res://src/Shaders/Effects/Rotation/SmearRotxel.gdshader")
|
||||
var nn_shader := preload("res://src/Shaders/Effects/Rotation/NearestNeighbour.gdshader")
|
||||
|
||||
|
||||
## Blends canvas layers into passed image starting from the origin position
|
||||
|
@ -270,6 +273,41 @@ func scale_3x(sprite: Image, tol := 0.196078) -> Image:
|
|||
return scaled
|
||||
|
||||
|
||||
func transform(
|
||||
image: Image,
|
||||
params: Dictionary,
|
||||
algorithm: RotationAlgorithm,
|
||||
project := Global.current_project
|
||||
) -> void:
|
||||
var pivot: Vector2 = params.get("pivot", image.get_size() / 2)
|
||||
if type_is_shader(algorithm):
|
||||
params["pivot"] = pivot / Vector2(image.get_size())
|
||||
var shader := rotxel_shader
|
||||
match algorithm:
|
||||
RotationAlgorithm.CLEANEDGE:
|
||||
shader = clean_edge_shader
|
||||
RotationAlgorithm.OMNISCALE:
|
||||
shader = omniscale_shader
|
||||
RotationAlgorithm.NNS:
|
||||
shader = nn_shader
|
||||
var gen := ShaderImageEffect.new()
|
||||
gen.generate_image(image, shader, params, project.size)
|
||||
else:
|
||||
var transformation_matrix: Transform2D = params.get("transformation_matrix", Transform2D())
|
||||
var angle := transformation_matrix.get_rotation()
|
||||
match algorithm:
|
||||
RotationAlgorithm.ROTXEL:
|
||||
rotxel(image, angle, pivot)
|
||||
RotationAlgorithm.NN:
|
||||
nn_rotate(image, angle, pivot)
|
||||
RotationAlgorithm.URD:
|
||||
fake_rotsprite(image, angle, pivot)
|
||||
|
||||
|
||||
func type_is_shader(algorithm: RotationAlgorithm) -> bool:
|
||||
return algorithm <= RotationAlgorithm.NNS
|
||||
|
||||
|
||||
func rotxel(sprite: Image, angle: float, pivot: Vector2) -> void:
|
||||
if is_zero_approx(angle) or is_equal_approx(angle, TAU):
|
||||
return
|
||||
|
|
|
@ -46,6 +46,7 @@ var undo_data: Dictionary
|
|||
var gizmos: Array[Gizmo] = []
|
||||
var dragged_gizmo: Gizmo = null
|
||||
var angle := 0.0
|
||||
var rotation_algorithm := DrawingAlgos.RotationAlgorithm.NN
|
||||
var content_pivot := Vector2.ZERO
|
||||
var mouse_pos_on_gizmo_drag := Vector2.ZERO
|
||||
var resize_keep_ratio := false
|
||||
|
@ -405,7 +406,9 @@ func resize_selection() -> void:
|
|||
)
|
||||
else:
|
||||
content_pivot = original_big_bounding_rectangle.size / 2.0
|
||||
DrawingAlgos.nn_rotate(preview_image, angle, content_pivot)
|
||||
var transformation_matrix := Transform2D(angle, Vector2.ZERO)
|
||||
var params := {"transformation_matrix": transformation_matrix, "pivot": content_pivot}
|
||||
DrawingAlgos.transform(preview_image, params, rotation_algorithm)
|
||||
preview_image.resize(size.x, size.y, Image.INTERPOLATE_NEAREST)
|
||||
if temp_rect.size.x < 0:
|
||||
preview_image.flip_x()
|
||||
|
@ -416,7 +419,9 @@ func resize_selection() -> void:
|
|||
Global.current_project.selection_map.copy_from(original_bitmap)
|
||||
|
||||
var bitmap_pivot := original_big_bounding_rectangle.get_center()
|
||||
DrawingAlgos.nn_rotate(Global.current_project.selection_map, angle, bitmap_pivot)
|
||||
var bitmap_matrix := Transform2D(angle, Vector2.ZERO)
|
||||
var bitmap_params := {"transformation_matrix": bitmap_matrix, "pivot": bitmap_pivot}
|
||||
DrawingAlgos.transform(Global.current_project.selection_map, bitmap_params, rotation_algorithm)
|
||||
Global.current_project.selection_map.resize_bitmap_values(
|
||||
Global.current_project, size, temp_rect.size.x < 0, temp_rect.size.y < 0
|
||||
)
|
||||
|
@ -552,7 +557,11 @@ func transform_content_confirm() -> void:
|
|||
src.crop(preview_image.get_width(), preview_image.get_height())
|
||||
tilemap.apply_resizing_to_image(src, selected_cells, big_bounding_rectangle)
|
||||
else:
|
||||
DrawingAlgos.nn_rotate(src, angle, content_pivot)
|
||||
var transformation_matrix := Transform2D(angle, Vector2.ZERO)
|
||||
var params := {
|
||||
"transformation_matrix": transformation_matrix, "pivot": content_pivot
|
||||
}
|
||||
DrawingAlgos.transform(src, params, rotation_algorithm)
|
||||
src.resize(
|
||||
preview_image.get_width(), preview_image.get_height(), Image.INTERPOLATE_NEAREST
|
||||
)
|
||||
|
|
|
@ -80,7 +80,7 @@ func _calculate_pivot() -> void:
|
|||
func commit_action(cel: Image, project := Global.current_project) -> void:
|
||||
var angle := deg_to_rad(animate_panel.get_animated_value(commit_idx, Animate.ANGLE))
|
||||
var init_angle := deg_to_rad(animate_panel.get_animated_value(commit_idx, Animate.INIT_ANGLE))
|
||||
|
||||
var rotation_algorithm := type_option_button.get_selected_id()
|
||||
var selection_tex: ImageTexture
|
||||
var image := Image.new()
|
||||
image.copy_from(cel)
|
||||
|
@ -88,7 +88,7 @@ func commit_action(cel: Image, project := Global.current_project) -> void:
|
|||
var selection := project.selection_map.return_cropped_copy(project.size)
|
||||
selection_tex = ImageTexture.create_from_image(selection)
|
||||
|
||||
if !_type_is_shader():
|
||||
if not DrawingAlgos.type_is_shader(rotation_algorithm):
|
||||
var blank := project.new_empty_image()
|
||||
cel.blit_rect_mask(
|
||||
blank, selection, Rect2i(Vector2i.ZERO, cel.get_size()), Vector2i.ZERO
|
||||
|
@ -97,41 +97,26 @@ func commit_action(cel: Image, project := Global.current_project) -> void:
|
|||
image.blit_rect_mask(
|
||||
blank, selection, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO
|
||||
)
|
||||
if _type_is_shader():
|
||||
var shader := rotxel_shader
|
||||
var transformation_matrix := Transform2D(angle, Vector2.ZERO)
|
||||
var params := {
|
||||
"transformation_matrix": Transform2D(angle, Vector2.ZERO),
|
||||
"transformation_matrix": transformation_matrix,
|
||||
"pivot": pivot,
|
||||
"selection_tex": selection_tex,
|
||||
"pivot": pivot / Vector2(cel.get_size()),
|
||||
"initial_angle": init_angle,
|
||||
"ending_angle": angle,
|
||||
"tolerance": tolerance_slider.value,
|
||||
"preview": true
|
||||
}
|
||||
match type_option_button.get_selected_id():
|
||||
ROTXEL_SMEAR:
|
||||
params["ending_angle"] = angle
|
||||
params["initial_angle"] = init_angle
|
||||
params["tolerance"] = tolerance_slider.value
|
||||
CLEANEDGE:
|
||||
shader = DrawingAlgos.clean_edge_shader
|
||||
OMNISCALE:
|
||||
shader = DrawingAlgos.omniscale_shader
|
||||
NNS:
|
||||
shader = nn_shader
|
||||
if DrawingAlgos.type_is_shader(rotation_algorithm):
|
||||
if !has_been_confirmed:
|
||||
params["pivot"] /= Vector2(cel.get_size())
|
||||
for param in params:
|
||||
preview.material.set_shader_parameter(param, params[param])
|
||||
else:
|
||||
params["preview"] = false
|
||||
var gen := ShaderImageEffect.new()
|
||||
gen.generate_image(cel, shader, params, project.size)
|
||||
DrawingAlgos.transform(cel, params, rotation_algorithm, project)
|
||||
else:
|
||||
match type_option_button.get_selected_id():
|
||||
ROTXEL:
|
||||
DrawingAlgos.rotxel(image, angle, pivot)
|
||||
NN:
|
||||
DrawingAlgos.nn_rotate(image, angle, pivot)
|
||||
URD:
|
||||
DrawingAlgos.fake_rotsprite(image, angle, pivot)
|
||||
|
||||
DrawingAlgos.transform(image, params, rotation_algorithm, project)
|
||||
if project.has_selection and selection_checkbox.button_pressed:
|
||||
cel.blend_rect(image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO)
|
||||
else:
|
||||
|
@ -140,10 +125,6 @@ func commit_action(cel: Image, project := Global.current_project) -> void:
|
|||
cel.convert_rgb_to_indexed()
|
||||
|
||||
|
||||
func _type_is_shader() -> bool:
|
||||
return type_option_button.get_selected_id() <= NNS
|
||||
|
||||
|
||||
func _on_TypeOptionButton_item_selected(_id: int) -> void:
|
||||
match type_option_button.get_selected_id():
|
||||
ROTXEL_SMEAR:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
[ext_resource type="Script" path="res://src/UI/Dialogs/ImageEffects/RotateImage.gd" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://bybqhhayl5ay5" path="res://src/UI/Dialogs/ImageEffects/ImageEffectParent.tscn" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/Sliders/ValueSlider.tscn" id="3"]
|
||||
[ext_resource type="PackedScene" path="res://src/UI/Nodes/Sliders/ValueSliderV2.tscn" id="4"]
|
||||
[ext_resource type="PackedScene" uid="uid://bbnqcxa20a5a5" path="res://src/UI/Nodes/Sliders/ValueSliderV2.tscn" id="4"]
|
||||
|
||||
[node name="RotateImage" instance=ExtResource("2")]
|
||||
title = "Rotate Image"
|
||||
|
|
Loading…
Reference in a new issue