diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index acd3b97c0..995189958 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -454,9 +454,9 @@ func generate_outline(image : Image, outline_color : Color, thickness : int, dia Global.canvas.handle_redo("Draw") -func adjust_hsv(img: Image, delta_h : float, delta_s : float, delta_v : float) -> void: +func adjust_hsv(img: Image, delta_h : float, delta_s : float, delta_v : float, pixels : Array) -> void: img.lock() - for i in Global.current_project.selected_pixels: + for i in pixels: var c : Color = img.get_pixelv(i) # Hue var hue = range_lerp(c.h,0,1,-180,180) diff --git a/src/Canvas.gd b/src/Canvas.gd index 593ba31f7..899f83e7f 100644 --- a/src/Canvas.gd +++ b/src/Canvas.gd @@ -129,50 +129,78 @@ func new_empty_frame(first_time := false, single_layer := false, size := Global. return frame -func handle_undo(action : String) -> void: +func handle_undo(action : String, project : Project = Global.current_project, layer_index := -2, frame_index := -2) -> void: if !can_undo: return + + if layer_index <= -2: + layer_index = project.current_layer + if frame_index <= -2: + frame_index = project.current_frame + + var cels := [] var frames := [] - var frame_index := -1 - var layer_index := -1 - if Global.animation_timer.is_stopped(): # if we're not animating, store only the current canvas - frames.append(Global.current_project.frames[Global.current_project.current_frame]) - frame_index = Global.current_project.current_frame - layer_index = Global.current_project.current_layer - else: # If we're animating, store all frames - frames = Global.current_project.frames - Global.current_project.undos += 1 - Global.current_project.undo_redo.create_action(action) + var layers := [] + if frame_index == -1: + frames = project.frames + else: + frames.append(project.frames[frame_index]) + + if layer_index == -1: + layers = project.layers + else: + layers.append(project.layers[layer_index]) + for f in frames: - # I'm not sure why I have to unlock it, but... - # ...if I don't, it doesn't work properly - f.cels[Global.current_project.current_layer].image.unlock() - var data = f.cels[Global.current_project.current_layer].image.data - f.cels[Global.current_project.current_layer].image.lock() - Global.current_project.undo_redo.add_undo_property(f.cels[Global.current_project.current_layer].image, "data", data) - Global.current_project.undo_redo.add_undo_method(Global, "undo", frame_index, layer_index) + for l in layers: + var index = project.layers.find(l) + cels.append(f.cels[index]) + + project.undos += 1 + project.undo_redo.create_action(action) + for cel in cels: + # If we don't unlock the image, it doesn't work properly + cel.image.unlock() + var data = cel.image.data + cel.image.lock() + project.undo_redo.add_undo_property(cel.image, "data", data) + project.undo_redo.add_undo_method(Global, "undo", frame_index, layer_index) can_undo = false -func handle_redo(_action : String) -> void: +func handle_redo(_action : String, project : Project = Global.current_project, layer_index := -2, frame_index := -2) -> void: can_undo = true - - if Global.current_project.undos < Global.current_project.undo_redo.get_version(): + if project.undos < project.undo_redo.get_version(): return + + if layer_index <= -2: + layer_index = project.current_layer + if frame_index <= -2: + frame_index = project.current_frame + + var cels := [] var frames := [] - var frame_index := -1 - var layer_index := -1 - if Global.animation_timer.is_stopped(): - frames.append(Global.current_project.frames[Global.current_project.current_frame]) - frame_index = Global.current_project.current_frame - layer_index = Global.current_project.current_layer + var layers := [] + if frame_index == -1: + frames = project.frames else: - frames = Global.current_project.frames + frames.append(project.frames[frame_index]) + + if layer_index == -1: + layers = project.layers + else: + layers.append(project.layers[layer_index]) + for f in frames: - Global.current_project.undo_redo.add_do_property(f.cels[Global.current_project.current_layer].image, "data", f.cels[Global.current_project.current_layer].image.data) - Global.current_project.undo_redo.add_do_method(Global, "redo", frame_index, layer_index) - Global.current_project.undo_redo.commit_action() + for l in layers: + var index = project.layers.find(l) + cels.append(f.cels[index]) + + for cel in cels: + project.undo_redo.add_do_property(cel.image, "data", cel.image.data) + project.undo_redo.add_do_method(Global, "redo", frame_index, layer_index) + project.undo_redo.commit_action() func update_texture(layer_index : int, frame_index := -1) -> void: diff --git a/src/UI/Dialogs/HSVDialog.gd b/src/UI/Dialogs/HSVDialog.gd index a67345859..768196859 100644 --- a/src/UI/Dialogs/HSVDialog.gd +++ b/src/UI/Dialogs/HSVDialog.gd @@ -1,5 +1,10 @@ extends WindowDialog + +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 @@ -13,6 +18,7 @@ onready var sat_spinbox = $MarginContainer/VBoxContainer/HBoxContainer/TextBoxes onready var val_spinbox = $MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Value onready var preview = $MarginContainer/VBoxContainer/TextureRect +onready var selection_checkbox : CheckBox = $MarginContainer/VBoxContainer/AffectHBoxContainer/SelectionCheckBox func _ready() -> void: @@ -25,6 +31,7 @@ func _ready() -> void: func _on_HSVDialog_about_to_show() -> void: current_cel = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image preview_image.copy_from(current_cel) + _on_SelectionCheckBox_toggled(selection_checkbox.pressed) update_preview() @@ -34,10 +41,15 @@ func _on_Cancel_pressed() -> void: func _on_Apply_pressed() -> void: - Global.canvas.handle_undo("Draw") - DrawingAlgos.adjust_hsv(current_cel, hue_slider.value, sat_slider.value, val_slider.value) - Global.canvas.update_texture(Global.current_project.current_layer) - Global.canvas.handle_redo("Draw") + if affect == CEL: + Global.canvas.handle_undo("Draw") + DrawingAlgos.adjust_hsv(current_cel, hue_slider.value, sat_slider.value, val_slider.value, pixels) + 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.adjust_hsv(cel.image, hue_slider.value, sat_slider.value, val_slider.value, pixels) + Global.canvas.handle_redo("Draw", Global.current_project, -1) reset() visible = false @@ -55,7 +67,7 @@ func reset() -> void: func update_preview() -> void: preview_image.copy_from(current_cel) - DrawingAlgos.adjust_hsv(preview_image, hue_slider.value, sat_slider.value, val_slider.value) + DrawingAlgos.adjust_hsv(preview_image, hue_slider.value, sat_slider.value, val_slider.value, pixels) preview_texture.create_from_image(preview_image, 0) preview.texture = preview_texture @@ -94,3 +106,19 @@ func _on_Value_value_changed(value : float) -> void: val_spinbox.value = value val_slider.value = value 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 diff --git a/src/UI/Dialogs/HSVDialog.tscn b/src/UI/Dialogs/HSVDialog.tscn index da9fc3fc1..fbbb3eb4e 100644 --- a/src/UI/Dialogs/HSVDialog.tscn +++ b/src/UI/Dialogs/HSVDialog.tscn @@ -33,15 +33,15 @@ __meta__ = { [node name="TextureRect" type="TextureRect" parent="MarginContainer/VBoxContainer"] margin_right = 453.0 -margin_bottom = 197.0 +margin_bottom = 169.0 size_flags_vertical = 3 expand = true stretch_mode = 6 [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] -margin_top = 201.0 +margin_top = 173.0 margin_right = 453.0 -margin_bottom = 285.0 +margin_bottom = 257.0 custom_constants/separation = 10 __meta__ = { "_edit_use_anchors_": false @@ -132,6 +132,27 @@ margin_bottom = 84.0 mouse_default_cursor_shape = 1 min_value = -100.0 +[node name="AffectHBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] +margin_top = 261.0 +margin_right = 453.0 +margin_bottom = 285.0 + +[node name="SelectionCheckBox" type="CheckBox" parent="MarginContainer/VBoxContainer/AffectHBoxContainer"] +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="MarginContainer/VBoxContainer/AffectHBoxContainer"] +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, true, 2, null, "All projects", null, true, 3, null ] +selected = 0 + [node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] margin_top = 289.0 margin_right = 453.0 @@ -162,5 +183,7 @@ text = "Cancel" [connection signal="value_changed" from="MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Hue" to="." method="_on_Hue_value_changed"] [connection signal="value_changed" from="MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Saturation" to="." method="_on_Saturation_value_changed"] [connection signal="value_changed" from="MarginContainer/VBoxContainer/HBoxContainer/TextBoxes/Value" to="." method="_on_Value_value_changed"] +[connection signal="toggled" from="MarginContainer/VBoxContainer/AffectHBoxContainer/SelectionCheckBox" to="." method="_on_SelectionCheckBox_toggled"] +[connection signal="item_selected" from="MarginContainer/VBoxContainer/AffectHBoxContainer/AffectOptionButton" to="." method="_on_AffectOptionButton_item_selected"] [connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/Apply" to="." method="_on_Apply_pressed"] [connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/Cancel" to="." method="_on_Cancel_pressed"]