diff --git a/Translations/Translations.pot b/Translations/Translations.pot index 035da9613..9ae1c0d43 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -407,6 +407,18 @@ msgstr "" msgid "Invert Colors" msgstr "" +msgid "Modify Red Channel" +msgstr "" + +msgid "Modify Green Channel" +msgstr "" + +msgid "Modify Blue Channel" +msgstr "" + +msgid "Modify Alpha Channel" +msgstr "" + msgid "Desaturation" msgstr "" @@ -560,6 +572,9 @@ msgstr "" msgid "Korean" msgstr "" +msgid "Hungarian" +msgstr "" + msgid "Development Team" msgstr "" diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index 97e1dc63b..828c9e882 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -294,15 +294,20 @@ func resize_canvas(width : int, height : int, offset_x : int, offset_y : int) -> Global.current_project.undo_redo.commit_action() -func invert_image_colors(image : Image) -> void: - Global.canvas.handle_undo("Draw") - for xx in image.get_size().x: - for yy in image.get_size().y: - var px_color = image.get_pixel(xx, yy).inverted() - if px_color.a == 0: - continue - image.set_pixel(xx, yy, px_color) - Global.canvas.handle_redo("Draw") +func invert_image_colors(image : Image, pixels : Array, red := true, green := true, blue := true, alpha := false) -> void: + image.lock() + for i in pixels: + var px_color := image.get_pixelv(i) + # Manually invert each color channel + if red: + px_color.r = 1.0 - px_color.r + if green: + px_color.g = 1.0 - px_color.g + if blue: + px_color.b = 1.0 - px_color.b + if alpha: + px_color.a = 1.0 - px_color.a + image.set_pixelv(i, px_color) func desaturate_image(image : Image) -> void: diff --git a/src/UI/Dialogs/ExportDialog.tscn b/src/UI/Dialogs/ExportDialog.tscn index 400c56153..05789363b 100644 --- a/src/UI/Dialogs/ExportDialog.tscn +++ b/src/UI/Dialogs/ExportDialog.tscn @@ -244,7 +244,7 @@ margin_right = 235.0 margin_bottom = 24.0 mouse_default_cursor_shape = 2 size_flags_horizontal = 3 -min_value = 10.0 +min_value = 50.0 max_value = 1000.0 step = 100.0 value = 100.0 diff --git a/src/UI/Dialogs/ImageEffects/ImageEffects.tscn b/src/UI/Dialogs/ImageEffects/ImageEffects.tscn index 004764d39..c4a0d8380 100644 --- a/src/UI/Dialogs/ImageEffects/ImageEffects.tscn +++ b/src/UI/Dialogs/ImageEffects/ImageEffects.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=9 format=2] +[gd_scene load_steps=10 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] [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] @@ -15,8 +16,6 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="FlipImageDialog" parent="." instance=ExtResource( 1 )] - [node name="ScaleImage" parent="." instance=ExtResource( 14 )] margin_bottom = 127.0 @@ -26,6 +25,12 @@ margin_bottom = 392.0 [node name="RotateImage" parent="." instance=ExtResource( 9 )] +[node name="FlipImageDialog" parent="." instance=ExtResource( 1 )] +margin_right = 283.0 +margin_bottom = 300.0 + +[node name="InvertColorsDialog" parent="." instance=ExtResource( 2 )] + [node name="OutlineDialog" parent="." instance=ExtResource( 13 )] margin_right = 217.0 margin_bottom = 106.0 diff --git a/src/UI/Dialogs/ImageEffects/InvertColorsDialog.gd b/src/UI/Dialogs/ImageEffects/InvertColorsDialog.gd new file mode 100644 index 000000000..e37dd927f --- /dev/null +++ b/src/UI/Dialogs/ImageEffects/InvertColorsDialog.gd @@ -0,0 +1,112 @@ +extends ConfirmationDialog + + +enum {CEL, FRAME, ALL_FRAMES, ALL_PROJECTS} + +var affect : int = CEL +var pixels := [] +var current_cel : Image +var preview_image : Image +var preview_texture : ImageTexture + +var red := true +var green := true +var blue := true +var alpha := false + +onready var preview : TextureRect = $VBoxContainer/Preview +onready var selection_checkbox = $VBoxContainer/OptionsContainer/SelectionCheckBox + + +func _ready() -> void: + current_cel = Image.new() + preview_image = Image.new() + preview_texture = ImageTexture.new() + + +func _on_FlipImageDialog_about_to_show() -> void: + current_cel = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image + _on_SelectionCheckBox_toggled(selection_checkbox.pressed) + + +func _on_FlipImageDialog_confirmed() -> void: + if affect == CEL: + Global.canvas.handle_undo("Draw") + DrawingAlgos.invert_image_colors(current_cel, pixels, red, green, blue, alpha) + Global.canvas.handle_redo("Draw") + elif affect == FRAME: + Global.canvas.handle_undo("Draw", Global.current_project, -1) + for cel in Global.current_project.frames[Global.current_project.current_frame].cels: + DrawingAlgos.invert_image_colors(cel.image, pixels, red, green, blue, alpha) + Global.canvas.handle_redo("Draw", Global.current_project, -1) + + elif affect == ALL_FRAMES: + Global.canvas.handle_undo("Draw", Global.current_project, -1, -1) + for frame in Global.current_project.frames: + for cel in frame.cels: + DrawingAlgos.invert_image_colors(cel.image, pixels, red, green, blue, alpha) + Global.canvas.handle_redo("Draw", Global.current_project, -1, -1) + + elif affect == ALL_PROJECTS: + for project in Global.projects: + var _pixels := [] + if selection_checkbox.pressed: + _pixels = project.selected_pixels.duplicate() + else: + for x in project.size.x: + for y in project.size.y: + _pixels.append(Vector2(x, y)) + + Global.canvas.handle_undo("Draw", project, -1, -1) + for frame in project.frames: + for cel in frame.cels: + DrawingAlgos.invert_image_colors(cel.image, _pixels, red, green, blue, alpha) + Global.canvas.handle_redo("Draw", project, -1, -1) + + +func _on_RButton_toggled(button_pressed : bool) -> void: + red = button_pressed + update_preview() + + +func _on_GButton_toggled(button_pressed : bool) -> void: + green = button_pressed + update_preview() + + +func _on_BButton_toggled(button_pressed : bool) -> void: + blue = button_pressed + update_preview() + + +func _on_AButton_toggled(button_pressed : bool) -> void: + alpha = button_pressed + update_preview() + + +func _on_SelectionCheckBox_toggled(button_pressed : bool) -> void: + pixels.clear() + if button_pressed: + pixels = Global.current_project.selected_pixels.duplicate() + else: + for x in Global.current_project.size.x: + for y in Global.current_project.size.y: + pixels.append(Vector2(x, y)) + + update_preview() + + +func _on_AffectOptionButton_item_selected(index : int) -> void: + affect = index + + +func update_preview() -> void: + preview_image.copy_from(current_cel) + DrawingAlgos.invert_image_colors(preview_image, pixels, red, green, blue, alpha) + preview_image.unlock() + preview_texture.create_from_image(preview_image, 0) + preview.texture = preview_texture + + +func _on_FlipImageDialog_popup_hide() -> void: + Global.dialog_open(false) diff --git a/src/UI/Dialogs/ImageEffects/InvertColorsDialog.tscn b/src/UI/Dialogs/ImageEffects/InvertColorsDialog.tscn new file mode 100644 index 000000000..2aa30b7af --- /dev/null +++ b/src/UI/Dialogs/ImageEffects/InvertColorsDialog.tscn @@ -0,0 +1,99 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://src/UI/Dialogs/ImageEffects/InvertColorsDialog.gd" type="Script" id=1] + +[node name="InvertColorsDialog" type="ConfirmationDialog"] +margin_right = 200.0 +margin_bottom = 70.0 +script = ExtResource( 1 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +margin_left = 8.0 +margin_top = 8.0 +margin_right = 271.0 +margin_bottom = 260.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Preview" type="TextureRect" parent="VBoxContainer"] +margin_right = 263.0 +margin_bottom = 200.0 +rect_min_size = Vector2( 200, 200 ) +expand = true +stretch_mode = 6 + +[node name="RGBAContainer" type="HBoxContainer" parent="VBoxContainer"] +margin_top = 204.0 +margin_right = 263.0 +margin_bottom = 224.0 +alignment = 1 + +[node name="RButton" type="Button" parent="VBoxContainer/RGBAContainer"] +margin_left = 83.0 +margin_right = 103.0 +margin_bottom = 20.0 +hint_tooltip = "Modify Red Channel" +mouse_default_cursor_shape = 2 +toggle_mode = true +pressed = true +text = "R" + +[node name="GButton" type="Button" parent="VBoxContainer/RGBAContainer"] +margin_left = 107.0 +margin_right = 129.0 +margin_bottom = 20.0 +hint_tooltip = "Modify Green Channel" +mouse_default_cursor_shape = 2 +toggle_mode = true +pressed = true +text = "G" + +[node name="BButton" type="Button" parent="VBoxContainer/RGBAContainer"] +margin_left = 133.0 +margin_right = 154.0 +margin_bottom = 20.0 +hint_tooltip = "Modify Blue Channel" +mouse_default_cursor_shape = 2 +toggle_mode = true +pressed = true +text = "B" + +[node name="AButton" type="Button" parent="VBoxContainer/RGBAContainer"] +margin_left = 158.0 +margin_right = 179.0 +margin_bottom = 20.0 +hint_tooltip = "Modify Alpha Channel" +mouse_default_cursor_shape = 2 +toggle_mode = true +text = "A" + +[node name="OptionsContainer" type="HBoxContainer" parent="VBoxContainer"] +margin_top = 228.0 +margin_right = 263.0 +margin_bottom = 252.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="about_to_show" from="." to="." method="_on_FlipImageDialog_about_to_show"] +[connection signal="confirmed" from="." to="." method="_on_FlipImageDialog_confirmed"] +[connection signal="popup_hide" from="." to="." method="_on_FlipImageDialog_popup_hide"] +[connection signal="toggled" from="VBoxContainer/RGBAContainer/RButton" to="." method="_on_RButton_toggled"] +[connection signal="toggled" from="VBoxContainer/RGBAContainer/GButton" to="." method="_on_GButton_toggled"] +[connection signal="toggled" from="VBoxContainer/RGBAContainer/BButton" to="." method="_on_BButton_toggled"] +[connection signal="toggled" from="VBoxContainer/RGBAContainer/AButton" to="." method="_on_AButton_toggled"] +[connection signal="toggled" from="VBoxContainer/OptionsContainer/SelectionCheckBox" to="." method="_on_SelectionCheckBox_toggled"] +[connection signal="item_selected" from="VBoxContainer/OptionsContainer/AffectOptionButton" to="." method="_on_AffectOptionButton_item_selected"] diff --git a/src/UI/TopMenuContainer.gd b/src/UI/TopMenuContainer.gd index 653d75d83..1ec9e1d28 100644 --- a/src/UI/TopMenuContainer.gd +++ b/src/UI/TopMenuContainer.gd @@ -318,7 +318,8 @@ func image_menu_id_pressed(id : int) -> void: show_rotate_image_popup() 5: # Invert Colors - DrawingAlgos.invert_image_colors(image) + Global.control.get_node("Dialogs/ImageEffects/InvertColorsDialog").popup_centered() + Global.dialog_open(true) 6: # Desaturation DrawingAlgos.desaturate_image(image)