diff --git a/Translations/Translations.pot b/Translations/Translations.pot index 93b6db2e6..1efddbe3c 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -395,6 +395,9 @@ msgstr "" msgid "Adjust Hue/Saturation/Value" msgstr "" +msgid "Gradient" +msgstr "" + msgid "Adjust HSV" msgstr "" @@ -425,6 +428,12 @@ msgstr "" msgid "Thickness:" msgstr "" +msgid "Colors:" +msgstr "" + +msgid "Steps:" +msgstr "" + msgid "View Splash Screen" msgstr "" diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index 55e558a98..3a560e079 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -499,3 +499,24 @@ func adjust_hsv(img: Image, id : int, delta : float) -> void: img.set_pixel(i,j,c) img.unlock() + + +func generate_gradient(image : Image, colors : Array, steps := 2) -> void: + if colors.size() < 2: + return + + var t = 1.0 / (steps - 1) + for i in range(1, steps - 1): + var color : Color + color = colors[-1].linear_interpolate(colors[0], t * i) + colors.insert(1, color) + + image.lock() + var size := image.get_size() + var gradient_height = size.y / steps + for i in steps: + for xx in size.x: + var start = i * gradient_height + var end = (i + 1) * gradient_height + for yy in range(start, end): + image.set_pixel(xx, yy, colors[i]) diff --git a/src/Main.tscn b/src/Main.tscn index ca2f8ff0d..88c72c458 100644 --- a/src/Main.tscn +++ b/src/Main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=20 format=2] +[gd_scene load_steps=21 format=2] [ext_resource path="res://assets/themes/dark/theme.tres" type="Theme" id=1] [ext_resource path="res://src/Main.gd" type="Script" id=2] @@ -8,6 +8,7 @@ [ext_resource path="res://src/UI/BrushesPopup.tscn" type="PackedScene" id=6] [ext_resource path="res://src/UI/Dialogs/ResizeCanvas.tscn" type="PackedScene" id=7] [ext_resource path="res://src/UI/Dialogs/SaveSpriteHTML5.tscn" type="PackedScene" id=8] +[ext_resource path="res://src/UI/Dialogs/GradientDialog.tscn" type="PackedScene" id=9] [ext_resource path="res://src/UI/Dialogs/SaveSprite.tscn" type="PackedScene" id=11] [ext_resource path="res://src/UI/Dialogs/OpenSprite.tscn" type="PackedScene" id=12] [ext_resource path="res://src/UI/Dialogs/SplashDialog.tscn" type="PackedScene" id=27] @@ -128,6 +129,8 @@ popup_exclusive = true dialog_text = "Autosaved backup for %s was found. Do you want to reload it?" +[node name="GradientDialog" parent="Dialogs" instance=ExtResource( 9 )] + [node name="LeftCursor" type="Sprite" parent="."] visible = false @@ -159,3 +162,4 @@ visible = false [connection signal="popup_hide" from="Dialogs/ErrorDialog" to="." method="_can_draw_true"] [connection signal="popup_hide" from="Dialogs/HSVDialog" to="." method="_can_draw_true"] [connection signal="popup_hide" from="Dialogs/BackupConfirmation" to="." method="_can_draw_true"] +[connection signal="popup_hide" from="Dialogs/GradientDialog" to="." method="_can_draw_true"] diff --git a/src/UI/Dialogs/GradientDialog.gd b/src/UI/Dialogs/GradientDialog.gd new file mode 100644 index 000000000..1e2b35722 --- /dev/null +++ b/src/UI/Dialogs/GradientDialog.gd @@ -0,0 +1,49 @@ +extends ConfirmationDialog + + +var current_cel : Image +var preview_image : Image +var preview_texture : ImageTexture + +onready var preview : TextureRect = $VBoxContainer/Preview +onready var color1 : ColorPickerButton = $VBoxContainer/ColorsContainer/ColorPickerButton +onready var color2 : ColorPickerButton = $VBoxContainer/ColorsContainer/ColorPickerButton2 +onready var steps : SpinBox = $VBoxContainer/StepsContainer/StepSpinBox + + +func _ready() -> void: + current_cel = Image.new() + preview_image = Image.new() + preview_texture = ImageTexture.new() + preview_texture.flags = 0 + + +func _on_GradientDialog_about_to_show() -> void: + current_cel = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image + update_preview() + + +func update_preview() -> void: + preview_image.copy_from(current_cel) + DrawingAlgos.generate_gradient(preview_image, [color1.color, color2.color], steps.value) + preview_texture.create_from_image(preview_image, 0) + preview.texture = preview_texture + + +func _on_ColorPickerButton_color_changed(_color : Color) -> void: + update_preview() + + +func _on_ColorPickerButton2_color_changed(_color : Color) -> void: + update_preview() + + +func _on_StepSpinBox_value_changed(_value : int) -> void: + update_preview() + + +func _on_GradientDialog_confirmed() -> void: + Global.canvas.handle_undo("Draw") + DrawingAlgos.generate_gradient(current_cel, [color1.color, color2.color], steps.value) + Global.canvas.update_texture(Global.current_project.current_layer) + Global.canvas.handle_redo("Draw") diff --git a/src/UI/Dialogs/GradientDialog.tscn b/src/UI/Dialogs/GradientDialog.tscn new file mode 100644 index 000000000..ac4a60508 --- /dev/null +++ b/src/UI/Dialogs/GradientDialog.tscn @@ -0,0 +1,83 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://src/UI/Dialogs/GradientDialog.gd" type="Script" id=1] + +[node name="GradientDialog" type="ConfirmationDialog"] +margin_right = 200.0 +margin_bottom = 196.0 +resizable = true +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 8.0 +margin_top = 8.0 +margin_right = -8.0 +margin_bottom = -36.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Preview" type="TextureRect" parent="VBoxContainer"] +margin_right = 184.0 +margin_bottom = 100.0 +rect_min_size = Vector2( 0, 100 ) +expand = true +stretch_mode = 6 + +[node name="ColorsContainer" type="HBoxContainer" parent="VBoxContainer"] +margin_top = 104.0 +margin_right = 184.0 +margin_bottom = 124.0 + +[node name="Label" type="Label" parent="VBoxContainer/ColorsContainer"] +margin_top = 3.0 +margin_right = 44.0 +margin_bottom = 17.0 +text = "Colors:" + +[node name="ColorPickerButton" type="ColorPickerButton" parent="VBoxContainer/ColorsContainer"] +margin_left = 48.0 +margin_right = 68.0 +margin_bottom = 20.0 +rect_min_size = Vector2( 20, 0 ) +mouse_default_cursor_shape = 2 + +[node name="ColorPickerButton2" type="ColorPickerButton" parent="VBoxContainer/ColorsContainer"] +margin_left = 72.0 +margin_right = 92.0 +margin_bottom = 20.0 +rect_min_size = Vector2( 20, 0 ) +mouse_default_cursor_shape = 2 +color = Color( 1, 1, 1, 1 ) + +[node name="StepsContainer" type="HBoxContainer" parent="VBoxContainer"] +margin_top = 128.0 +margin_right = 184.0 +margin_bottom = 152.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Label" type="Label" parent="VBoxContainer/StepsContainer"] +margin_top = 5.0 +margin_right = 39.0 +margin_bottom = 19.0 +text = "Steps:" + +[node name="StepSpinBox" type="SpinBox" parent="VBoxContainer/StepsContainer"] +margin_left = 43.0 +margin_right = 117.0 +margin_bottom = 24.0 +mouse_default_cursor_shape = 2 +min_value = 2.0 +value = 2.0 +[connection signal="about_to_show" from="." to="." method="_on_GradientDialog_about_to_show"] +[connection signal="confirmed" from="." to="." method="_on_GradientDialog_confirmed"] +[connection signal="color_changed" from="VBoxContainer/ColorsContainer/ColorPickerButton" to="." method="_on_ColorPickerButton_color_changed"] +[connection signal="color_changed" from="VBoxContainer/ColorsContainer/ColorPickerButton2" to="." method="_on_ColorPickerButton2_color_changed"] +[connection signal="value_changed" from="VBoxContainer/StepsContainer/StepSpinBox" to="." method="_on_StepSpinBox_value_changed"] diff --git a/src/UI/Dialogs/HSVDialog.tscn b/src/UI/Dialogs/HSVDialog.tscn index f32419d72..da9fc3fc1 100644 --- a/src/UI/Dialogs/HSVDialog.tscn +++ b/src/UI/Dialogs/HSVDialog.tscn @@ -2,8 +2,6 @@ [ext_resource path="res://src/UI/Dialogs/HSVDialog.gd" type="Script" id=1] - - [node name="HSVDialog" type="WindowDialog"] margin_left = 1.0 margin_top = -1.0 diff --git a/src/UI/TopMenuContainer.gd b/src/UI/TopMenuContainer.gd index a050e9b22..84abf3d49 100644 --- a/src/UI/TopMenuContainer.gd +++ b/src/UI/TopMenuContainer.gd @@ -92,7 +92,8 @@ func setup_image_menu() -> void: "Invert Colors" : 0, "Desaturation" : 0, "Outline" : 0, - "Adjust Hue/Saturation/Value" : 0 + "Adjust Hue/Saturation/Value" : 0, + "Gradient" : 0 } var image_menu : PopupMenu = Global.image_menu.get_popup() @@ -321,6 +322,9 @@ func image_menu_id_pressed(id : int) -> void: 9: # HSV show_hsv_configuration_popup() + 10: # Gradient + Global.control.get_node("Dialogs/GradientDialog").popup_centered() + Global.dialog_open(true) func show_scale_image_popup() -> void: