1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-19 01:29:49 +00:00

[EXPERIMENTAL] Re-making the timeline

Trying to merge layers into the timeline, and eventually add more features like "share layer with all frames", among others. THIS IS NOT FINISHED, IT WILL *NOT* WORK PROPERLY. Once it is finished, this branch will be merged onto master.

So far only add layer and add frame work, and even they may have some issues. Undoing also does not work properly yet.

The UI is also not finished, as it currently has problems with the scroll containers.
This commit is contained in:
OverloadedOrama 2020-01-18 21:06:47 +02:00
parent 7c408731b8
commit 953d002d91
12 changed files with 758 additions and 710 deletions

379
Main.tscn

File diff suppressed because one or more lines are too long

View file

@ -1,23 +1,39 @@
[gd_scene load_steps=31 format=2] [gd_scene load_steps=47 format=2]
[ext_resource path="res://Scripts/AnimationTimeline.gd" type="Script" id=1] [ext_resource path="res://Scripts/AnimationTimeline.gd" type="Script" id=1]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Go_To_First_Frame.png" type="Texture" id=2] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/New_Layer.png" type="Texture" id=2]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Go_To_First_Frame_Hover.png" type="Texture" id=3] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/New_Layer_Hover.png" type="Texture" id=3]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Previous_Frame.png" type="Texture" id=4] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Delete_Layer.png" type="Texture" id=4]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Previous_Frame_Hover.png" type="Texture" id=5] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Delete_Layer_Hover.png" type="Texture" id=5]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Play Backwards.png" type="Texture" id=6] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Delete_Layer_Disabled.png" type="Texture" id=6]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Pause.png" type="Texture" id=7] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Up.png" type="Texture" id=7]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Play Backwards_Hover.png" type="Texture" id=8] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Up_Hover.png" type="Texture" id=8]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Play.png" type="Texture" id=9] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Up_Disabled.png" type="Texture" id=9]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Play_Hover.png" type="Texture" id=10] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Down.png" type="Texture" id=10]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Next_Frame.png" type="Texture" id=11] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Down_Hover.png" type="Texture" id=11]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Next_Frame_Hover.png" type="Texture" id=12] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Down_Disabled.png" type="Texture" id=12]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Go_To_Last_Frame.png" type="Texture" id=13] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Clone_Layer.png" type="Texture" id=13]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Go_To_Last_Frame_Hover.png" type="Texture" id=14] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Clone_Layer_Hover.png" type="Texture" id=14]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Loop_None.png" type="Texture" id=15] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Merge_Down.png" type="Texture" id=15]
[ext_resource path="res://Scripts/Rulers/TimelineSeconds.gd" type="Script" id=16] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Merge_Down_Hover.png" type="Texture" id=16]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/New_Frame.png" type="Texture" id=17] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Merge_Down_Disabled.png" type="Texture" id=17]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/New_Frame_Hover.png" type="Texture" id=18] [ext_resource path="res://Prefabs/LayerContainer.tscn" type="PackedScene" id=18]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/New_Frame.png" type="Texture" id=19]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/New_Frame_Hover.png" type="Texture" id=20]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Go_To_First_Frame.png" type="Texture" id=21]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Go_To_First_Frame_Hover.png" type="Texture" id=22]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Previous_Frame.png" type="Texture" id=23]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Previous_Frame_Hover.png" type="Texture" id=24]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Play Backwards.png" type="Texture" id=25]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Pause.png" type="Texture" id=26]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Play Backwards_Hover.png" type="Texture" id=27]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Play.png" type="Texture" id=28]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Play_Hover.png" type="Texture" id=29]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Next_Frame.png" type="Texture" id=30]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Next_Frame_Hover.png" type="Texture" id=31]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Go_To_Last_Frame.png" type="Texture" id=32]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Go_To_Last_Frame_Hover.png" type="Texture" id=33]
[ext_resource path="res://Assets/Graphics/Dark Themes/Timeline/Loop_None.png" type="Texture" id=34]
[sub_resource type="InputEventKey" id=1] [sub_resource type="InputEventKey" id=1]
control = true control = true
@ -64,19 +80,17 @@ scancode = 16777230
shortcut = SubResource( 11 ) shortcut = SubResource( 11 )
[node name="AnimationTimeline" type="Panel"] [node name="AnimationTimeline" type="Panel"]
margin_top = 478.0 margin_top = 438.0
margin_right = 704.0 margin_right = 704.0
margin_bottom = 620.0 margin_bottom = 620.0
rect_min_size = Vector2( 0, 142 ) rect_min_size = Vector2( 0, 200 )
size_flags_horizontal = 3 size_flags_horizontal = 3
script = ExtResource( 1 ) script = ExtResource( 1 )
[node name="VSeparator" type="VSeparator" parent="."] [node name="VSeparator" type="VSeparator" parent="."]
anchor_top = 0.5 anchor_bottom = 1.0
anchor_bottom = 0.5
margin_top = -71.0
margin_right = 4.0 margin_right = 4.0
margin_bottom = 71.0 size_flags_vertical = 3
[node name="AnimationContainer" type="HBoxContainer" parent="."] [node name="AnimationContainer" type="HBoxContainer" parent="."]
anchor_right = 1.0 anchor_right = 1.0
@ -86,26 +100,218 @@ margin_top = 4.0
[node name="TimelineContainer" type="VBoxContainer" parent="AnimationContainer"] [node name="TimelineContainer" type="VBoxContainer" parent="AnimationContainer"]
margin_right = 543.0 margin_right = 543.0
margin_bottom = 138.0 margin_bottom = 196.0
size_flags_horizontal = 3 size_flags_horizontal = 3
[node name="AnimationButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"] [node name="FrameLayerButtonContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"]
margin_right = 543.0 margin_right = 543.0
margin_bottom = 36.0
[node name="LayerButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer"]
margin_right = 326.0
margin_bottom = 36.0
[node name="AddLayer" type="TextureButton" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons" groups=[
"UIButtons",
]]
margin_right = 32.0
margin_bottom = 36.0
hint_tooltip = "LAYERNEW_HT"
mouse_default_cursor_shape = 2
texture_normal = ExtResource( 2 )
texture_hover = ExtResource( 3 )
[node name="RemoveLayer" type="TextureButton" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons" groups=[
"UIButtons",
]]
margin_left = 36.0
margin_right = 68.0
margin_bottom = 36.0
hint_tooltip = "LAYERREMOVE_HT"
mouse_default_cursor_shape = 8
disabled = true
texture_normal = ExtResource( 4 )
texture_hover = ExtResource( 5 )
texture_disabled = ExtResource( 6 )
[node name="MoveUpLayer" type="TextureButton" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons" groups=[
"UIButtons",
]]
margin_left = 72.0
margin_right = 104.0
margin_bottom = 36.0
hint_tooltip = "LAYERUP_HT"
mouse_default_cursor_shape = 8
disabled = true
texture_normal = ExtResource( 7 )
texture_hover = ExtResource( 8 )
texture_disabled = ExtResource( 9 )
[node name="MovwDownLayer" type="TextureButton" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons" groups=[
"UIButtons",
]]
margin_left = 108.0
margin_right = 140.0
margin_bottom = 36.0
hint_tooltip = "LAYERDOWN_HT"
mouse_default_cursor_shape = 8
disabled = true
texture_normal = ExtResource( 10 )
texture_hover = ExtResource( 11 )
texture_disabled = ExtResource( 12 )
[node name="CloneLayer" type="TextureButton" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons" groups=[
"UIButtons",
]]
margin_left = 144.0
margin_right = 176.0
margin_bottom = 36.0
hint_tooltip = "LAYERCLONE_HT"
mouse_default_cursor_shape = 2
texture_normal = ExtResource( 13 )
texture_hover = ExtResource( 14 )
[node name="MergeDownLayer" type="TextureButton" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons" groups=[
"UIButtons",
]]
margin_left = 180.0
margin_right = 212.0
margin_bottom = 36.0
hint_tooltip = "LAYERMERGE_HT"
mouse_default_cursor_shape = 8
disabled = true
texture_normal = ExtResource( 15 )
texture_hover = ExtResource( 16 )
texture_disabled = ExtResource( 17 )
[node name="TagsAndFrameIDs" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons"]
margin_left = 216.0
margin_right = 326.0
margin_bottom = 36.0
[node name="AnimationTags" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/TagsAndFrameIDs"]
editor/display_folded = true
margin_right = 110.0
margin_bottom = 36.0
size_flags_vertical = 0
[node name="Line2D" type="Line2D" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/TagsAndFrameIDs/AnimationTags"]
points = PoolVector2Array( 0, 32, 0, 0, 110, 0, 110, 32 )
width = 1.0
[node name="Label" type="Label" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/TagsAndFrameIDs/AnimationTags"]
margin_right = 110.0
margin_bottom = 32.0
rect_min_size = Vector2( 110, 32 )
size_flags_vertical = 1
text = "Animation Tags"
align = 1
valign = 1
[node name="FramesContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/TagsAndFrameIDs/AnimationTags"]
margin_top = 36.0
margin_right = 110.0
margin_bottom = 36.0
[node name="OpacityContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"]
margin_top = 40.0
margin_right = 543.0
margin_bottom = 64.0
custom_constants/separation = 2
[node name="OpacityLabel" type="Label" parent="AnimationContainer/TimelineContainer/OpacityContainer"]
margin_right = 53.0
margin_bottom = 24.0 margin_bottom = 24.0
size_flags_horizontal = 0
size_flags_vertical = 1
text = "Opacity:"
valign = 1
[node name="OpacitySlider" type="HSlider" parent="AnimationContainer/TimelineContainer/OpacityContainer"]
margin_left = 55.0
margin_right = 167.0
margin_bottom = 24.0
rect_min_size = Vector2( 112, 0 )
mouse_default_cursor_shape = 2
size_flags_vertical = 1
value = 100.0
ticks_on_borders = true
[node name="OpacitySpinBox" type="SpinBox" parent="AnimationContainer/TimelineContainer/OpacityContainer"]
margin_left = 169.0
margin_right = 243.0
margin_bottom = 24.0
mouse_default_cursor_shape = 2
size_flags_vertical = 4
value = 100.0
align = 1
[node name="FrameIDs" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/OpacityContainer"]
margin_left = 245.0
margin_right = 281.0
margin_bottom = 24.0
[node name="Label" type="Label" parent="AnimationContainer/TimelineContainer/OpacityContainer/FrameIDs"]
margin_top = 5.0
margin_right = 36.0
margin_bottom = 19.0
rect_min_size = Vector2( 36, 0 )
text = "1"
align = 1
[node name="TimelineScroll" type="ScrollContainer" parent="AnimationContainer/TimelineContainer"]
margin_top = 68.0
margin_right = 543.0
margin_bottom = 160.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="LayersAndFrames" type="GridContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll"]
margin_right = 212.0
margin_bottom = 36.0
custom_constants/vseparation = 4
custom_constants/hseparation = 4
columns = 2
[node name="LayerContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames" instance=ExtResource( 18 )]
margin_right = 212.0
[node name="HSeparator" type="HSeparator" parent="AnimationContainer/TimelineContainer"]
margin_top = 164.0
margin_right = 543.0
margin_bottom = 168.0
[node name="AnimationButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"]
margin_top = 172.0
margin_right = 543.0
margin_bottom = 196.0
rect_min_size = Vector2( 0, 24 ) rect_min_size = Vector2( 0, 24 )
[node name="CurrentFrame" type="Label" parent="AnimationContainer/TimelineContainer/AnimationButtons"] [node name="CurrentFrame" type="Label" parent="AnimationContainer/TimelineContainer/AnimationButtons"]
margin_top = 5.0 margin_top = 5.0
margin_right = 218.0 margin_right = 117.0
margin_bottom = 19.0 margin_bottom = 19.0
size_flags_horizontal = 3
text = "Current frame: 1/1" text = "Current frame: 1/1"
[node name="AddFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons" groups=[
"UIButtons",
]]
margin_left = 121.0
margin_right = 141.0
margin_bottom = 20.0
hint_tooltip = "Add a new frame"
mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 0
texture_normal = ExtResource( 19 )
texture_hover = ExtResource( 20 )
[node name="PlaybackButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/AnimationButtons"] [node name="PlaybackButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/AnimationButtons"]
margin_left = 222.0 editor/display_folded = true
margin_right = 362.0 margin_left = 223.0
margin_right = 363.0
margin_bottom = 24.0 margin_bottom = 24.0
size_flags_horizontal = 2 size_flags_horizontal = 6
[node name="FirstFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[ [node name="FirstFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons", "UIButtons",
@ -116,8 +322,8 @@ hint_tooltip = "FIRSTFRAME_HT"
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
shortcut_in_tooltip = false shortcut_in_tooltip = false
shortcut = SubResource( 2 ) shortcut = SubResource( 2 )
texture_normal = ExtResource( 2 ) texture_normal = ExtResource( 21 )
texture_hover = ExtResource( 3 ) texture_hover = ExtResource( 22 )
[node name="PreviousFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[ [node name="PreviousFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons", "UIButtons",
@ -129,8 +335,8 @@ hint_tooltip = "PREVIOUSFRAME_HT"
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
shortcut_in_tooltip = false shortcut_in_tooltip = false
shortcut = SubResource( 4 ) shortcut = SubResource( 4 )
texture_normal = ExtResource( 4 ) texture_normal = ExtResource( 23 )
texture_hover = ExtResource( 5 ) texture_hover = ExtResource( 24 )
[node name="PlayBackwards" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[ [node name="PlayBackwards" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons", "UIButtons",
@ -143,9 +349,9 @@ mouse_default_cursor_shape = 2
toggle_mode = true toggle_mode = true
shortcut_in_tooltip = false shortcut_in_tooltip = false
shortcut = SubResource( 6 ) shortcut = SubResource( 6 )
texture_normal = ExtResource( 6 ) texture_normal = ExtResource( 25 )
texture_pressed = ExtResource( 7 ) texture_pressed = ExtResource( 26 )
texture_hover = ExtResource( 8 ) texture_hover = ExtResource( 27 )
[node name="PlayForward" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[ [node name="PlayForward" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons", "UIButtons",
@ -159,9 +365,9 @@ size_flags_horizontal = 0
toggle_mode = true toggle_mode = true
shortcut_in_tooltip = false shortcut_in_tooltip = false
shortcut = SubResource( 8 ) shortcut = SubResource( 8 )
texture_normal = ExtResource( 9 ) texture_normal = ExtResource( 28 )
texture_pressed = ExtResource( 7 ) texture_pressed = ExtResource( 26 )
texture_hover = ExtResource( 10 ) texture_hover = ExtResource( 29 )
[node name="NextFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[ [node name="NextFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons", "UIButtons",
@ -173,8 +379,8 @@ hint_tooltip = "NEXTFRAME_HT"
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
shortcut_in_tooltip = false shortcut_in_tooltip = false
shortcut = SubResource( 10 ) shortcut = SubResource( 10 )
texture_normal = ExtResource( 11 ) texture_normal = ExtResource( 30 )
texture_hover = ExtResource( 12 ) texture_hover = ExtResource( 31 )
[node name="LastFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[ [node name="LastFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons", "UIButtons",
@ -186,12 +392,12 @@ hint_tooltip = "LASTFRAME_HT"
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
shortcut_in_tooltip = false shortcut_in_tooltip = false
shortcut = SubResource( 12 ) shortcut = SubResource( 12 )
texture_normal = ExtResource( 13 ) texture_normal = ExtResource( 32 )
texture_hover = ExtResource( 14 ) texture_hover = ExtResource( 33 )
[node name="LoopButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/AnimationButtons"] [node name="LoopButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/AnimationButtons"]
margin_left = 444.0 margin_left = 445.0
margin_right = 542.0 margin_right = 543.0
margin_bottom = 24.0 margin_bottom = 24.0
size_flags_horizontal = 0 size_flags_horizontal = 0
@ -214,60 +420,17 @@ margin_right = 98.0
margin_bottom = 24.0 margin_bottom = 24.0
hint_tooltip = "No loop" hint_tooltip = "No loop"
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
texture_normal = ExtResource( 15 ) texture_normal = ExtResource( 34 )
[node name="HSeparator" type="HSeparator" parent="AnimationContainer/TimelineContainer"]
margin_top = 28.0
margin_right = 543.0
margin_bottom = 32.0
[node name="TimelineSeconds" type="Control" parent="AnimationContainer/TimelineContainer"]
margin_top = 36.0
margin_right = 543.0
margin_bottom = 52.0
rect_min_size = Vector2( 0, 16 )
script = ExtResource( 16 )
[node name="HSeparator2" type="HSeparator" parent="AnimationContainer/TimelineContainer"]
margin_top = 56.0
margin_right = 543.0
margin_bottom = 60.0
[node name="FrameAndButtonContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"]
margin_top = 64.0
margin_right = 543.0
margin_bottom = 84.0
[node name="AddFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/FrameAndButtonContainer" groups=[
"UIButtons",
]]
margin_right = 20.0
margin_bottom = 20.0
hint_tooltip = "Add a new frame"
mouse_default_cursor_shape = 2
size_flags_horizontal = 0
texture_normal = ExtResource( 17 )
texture_hover = ExtResource( 18 )
[node name="ScrollContainer" type="ScrollContainer" parent="AnimationContainer/TimelineContainer/FrameAndButtonContainer"]
margin_left = 24.0
margin_right = 543.0
margin_bottom = 20.0
size_flags_horizontal = 3
size_flags_vertical = 3
scroll_vertical_enabled = false
[node name="FrameContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/FrameAndButtonContainer/ScrollContainer"]
[node name="VSeparator" type="VSeparator" parent="AnimationContainer"] [node name="VSeparator" type="VSeparator" parent="AnimationContainer"]
margin_left = 547.0 margin_left = 547.0
margin_right = 551.0 margin_right = 551.0
margin_bottom = 138.0 margin_bottom = 196.0
[node name="OnionSkinningButtons" type="VBoxContainer" parent="AnimationContainer"] [node name="OnionSkinningButtons" type="VBoxContainer" parent="AnimationContainer"]
margin_left = 555.0 margin_left = 555.0
margin_right = 681.0 margin_right = 681.0
margin_bottom = 138.0 margin_bottom = 196.0
[node name="OnionSkinning" type="Label" parent="AnimationContainer/OnionSkinningButtons"] [node name="OnionSkinning" type="Label" parent="AnimationContainer/OnionSkinningButtons"]
margin_right = 126.0 margin_right = 126.0
@ -310,9 +473,18 @@ text = "Blue-Red Mode"
[node name="VSeparator2" type="VSeparator" parent="AnimationContainer"] [node name="VSeparator2" type="VSeparator" parent="AnimationContainer"]
margin_left = 685.0 margin_left = 685.0
margin_right = 689.0 margin_right = 689.0
margin_bottom = 138.0 margin_bottom = 196.0
[node name="AnimationTimer" type="Timer" parent="."] [node name="AnimationTimer" type="Timer" parent="."]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/AddLayer" to="." method="add_layer" binds= [ true ]]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ 1 ]]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/MovwDownLayer" to="." method="change_layer_order" binds= [ -1 ]]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/CloneLayer" to="." method="add_layer" binds= [ false ]]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/FrameLayerButtonContainer/LayerButtons/MergeDownLayer" to="." method="_on_MergeDownLayer_pressed"]
[connection signal="value_changed" from="AnimationContainer/TimelineContainer/OpacityContainer/OpacitySlider" to="." method="_on_OpacitySlider_value_changed"]
[connection signal="value_changed" from="AnimationContainer/TimelineContainer/OpacityContainer/OpacitySpinBox" to="." method="_on_OpacitySlider_value_changed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/AddFrame" to="." method="add_frame"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/FirstFrame" to="." method="_on_FirstFrame_pressed"] [connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/FirstFrame" to="." method="_on_FirstFrame_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PreviousFrame" to="." method="_on_PreviousFrame_pressed"] [connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PreviousFrame" to="." method="_on_PreviousFrame_pressed"]
[connection signal="toggled" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PlayBackwards" to="." method="_on_PlayBackwards_toggled"] [connection signal="toggled" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/PlayBackwards" to="." method="_on_PlayBackwards_toggled"]
@ -321,8 +493,6 @@ margin_bottom = 138.0
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/LastFrame" to="." method="_on_LastFrame_pressed"] [connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons/LastFrame" to="." method="_on_LastFrame_pressed"]
[connection signal="value_changed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/FPSValue" to="." method="_on_FPSValue_value_changed"] [connection signal="value_changed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/FPSValue" to="." method="_on_FPSValue_value_changed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/LoopAnim" to="." method="_on_LoopAnim_pressed"] [connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/LoopAnim" to="." method="_on_LoopAnim_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/FrameAndButtonContainer/AddFrame" to="." method="add_frame"]
[connection signal="gui_input" from="AnimationContainer/TimelineContainer/FrameAndButtonContainer/ScrollContainer" to="AnimationContainer/TimelineContainer/TimelineSeconds" method="_on_ScrollContainer_gui_input"]
[connection signal="value_changed" from="AnimationContainer/OnionSkinningButtons/PastOnionSkinning" to="." method="_on_PastOnionSkinning_value_changed"] [connection signal="value_changed" from="AnimationContainer/OnionSkinningButtons/PastOnionSkinning" to="." method="_on_PastOnionSkinning_value_changed"]
[connection signal="value_changed" from="AnimationContainer/OnionSkinningButtons/FutureOnionSkinning" to="." method="_on_FutureOnionSkinning_value_changed"] [connection signal="value_changed" from="AnimationContainer/OnionSkinningButtons/FutureOnionSkinning" to="." method="_on_FutureOnionSkinning_value_changed"]
[connection signal="toggled" from="AnimationContainer/OnionSkinningButtons/BlueRedMode" to="." method="_on_BlueRedMode_toggled"] [connection signal="toggled" from="AnimationContainer/OnionSkinningButtons/BlueRedMode" to="." method="_on_BlueRedMode_toggled"]

View file

@ -2,13 +2,10 @@
[ext_resource path="res://Scripts/FrameButton.gd" type="Script" id=1] [ext_resource path="res://Scripts/FrameButton.gd" type="Script" id=1]
[node name="Frame" type="VBoxContainer"] [node name="FrameButton" type="Button"]
margin_right = 32.0 margin_top = 18.0
margin_bottom = 50.0
[node name="FrameButton" type="Button" parent="."]
margin_right = 36.0 margin_right = 36.0
margin_bottom = 36.0 margin_bottom = 54.0
rect_min_size = Vector2( 36, 36 ) rect_min_size = Vector2( 36, 36 )
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
size_flags_horizontal = 0 size_flags_horizontal = 0
@ -17,7 +14,7 @@ toggle_mode = true
button_mask = 7 button_mask = 7
script = ExtResource( 1 ) script = ExtResource( 1 )
[node name="FrameTexture" type="TextureRect" parent="FrameButton"] [node name="FrameTexture" type="TextureRect" parent="."]
margin_left = 2.0 margin_left = 2.0
margin_top = 2.0 margin_top = 2.0
margin_right = 34.0 margin_right = 34.0
@ -28,17 +25,10 @@ size_flags_vertical = 0
expand = true expand = true
stretch_mode = 6 stretch_mode = 6
[node name="PopupMenu" type="PopupMenu" parent="FrameButton"] [node name="PopupMenu" type="PopupMenu" parent="."]
margin_right = 20.0 margin_right = 20.0
margin_bottom = 20.0 margin_bottom = 20.0
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
items = [ "Remove Frame", null, 0, false, true, -1, 0, null, "", false, "Clone Frame", null, 0, false, false, -1, 0, null, "", false, "Move Left", null, 0, false, true, -1, 0, null, "", false, "Move Right", null, 0, false, true, -1, 0, null, "", false ] items = [ "Remove Frame", null, 0, false, true, -1, 0, null, "", false, "Clone Frame", null, 0, false, false, -1, 0, null, "", false, "Move Left", null, 0, false, true, -1, 0, null, "", false, "Move Right", null, 0, false, true, -1, 0, null, "", false ]
[connection signal="pressed" from="." to="." method="_on_FrameButton_pressed"]
[node name="FrameID" type="Label" parent="."] [connection signal="id_pressed" from="PopupMenu" to="." method="_on_PopupMenu_id_pressed"]
margin_top = 40.0
margin_right = 36.0
margin_bottom = 54.0
text = "0"
align = 1
[connection signal="pressed" from="FrameButton" to="FrameButton" method="_on_FrameButton_pressed"]
[connection signal="id_pressed" from="FrameButton/PopupMenu" to="FrameButton" method="_on_PopupMenu_id_pressed"]

View file

@ -0,0 +1,18 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Prefabs/FrameButton.tscn" type="PackedScene" id=1]
[node name="FrameContainer" type="VBoxContainer"]
margin_right = 32.0
margin_bottom = 50.0
[node name="FrameID" type="Label" parent="."]
margin_right = 36.0
margin_bottom = 17.0
rect_min_size = Vector2( 0, 17 )
text = "0"
align = 1
[node name="FrameButton" parent="." instance=ExtResource( 1 )]
margin_top = 21.0
margin_bottom = 57.0

View file

@ -5,22 +5,30 @@
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Layer_Visible_Hover.png" type="Texture" id=3] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Layer_Visible_Hover.png" type="Texture" id=3]
[node name="LayerContainer" type="Button"] [node name="LayerContainer" type="Button"]
margin_right = 160.0 margin_right = 210.0
margin_bottom = 42.0 margin_bottom = 36.0
rect_min_size = Vector2( 160, 42 ) rect_min_size = Vector2( 212, 36 )
toggle_mode = true toggle_mode = true
script = ExtResource( 1 ) script = ExtResource( 1 )
__meta__ = { __meta__ = {
"_edit_horizontal_guides_": [ ] "_edit_horizontal_guides_": [ ]
} }
[node name="VisibilityButton" type="TextureButton" parent="." groups=[ [node name="HBoxContainer" type="HBoxContainer" parent="."]
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
margin_top = -16.0
margin_bottom = 16.0
mouse_default_cursor_shape = 2
alignment = 1
[node name="VisibilityButton" type="TextureButton" parent="HBoxContainer" groups=[
"UIButtons", "UIButtons",
]] ]]
margin_left = 6.0 margin_left = 65.0
margin_top = 5.0 margin_right = 97.0
margin_right = 38.0 margin_bottom = 32.0
margin_bottom = 37.0
hint_tooltip = "LAYERVISIBILITY_HT" hint_tooltip = "LAYERVISIBILITY_HT"
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
size_flags_horizontal = 0 size_flags_horizontal = 0
@ -28,29 +36,10 @@ size_flags_vertical = 4
texture_normal = ExtResource( 2 ) texture_normal = ExtResource( 2 )
texture_hover = ExtResource( 3 ) texture_hover = ExtResource( 3 )
[node name="HBoxContainer" type="HBoxContainer" parent="."]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -41.0
margin_top = -16.0
margin_right = 41.0
margin_bottom = 16.0
mouse_default_cursor_shape = 2
[node name="TextureRect" type="TextureRect" parent="HBoxContainer"]
margin_right = 32.0
margin_bottom = 32.0
rect_min_size = Vector2( 32, 32 )
size_flags_vertical = 4
expand = true
stretch_mode = 6
[node name="Label" type="Label" parent="HBoxContainer"] [node name="Label" type="Label" parent="HBoxContainer"]
margin_left = 36.0 margin_left = 101.0
margin_top = 9.0 margin_top = 9.0
margin_right = 82.0 margin_right = 147.0
margin_bottom = 23.0 margin_bottom = 23.0
text = "Layer 0" text = "Layer 0"
align = 1 align = 1
@ -68,5 +57,5 @@ editable = false
caret_blink = true caret_blink = true
caret_blink_speed = 0.5 caret_blink_speed = 0.5
[connection signal="pressed" from="." to="." method="_on_LayerContainer_pressed"] [connection signal="pressed" from="." to="." method="_on_LayerContainer_pressed"]
[connection signal="pressed" from="VisibilityButton" to="." method="_on_VisibilityButton_pressed"] [connection signal="pressed" from="HBoxContainer/VisibilityButton" to="." method="_on_VisibilityButton_pressed"]
[connection signal="text_changed" from="HBoxContainer/LineEdit" to="." method="_on_LineEdit_text_changed"] [connection signal="text_changed" from="HBoxContainer/LineEdit" to="." method="_on_LineEdit_text_changed"]

View file

@ -23,10 +23,10 @@ func add_frame() -> void:
Global.undo_redo.add_do_property(Global, "hidden_canvases", Global.hidden_canvases) Global.undo_redo.add_do_property(Global, "hidden_canvases", Global.hidden_canvases)
Global.undo_redo.add_do_property(Global, "canvas", new_canvas) Global.undo_redo.add_do_property(Global, "canvas", new_canvas)
Global.undo_redo.add_do_property(Global, "current_frame", new_canvases.size() - 1) Global.undo_redo.add_do_property(Global, "current_frame", new_canvases.size() - 1)
for child in Global.frame_container.get_children(): for i in range(Global.layers.size()):
var frame_button = child.get_node("FrameButton") for child in Global.layers[i][1].get_children():
Global.undo_redo.add_do_property(frame_button, "pressed", false) Global.undo_redo.add_do_property(child, "pressed", false)
Global.undo_redo.add_undo_property(frame_button, "pressed", frame_button.pressed) Global.undo_redo.add_undo_property(child, "pressed", child.pressed)
for c in Global.canvases: for c in Global.canvases:
Global.undo_redo.add_do_property(c, "visible", false) Global.undo_redo.add_do_property(c, "visible", false)
Global.undo_redo.add_undo_property(c, "visible", c.visible) Global.undo_redo.add_undo_property(c, "visible", c.visible)
@ -39,18 +39,15 @@ func add_frame() -> void:
func _on_LoopAnim_pressed() -> void: func _on_LoopAnim_pressed() -> void:
match animation_loop: match animation_loop:
0: 0: # Make it loop
# Make it loop
animation_loop = 1 animation_loop = 1
Global.loop_animation_button.texture_normal = load("res://Assets/Graphics/%s Themes/Timeline/Loop.png" % Global.theme_type) Global.loop_animation_button.texture_normal = load("res://Assets/Graphics/%s Themes/Timeline/Loop.png" % Global.theme_type)
Global.loop_animation_button.hint_tooltip = "Cycle loop" Global.loop_animation_button.hint_tooltip = "Cycle loop"
1: 1: # Make it ping-pong
# Make it ping-pong
animation_loop = 2 animation_loop = 2
Global.loop_animation_button.texture_normal = load("res://Assets/Graphics/%s Themes/Timeline/Loop_PingPong.png" % Global.theme_type) Global.loop_animation_button.texture_normal = load("res://Assets/Graphics/%s Themes/Timeline/Loop_PingPong.png" % Global.theme_type)
Global.loop_animation_button.hint_tooltip = "Ping-pong loop" Global.loop_animation_button.hint_tooltip = "Ping-pong loop"
2: 2: # Make it stop
# Make it stop
animation_loop = 0 animation_loop = 0
Global.loop_animation_button.texture_normal = load("res://Assets/Graphics/%s Themes/Timeline/Loop_None.png" % Global.theme_type) Global.loop_animation_button.texture_normal = load("res://Assets/Graphics/%s Themes/Timeline/Loop_None.png" % Global.theme_type)
Global.loop_animation_button.hint_tooltip = "No loop" Global.loop_animation_button.hint_tooltip = "No loop"
@ -101,13 +98,13 @@ func _on_AnimationTimer_timeout() -> void:
Global.current_frame += 1 Global.current_frame += 1
else: else:
match animation_loop: match animation_loop:
0: #No loop 0: # No loop
Global.play_forward.pressed = false Global.play_forward.pressed = false
Global.play_backwards.pressed = false Global.play_backwards.pressed = false
Global.animation_timer.stop() Global.animation_timer.stop()
1: #Cycle loop 1: # Cycle loop
Global.current_frame = 0 Global.current_frame = 0
2: #Ping pong loop 2: # Ping pong loop
animation_forward = false animation_forward = false
_on_AnimationTimer_timeout() _on_AnimationTimer_timeout()
@ -116,13 +113,13 @@ func _on_AnimationTimer_timeout() -> void:
Global.current_frame -= 1 Global.current_frame -= 1
else: else:
match animation_loop: match animation_loop:
0: #No loop 0: # No loop
Global.play_backwards.pressed = false Global.play_backwards.pressed = false
Global.play_forward.pressed = false Global.play_forward.pressed = false
Global.animation_timer.stop() Global.animation_timer.stop()
1: #Cycle loop 1: # Cycle loop
Global.current_frame = Global.canvases.size() - 1 Global.current_frame = Global.canvases.size() - 1
2: #Ping pong loop 2: # Ping pong loop
animation_forward = true animation_forward = true
_on_AnimationTimer_timeout() _on_AnimationTimer_timeout()
@ -142,3 +139,104 @@ func _on_FutureOnionSkinning_value_changed(value) -> void:
func _on_BlueRedMode_toggled(button_pressed) -> void: func _on_BlueRedMode_toggled(button_pressed) -> void:
Global.onion_skinning_blue_red = button_pressed Global.onion_skinning_blue_red = button_pressed
Global.canvas.update() Global.canvas.update()
# Layer buttons
func add_layer(is_new := true) -> void:
var new_layer := Image.new()
var layer_name = null
if is_new:
new_layer.create(Global.canvas.size.x, Global.canvas.size.y, false, Image.FORMAT_RGBA8)
else: # clone layer
new_layer.copy_from(Global.canvas.layers[Global.current_layer][0])
layer_name = Global.canvas.layers[Global.current_layer][2] + " (" + tr("copy") + ")"
new_layer.lock()
var new_layer_tex := ImageTexture.new()
new_layer_tex.create_from_image(new_layer, 0)
var new_layers : Array = Global.layers.duplicate()
# Store [layer name, frame container]
new_layers.append([layer_name, HBoxContainer.new()])
Global.undos += 1
Global.undo_redo.create_action("Add Layer")
Global.undo_redo.add_do_property(Global, "current_layer", Global.current_layer + 1)
Global.undo_redo.add_do_property(Global, "layers", new_layers)
for c in Global.canvases:
var new_canvas_layers : Array = c.layers.duplicate()
# Store [Image, ImageTexture, Visibity boolean, Opacity]
new_canvas_layers.append([new_layer, new_layer_tex, true, 1])
Global.undo_redo.add_do_property(c, "layers", new_canvas_layers)
Global.undo_redo.add_undo_property(c, "layers", c.layers)
Global.undo_redo.add_undo_property(Global, "current_layer", Global.current_layer)
Global.undo_redo.add_undo_property(Global, "layers", Global.layers)
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
Global.undo_redo.commit_action()
func _on_RemoveLayer_pressed() -> void:
var new_layers : Array = Global.canvas.layers.duplicate()
new_layers.remove(Global.canvas.current_layer_index)
Global.undos += 1
Global.undo_redo.create_action("Remove Layer")
Global.undo_redo.add_do_property(Global.canvas, "layers", new_layers)
Global.undo_redo.add_undo_property(Global.canvas, "layers", Global.canvas.layers)
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
Global.undo_redo.commit_action()
func change_layer_order(rate : int) -> void:
var change = Global.canvas.current_layer_index + rate
var new_layers : Array = Global.canvas.layers.duplicate()
var temp = new_layers[Global.canvas.current_layer_index]
new_layers[Global.canvas.current_layer_index] = new_layers[change]
new_layers[change] = temp
Global.undo_redo.create_action("Change Layer Order")
Global.undo_redo.add_do_property(Global.canvas, "layers", new_layers)
Global.undo_redo.add_do_property(Global.canvas, "current_layer_index", change)
Global.undo_redo.add_undo_property(Global.canvas, "layers", Global.canvas.layers)
Global.undo_redo.add_undo_property(Global.canvas, "current_layer_index", Global.canvas.current_layer_index)
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
Global.undo_redo.commit_action()
func _on_MergeDownLayer_pressed() -> void:
var new_layers : Array = Global.canvas.layers.duplicate()
new_layers.remove(Global.canvas.current_layer_index)
var selected_layer = Global.canvas.layers[Global.canvas.current_layer_index][0]
if Global.canvas.layers[Global.canvas.current_layer_index][4] < 1: # If we have layer transparency
for xx in selected_layer.get_size().x:
for yy in selected_layer.get_size().y:
var pixel_color : Color = selected_layer.get_pixel(xx, yy)
var alpha : float = pixel_color.a * Global.canvas.layers[Global.canvas.current_layer_index][4]
selected_layer.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
var new_layer := Image.new()
new_layer.copy_from(Global.canvas.layers[Global.canvas.current_layer_index - 1][0])
new_layer.lock()
Global.canvas.blend_rect(new_layer, selected_layer, Rect2(Global.canvas.position, Global.canvas.size), Vector2.ZERO)
Global.undos += 1
Global.undo_redo.create_action("Merge Layer")
Global.undo_redo.add_do_property(Global.canvas, "layers", new_layers)
Global.undo_redo.add_do_property(Global.canvas.layers[Global.canvas.current_layer_index - 1][0], "data", new_layer.data)
Global.undo_redo.add_undo_property(Global.canvas, "layers", Global.canvas.layers)
Global.undo_redo.add_undo_property(Global.canvas.layers[Global.canvas.current_layer_index - 1][0], "data", Global.canvas.layers[Global.canvas.current_layer_index - 1][0].data)
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
Global.undo_redo.commit_action()
func _on_OpacitySlider_value_changed(value) -> void:
Global.canvas.layers[Global.current_layer][3] = value / 100
Global.layer_opacity_slider.value = value
Global.layer_opacity_spinbox.value = value
Global.canvas.update()

View file

@ -7,8 +7,6 @@ var location := Vector2.ZERO
var size := Vector2(64, 64) var size := Vector2(64, 64)
var fill_color := Color(0, 0, 0, 0) var fill_color := Color(0, 0, 0, 0)
var frame := 0 setget frame_changed var frame := 0 setget frame_changed
var frame_button : VBoxContainer
var frame_texture_rect : TextureRect
var current_pixel := Vector2.ZERO # pretty much same as mouse_pos, but can be accessed externally var current_pixel := Vector2.ZERO # pretty much same as mouse_pos, but can be accessed externally
var previous_mouse_pos := Vector2.ZERO var previous_mouse_pos := Vector2.ZERO
var previous_mouse_pos_for_lines := Vector2.ZERO var previous_mouse_pos_for_lines := Vector2.ZERO
@ -31,8 +29,11 @@ var pen_pressure := 1.0 # For tablet pressure sensitivity
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready() -> void: func _ready() -> void:
var fill_layers := layers.empty()
for i in range(Global.layers.size()):
print(i)
if fill_layers:
# The sprite itself # The sprite itself
if layers.empty():
var sprite := Image.new() var sprite := Image.new()
if Global.is_default_image: if Global.is_default_image:
if Global.config_cache.has_section_key("preferences", "default_width"): if Global.config_cache.has_section_key("preferences", "default_width"):
@ -50,21 +51,16 @@ func _ready() -> void:
var tex := ImageTexture.new() var tex := ImageTexture.new()
tex.create_from_image(sprite, 0) tex.create_from_image(sprite, 0)
# Store [Image, ImageTexture, Layer Name, Visibity boolean, Opacity] # Store [Image, ImageTexture, Layer Name, Opacity]
layers.append([sprite, tex, tr("Layer") + " 0", true, 1]) layers.append([sprite, tex, 1])
generate_layer_panels() var frame_button = load("res://Prefabs/FrameButton.tscn").instance()
frame_button.frame = frame
frame_button = load("res://Prefabs/FrameButton.tscn").instance() frame_button.layer = i
frame_button.name = "Frame_%s" % frame frame_button.pressed = true
frame_button.get_node("FrameButton").frame = frame #frame_button.get_node("FrameID").text = str(frame + 1)
frame_button.get_node("FrameButton").pressed = true #frame_button.get_node("FrameID").add_color_override("font_color", Color("#3c5d75"))
frame_button.get_node("FrameID").text = str(frame + 1) Global.layers[i][2].add_child(frame_button)
frame_button.get_node("FrameID").add_color_override("font_color", Color("#3c5d75"))
Global.frame_container.add_child(frame_button)
frame_texture_rect = Global.find_node_by_name(frame_button, "FrameTexture")
frame_texture_rect.texture = layers[0][1] #ImageTexture current_layer_index
# Only handle camera zoom settings & offset on the first frame # Only handle camera zoom settings & offset on the first frame
if Global.canvases[0] == self: if Global.canvases[0] == self:
@ -79,8 +75,8 @@ func _ready() -> void:
func _draw() -> void: func _draw() -> void:
draw_texture_rect(Global.transparent_background, Rect2(location, size), true) #Draw transparent background draw_texture_rect(Global.transparent_background, Rect2(location, size), true) #Draw transparent background
#Onion Skinning # Onion Skinning
#Past # Past
if Global.onion_skinning_past_rate > 0: if Global.onion_skinning_past_rate > 0:
var color : Color var color : Color
if Global.onion_skinning_blue_red: if Global.onion_skinning_blue_red:
@ -89,11 +85,11 @@ func _draw() -> void:
color = Color.white color = Color.white
for i in range(1, Global.onion_skinning_past_rate + 1): for i in range(1, Global.onion_skinning_past_rate + 1):
if Global.current_frame >= i: if Global.current_frame >= i:
for texture in Global.canvases[Global.current_frame - i].layers: for layer in Global.canvases[Global.current_frame - i].layers:
color.a = 0.6/i color.a = 0.6/i
draw_texture(texture[1], location, color) draw_texture(layer[1], location, color)
#Future # Future
if Global.onion_skinning_future_rate > 0: if Global.onion_skinning_future_rate > 0:
var color : Color var color : Color
if Global.onion_skinning_blue_red: if Global.onion_skinning_blue_red:
@ -102,44 +98,44 @@ func _draw() -> void:
color = Color.white color = Color.white
for i in range(1, Global.onion_skinning_future_rate + 1): for i in range(1, Global.onion_skinning_future_rate + 1):
if Global.current_frame < Global.canvases.size() - i: if Global.current_frame < Global.canvases.size() - i:
for texture in Global.canvases[Global.current_frame + i].layers: for layer in Global.canvases[Global.current_frame + i].layers:
color.a = 0.6/i color.a = 0.6/i
draw_texture(texture[1], location, color) draw_texture(layer[1], location, color)
#Draw current frame layers # Draw current frame layers
for texture in layers: for i in range(layers.size()):
var modulate_color := Color(1, 1, 1, texture[4]) var modulate_color := Color(1, 1, 1, layers[i][2])
if texture[3]: #if it's visible if Global.layers[i][1]: # if it's visible
draw_texture(texture[1], location, modulate_color) draw_texture(layers[i][1], location, modulate_color)
if Global.tile_mode: if Global.tile_mode:
draw_texture(texture[1], Vector2(location.x, location.y + size.y), modulate_color) #Down draw_texture(layers[i][1], Vector2(location.x, location.y + size.y), modulate_color) #Down
draw_texture(texture[1], Vector2(location.x - size.x, location.y + size.y), modulate_color) #Down Left draw_texture(layers[i][1], Vector2(location.x - size.x, location.y + size.y), modulate_color) #Down Left
draw_texture(texture[1], Vector2(location.x - size.x, location.y), modulate_color) #Left draw_texture(layers[i][1], Vector2(location.x - size.x, location.y), modulate_color) #Left
draw_texture(texture[1], location - size, modulate_color) #Up left draw_texture(layers[i][1], location - size, modulate_color) #Up left
draw_texture(texture[1], Vector2(location.x, location.y - size.y), modulate_color) #Up draw_texture(layers[i][1], Vector2(location.x, location.y - size.y), modulate_color) #Up
draw_texture(texture[1], Vector2(location.x + size.x, location.y - size.y), modulate_color) #Up right draw_texture(layers[i][1], Vector2(location.x + size.x, location.y - size.y), modulate_color) #Up right
draw_texture(texture[1], Vector2(location.x + size.x, location.y), modulate_color) #Right draw_texture(layers[i][1], Vector2(location.x + size.x, location.y), modulate_color) #Right
draw_texture(texture[1], location + size, modulate_color) #Down right draw_texture(layers[i][1], location + size, modulate_color) #Down right
#Idea taken from flurick (on GitHub) # Idea taken from flurick (on GitHub)
if Global.draw_grid: if Global.draw_grid:
for x in range(0, size.x, Global.grid_width): for x in range(0, size.x, Global.grid_width):
draw_line(Vector2(x, location.y), Vector2(x, size.y), Global.grid_color, true) draw_line(Vector2(x, location.y), Vector2(x, size.y), Global.grid_color, true)
for y in range(0, size.y, Global.grid_height): for y in range(0, size.y, Global.grid_height):
draw_line(Vector2(location.x, y), Vector2(size.x, y), Global.grid_color, true) draw_line(Vector2(location.x, y), Vector2(size.x, y), Global.grid_color, true)
#Draw rectangle to indicate the pixel currently being hovered on # Draw rectangle to indicate the pixel currently being hovered on
var mouse_pos := current_pixel var mouse_pos := current_pixel
if point_in_rectangle(mouse_pos, location, location + size): if point_in_rectangle(mouse_pos, location, location + size):
mouse_pos = mouse_pos.floor() mouse_pos = mouse_pos.floor()
if Global.left_square_indicator_visible && Global.can_draw: if Global.left_square_indicator_visible && Global.can_draw:
if Global.current_left_brush_type == Global.Brush_Types.PIXEL || Global.current_left_tool == "LightenDarken": if Global.current_left_brush_type == Global.BRUSH_TYPES.PIXEL || Global.current_left_tool == "LightenDarken":
if Global.current_left_tool == "Pencil" || Global.current_left_tool == "Eraser" || Global.current_left_tool == "LightenDarken": if Global.current_left_tool == "Pencil" || Global.current_left_tool == "Eraser" || Global.current_left_tool == "LightenDarken":
var start_pos_x = mouse_pos.x - (Global.left_brush_size >> 1) var start_pos_x = mouse_pos.x - (Global.left_brush_size >> 1)
var start_pos_y = mouse_pos.y - (Global.left_brush_size >> 1) var start_pos_y = mouse_pos.y - (Global.left_brush_size >> 1)
draw_rect(Rect2(start_pos_x, start_pos_y, Global.left_brush_size, Global.left_brush_size), Color.blue, false) draw_rect(Rect2(start_pos_x, start_pos_y, Global.left_brush_size, Global.left_brush_size), Color.blue, false)
elif Global.current_left_brush_type == Global.Brush_Types.CIRCLE || Global.current_left_brush_type == Global.Brush_Types.FILLED_CIRCLE: elif Global.current_left_brush_type == Global.BRUSH_TYPES.CIRCLE || Global.current_left_brush_type == Global.BRUSH_TYPES.FILLED_CIRCLE:
if Global.current_left_tool == "Pencil" || Global.current_left_tool == "Eraser": if Global.current_left_tool == "Pencil" || Global.current_left_tool == "Eraser":
draw_set_transform(mouse_pos, rotation, scale) draw_set_transform(mouse_pos, rotation, scale)
for rect in Global.left_circle_points: for rect in Global.left_circle_points:
@ -152,12 +148,12 @@ func _draw() -> void:
draw_texture(Global.custom_left_brush_texture, dst) draw_texture(Global.custom_left_brush_texture, dst)
if Global.right_square_indicator_visible && Global.can_draw: if Global.right_square_indicator_visible && Global.can_draw:
if Global.current_right_brush_type == Global.Brush_Types.PIXEL || Global.current_right_tool == "LightenDarken": if Global.current_right_brush_type == Global.BRUSH_TYPES.PIXEL || Global.current_right_tool == "LightenDarken":
if Global.current_right_tool == "Pencil" || Global.current_right_tool == "Eraser" || Global.current_right_tool == "LightenDarken": if Global.current_right_tool == "Pencil" || Global.current_right_tool == "Eraser" || Global.current_right_tool == "LightenDarken":
var start_pos_x = mouse_pos.x - (Global.right_brush_size >> 1) var start_pos_x = mouse_pos.x - (Global.right_brush_size >> 1)
var start_pos_y = mouse_pos.y - (Global.right_brush_size >> 1) var start_pos_y = mouse_pos.y - (Global.right_brush_size >> 1)
draw_rect(Rect2(start_pos_x, start_pos_y, Global.right_brush_size, Global.right_brush_size), Color.red, false) draw_rect(Rect2(start_pos_x, start_pos_y, Global.right_brush_size, Global.right_brush_size), Color.red, false)
elif Global.current_right_brush_type == Global.Brush_Types.CIRCLE || Global.current_right_brush_type == Global.Brush_Types.FILLED_CIRCLE: elif Global.current_right_brush_type == Global.BRUSH_TYPES.CIRCLE || Global.current_right_brush_type == Global.BRUSH_TYPES.FILLED_CIRCLE:
if Global.current_right_tool == "Pencil" || Global.current_right_tool == "Eraser": if Global.current_right_tool == "Pencil" || Global.current_right_tool == "Eraser":
draw_set_transform(mouse_pos, rotation, scale) draw_set_transform(mouse_pos, rotation, scale)
for rect in Global.right_circle_points: for rect in Global.right_circle_points:
@ -204,6 +200,7 @@ func _input(event : InputEvent) -> void:
pen_pressure = 1 # This causes problems with tablets though pen_pressure = 1 # This causes problems with tablets though
sprite_changed_this_frame = false sprite_changed_this_frame = false
var sprite : Image = layers[Global.current_layer][0]
var mouse_pos := current_pixel var mouse_pos := current_pixel
var mouse_pos_floored := mouse_pos.floor() var mouse_pos_floored := mouse_pos.floor()
var mouse_pos_ceiled := mouse_pos.ceil() var mouse_pos_ceiled := mouse_pos.ceil()
@ -292,9 +289,9 @@ func _input(event : InputEvent) -> void:
match current_action: # Handle current tool match current_action: # Handle current tool
"Pencil": "Pencil":
pencil_and_eraser(mouse_pos, current_color, current_mouse_button, current_action) pencil_and_eraser(sprite, mouse_pos, current_color, current_mouse_button, current_action)
"Eraser": "Eraser":
pencil_and_eraser(mouse_pos, Color(0, 0, 0, 0), current_mouse_button, current_action) pencil_and_eraser(sprite, mouse_pos, Color(0, 0, 0, 0), current_mouse_button, current_action)
"Bucket": "Bucket":
if can_handle: if can_handle:
if fill_area == 0: # Paint the specific area of the same color if fill_area == 0: # Paint the specific area of the same color
@ -309,34 +306,34 @@ func _input(event : InputEvent) -> void:
horizontal_mirror = Global.right_horizontal_mirror horizontal_mirror = Global.right_horizontal_mirror
vertical_mirror = Global.right_vertical_mirror vertical_mirror = Global.right_vertical_mirror
flood_fill(mouse_pos, layers[current_layer_index][0].get_pixelv(mouse_pos), current_color) flood_fill(sprite, mouse_pos, sprite.get_pixelv(mouse_pos), current_color)
if horizontal_mirror: if horizontal_mirror:
var pos := Vector2(mirror_x, mouse_pos.y) var pos := Vector2(mirror_x, mouse_pos.y)
flood_fill(pos, layers[current_layer_index][0].get_pixelv(pos), current_color) flood_fill(sprite, pos, sprite.get_pixelv(pos), current_color)
if vertical_mirror: if vertical_mirror:
var pos := Vector2(mouse_pos.x, mirror_y) var pos := Vector2(mouse_pos.x, mirror_y)
flood_fill(pos, layers[current_layer_index][0].get_pixelv(pos), current_color) flood_fill(sprite, pos, sprite.get_pixelv(pos), current_color)
if horizontal_mirror && vertical_mirror: if horizontal_mirror && vertical_mirror:
var pos := Vector2(mirror_x, mirror_y) var pos := Vector2(mirror_x, mirror_y)
flood_fill(pos, layers[current_layer_index][0].get_pixelv(pos), current_color) flood_fill(sprite, pos, sprite.get_pixelv(pos), current_color)
else: # Paint all pixels of the same color else: # Paint all pixels of the same color
var pixel_color : Color = layers[current_layer_index][0].get_pixelv(mouse_pos) var pixel_color : Color = sprite.get_pixelv(mouse_pos)
for xx in range(west_limit, east_limit): for xx in range(west_limit, east_limit):
for yy in range(north_limit, south_limit): for yy in range(north_limit, south_limit):
var c : Color = layers[current_layer_index][0].get_pixel(xx, yy) var c : Color = sprite.get_pixel(xx, yy)
if c == pixel_color: if c == pixel_color:
layers[current_layer_index][0].set_pixel(xx, yy, current_color) sprite.set_pixel(xx, yy, current_color)
sprite_changed_this_frame = true sprite_changed_this_frame = true
"LightenDarken": "LightenDarken":
if can_handle: if can_handle:
var pixel_color : Color = layers[current_layer_index][0].get_pixelv(mouse_pos) var pixel_color : Color = sprite.get_pixelv(mouse_pos)
var color_changed : Color var color_changed : Color
if ld == 0: # Lighten if ld == 0: # Lighten
color_changed = pixel_color.lightened(ld_amount) color_changed = pixel_color.lightened(ld_amount)
else: # Darken else: # Darken
color_changed = pixel_color.darkened(ld_amount) color_changed = pixel_color.darkened(ld_amount)
pencil_and_eraser(mouse_pos, color_changed, current_mouse_button, current_action) pencil_and_eraser(sprite, mouse_pos, color_changed, current_mouse_button, current_action)
"RectSelect": "RectSelect":
# Check SelectionRectangle.gd for more code on Rectangle Selection # Check SelectionRectangle.gd for more code on Rectangle Selection
if Global.can_draw && Global.has_focus: if Global.can_draw && Global.has_focus:
@ -363,7 +360,7 @@ func _input(event : InputEvent) -> void:
Global.selection_rectangle.polygon[3] = Vector2(start_pos.x, end_pos.y) Global.selection_rectangle.polygon[3] = Vector2(start_pos.x, end_pos.y)
"ColorPicker": "ColorPicker":
if can_handle: if can_handle:
var pixel_color : Color = layers[current_layer_index][0].get_pixelv(mouse_pos) var pixel_color : Color = sprite.get_pixelv(mouse_pos)
if color_picker_for == 0: # Pick for the left color if color_picker_for == 0: # Pick for the left color
Global.left_color_picker.color = pixel_color Global.left_color_picker.color = pixel_color
Global.update_left_custom_brush() Global.update_left_custom_brush()
@ -422,7 +419,7 @@ func _input(event : InputEvent) -> void:
previous_mouse_pos.x = clamp(previous_mouse_pos.x, location.x, location.x + size.x) previous_mouse_pos.x = clamp(previous_mouse_pos.x, location.x, location.x + size.x)
previous_mouse_pos.y = clamp(previous_mouse_pos.y, location.y, location.y + size.y) previous_mouse_pos.y = clamp(previous_mouse_pos.y, location.y, location.y + size.y)
if sprite_changed_this_frame: if sprite_changed_this_frame:
update_texture(current_layer_index, (Input.is_action_just_released("left_mouse") || Input.is_action_just_released("right_mouse"))) update_texture(Global.current_layer, (Input.is_action_just_released("left_mouse") || Input.is_action_just_released("right_mouse")))
func camera_zoom() -> void: func camera_zoom() -> void:
# Set camera zoom based on the sprite size # Set camera zoom based on the sprite size
@ -454,7 +451,7 @@ func handle_undo(action : String) -> void:
var layer_index := -1 var layer_index := -1
if Global.animation_timer.is_stopped(): # if we're not animating, store only the current canvas if Global.animation_timer.is_stopped(): # if we're not animating, store only the current canvas
canvases = [self] canvases = [self]
layer_index = current_layer_index layer_index = Global.current_layer
else: # If we're animating, store all canvases else: # If we're animating, store all canvases
canvases = Global.canvases canvases = Global.canvases
Global.undos += 1 Global.undos += 1
@ -496,27 +493,29 @@ func handle_redo(action : String) -> void:
func update_texture(layer_index : int, update_frame_tex := true) -> void: func update_texture(layer_index : int, update_frame_tex := true) -> void:
layers[layer_index][1].create_from_image(layers[layer_index][0], 0) layers[layer_index][1].create_from_image(layers[layer_index][0], 0)
var layer_container := get_layer_container(layer_index) # var layer_container := get_layer_container(layer_index)
if layer_container: # if layer_container:
layer_container.get_child(1).get_child(0).texture = layers[layer_index][1] # layer_container.get_child(1).get_child(0).texture = layers[layer_index][1]
var frame_texture_rect : TextureRect
if update_frame_tex: frame_texture_rect = Global.find_node_by_name(Global.layers[layer_index][2].get_child(frame),"FrameTexture")
# This code is used to update the texture in the animation timeline frame button frame_texture_rect.texture = layers[layer_index][1]
# but blend_rect causes major performance issues on large images # if update_frame_tex:
var whole_image := Image.new() # # This code is used to update the texture in the animation timeline frame button
whole_image.create(size.x, size.y, false, Image.FORMAT_RGBA8) # # but blend_rect causes major performance issues on large images
for layer in layers: # var whole_image := Image.new()
whole_image.blend_rect(layer[0], Rect2(position, size), Vector2.ZERO) # whole_image.create(size.x, size.y, false, Image.FORMAT_RGBA8)
layer[0].lock() # for layer in layers:
var whole_image_texture := ImageTexture.new() # whole_image.blend_rect(layer[0], Rect2(position, size), Vector2.ZERO)
whole_image_texture.create_from_image(whole_image, 0) # layer[0].lock()
frame_texture_rect.texture = whole_image_texture # var whole_image_texture := ImageTexture.new()
# whole_image_texture.create_from_image(whole_image, 0)
# frame_texture_rect.texture = whole_image_texture
func frame_changed(value : int) -> void: func frame_changed(value : int) -> void:
frame = value frame = value
if frame_button: # if frame_button:
frame_button.get_node("FrameButton").frame = frame # frame_button.get_node("FrameButton").frame = frame
frame_button.get_node("FrameID").text = str(frame + 1) # frame_button.get_node("FrameID").text = str(frame + 1)
func get_layer_container(layer_index : int) -> LayerContainer: func get_layer_container(layer_index : int) -> LayerContainer:
for container in Global.vbox_layer_container.get_children(): for container in Global.vbox_layer_container.get_children():
@ -525,7 +524,8 @@ func get_layer_container(layer_index : int) -> LayerContainer:
return null return null
func generate_layer_panels() -> void: func generate_layer_panels() -> void:
for child in Global.vbox_layer_container.get_children(): return
for child in Global.layers_container.get_children():
if child is LayerContainer: if child is LayerContainer:
child.queue_free() child.queue_free()
@ -539,32 +539,31 @@ func generate_layer_panels() -> void:
for i in range(layers.size() -1, -1, -1): for i in range(layers.size() -1, -1, -1):
var layer_container = load("res://Prefabs/LayerContainer.tscn").instance() var layer_container = load("res://Prefabs/LayerContainer.tscn").instance()
if !layers[i][2]: # if !layers[i][2]:
layers[i][2] = tr("Layer") + " %s" % i # layers[i][2] = tr("Layer") + " %s" % i
layer_container.i = i layer_container.i = i
layer_container.get_child(1).get_child(0).texture = layers[i][1] layer_container.get_child(0).get_child(1).text = layers[i][2]
layer_container.get_child(1).get_child(1).text = layers[i][2] layer_container.get_child(0).get_child(2).text = layers[i][2]
layer_container.get_child(1).get_child(2).text = layers[i][2] Global.layer_and_frame_container.add_child(layer_container)
Global.vbox_layer_container.add_child(layer_container)
func pencil_and_eraser(mouse_pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void: func pencil_and_eraser(sprite : Image, mouse_pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void:
if made_line: if made_line:
return return
if is_making_line: if is_making_line:
fill_gaps(line_2d.points[1], previous_mouse_pos_for_lines, color, current_mouse_button, current_action) fill_gaps(sprite, line_2d.points[1], previous_mouse_pos_for_lines, color, current_mouse_button, current_action)
draw_brush(line_2d.points[1], color, current_mouse_button, current_action) draw_brush(sprite, line_2d.points[1], color, current_mouse_button, current_action)
made_line = true made_line = true
else: else:
if point_in_rectangle(mouse_pos, location, location + size): if point_in_rectangle(mouse_pos, location, location + size):
mouse_inside_canvas = true mouse_inside_canvas = true
# Draw # Draw
draw_brush(mouse_pos, color, current_mouse_button, current_action) draw_brush(sprite, mouse_pos, color, current_mouse_button, current_action)
fill_gaps(mouse_pos, previous_mouse_pos, color, current_mouse_button, current_action) #Fill the gaps fill_gaps(sprite, mouse_pos, previous_mouse_pos, color, current_mouse_button, current_action) # Fill the gaps
# If mouse is not inside bounds but it used to be, fill the gaps # If mouse is not inside bounds but it used to be, fill the gaps
elif point_in_rectangle(previous_mouse_pos, location, location + size): elif point_in_rectangle(previous_mouse_pos, location, location + size):
fill_gaps(mouse_pos, previous_mouse_pos, color, current_mouse_button, current_action) fill_gaps(sprite, mouse_pos, previous_mouse_pos, color, current_mouse_button, current_action)
func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void: func draw_brush(sprite : Image, pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void:
if Global.can_draw && Global.has_focus: if Global.can_draw && Global.has_focus:
var brush_size := 1 var brush_size := 1
var brush_type = Global.Brush_Types.PIXEL var brush_type = Global.Brush_Types.PIXEL
@ -635,7 +634,7 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
if point_in_rectangle(Vector2(cur_pos_x, cur_pos_y), Vector2(west_limit - 1, north_limit - 1), Vector2(east_limit, south_limit)): if point_in_rectangle(Vector2(cur_pos_x, cur_pos_y), Vector2(west_limit - 1, north_limit - 1), Vector2(east_limit, south_limit)):
var pos_floored := Vector2(cur_pos_x, cur_pos_y).floor() var pos_floored := Vector2(cur_pos_x, cur_pos_y).floor()
# Don't draw the same pixel over and over and don't re-lighten/darken it # Don't draw the same pixel over and over and don't re-lighten/darken it
var current_pixel_color : Color = layers[current_layer_index][0].get_pixel(cur_pos_x, cur_pos_y) var current_pixel_color : Color = layers[Global.current_layer][0].get_pixel(cur_pos_x, cur_pos_y)
var _c := color var _c := color
if current_action == "Pencil" && color.a < 1: if current_action == "Pencil" && color.a < 1:
_c = blend_colors(color, current_pixel_color) _c = blend_colors(color, current_pixel_color)
@ -655,14 +654,14 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
mouse_press_pressure_values.append(pen_pressure) mouse_press_pressure_values.append(pen_pressure)
else: else:
mouse_press_pressure_values[saved_pixel_index] = pen_pressure mouse_press_pressure_values[saved_pixel_index] = pen_pressure
layers[current_layer_index][0].set_pixel(cur_pos_x, cur_pos_y, _c) layers[Global.current_layer][0].set_pixel(cur_pos_x, cur_pos_y, _c)
sprite_changed_this_frame = true sprite_changed_this_frame = true
# Handle mirroring # Handle mirroring
var mirror_x := east_limit + west_limit - cur_pos_x - 1 var mirror_x := east_limit + west_limit - cur_pos_x - 1
var mirror_y := south_limit + north_limit - cur_pos_y - 1 var mirror_y := south_limit + north_limit - cur_pos_y - 1
if horizontal_mirror: if horizontal_mirror:
current_pixel_color = layers[current_layer_index][0].get_pixel(mirror_x, cur_pos_y) current_pixel_color = layers[Global.current_layer][0].get_pixel(mirror_x, cur_pos_y)
if current_pixel_color != _c: # don't draw the same pixel over and over if current_pixel_color != _c: # don't draw the same pixel over and over
if current_action == "LightenDarken": if current_action == "LightenDarken":
if ld == 0: # Lighten if ld == 0: # Lighten
@ -672,23 +671,24 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
mouse_press_pixels.append(pos_floored) mouse_press_pixels.append(pos_floored)
mouse_press_pressure_values.append(pen_pressure) mouse_press_pressure_values.append(pen_pressure)
layers[current_layer_index][0].set_pixel(mirror_x, cur_pos_y, _c) layers[Global.current_layer][0].set_pixel(mirror_x, cur_pos_y, _c)
sprite_changed_this_frame = true sprite_changed_this_frame = true
if vertical_mirror: if vertical_mirror:
current_pixel_color = layers[current_layer_index][0].get_pixel(cur_pos_x, mirror_y) current_pixel_color = layers[Global.current_layer][0].get_pixel(cur_pos_x, mirror_y)
if current_pixel_color != _c: # don't draw the same pixel over and over if current_pixel_color != _c: # don't draw the same pixel over and over
if current_action == "LightenDarken": if current_action == "LightenDarken":
if ld == 0: # Lighten if ld == 0: # Lighten
_c = current_pixel_color.lightened(ld_amount) _c = current_pixel_color.lightened(ld_amount)
else: else:
_c = current_pixel_color.darkened(ld_amount) _c = current_pixel_color.darkened(ld_amount)
mouse_press_pixels.append(pos_floored) mouse_press_pixels.append(pos_floored)
mouse_press_pressure_values.append(pen_pressure) mouse_press_pressure_values.append(pen_pressure)
layers[current_layer_index][0].set_pixel(cur_pos_x, mirror_y, _c) layers[Global.current_layer][0].set_pixel(cur_pos_x, mirror_y, _c)
sprite_changed_this_frame = true sprite_changed_this_frame = true
if horizontal_mirror && vertical_mirror: if horizontal_mirror && vertical_mirror:
current_pixel_color = layers[current_layer_index][0].get_pixel(mirror_x, mirror_y) current_pixel_color = layers[Global.current_layer][0].get_pixel(mirror_x, mirror_y)
if current_pixel_color != _c: # don't draw the same pixel over and over if current_pixel_color != _c: # don't draw the same pixel over and over
if current_action == "LightenDarken": if current_action == "LightenDarken":
if ld == 0: # Lighten if ld == 0: # Lighten
@ -698,21 +698,21 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
mouse_press_pixels.append(pos_floored) mouse_press_pixels.append(pos_floored)
mouse_press_pressure_values.append(pen_pressure) mouse_press_pressure_values.append(pen_pressure)
layers[current_layer_index][0].set_pixel(mirror_x, mirror_y, _c) sprite.set_pixel(mirror_x, mirror_y, _c)
sprite_changed_this_frame = true sprite_changed_this_frame = true
elif brush_type == Global.Brush_Types.CIRCLE || brush_type == Global.Brush_Types.FILLED_CIRCLE: elif brush_type == Global.BRUSH_TYPES.CIRCLE || brush_type == Global.Brush_Types.FILLED_CIRCLE:
plot_circle(layers[current_layer_index][0], pos.x, pos.y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) plot_circle(sprite, pos.x, pos.y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE)
# Handle mirroring # Handle mirroring
var mirror_x := east_limit + west_limit - pos.x var mirror_x := east_limit + west_limit - pos.x
var mirror_y := south_limit + north_limit - pos.y var mirror_y := south_limit + north_limit - pos.y
if horizontal_mirror: if horizontal_mirror:
plot_circle(layers[current_layer_index][0], mirror_x, pos.y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) plot_circle(sprite, mirror_x, pos.y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE)
if vertical_mirror: if vertical_mirror:
plot_circle(layers[current_layer_index][0], pos.x, mirror_y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) plot_circle(sprite, pos.x, mirror_y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE)
if horizontal_mirror && vertical_mirror: if horizontal_mirror && vertical_mirror:
plot_circle(layers[current_layer_index][0], mirror_x, mirror_y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE) plot_circle(sprite, mirror_x, mirror_y, brush_size, color, brush_type == Global.Brush_Types.FILLED_CIRCLE)
sprite_changed_this_frame = true sprite_changed_this_frame = true
@ -755,13 +755,13 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
mirror_y -= 1 mirror_y -= 1
# Use custom blend function cause of godot's issue #31124 # Use custom blend function cause of godot's issue #31124
if color.a > 0: # If it's the pencil if color.a > 0: # If it's the pencil
blend_rect(layers[current_layer_index][0], custom_brush_image, src_rect, dst) blend_rect(sprite, custom_brush_image, src_rect, dst)
if horizontal_mirror: if horizontal_mirror:
blend_rect(layers[current_layer_index][0], custom_brush_image, src_rect, Vector2(mirror_x, dst.y)) blend_rect(sprite, custom_brush_image, src_rect, Vector2(mirror_x, dst.y))
if vertical_mirror: if vertical_mirror:
blend_rect(layers[current_layer_index][0], custom_brush_image, src_rect, Vector2(dst.x, mirror_y)) blend_rect(sprite, custom_brush_image, src_rect, Vector2(dst.x, mirror_y))
if horizontal_mirror && vertical_mirror: if horizontal_mirror && vertical_mirror:
blend_rect(layers[current_layer_index][0], custom_brush_image, src_rect, Vector2(mirror_x, mirror_y)) blend_rect(sprite, custom_brush_image, src_rect, Vector2(mirror_x, mirror_y))
else: # if it's transparent - if it's the eraser else: # if it's transparent - if it's the eraser
var custom_brush := Image.new() var custom_brush := Image.new()
@ -770,15 +770,15 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
custom_brush.resize(custom_brush_size.x * brush_size, custom_brush_size.y * brush_size, Image.INTERPOLATE_NEAREST) custom_brush.resize(custom_brush_size.x * brush_size, custom_brush_size.y * brush_size, Image.INTERPOLATE_NEAREST)
var custom_brush_blended = Global.blend_image_with_color(custom_brush, color, 1) var custom_brush_blended = Global.blend_image_with_color(custom_brush, color, 1)
layers[current_layer_index][0].blit_rect_mask(custom_brush_blended, custom_brush, src_rect, dst) sprite.blit_rect_mask(custom_brush_blended, custom_brush, src_rect, dst)
if horizontal_mirror: if horizontal_mirror:
layers[current_layer_index][0].blit_rect_mask(custom_brush_blended, custom_brush, src_rect, Vector2(mirror_x, dst.y)) sprite.blit_rect_mask(custom_brush_blended, custom_brush, src_rect, Vector2(mirror_x, dst.y))
if vertical_mirror: if vertical_mirror:
layers[current_layer_index][0].blit_rect_mask(custom_brush_blended, custom_brush, src_rect, Vector2(dst.x, mirror_y)) sprite.blit_rect_mask(custom_brush_blended, custom_brush, src_rect, Vector2(dst.x, mirror_y))
if horizontal_mirror && vertical_mirror: if horizontal_mirror && vertical_mirror:
layers[current_layer_index][0].blit_rect_mask(custom_brush_blended, custom_brush, src_rect, Vector2(mirror_x, mirror_y)) sprite.blit_rect_mask(custom_brush_blended, custom_brush, src_rect, Vector2(mirror_x, mirror_y))
layers[current_layer_index][0].lock() sprite.lock()
sprite_changed_this_frame = true sprite_changed_this_frame = true
previous_mouse_pos_for_lines = pos.floor() + Vector2(0.5, 0.5) previous_mouse_pos_for_lines = pos.floor() + Vector2(0.5, 0.5)
@ -789,7 +789,7 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
# Bresenham's Algorithm # Bresenham's Algorithm
# Thanks to https://godotengine.org/qa/35276/tile-based-line-drawing-algorithm-efficiency # Thanks to https://godotengine.org/qa/35276/tile-based-line-drawing-algorithm-efficiency
func fill_gaps(mouse_pos : Vector2, prev_mouse_pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void: func fill_gaps(sprite : Image, mouse_pos : Vector2, prev_mouse_pos : Vector2, color : Color, current_mouse_button : String, current_action := "None") -> void:
var previous_mouse_pos_floored = prev_mouse_pos.floor() var previous_mouse_pos_floored = prev_mouse_pos.floor()
var mouse_pos_floored = mouse_pos.floor() var mouse_pos_floored = mouse_pos.floor()
mouse_pos_floored.x = clamp(mouse_pos_floored.x, location.x - 1, location.x + size.x) mouse_pos_floored.x = clamp(mouse_pos_floored.x, location.x - 1, location.x + size.x)
@ -803,7 +803,7 @@ func fill_gaps(mouse_pos : Vector2, prev_mouse_pos : Vector2, color : Color, cur
var x = previous_mouse_pos_floored.x var x = previous_mouse_pos_floored.x
var y = previous_mouse_pos_floored.y var y = previous_mouse_pos_floored.y
while !(x == mouse_pos_floored.x && y == mouse_pos_floored.y): while !(x == mouse_pos_floored.x && y == mouse_pos_floored.y):
draw_brush(Vector2(x, y), color, current_mouse_button, current_action) draw_brush(sprite, Vector2(x, y), color, current_mouse_button, current_action)
e2 = err << 1 e2 = err << 1
if e2 >= dy: if e2 >= dy:
err += dy err += dy
@ -813,9 +813,9 @@ func fill_gaps(mouse_pos : Vector2, prev_mouse_pos : Vector2, color : Color, cur
y += sy y += sy
# Thanks to https://en.wikipedia.org/wiki/Flood_fill # Thanks to https://en.wikipedia.org/wiki/Flood_fill
func flood_fill(pos : Vector2, target_color : Color, replace_color : Color) -> void: func flood_fill(sprite : Image, pos : Vector2, target_color : Color, replace_color : Color) -> void:
pos = pos.floor() pos = pos.floor()
var pixel = layers[current_layer_index][0].get_pixelv(pos) var pixel = sprite.get_pixelv(pos)
if target_color == replace_color: if target_color == replace_color:
return return
elif pixel != target_color: elif pixel != target_color:
@ -832,20 +832,20 @@ func flood_fill(pos : Vector2, target_color : Color, replace_color : Color) -> v
break break
var west : Vector2 = n var west : Vector2 = n
var east : Vector2 = n var east : Vector2 = n
while west.x >= west_limit && layers[current_layer_index][0].get_pixelv(west) == target_color: while west.x >= west_limit && sprite.get_pixelv(west) == target_color:
west += Vector2.LEFT west += Vector2.LEFT
while east.x < east_limit && layers[current_layer_index][0].get_pixelv(east) == target_color: while east.x < east_limit && sprite.get_pixelv(east) == target_color:
east += Vector2.RIGHT east += Vector2.RIGHT
for px in range(west.x + 1, east.x): for px in range(west.x + 1, east.x):
var p := Vector2(px, n.y) var p := Vector2(px, n.y)
# Draw # Draw
layers[current_layer_index][0].set_pixelv(p, replace_color) sprite.set_pixelv(p, replace_color)
replace_color = layers[current_layer_index][0].get_pixelv(p) replace_color = sprite.get_pixelv(p)
var north := p + Vector2.UP var north := p + Vector2.UP
var south := p + Vector2.DOWN var south := p + Vector2.DOWN
if north.y >= north_limit && layers[current_layer_index][0].get_pixelv(north) == target_color: if north.y >= north_limit && sprite.get_pixelv(north) == target_color:
q.append(north) q.append(north)
if south.y < south_limit && layers[current_layer_index][0].get_pixelv(south) == target_color: if south.y < south_limit && sprite.get_pixelv(south) == target_color:
q.append(south) q.append(south)
sprite_changed_this_frame = true sprite_changed_this_frame = true

View file

@ -1,12 +1,15 @@
extends Button extends Button
var frame := 0 var frame := 0
var layer := 0
onready var popup_menu := $PopupMenu onready var popup_menu := $PopupMenu
func _on_FrameButton_pressed() -> void: func _on_FrameButton_pressed() -> void:
if Input.is_action_just_released("left_mouse"): if Input.is_action_just_released("left_mouse"):
Global.current_frame = frame Global.current_frame = frame
Global.current_layer = layer
print(str(frame), str(layer))
elif Input.is_action_just_released("right_mouse"): elif Input.is_action_just_released("right_mouse"):
if Global.canvases.size() == 1: if Global.canvases.size() == 1:
popup_menu.set_item_disabled(0, true) popup_menu.set_item_disabled(0, true)
@ -30,7 +33,7 @@ func _on_PopupMenu_id_pressed(ID : int) -> void:
0: #Remove Frame 0: #Remove Frame
remove_frame() remove_frame()
1: #Clone Layer 1: # Clone Layer
var canvas : Canvas = Global.canvases[frame] var canvas : Canvas = Global.canvases[frame]
var new_canvas : Canvas = load("res://Prefabs/Canvas.tscn").instance() var new_canvas : Canvas = load("res://Prefabs/Canvas.tscn").instance()
new_canvas.size = Global.canvas.size new_canvas.size = Global.canvas.size
@ -58,7 +61,7 @@ func _on_PopupMenu_id_pressed(ID : int) -> void:
Global.undo_redo.add_do_property(Global, "hidden_canvases", Global.hidden_canvases) Global.undo_redo.add_do_property(Global, "hidden_canvases", Global.hidden_canvases)
Global.undo_redo.add_do_property(Global, "canvas", new_canvas) Global.undo_redo.add_do_property(Global, "canvas", new_canvas)
Global.undo_redo.add_do_property(Global, "current_frame", new_canvases.size() - 1) Global.undo_redo.add_do_property(Global, "current_frame", new_canvases.size() - 1)
for child in Global.frame_container.get_children(): for child in Global.frame_containers.get_children():
var frame_button = child.get_node("FrameButton") var frame_button = child.get_node("FrameButton")
Global.undo_redo.add_do_property(frame_button, "pressed", false) Global.undo_redo.add_do_property(frame_button, "pressed", false)
Global.undo_redo.add_undo_property(frame_button, "pressed", frame_button.pressed) Global.undo_redo.add_undo_property(frame_button, "pressed", frame_button.pressed)

View file

@ -13,7 +13,9 @@ var undos := 0 # The number of times we added undo properties
var saved := true # Checks if the user has saved var saved := true # Checks if the user has saved
# Canvas related stuff # Canvas related stuff
var layers := []
var current_frame := 0 setget frame_changed var current_frame := 0 setget frame_changed
var current_layer := 0
# warning-ignore:unused_class_variable # warning-ignore:unused_class_variable
var can_draw := false var can_draw := false
# warning-ignore:unused_class_variable # warning-ignore:unused_class_variable
@ -223,14 +225,14 @@ var right_mirror_container : Container
var animation_timeline : Panel var animation_timeline : Panel
var animation_timer : Timer var animation_timer : Timer
var frame_ids : HBoxContainer
var current_frame_label : Label var current_frame_label : Label
var loop_animation_button : BaseButton var loop_animation_button : BaseButton
var play_forward : BaseButton var play_forward : BaseButton
var play_backwards : BaseButton var play_backwards : BaseButton
var timeline_seconds : Control var timeline_seconds : Control
var frame_container : HBoxContainer var layer_and_frame_container : GridContainer
var vbox_layer_container : VBoxContainer
var remove_layer_button : BaseButton var remove_layer_button : BaseButton
var move_up_layer_button : BaseButton var move_up_layer_button : BaseButton
var move_down_layer_button : BaseButton var move_down_layer_button : BaseButton
@ -340,24 +342,23 @@ func _ready() -> void:
animation_timeline = find_node_by_name(root, "AnimationTimeline") animation_timeline = find_node_by_name(root, "AnimationTimeline")
layer_and_frame_container = find_node_by_name(animation_timeline, "LayersAndFrames")
animation_timer = find_node_by_name(animation_timeline, "AnimationTimer") animation_timer = find_node_by_name(animation_timeline, "AnimationTimer")
frame_ids = find_node_by_name(animation_timeline, "FrameIDs")
current_frame_label = find_node_by_name(animation_timeline, "CurrentFrame") current_frame_label = find_node_by_name(animation_timeline, "CurrentFrame")
loop_animation_button = find_node_by_name(animation_timeline, "LoopAnim") loop_animation_button = find_node_by_name(animation_timeline, "LoopAnim")
play_forward = find_node_by_name(animation_timeline, "PlayForward") play_forward = find_node_by_name(animation_timeline, "PlayForward")
play_backwards = find_node_by_name(animation_timeline, "PlayBackwards") play_backwards = find_node_by_name(animation_timeline, "PlayBackwards")
timeline_seconds = find_node_by_name(animation_timeline, "TimelineSeconds")
frame_container = find_node_by_name(animation_timeline, "FrameContainer")
var layer_stuff_container = find_node_by_name(root, "LayerVBoxContainer") #var layer_stuff_container = find_node_by_name(animation_timeline, "LayerVBoxContainer")
var layer_buttons = find_node_by_name(layer_stuff_container, "LayerButtons")
remove_layer_button = find_node_by_name(layer_buttons, "RemoveLayer")
move_up_layer_button = find_node_by_name(layer_buttons, "MoveUpLayer")
move_down_layer_button = find_node_by_name(layer_buttons, "MovwDownLayer")
merge_down_layer_button = find_node_by_name(layer_buttons, "MergeDownLayer")
layer_opacity_slider = find_node_by_name(layer_stuff_container, "OpacitySlider") remove_layer_button = find_node_by_name(animation_timeline, "RemoveLayer")
layer_opacity_spinbox = find_node_by_name(layer_stuff_container, "OpacitySpinBox") move_up_layer_button = find_node_by_name(animation_timeline, "MoveUpLayer")
vbox_layer_container = find_node_by_name(layer_stuff_container, "VBoxLayerContainer") move_down_layer_button = find_node_by_name(animation_timeline, "MovwDownLayer")
merge_down_layer_button = find_node_by_name(animation_timeline, "MergeDownLayer")
layer_opacity_slider = find_node_by_name(animation_timeline, "OpacitySlider")
layer_opacity_spinbox = find_node_by_name(animation_timeline, "OpacitySpinBox")
add_palette_button = find_node_by_name(root, "AddPalette") add_palette_button = find_node_by_name(root, "AddPalette")
edit_palette_button = find_node_by_name(root, "EditPalette") edit_palette_button = find_node_by_name(root, "EditPalette")
@ -370,6 +371,10 @@ func _ready() -> void:
error_dialog = find_node_by_name(root, "ErrorDialog") error_dialog = find_node_by_name(root, "ErrorDialog")
# Store [layer name, frame container]
layers.append([tr("Layer") + " 0", HBoxContainer.new()])
layer_and_frame_container.add_child(layers[0][1])
# Thanks to https://godotengine.org/qa/17524/how-to-find-an-instanced-scene-by-its-name # Thanks to https://godotengine.org/qa/17524/how-to-find-an-instanced-scene-by-its-name
func find_node_by_name(root, node_name) -> Node: func find_node_by_name(root, node_name) -> Node:
if root.get_name() == node_name: if root.get_name() == node_name:
@ -412,7 +417,7 @@ func undo(_canvases : Array, layer_index : int = -1) -> void:
if action_name == "Add Frame": if action_name == "Add Frame":
canvas_parent.remove_child(_canvases[0]) canvas_parent.remove_child(_canvases[0])
frame_container.remove_child(_canvases[0].frame_button) layer_and_frame_container.remove_child(_canvases[0].frame_button)
# This actually means that canvases.size is one, but it hasn't been updated yet # This actually means that canvases.size is one, but it hasn't been updated yet
if canvases.size() == 2: # Stop animating if canvases.size() == 2: # Stop animating
play_forward.pressed = false play_forward.pressed = false
@ -421,10 +426,10 @@ func undo(_canvases : Array, layer_index : int = -1) -> void:
elif action_name == "Remove Frame": elif action_name == "Remove Frame":
canvas_parent.add_child(_canvases[0]) canvas_parent.add_child(_canvases[0])
canvas_parent.move_child(_canvases[0], _canvases[0].frame) canvas_parent.move_child(_canvases[0], _canvases[0].frame)
frame_container.add_child(_canvases[0].frame_button) layer_and_frame_container.add_child(_canvases[0].frame_button)
frame_container.move_child(_canvases[0].frame_button, _canvases[0].frame) layer_and_frame_container.move_child(_canvases[0].frame_button, _canvases[0].frame)
elif action_name == "Change Frame Order": elif action_name == "Change Frame Order":
frame_container.move_child(_canvases[0].frame_button, _canvases[0].frame) layer_and_frame_container.move_child(_canvases[0].frame_button, _canvases[0].frame)
canvas_parent.move_child(_canvases[0], _canvases[0].frame) canvas_parent.move_child(_canvases[0], _canvases[0].frame)
canvas.update() canvas.update()
@ -448,26 +453,49 @@ func redo(_canvases : Array, layer_index : int = -1) -> void:
if action_name == "Scale": if action_name == "Scale":
c.camera_zoom() c.camera_zoom()
if "Layer" in action_name: if action_name == "Add Layer":
var current_layer_index : int = _canvases[0].current_layer_index var layer_container = load("res://Prefabs/LayerContainer.tscn").instance()
_canvases[0].generate_layer_panels() _canvases[0].layers[current_layer][2] = tr("Layer") + " %s" % current_layer
if action_name == "Change Layer Order": layer_container.i = current_layer
_canvases[0].current_layer_index = current_layer_index layer_container.get_child(0).get_child(1).text = _canvases[0].layers[current_layer][2]
_canvases[0].get_layer_container(current_layer_index).changed_selection() layer_container.get_child(0).get_child(2).text = _canvases[0].layers[current_layer][2]
layer_and_frame_container.add_child(layer_container)
layer_and_frame_container.move_child(layer_container, 0)
layer_and_frame_container.add_child(layers[current_layer][1])
layer_and_frame_container.move_child(layers[current_layer][1], 1)
for i in range(canvases.size()):
var frame_button = load("res://Prefabs/FrameButton.tscn").instance()
frame_button.frame = i
frame_button.layer = current_layer
frame_button.pressed = true
layers[current_layer][1].add_child(frame_button)
# if action_name == "Change Layer Order":
# var current_layer_index : int = _canvases[0].current_layer_index
# _canvases[0].current_layer_index = current_layer_index
# _canvases[0].get_layer_container(current_layer_index).changed_selection()
if action_name == "Add Frame": if action_name == "Add Frame":
canvas_parent.add_child(_canvases[0]) canvas_parent.add_child(_canvases[0])
if !Global.frame_container.is_a_parent_of(_canvases[0].frame_button): var label := Label.new()
Global.frame_container.add_child(_canvases[0].frame_button) label.rect_min_size.x = 36
label.align = Label.ALIGN_CENTER
label.text = str(canvases.size() + 1)
frame_ids.add_child(label)
if !layer_and_frame_container.is_a_parent_of(_canvases[0].frame_button):
layer_and_frame_container.add_child(_canvases[0].frame_button)
elif action_name == "Remove Frame": elif action_name == "Remove Frame":
canvas_parent.remove_child(_canvases[0]) canvas_parent.remove_child(_canvases[0])
frame_container.remove_child(_canvases[0].frame_button) layer_and_frame_container.remove_child(_canvases[0].frame_button)
if canvases.size() == 1: # Stop animating if canvases.size() == 1: # Stop animating
play_forward.pressed = false play_forward.pressed = false
play_backwards.pressed = false play_backwards.pressed = false
animation_timer.stop() animation_timer.stop()
elif action_name == "Change Frame Order": elif action_name == "Change Frame Order":
frame_container.move_child(_canvases[0].frame_button, _canvases[0].frame) layer_and_frame_container.move_child(_canvases[0].frame_button, _canvases[0].frame)
canvas_parent.move_child(_canvases[0], _canvases[0].frame) canvas_parent.move_child(_canvases[0], _canvases[0].frame)
canvas.update() canvas.update()
@ -491,18 +519,17 @@ func frame_changed(value : int) -> void:
c.line_2d.set_point_position(1, c.line_2d.points[0]) c.line_2d.set_point_position(1, c.line_2d.points[0])
canvas = canvases[current_frame] canvas = canvases[current_frame]
canvas.visible = true canvas.visible = true
canvas.generate_layer_panels() #canvas.generate_layer_panels()
# Make all frame buttons unpressed # Make all frame buttons unpressed
for c in canvases: for c in canvases:
var text_color := Color.white var text_color := Color.white
if theme_type == "Gold" || theme_type == "Light": if theme_type == "Gold" || theme_type == "Light":
text_color = Color.black text_color = Color.black
c.frame_button.get_node("FrameButton").pressed = false c.frame_button.pressed = false
c.frame_button.get_node("FrameID").add_color_override("font_color", text_color) #c.frame_button.get_node("FrameID").add_color_override("font_color", text_color)
# Make only the current frame button pressed # Make only the current frame button pressed
canvas.frame_button.get_node("FrameButton").pressed = true canvas.frame_button.pressed = true
canvas.frame_button.get_node("FrameID").add_color_override("font_color", Color("#3c5d75")) #canvas.frame_button.get_node("FrameID").add_color_override("font_color", Color("#3c5d75"))
func create_brush_button(brush_img : Image, brush_type := Brush_Types.CUSTOM, hint_tooltip := "") -> void: func create_brush_button(brush_img : Image, brush_type := Brush_Types.CUSTOM, hint_tooltip := "") -> void:
var brush_container var brush_container

View file

@ -1,16 +1,16 @@
class_name LayerContainer class_name LayerContainer
extends Button extends Button
var i var i := 0
# warning-ignore:unused_class_variable # warning-ignore:unused_class_variable
var currently_selected := false var currently_selected := false
onready var visibility_button := $VisibilityButton onready var visibility_button := $HBoxContainer/VisibilityButton
onready var label := $HBoxContainer/Label onready var label := $HBoxContainer/Label
onready var line_edit := $HBoxContainer/LineEdit onready var line_edit := $HBoxContainer/LineEdit
func _ready() -> void: func _ready() -> void:
changed_selection() #changed_selection()
if Global.canvas.layers[i][3]: if Global.canvas.layers[i][3]:
visibility_button.texture_normal = load("res://Assets/Graphics/%s Themes/Layers/Layer_Visible.png" % Global.theme_type) visibility_button.texture_normal = load("res://Assets/Graphics/%s Themes/Layers/Layer_Visible.png" % Global.theme_type)
visibility_button.texture_hover = load("res://Assets/Graphics/%s Themes/Layers/Layer_Visible_Hover.png" % Global.theme_type) visibility_button.texture_hover = load("res://Assets/Graphics/%s Themes/Layers/Layer_Visible_Hover.png" % Global.theme_type)
@ -27,8 +27,8 @@ func _input(event : InputEvent) -> void:
func _on_LayerContainer_pressed() -> void: func _on_LayerContainer_pressed() -> void:
var initially_pressed := pressed var initially_pressed := pressed
var label_initially_visible : bool = label.visible var label_initially_visible : bool = label.visible
Global.canvas.current_layer_index = i # Global.canvas.current_layer_index = i
changed_selection() # changed_selection()
if !initially_pressed: if !initially_pressed:
if label_initially_visible: if label_initially_visible:
label.visible = false label.visible = false
@ -44,14 +44,15 @@ func changed_selection() -> void:
var parent := get_parent() var parent := get_parent()
for child in parent.get_children(): for child in parent.get_children():
if child is Button: if child is Button:
#print(child.name)
child.label.visible = true child.label.visible = true
child.line_edit.visible = false child.line_edit.visible = false
child.line_edit.editable = false child.line_edit.editable = false
if Global.canvas.current_layer_index == child.i: # The selected layer if Global.canvas.current_layer_index == child.i: # The selected layer
child.currently_selected = true child.currently_selected = true
child.pressed = true child.pressed = true
Global.layer_opacity_slider.value = Global.canvas.layers[child.i][4] * 100 Global.layer_opacity_slider.value = Global.canvas.layers[child.i][3] * 100
Global.layer_opacity_spinbox.value = Global.canvas.layers[child.i][4] * 100 Global.layer_opacity_spinbox.value = Global.canvas.layers[child.i][3] * 100
if Global.canvas.current_layer_index < Global.canvas.layers.size() - 1: if Global.canvas.current_layer_index < Global.canvas.layers.size() - 1:
Global.move_up_layer_button.disabled = false Global.move_up_layer_button.disabled = false
@ -86,5 +87,5 @@ func _on_VisibilityButton_pressed() -> void:
Global.canvas.update() Global.canvas.update()
func _on_LineEdit_text_changed(new_text : String) -> void: func _on_LineEdit_text_changed(new_text : String) -> void:
Global.canvas.layers[i][2] = new_text Global.layers[i][0] = new_text
label.text = new_text label.text = new_text

View file

@ -406,9 +406,10 @@ func _on_OpenSprite_file_selected(path : String) -> void:
Global.canvas = canvas Global.canvas = canvas
var width := file.get_16() var width := file.get_16()
var height := file.get_16() var height := file.get_16()
print(width, height)
var layer_line := file.get_line() var layer_line := file.get_line()
while layer_line == "-": #Load layers while layer_line == "-": # Load layers
var buffer := file.get_buffer(width * height * 4) var buffer := file.get_buffer(width * height * 4)
var layer_name := file.get_line() var layer_name := file.get_line()
var layer_transparency := 1.0 var layer_transparency := 1.0
@ -507,7 +508,7 @@ func _on_SaveSprite_file_selected(path : String) -> void:
file.store_float(layer[4]) # Layer transparency file.store_float(layer[4]) # Layer transparency
file.store_line("END_LAYERS") file.store_line("END_LAYERS")
for child in canvas.get_children(): #Store guides for child in canvas.get_children(): # Store guides
if child is Guide: if child is Guide:
file.store_line("|") file.store_line("|")
file.store_8(child.type) file.store_8(child.type)
@ -554,7 +555,7 @@ func clear_canvases() -> void:
for child in Global.vbox_layer_container.get_children(): for child in Global.vbox_layer_container.get_children():
if child is PanelContainer: if child is PanelContainer:
child.queue_free() child.queue_free()
for child in Global.frame_container.get_children(): for child in Global.frame_containers.get_children():
child.queue_free() child.queue_free()
for child in Global.canvas_parent.get_children(): for child in Global.canvas_parent.get_children():
if child is Canvas: if child is Canvas:
@ -687,86 +688,6 @@ func _on_RightBrushSizeEdit_value_changed(value) -> void:
Global.right_brush_size = new_size Global.right_brush_size = new_size
update_right_custom_brush() update_right_custom_brush()
func add_layer(is_new := true) -> void:
var new_layer := Image.new()
var layer_name = null
if is_new:
new_layer.create(Global.canvas.size.x, Global.canvas.size.y, false, Image.FORMAT_RGBA8)
else: # clone layer
new_layer.copy_from(Global.canvas.layers[Global.canvas.current_layer_index][0])
layer_name = Global.canvas.layers[Global.canvas.current_layer_index][2] + " (" + tr("copy") + ")"
new_layer.lock()
var new_layer_tex := ImageTexture.new()
new_layer_tex.create_from_image(new_layer, 0)
var new_layers: Array = Global.canvas.layers.duplicate()
# Store [Image, ImageTexture, Layer Name, Visibity boolean, Opacity]
new_layers.append([new_layer, new_layer_tex, layer_name, true, 1])
Global.undos += 1
Global.undo_redo.create_action("Add Layer")
Global.undo_redo.add_do_property(Global.canvas, "layers", new_layers)
Global.undo_redo.add_undo_property(Global.canvas, "layers", Global.canvas.layers)
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
Global.undo_redo.commit_action()
func _on_RemoveLayerButton_pressed() -> void:
var new_layers: Array = Global.canvas.layers.duplicate()
new_layers.remove(Global.canvas.current_layer_index)
Global.undos += 1
Global.undo_redo.create_action("Remove Layer")
Global.undo_redo.add_do_property(Global.canvas, "layers", new_layers)
Global.undo_redo.add_undo_property(Global.canvas, "layers", Global.canvas.layers)
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
Global.undo_redo.commit_action()
func change_layer_order(rate : int) -> void:
var change = Global.canvas.current_layer_index + rate
var new_layers: Array = Global.canvas.layers.duplicate()
var temp = new_layers[Global.canvas.current_layer_index]
new_layers[Global.canvas.current_layer_index] = new_layers[change]
new_layers[change] = temp
Global.undo_redo.create_action("Change Layer Order")
Global.undo_redo.add_do_property(Global.canvas, "layers", new_layers)
Global.undo_redo.add_do_property(Global.canvas, "current_layer_index", change)
Global.undo_redo.add_undo_property(Global.canvas, "layers", Global.canvas.layers)
Global.undo_redo.add_undo_property(Global.canvas, "current_layer_index", Global.canvas.current_layer_index)
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
Global.undo_redo.commit_action()
func _on_MergeLayer_pressed() -> void:
var new_layers: Array = Global.canvas.layers.duplicate()
new_layers.remove(Global.canvas.current_layer_index)
var selected_layer = Global.canvas.layers[Global.canvas.current_layer_index][0]
if Global.canvas.layers[Global.canvas.current_layer_index][4] < 1: # If we have layer transparency
for xx in selected_layer.get_size().x:
for yy in selected_layer.get_size().y:
var pixel_color : Color = selected_layer.get_pixel(xx, yy)
var alpha : float = pixel_color.a * Global.canvas.layers[Global.canvas.current_layer_index][4]
selected_layer.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
var new_layer := Image.new()
new_layer.copy_from(Global.canvas.layers[Global.canvas.current_layer_index - 1][0])
new_layer.lock()
Global.canvas.blend_rect(new_layer, selected_layer, Rect2(Global.canvas.position, Global.canvas.size), Vector2.ZERO)
Global.undos += 1
Global.undo_redo.create_action("Merge Layer")
Global.undo_redo.add_do_property(Global.canvas, "layers", new_layers)
Global.undo_redo.add_do_property(Global.canvas.layers[Global.canvas.current_layer_index - 1][0], "data", new_layer.data)
Global.undo_redo.add_undo_property(Global.canvas, "layers", Global.canvas.layers)
Global.undo_redo.add_undo_property(Global.canvas.layers[Global.canvas.current_layer_index - 1][0], "data", Global.canvas.layers[Global.canvas.current_layer_index - 1][0].data)
Global.undo_redo.add_undo_method(Global, "undo", [Global.canvas])
Global.undo_redo.add_do_method(Global, "redo", [Global.canvas])
Global.undo_redo.commit_action()
func _on_ColorSwitch_pressed() -> void: func _on_ColorSwitch_pressed() -> void:
var temp: Color = Global.left_color_picker.color var temp: Color = Global.left_color_picker.color