mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-18 17:19:50 +00:00
Add an offset image effect
Some functionality as the move tool, but with more precision, wrap around ability and of course animation.
This commit is contained in:
parent
81c0b49c59
commit
08064098b8
|
@ -148,6 +148,16 @@ msgstr ""
|
|||
msgid "Resize Canvas"
|
||||
msgstr ""
|
||||
|
||||
msgid "Offset Image"
|
||||
msgstr ""
|
||||
|
||||
msgid "Offset:"
|
||||
msgstr ""
|
||||
|
||||
#. Found in the Offset Image dialog. It's a checkbox that, if enabled, wraps around the image if pixels go out of canvas bounds.
|
||||
msgid "Wrap around:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Centralize Image"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ enum ViewMenu {
|
|||
enum WindowMenu { WINDOW_OPACITY, PANELS, LAYOUTS, MOVABLE_PANELS, ZEN_MODE, FULLSCREEN_MODE }
|
||||
enum ImageMenu {
|
||||
RESIZE_CANVAS,
|
||||
OFFSET_IMAGE,
|
||||
SCALE_IMAGE,
|
||||
CROP_IMAGE,
|
||||
FLIP,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class_name ImageEffect
|
||||
extends ConfirmationDialog
|
||||
# Parent class for all image effects
|
||||
# Methods that have "pass" are meant to be replaced by the inherited Scripts
|
||||
## Parent class for all image effects
|
||||
## Methods that have "pass" are meant to be replaced by the inherited scripts
|
||||
|
||||
enum { SELECTED_CELS, FRAME, ALL_FRAMES, ALL_PROJECTS }
|
||||
|
||||
|
|
24
src/Shaders/OffsetPixels.gdshader
Normal file
24
src/Shaders/OffsetPixels.gdshader
Normal file
|
@ -0,0 +1,24 @@
|
|||
shader_type canvas_item;
|
||||
|
||||
uniform sampler2D selection;
|
||||
uniform vec2 offset = vec2(0.0); // In pixels
|
||||
uniform bool wrap_around = false;
|
||||
|
||||
void fragment() {
|
||||
vec4 original_color = texture(TEXTURE, UV);
|
||||
vec4 selection_color = texture(selection, UV);
|
||||
|
||||
vec2 uv = UV - (offset * TEXTURE_PIXEL_SIZE); // Offset the uv by an amount of pixels
|
||||
if (wrap_around) {
|
||||
uv = fract(uv);
|
||||
}
|
||||
|
||||
vec4 output = texture(TEXTURE, uv);
|
||||
// Cut original selected content
|
||||
original_color.a = 0.0 * step(0.5, selection_color.a) + original_color.a * step(selection_color.a, 0.5);
|
||||
output.a = min(step(uv.x, 1.0) * step(0.0, uv.x), output.a); // Remove left and right edges
|
||||
output.a = min(step(uv.y, 1.0) * step(0.0, uv.y), output.a); // Remove up and bottom edges
|
||||
|
||||
selection_color = texture(selection, uv);
|
||||
COLOR = mix(original_color, output, selection_color.a);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=14 format=2]
|
||||
[gd_scene load_steps=15 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/FlipImageDialog.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/InvertColorsDialog.tscn" type="PackedScene" id=2]
|
||||
|
@ -6,6 +6,7 @@
|
|||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/DropShadowDialog.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/GradientMapDialog.tscn" type="PackedScene" id=5]
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/Posterize.tscn" type="PackedScene" id=6]
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/OffsetImage.tscn" type="PackedScene" id=7]
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/ResizeCanvas.tscn" type="PackedScene" id=8]
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/RotateImage.tscn" type="PackedScene" id=9]
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/ShaderEffect.tscn" type="PackedScene" id=10]
|
||||
|
@ -17,6 +18,10 @@
|
|||
[node name="ImageEffects" type="Control"]
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="OffsetImage" parent="." instance=ExtResource( 7 )]
|
||||
margin_right = 376.0
|
||||
margin_bottom = 370.0
|
||||
|
||||
[node name="ScaleImage" parent="." instance=ExtResource( 14 )]
|
||||
margin_bottom = 127.0
|
||||
|
||||
|
|
54
src/UI/Dialogs/ImageEffects/OffsetImage.gd
Normal file
54
src/UI/Dialogs/ImageEffects/OffsetImage.gd
Normal file
|
@ -0,0 +1,54 @@
|
|||
extends ImageEffect
|
||||
|
||||
enum Animate { OFFSET_X, OFFSET_Y }
|
||||
|
||||
var shader: Shader = preload("res://src/Shaders/OffsetPixels.gdshader")
|
||||
var wrap_around := false
|
||||
|
||||
onready var offset_sliders := $VBoxContainer/OffsetOptions/OffsetSliders as ValueSliderV2
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var sm := ShaderMaterial.new()
|
||||
sm.shader = shader
|
||||
preview.set_material(sm)
|
||||
# Set as in the Animate enum
|
||||
animate_panel.add_float_property(
|
||||
"Offset X", $VBoxContainer/OffsetOptions/OffsetSliders.get_sliders()[0]
|
||||
)
|
||||
animate_panel.add_float_property(
|
||||
"Offset Y", $VBoxContainer/OffsetOptions/OffsetSliders.get_sliders()[1]
|
||||
)
|
||||
|
||||
|
||||
func _about_to_show() -> void:
|
||||
offset_sliders.min_value = -Global.current_project.size
|
||||
offset_sliders.max_value = Global.current_project.size
|
||||
._about_to_show()
|
||||
|
||||
|
||||
func commit_action(cel: Image, project: Project = Global.current_project) -> void:
|
||||
var offset_x := animate_panel.get_animated_value(commit_idx, Animate.OFFSET_X)
|
||||
var offset_y := animate_panel.get_animated_value(commit_idx, Animate.OFFSET_Y)
|
||||
var offset := Vector2(offset_x, offset_y)
|
||||
var selection_tex := ImageTexture.new()
|
||||
if selection_checkbox.pressed and project.has_selection:
|
||||
selection_tex.create_from_image(project.selection_map, 0)
|
||||
|
||||
var params := {"offset": offset, "wrap_around": wrap_around, "selection": selection_tex}
|
||||
if !confirmed:
|
||||
for param in params:
|
||||
preview.material.set_shader_param(param, params[param])
|
||||
else:
|
||||
var gen := ShaderImageEffect.new()
|
||||
gen.generate_image(cel, shader, params, project.size)
|
||||
yield(gen, "done")
|
||||
|
||||
|
||||
func _on_OffsetSliders_value_changed(_value: Vector2) -> void:
|
||||
update_preview()
|
||||
|
||||
|
||||
func _on_WrapCheckBox_toggled(button_pressed: bool) -> void:
|
||||
wrap_around = button_pressed
|
||||
update_preview()
|
71
src/UI/Dialogs/ImageEffects/OffsetImage.tscn
Normal file
71
src/UI/Dialogs/ImageEffects/OffsetImage.tscn
Normal file
|
@ -0,0 +1,71 @@
|
|||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/ImageEffectParent.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://src/UI/Nodes/ValueSliderV2.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/OffsetImage.gd" type="Script" id=3]
|
||||
|
||||
[node name="OffsetImage" instance=ExtResource( 1 )]
|
||||
window_title = "Offset Image"
|
||||
script = ExtResource( 3 )
|
||||
|
||||
[node name="VBoxContainer" parent="." index="3"]
|
||||
margin_bottom = 344.0
|
||||
|
||||
[node name="AspectRatioContainer" parent="VBoxContainer" index="1"]
|
||||
margin_bottom = 224.0
|
||||
|
||||
[node name="Preview" parent="VBoxContainer/AspectRatioContainer" index="0"]
|
||||
margin_left = 80.0
|
||||
margin_right = 280.0
|
||||
margin_bottom = 200.0
|
||||
|
||||
[node name="OffsetOptions" type="GridContainer" parent="VBoxContainer" index="2"]
|
||||
margin_top = 228.0
|
||||
margin_right = 360.0
|
||||
margin_bottom = 308.0
|
||||
columns = 2
|
||||
|
||||
[node name="OffsetLabel" type="Label" parent="VBoxContainer/OffsetOptions" index="0"]
|
||||
margin_top = 19.0
|
||||
margin_right = 178.0
|
||||
margin_bottom = 33.0
|
||||
size_flags_horizontal = 3
|
||||
text = "Offset:"
|
||||
|
||||
[node name="OffsetSliders" parent="VBoxContainer/OffsetOptions" index="1" instance=ExtResource( 2 )]
|
||||
margin_left = 182.0
|
||||
margin_right = 360.0
|
||||
size_flags_horizontal = 3
|
||||
min_value = Vector2( -64, -64 )
|
||||
max_value = Vector2( 64, 64 )
|
||||
allow_greater = true
|
||||
allow_lesser = true
|
||||
show_ratio = true
|
||||
suffix_x = "px"
|
||||
suffix_y = "px"
|
||||
|
||||
[node name="WrapLabel" type="Label" parent="VBoxContainer/OffsetOptions" index="2"]
|
||||
margin_top = 61.0
|
||||
margin_right = 178.0
|
||||
margin_bottom = 75.0
|
||||
size_flags_horizontal = 3
|
||||
text = "Wrap around:"
|
||||
|
||||
[node name="WrapCheckBox" type="CheckBox" parent="VBoxContainer/OffsetOptions" index="3"]
|
||||
margin_left = 182.0
|
||||
margin_top = 56.0
|
||||
margin_right = 360.0
|
||||
margin_bottom = 80.0
|
||||
mouse_default_cursor_shape = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "On"
|
||||
|
||||
[node name="OptionsContainer" parent="VBoxContainer" index="3"]
|
||||
margin_top = 312.0
|
||||
margin_bottom = 336.0
|
||||
|
||||
[node name="AnimateDialog" parent="." index="4"]
|
||||
margin_bottom = 344.0
|
||||
|
||||
[connection signal="value_changed" from="VBoxContainer/OffsetOptions/OffsetSliders" to="." method="_on_OffsetSliders_value_changed"]
|
||||
[connection signal="toggled" from="VBoxContainer/OffsetOptions/WrapCheckBox" to="." method="_on_WrapCheckBox_toggled"]
|
|
@ -273,6 +273,7 @@ func _setup_image_menu() -> void:
|
|||
# Order as in Global.ImageMenu enum
|
||||
var image_menu_items := [
|
||||
"Resize Canvas",
|
||||
"Offset Image",
|
||||
"Scale Image",
|
||||
"Crop Image",
|
||||
"Mirror Image",
|
||||
|
@ -650,6 +651,9 @@ func image_menu_id_pressed(id: int) -> void:
|
|||
Global.ImageMenu.SCALE_IMAGE:
|
||||
_popup_dialog(Global.control.get_node("Dialogs/ImageEffects/ScaleImage"))
|
||||
|
||||
Global.ImageMenu.OFFSET_IMAGE:
|
||||
_popup_dialog(Global.control.get_node("Dialogs/ImageEffects/OffsetImage"))
|
||||
|
||||
Global.ImageMenu.CENTRALIZE_IMAGE:
|
||||
DrawingAlgos.centralize()
|
||||
|
||||
|
|
Loading…
Reference in a new issue