diff --git a/CHANGELOG.md b/CHANGELOG.md index 705842c42..6dc2561a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,10 @@ Darshan Phaldesai (luiq54), Igor Santarek (jegor377), rob-a-bolton, Kinwailo - Added "Copy", "Paste" and "Delete" options in the Edit menu. ([#281](https://github.com/Orama-Interactive/Pixelorama/pull/281)) - Selection region and size are now being shown when making a selection on the top, next to the position label. ([#281](https://github.com/Orama-Interactive/Pixelorama/pull/281)) - Added color overwrite option for the Pencil tool. ([#282](https://github.com/Orama-Interactive/Pixelorama/pull/282)) -- Added color previews next to the themes in Preferences +- Flip, desaturation and invert colors now have dialogs with previews and extra options. You can now choose individual color channels to invert, including alpha. +- Added extra options for most image effects. The user can now choose if the effects will affect the selection, the current cel, current frame, all frames or even all projects! +- A play button has been added for playing the animation exclusively on the small canvas preview area. A zoom slider for the preview area has been added, too. +- Added color previews next to the themes in Preferences. ### Changed - Drawing is no longer limited by the canvas boundaries. This means that, if you have a brush largen than 1px, you can draw on the edges of the canvas. All pixels that are being drawn outside of the canvas will still have no effect. diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index f81a02500..800b3ebdc 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -146,6 +146,8 @@ var merge_down_layer_button : BaseButton var layer_opacity_slider : HSlider var layer_opacity_spinbox : SpinBox +var preview_zoom_slider : VSlider + var add_palette_button : BaseButton var edit_palette_button : BaseButton var palette_option_button : OptionButton @@ -154,6 +156,7 @@ var edit_palette_popup : WindowDialog var new_palette_dialog : ConfirmationDialog var new_palette_name_line_edit : LineEdit var palette_import_file_dialog : FileDialog + var error_dialog : AcceptDialog var quit_dialog : ConfirmationDialog var quit_and_save_dialog : ConfirmationDialog @@ -238,6 +241,8 @@ func _ready() -> void: layer_opacity_slider = find_node_by_name(animation_timeline, "OpacitySlider") layer_opacity_spinbox = find_node_by_name(animation_timeline, "OpacitySpinBox") + preview_zoom_slider = find_node_by_name(root, "PreviewZoomSlider") + add_palette_button = find_node_by_name(root, "AddPalette") edit_palette_button = find_node_by_name(root, "EditPalette") palette_option_button = find_node_by_name(root, "PaletteOptionButton") diff --git a/src/CameraMovement.gd b/src/CameraMovement.gd index 318f50fbc..0446f62b9 100644 --- a/src/CameraMovement.gd +++ b/src/CameraMovement.gd @@ -141,6 +141,8 @@ func zoom_camera(dir : int) -> void: if name == "Camera2D": Global.zoom_level_label.text = str(round(100 / new_zoom.x)) + " %" + elif name == "CameraPreview": + Global.preview_zoom_slider.value = -new_zoom.x else: var prev_zoom := zoom @@ -154,7 +156,8 @@ func zoom_camera(dir : int) -> void: offset = offset + (-0.5 * viewport_size + mouse_pos) * (prev_zoom - zoom) if name == "Camera2D": Global.zoom_level_label.text = str(round(100 / Global.camera.zoom.x)) + " %" - + elif name == "CameraPreview": + Global.preview_zoom_slider.value = -zoom.x func _on_tween_step(_object: Object, _key: NodePath, _elapsed: float, _value: Object) -> void: @@ -186,15 +189,17 @@ func fit_to_frame(size : Vector2) -> void: Global.zoom_level_label.text = str(round(100 / Global.camera.zoom.x)) + " %" Global.horizontal_ruler.update() Global.vertical_ruler.update() + elif name == "CameraPreview": + Global.preview_zoom_slider.value = -zoom.x func save_values_to_project() -> void: if name == "Camera2D": Global.current_project.cameras_zoom[0] = zoom Global.current_project.cameras_offset[0] = offset - if name == "Camera2D2": + elif name == "Camera2D2": Global.current_project.cameras_zoom[1] = zoom Global.current_project.cameras_offset[1] = offset - if name == "CameraPreview": + elif name == "CameraPreview": Global.current_project.cameras_zoom[2] = zoom Global.current_project.cameras_offset[2] = offset diff --git a/src/Canvas.gd b/src/Canvas.gd index 493af0930..c92fe3032 100644 --- a/src/Canvas.gd +++ b/src/Canvas.gd @@ -100,6 +100,10 @@ func camera_zoom() -> void: else: camera.zoom_max = Vector2.ONE + if camera == Global.camera_preview: + Global.preview_zoom_slider.max_value = -camera.zoom_min.x + Global.preview_zoom_slider.min_value = -camera.zoom_max.x + camera.fit_to_frame(Global.current_project.size) camera.save_values_to_project() diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index c3696ad95..4c1254ff9 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -163,6 +163,8 @@ func change_project() -> void: Global.transparent_checker._ready() Global.horizontal_ruler.update() Global.vertical_ruler.update() + Global.preview_zoom_slider.value = -Global.camera_preview.zoom.x + Global.window_title = "%s - Pixelorama %s" % [name, Global.current_version] if has_changed: Global.window_title = Global.window_title + "(*)" diff --git a/src/UI/CanvasPreview.gd b/src/UI/CanvasPreview.gd index 70cc2a64e..193037346 100644 --- a/src/UI/CanvasPreview.gd +++ b/src/UI/CanvasPreview.gd @@ -1,9 +1,15 @@ extends Node2D +var frame : int = 0 +onready var animation_timer : Timer = $AnimationTimer + func _draw() -> void: var current_project : Project = Global.current_project - var frame : int = current_project.current_frame + $AnimationTimer.wait_time = Global.animation_timer.wait_time + + if animation_timer.is_stopped(): + frame = current_project.current_frame var current_cels : Array = current_project.frames[frame].cels # Draw current frame layers @@ -11,3 +17,13 @@ func _draw() -> void: var modulate_color := Color(1, 1, 1, current_cels[i].opacity) if i < current_project.layers.size() and current_project.layers[i].visible: draw_texture(current_cels[i].image_texture, Vector2.ZERO, modulate_color) + + +func _on_AnimationTimer_timeout() -> void: + var current_project : Project = Global.current_project + + if frame < current_project.frames.size() - 1: + frame += 1 + else: + frame = 0 + update() diff --git a/src/UI/CanvasPreview.tscn b/src/UI/CanvasPreview.tscn index 700d8ef5e..cc9cf7923 100644 --- a/src/UI/CanvasPreview.tscn +++ b/src/UI/CanvasPreview.tscn @@ -4,3 +4,6 @@ [node name="CanvasPreview" type="Node2D"] script = ExtResource( 1 ) + +[node name="AnimationTimer" type="Timer" parent="."] +[connection signal="timeout" from="AnimationTimer" to="." method="_on_AnimationTimer_timeout"] diff --git a/src/UI/CanvasPreviewContainer.gd b/src/UI/CanvasPreviewContainer.gd new file mode 100644 index 000000000..779c87ea3 --- /dev/null +++ b/src/UI/CanvasPreviewContainer.gd @@ -0,0 +1,20 @@ +extends HBoxContainer + + +onready var canvas_preview = $PreviewContainer/PreviewViewportContainer/Viewport/CanvasPreview +onready var camera : Camera2D = $PreviewContainer/PreviewViewportContainer/Viewport/CameraPreview +onready var play_button : Button = $SettingsContainer/VBoxContainer/PlayButton + + +func _on_PreviewZoomSlider_value_changed(value : float) -> void: + camera.zoom = -Vector2(value, value) + camera.save_values_to_project() + + +func _on_PlayButton_toggled(button_pressed : bool) -> void: + if button_pressed: + canvas_preview.animation_timer.start() + Global.change_button_texturerect(play_button.get_child(0), "pause.png") + else: + canvas_preview.animation_timer.stop() + Global.change_button_texturerect(play_button.get_child(0), "play.png") diff --git a/src/UI/CanvasPreviewContainer.tscn b/src/UI/CanvasPreviewContainer.tscn new file mode 100644 index 000000000..ebb3db1a3 --- /dev/null +++ b/src/UI/CanvasPreviewContainer.tscn @@ -0,0 +1,102 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://src/UI/CanvasPreview.tscn" type="PackedScene" id=1] +[ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2] +[ext_resource path="res://src/UI/CanvasPreviewContainer.gd" type="Script" id=3] +[ext_resource path="res://src/CameraMovement.gd" type="Script" id=4] +[ext_resource path="res://src/Shaders/TransparentChecker.shader" type="Shader" id=5] +[ext_resource path="res://assets/graphics/dark_themes/timeline/play.png" type="Texture" id=7] + +[sub_resource type="ShaderMaterial" id=1] +shader = ExtResource( 5 ) +shader_param/size = 10.0 +shader_param/color1 = Color( 0.7, 0.7, 0.7, 1 ) +shader_param/color2 = Color( 1, 1, 1, 1 ) + +[node name="CanvasPreviewContainer" type="HBoxContainer"] +margin_right = 332.0 +margin_bottom = 164.0 +size_flags_horizontal = 4 +script = ExtResource( 3 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="SettingsContainer" type="PanelContainer" parent="."] +margin_right = 34.0 +margin_bottom = 164.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="SettingsContainer"] +margin_left = 7.0 +margin_top = 7.0 +margin_right = 27.0 +margin_bottom = 157.0 + +[node name="PreviewZoomSlider" type="VSlider" parent="SettingsContainer/VBoxContainer"] +margin_right = 16.0 +margin_bottom = 126.0 +mouse_default_cursor_shape = 2 +size_flags_vertical = 3 +step = 0.01 + +[node name="PlayButton" type="Button" parent="SettingsContainer/VBoxContainer" groups=[ +"UIButtons", +]] +margin_top = 130.0 +margin_right = 20.0 +margin_bottom = 150.0 +rect_min_size = Vector2( 20, 0 ) +mouse_default_cursor_shape = 2 +toggle_mode = true + +[node name="TextureRect" type="TextureRect" parent="SettingsContainer/VBoxContainer/PlayButton"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -3.5 +margin_top = -6.0 +margin_right = 3.5 +margin_bottom = 6.0 +mouse_default_cursor_shape = 2 +texture = ExtResource( 7 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="PreviewContainer" type="PanelContainer" parent="."] +margin_left = 38.0 +margin_right = 332.0 +margin_bottom = 164.0 +size_flags_horizontal = 4 + +[node name="PreviewViewportContainer" type="ViewportContainer" parent="PreviewContainer"] +margin_left = 7.0 +margin_top = 7.0 +margin_right = 287.0 +margin_bottom = 157.0 +rect_min_size = Vector2( 0, 150 ) + +[node name="Viewport" type="Viewport" parent="PreviewContainer/PreviewViewportContainer"] +size = Vector2( 280, 150 ) +transparent_bg = true +handle_input_locally = false +render_target_update_mode = 3 + +[node name="TransparentChecker" parent="PreviewContainer/PreviewViewportContainer/Viewport" instance=ExtResource( 2 )] +material = SubResource( 1 ) + +[node name="CanvasPreview" parent="PreviewContainer/PreviewViewportContainer/Viewport" instance=ExtResource( 1 )] + +[node name="CameraPreview" type="Camera2D" parent="PreviewContainer/PreviewViewportContainer/Viewport"] +offset = Vector2( 32, 32 ) +current = true +zoom = Vector2( 0.15, 0.15 ) +script = ExtResource( 4 ) + +[node name="Panel" type="Panel" parent="."] +margin_left = 336.0 +margin_right = 336.0 +margin_bottom = 164.0 +[connection signal="value_changed" from="SettingsContainer/VBoxContainer/PreviewZoomSlider" to="." method="_on_PreviewZoomSlider_value_changed"] +[connection signal="toggled" from="SettingsContainer/VBoxContainer/PlayButton" to="." method="_on_PlayButton_toggled"] diff --git a/src/UI/UI.tscn b/src/UI/UI.tscn index d677b2ba3..73c3e1ec2 100644 --- a/src/UI/UI.tscn +++ b/src/UI/UI.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=23 format=2] +[gd_scene load_steps=24 format=2] [ext_resource path="res://src/UI/ToolButtons.gd" type="Script" id=1] [ext_resource path="res://src/UI/CanvasPreview.tscn" type="PackedScene" id=2] @@ -15,6 +15,7 @@ [ext_resource path="res://assets/graphics/dark_themes/tools/eraser_r.png" type="Texture" id=13] [ext_resource path="res://assets/graphics/dark_themes/tools/pencil_l.png" type="Texture" id=14] [ext_resource path="res://assets/graphics/dark_themes/tools/lightendarken.png" type="Texture" id=15] +[ext_resource path="res://src/UI/CanvasPreviewContainer.tscn" type="PackedScene" id=16] [ext_resource path="res://src/UI/ColorAndToolOptions.tscn" type="PackedScene" id=17] [ext_resource path="res://src/UI/Timeline/AnimationTimeline.tscn" type="PackedScene" id=18] [ext_resource path="res://src/Canvas.tscn" type="PackedScene" id=19] @@ -339,47 +340,24 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="PanelContainer" type="PanelContainer" parent="RightPanel/PreviewAndPalettes"] -margin_left = 8.0 -margin_right = 322.0 -margin_bottom = 164.0 -size_flags_horizontal = 4 - -[node name="PreviewViewportContainer" type="ViewportContainer" parent="RightPanel/PreviewAndPalettes/PanelContainer"] -margin_left = 7.0 -margin_top = 7.0 -margin_right = 307.0 -margin_bottom = 157.0 -rect_min_size = Vector2( 0, 150 ) - -[node name="Viewport" type="Viewport" parent="RightPanel/PreviewAndPalettes/PanelContainer/PreviewViewportContainer"] -size = Vector2( 300, 150 ) -transparent_bg = true -handle_input_locally = false -render_target_update_mode = 3 - -[node name="TransparentChecker" parent="RightPanel/PreviewAndPalettes/PanelContainer/PreviewViewportContainer/Viewport" instance=ExtResource( 5 )] - -[node name="CanvasPreview" parent="RightPanel/PreviewAndPalettes/PanelContainer/PreviewViewportContainer/Viewport" instance=ExtResource( 2 )] - -[node name="CameraPreview" type="Camera2D" parent="RightPanel/PreviewAndPalettes/PanelContainer/PreviewViewportContainer/Viewport"] -offset = Vector2( 32, 32 ) -current = true -zoom = Vector2( 0.15, 0.15 ) -script = ExtResource( 7 ) +[node name="CanvasPreviewContainer" parent="RightPanel/PreviewAndPalettes" instance=ExtResource( 16 )] +margin_right = 336.0 [node name="ToolAndPaletteVSplit" type="VSplitContainer" parent="RightPanel/PreviewAndPalettes"] margin_top = 168.0 -margin_right = 330.0 +margin_right = 336.0 margin_bottom = 676.0 size_flags_vertical = 3 custom_constants/autohide = 0 [node name="ColorAndToolOptions" parent="RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit" instance=ExtResource( 17 )] +margin_right = 336.0 margin_bottom = 248.0 [node name="PalettePanelContainer" parent="RightPanel/PreviewAndPalettes/ToolAndPaletteVSplit" instance=ExtResource( 20 )] +margin_left = 18.0 margin_top = 260.0 +margin_right = 318.0 margin_bottom = 508.0 [connection signal="reposition_active_tab_request" from="CanvasAndTimeline/ViewportAndRulers/TabsContainer/Tabs" to="CanvasAndTimeline/ViewportAndRulers/TabsContainer/Tabs" method="_on_Tabs_reposition_active_tab_request"] [connection signal="tab_changed" from="CanvasAndTimeline/ViewportAndRulers/TabsContainer/Tabs" to="CanvasAndTimeline/ViewportAndRulers/TabsContainer/Tabs" method="_on_Tabs_tab_changed"]