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://Assets/Graphics/Dark Themes/Timeline/Go_To_First_Frame.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/Timeline/Previous_Frame.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/Timeline/Play Backwards.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/Timeline/Play Backwards_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/Timeline/Play_Hover.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/Timeline/Next_Frame_Hover.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/Timeline/Go_To_Last_Frame_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://Scripts/Rulers/TimelineSeconds.gd" type="Script" 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/Timeline/New_Frame_Hover.png" type="Texture" id=18]
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/New_Layer.png" type="Texture" id=2]
[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/Layers/Delete_Layer.png" type="Texture" id=4]
[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/Layers/Delete_Layer_Disabled.png" type="Texture" id=6]
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Up.png" type="Texture" id=7]
[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/Layers/Move_Up_Disabled.png" type="Texture" id=9]
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Move_Down.png" type="Texture" id=10]
[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/Layers/Move_Down_Disabled.png" type="Texture" id=12]
[ext_resource path="res://Assets/Graphics/Dark Themes/Layers/Clone_Layer.png" type="Texture" id=13]
[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/Layers/Merge_Down.png" type="Texture" id=15]
[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/Layers/Merge_Down_Disabled.png" type="Texture" id=17]
[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]
control = true
@ -64,19 +80,17 @@ scancode = 16777230
shortcut = SubResource( 11 )
[node name="AnimationTimeline" type="Panel"]
margin_top = 478.0
margin_top = 438.0
margin_right = 704.0
margin_bottom = 620.0
rect_min_size = Vector2( 0, 142 )
rect_min_size = Vector2( 0, 200 )
size_flags_horizontal = 3
script = ExtResource( 1 )
[node name="VSeparator" type="VSeparator" parent="."]
anchor_top = 0.5
anchor_bottom = 0.5
margin_top = -71.0
anchor_bottom = 1.0
margin_right = 4.0
margin_bottom = 71.0
size_flags_vertical = 3
[node name="AnimationContainer" type="HBoxContainer" parent="."]
anchor_right = 1.0
@ -86,26 +100,218 @@ margin_top = 4.0
[node name="TimelineContainer" type="VBoxContainer" parent="AnimationContainer"]
margin_right = 543.0
margin_bottom = 138.0
margin_bottom = 196.0
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_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
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 )
[node name="CurrentFrame" type="Label" parent="AnimationContainer/TimelineContainer/AnimationButtons"]
margin_top = 5.0
margin_right = 218.0
margin_right = 117.0
margin_bottom = 19.0
size_flags_horizontal = 3
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"]
margin_left = 222.0
margin_right = 362.0
editor/display_folded = true
margin_left = 223.0
margin_right = 363.0
margin_bottom = 24.0
size_flags_horizontal = 2
size_flags_horizontal = 6
[node name="FirstFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons",
@ -116,8 +322,8 @@ hint_tooltip = "FIRSTFRAME_HT"
mouse_default_cursor_shape = 2
shortcut_in_tooltip = false
shortcut = SubResource( 2 )
texture_normal = ExtResource( 2 )
texture_hover = ExtResource( 3 )
texture_normal = ExtResource( 21 )
texture_hover = ExtResource( 22 )
[node name="PreviousFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons",
@ -129,8 +335,8 @@ hint_tooltip = "PREVIOUSFRAME_HT"
mouse_default_cursor_shape = 2
shortcut_in_tooltip = false
shortcut = SubResource( 4 )
texture_normal = ExtResource( 4 )
texture_hover = ExtResource( 5 )
texture_normal = ExtResource( 23 )
texture_hover = ExtResource( 24 )
[node name="PlayBackwards" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons",
@ -143,9 +349,9 @@ mouse_default_cursor_shape = 2
toggle_mode = true
shortcut_in_tooltip = false
shortcut = SubResource( 6 )
texture_normal = ExtResource( 6 )
texture_pressed = ExtResource( 7 )
texture_hover = ExtResource( 8 )
texture_normal = ExtResource( 25 )
texture_pressed = ExtResource( 26 )
texture_hover = ExtResource( 27 )
[node name="PlayForward" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons",
@ -159,9 +365,9 @@ size_flags_horizontal = 0
toggle_mode = true
shortcut_in_tooltip = false
shortcut = SubResource( 8 )
texture_normal = ExtResource( 9 )
texture_pressed = ExtResource( 7 )
texture_hover = ExtResource( 10 )
texture_normal = ExtResource( 28 )
texture_pressed = ExtResource( 26 )
texture_hover = ExtResource( 29 )
[node name="NextFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons",
@ -173,8 +379,8 @@ hint_tooltip = "NEXTFRAME_HT"
mouse_default_cursor_shape = 2
shortcut_in_tooltip = false
shortcut = SubResource( 10 )
texture_normal = ExtResource( 11 )
texture_hover = ExtResource( 12 )
texture_normal = ExtResource( 30 )
texture_hover = ExtResource( 31 )
[node name="LastFrame" type="TextureButton" parent="AnimationContainer/TimelineContainer/AnimationButtons/PlaybackButtons" groups=[
"UIButtons",
@ -186,12 +392,12 @@ hint_tooltip = "LASTFRAME_HT"
mouse_default_cursor_shape = 2
shortcut_in_tooltip = false
shortcut = SubResource( 12 )
texture_normal = ExtResource( 13 )
texture_hover = ExtResource( 14 )
texture_normal = ExtResource( 32 )
texture_hover = ExtResource( 33 )
[node name="LoopButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/AnimationButtons"]
margin_left = 444.0
margin_right = 542.0
margin_left = 445.0
margin_right = 543.0
margin_bottom = 24.0
size_flags_horizontal = 0
@ -214,60 +420,17 @@ margin_right = 98.0
margin_bottom = 24.0
hint_tooltip = "No loop"
mouse_default_cursor_shape = 2
texture_normal = ExtResource( 15 )
[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"]
texture_normal = ExtResource( 34 )
[node name="VSeparator" type="VSeparator" parent="AnimationContainer"]
margin_left = 547.0
margin_right = 551.0
margin_bottom = 138.0
margin_bottom = 196.0
[node name="OnionSkinningButtons" type="VBoxContainer" parent="AnimationContainer"]
margin_left = 555.0
margin_right = 681.0
margin_bottom = 138.0
margin_bottom = 196.0
[node name="OnionSkinning" type="Label" parent="AnimationContainer/OnionSkinningButtons"]
margin_right = 126.0
@ -310,9 +473,18 @@ text = "Blue-Red Mode"
[node name="VSeparator2" type="VSeparator" parent="AnimationContainer"]
margin_left = 685.0
margin_right = 689.0
margin_bottom = 138.0
margin_bottom = 196.0
[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/PreviousFrame" to="." method="_on_PreviousFrame_pressed"]
[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="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/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/FutureOnionSkinning" to="." method="_on_FutureOnionSkinning_value_changed"]
[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]
[node name="Frame" type="VBoxContainer"]
margin_right = 32.0
margin_bottom = 50.0
[node name="FrameButton" type="Button" parent="."]
[node name="FrameButton" type="Button"]
margin_top = 18.0
margin_right = 36.0
margin_bottom = 36.0
margin_bottom = 54.0
rect_min_size = Vector2( 36, 36 )
mouse_default_cursor_shape = 2
size_flags_horizontal = 0
@ -17,7 +14,7 @@ toggle_mode = true
button_mask = 7
script = ExtResource( 1 )
[node name="FrameTexture" type="TextureRect" parent="FrameButton"]
[node name="FrameTexture" type="TextureRect" parent="."]
margin_left = 2.0
margin_top = 2.0
margin_right = 34.0
@ -28,17 +25,10 @@ size_flags_vertical = 0
expand = true
stretch_mode = 6
[node name="PopupMenu" type="PopupMenu" parent="FrameButton"]
[node name="PopupMenu" type="PopupMenu" parent="."]
margin_right = 20.0
margin_bottom = 20.0
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 ]
[node name="FrameID" type="Label" parent="."]
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"]
[connection signal="pressed" from="." to="." method="_on_FrameButton_pressed"]
[connection signal="id_pressed" from="PopupMenu" to="." 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]
[node name="LayerContainer" type="Button"]
margin_right = 160.0
margin_bottom = 42.0
rect_min_size = Vector2( 160, 42 )
margin_right = 210.0
margin_bottom = 36.0
rect_min_size = Vector2( 212, 36 )
toggle_mode = true
script = ExtResource( 1 )
__meta__ = {
"_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",
]]
margin_left = 6.0
margin_top = 5.0
margin_right = 38.0
margin_bottom = 37.0
margin_left = 65.0
margin_right = 97.0
margin_bottom = 32.0
hint_tooltip = "LAYERVISIBILITY_HT"
mouse_default_cursor_shape = 2
size_flags_horizontal = 0
@ -28,29 +36,10 @@ size_flags_vertical = 4
texture_normal = ExtResource( 2 )
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"]
margin_left = 36.0
margin_left = 101.0
margin_top = 9.0
margin_right = 82.0
margin_right = 147.0
margin_bottom = 23.0
text = "Layer 0"
align = 1
@ -68,5 +57,5 @@ editable = false
caret_blink = true
caret_blink_speed = 0.5
[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"]

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, "canvas", new_canvas)
Global.undo_redo.add_do_property(Global, "current_frame", new_canvases.size() - 1)
for child in Global.frame_container.get_children():
var frame_button = child.get_node("FrameButton")
Global.undo_redo.add_do_property(frame_button, "pressed", false)
Global.undo_redo.add_undo_property(frame_button, "pressed", frame_button.pressed)
for i in range(Global.layers.size()):
for child in Global.layers[i][1].get_children():
Global.undo_redo.add_do_property(child, "pressed", false)
Global.undo_redo.add_undo_property(child, "pressed", child.pressed)
for c in Global.canvases:
Global.undo_redo.add_do_property(c, "visible", false)
Global.undo_redo.add_undo_property(c, "visible", c.visible)
@ -39,18 +39,15 @@ func add_frame() -> void:
func _on_LoopAnim_pressed() -> void:
match animation_loop:
0:
# Make it loop
0: # Make it loop
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.hint_tooltip = "Cycle loop"
1:
# Make it ping-pong
1: # Make it ping-pong
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.hint_tooltip = "Ping-pong loop"
2:
# Make it stop
2: # Make it stop
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.hint_tooltip = "No loop"
@ -101,13 +98,13 @@ func _on_AnimationTimer_timeout() -> void:
Global.current_frame += 1
else:
match animation_loop:
0: #No loop
0: # No loop
Global.play_forward.pressed = false
Global.play_backwards.pressed = false
Global.animation_timer.stop()
1: #Cycle loop
1: # Cycle loop
Global.current_frame = 0
2: #Ping pong loop
2: # Ping pong loop
animation_forward = false
_on_AnimationTimer_timeout()
@ -116,13 +113,13 @@ func _on_AnimationTimer_timeout() -> void:
Global.current_frame -= 1
else:
match animation_loop:
0: #No loop
0: # No loop
Global.play_backwards.pressed = false
Global.play_forward.pressed = false
Global.animation_timer.stop()
1: #Cycle loop
1: # Cycle loop
Global.current_frame = Global.canvases.size() - 1
2: #Ping pong loop
2: # Ping pong loop
animation_forward = true
_on_AnimationTimer_timeout()
@ -142,3 +139,104 @@ func _on_FutureOnionSkinning_value_changed(value) -> void:
func _on_BlueRedMode_toggled(button_pressed) -> void:
Global.onion_skinning_blue_red = button_pressed
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 fill_color := Color(0, 0, 0, 0)
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 previous_mouse_pos := Vector2.ZERO
var previous_mouse_pos_for_lines := Vector2.ZERO
@ -31,40 +29,38 @@ var pen_pressure := 1.0 # For tablet pressure sensitivity
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
# The sprite itself
if layers.empty():
var sprite := Image.new()
if Global.is_default_image:
if Global.config_cache.has_section_key("preferences", "default_width"):
size.x = Global.config_cache.get_value("preferences", "default_width")
if Global.config_cache.has_section_key("preferences", "default_height"):
size.y = Global.config_cache.get_value("preferences", "default_height")
if Global.config_cache.has_section_key("preferences", "default_fill_color"):
fill_color = Global.config_cache.get_value("preferences", "default_fill_color")
Global.is_default_image = !Global.is_default_image
var fill_layers := layers.empty()
for i in range(Global.layers.size()):
print(i)
if fill_layers:
# The sprite itself
var sprite := Image.new()
if Global.is_default_image:
if Global.config_cache.has_section_key("preferences", "default_width"):
size.x = Global.config_cache.get_value("preferences", "default_width")
if Global.config_cache.has_section_key("preferences", "default_height"):
size.y = Global.config_cache.get_value("preferences", "default_height")
if Global.config_cache.has_section_key("preferences", "default_fill_color"):
fill_color = Global.config_cache.get_value("preferences", "default_fill_color")
Global.is_default_image = !Global.is_default_image
sprite.create(size.x, size.y, false, Image.FORMAT_RGBA8)
sprite.fill(fill_color)
sprite.lock()
sprite.create(size.x, size.y, false, Image.FORMAT_RGBA8)
sprite.fill(fill_color)
sprite.lock()
var tex := ImageTexture.new()
tex.create_from_image(sprite, 0)
var tex := ImageTexture.new()
tex.create_from_image(sprite, 0)
# Store [Image, ImageTexture, Layer Name, Visibity boolean, Opacity]
layers.append([sprite, tex, tr("Layer") + " 0", true, 1])
# Store [Image, ImageTexture, Layer Name, Opacity]
layers.append([sprite, tex, 1])
generate_layer_panels()
frame_button = load("res://Prefabs/FrameButton.tscn").instance()
frame_button.name = "Frame_%s" % frame
frame_button.get_node("FrameButton").frame = frame
frame_button.get_node("FrameButton").pressed = true
frame_button.get_node("FrameID").text = str(frame + 1)
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
var frame_button = load("res://Prefabs/FrameButton.tscn").instance()
frame_button.frame = frame
frame_button.layer = i
frame_button.pressed = true
#frame_button.get_node("FrameID").text = str(frame + 1)
#frame_button.get_node("FrameID").add_color_override("font_color", Color("#3c5d75"))
Global.layers[i][2].add_child(frame_button)
# Only handle camera zoom settings & offset on the first frame
if Global.canvases[0] == self:
@ -79,8 +75,8 @@ func _ready() -> void:
func _draw() -> void:
draw_texture_rect(Global.transparent_background, Rect2(location, size), true) #Draw transparent background
#Onion Skinning
#Past
# Onion Skinning
# Past
if Global.onion_skinning_past_rate > 0:
var color : Color
if Global.onion_skinning_blue_red:
@ -89,11 +85,11 @@ func _draw() -> void:
color = Color.white
for i in range(1, Global.onion_skinning_past_rate + 1):
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
draw_texture(texture[1], location, color)
draw_texture(layer[1], location, color)
#Future
# Future
if Global.onion_skinning_future_rate > 0:
var color : Color
if Global.onion_skinning_blue_red:
@ -102,44 +98,44 @@ func _draw() -> void:
color = Color.white
for i in range(1, Global.onion_skinning_future_rate + 1):
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
draw_texture(texture[1], location, color)
draw_texture(layer[1], location, color)
#Draw current frame layers
for texture in layers:
var modulate_color := Color(1, 1, 1, texture[4])
if texture[3]: #if it's visible
draw_texture(texture[1], location, modulate_color)
# Draw current frame layers
for i in range(layers.size()):
var modulate_color := Color(1, 1, 1, layers[i][2])
if Global.layers[i][1]: # if it's visible
draw_texture(layers[i][1], location, modulate_color)
if Global.tile_mode:
draw_texture(texture[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(texture[1], Vector2(location.x - size.x, location.y), modulate_color) #Left
draw_texture(texture[1], location - size, modulate_color) #Up left
draw_texture(texture[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(texture[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], Vector2(location.x, location.y + size.y), modulate_color) #Down
draw_texture(layers[i][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), modulate_color) #Left
draw_texture(layers[i][1], location - size, modulate_color) #Up left
draw_texture(layers[i][1], Vector2(location.x, location.y - size.y), modulate_color) #Up
draw_texture(layers[i][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), modulate_color) #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:
for x in range(0, size.x, Global.grid_width):
draw_line(Vector2(x, location.y), Vector2(x, size.y), Global.grid_color, true)
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 rectangle to indicate the pixel currently being hovered on
# Draw rectangle to indicate the pixel currently being hovered on
var mouse_pos := current_pixel
if point_in_rectangle(mouse_pos, location, location + size):
mouse_pos = mouse_pos.floor()
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":
var start_pos_x = mouse_pos.x - (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)
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":
draw_set_transform(mouse_pos, rotation, scale)
for rect in Global.left_circle_points:
@ -152,12 +148,12 @@ func _draw() -> void:
draw_texture(Global.custom_left_brush_texture, dst)
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":
var start_pos_x = mouse_pos.x - (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)
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":
draw_set_transform(mouse_pos, rotation, scale)
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
sprite_changed_this_frame = false
var sprite : Image = layers[Global.current_layer][0]
var mouse_pos := current_pixel
var mouse_pos_floored := mouse_pos.floor()
var mouse_pos_ceiled := mouse_pos.ceil()
@ -292,9 +289,9 @@ func _input(event : InputEvent) -> void:
match current_action: # Handle current tool
"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":
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":
if can_handle:
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
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:
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:
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:
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
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 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:
layers[current_layer_index][0].set_pixel(xx, yy, current_color)
sprite.set_pixel(xx, yy, current_color)
sprite_changed_this_frame = true
"LightenDarken":
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
if ld == 0: # Lighten
color_changed = pixel_color.lightened(ld_amount)
else: # Darken
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":
# Check SelectionRectangle.gd for more code on Rectangle Selection
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)
"ColorPicker":
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
Global.left_color_picker.color = pixel_color
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.y = clamp(previous_mouse_pos.y, location.y, location.y + size.y)
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:
# Set camera zoom based on the sprite size
@ -454,7 +451,7 @@ func handle_undo(action : String) -> void:
var layer_index := -1
if Global.animation_timer.is_stopped(): # if we're not animating, store only the current canvas
canvases = [self]
layer_index = current_layer_index
layer_index = Global.current_layer
else: # If we're animating, store all canvases
canvases = Global.canvases
Global.undos += 1
@ -496,27 +493,29 @@ func handle_redo(action : String) -> void:
func update_texture(layer_index : int, update_frame_tex := true) -> void:
layers[layer_index][1].create_from_image(layers[layer_index][0], 0)
var layer_container := get_layer_container(layer_index)
if layer_container:
layer_container.get_child(1).get_child(0).texture = layers[layer_index][1]
if update_frame_tex:
# This code is used to update the texture in the animation timeline frame button
# but blend_rect causes major performance issues on large images
var whole_image := Image.new()
whole_image.create(size.x, size.y, false, Image.FORMAT_RGBA8)
for layer in layers:
whole_image.blend_rect(layer[0], Rect2(position, size), Vector2.ZERO)
layer[0].lock()
var whole_image_texture := ImageTexture.new()
whole_image_texture.create_from_image(whole_image, 0)
frame_texture_rect.texture = whole_image_texture
# var layer_container := get_layer_container(layer_index)
# if layer_container:
# layer_container.get_child(1).get_child(0).texture = layers[layer_index][1]
var frame_texture_rect : TextureRect
frame_texture_rect = Global.find_node_by_name(Global.layers[layer_index][2].get_child(frame),"FrameTexture")
frame_texture_rect.texture = layers[layer_index][1]
# if update_frame_tex:
# # This code is used to update the texture in the animation timeline frame button
# # but blend_rect causes major performance issues on large images
# var whole_image := Image.new()
# whole_image.create(size.x, size.y, false, Image.FORMAT_RGBA8)
# for layer in layers:
# whole_image.blend_rect(layer[0], Rect2(position, size), Vector2.ZERO)
# layer[0].lock()
# 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:
frame = value
if frame_button:
frame_button.get_node("FrameButton").frame = frame
frame_button.get_node("FrameID").text = str(frame + 1)
# if frame_button:
# frame_button.get_node("FrameButton").frame = frame
# frame_button.get_node("FrameID").text = str(frame + 1)
func get_layer_container(layer_index : int) -> LayerContainer:
for container in Global.vbox_layer_container.get_children():
@ -525,7 +524,8 @@ func get_layer_container(layer_index : int) -> LayerContainer:
return null
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:
child.queue_free()
@ -539,32 +539,31 @@ func generate_layer_panels() -> void:
for i in range(layers.size() -1, -1, -1):
var layer_container = load("res://Prefabs/LayerContainer.tscn").instance()
if !layers[i][2]:
layers[i][2] = tr("Layer") + " %s" % i
# if !layers[i][2]:
# layers[i][2] = tr("Layer") + " %s" % i
layer_container.i = i
layer_container.get_child(1).get_child(0).texture = layers[i][1]
layer_container.get_child(1).get_child(1).text = layers[i][2]
layer_container.get_child(1).get_child(2).text = layers[i][2]
Global.vbox_layer_container.add_child(layer_container)
layer_container.get_child(0).get_child(1).text = layers[i][2]
layer_container.get_child(0).get_child(2).text = layers[i][2]
Global.layer_and_frame_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:
return
if is_making_line:
fill_gaps(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)
fill_gaps(sprite, line_2d.points[1], previous_mouse_pos_for_lines, color, current_mouse_button, current_action)
draw_brush(sprite, line_2d.points[1], color, current_mouse_button, current_action)
made_line = true
else:
if point_in_rectangle(mouse_pos, location, location + size):
mouse_inside_canvas = true
# Draw
draw_brush(mouse_pos, color, current_mouse_button, current_action)
fill_gaps(mouse_pos, previous_mouse_pos, color, current_mouse_button, current_action) #Fill the gaps
draw_brush(sprite, mouse_pos, color, current_mouse_button, current_action)
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
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:
var brush_size := 1
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)):
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
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
if current_action == "Pencil" && color.a < 1:
_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)
else:
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
# Handle mirroring
var mirror_x := east_limit + west_limit - cur_pos_x - 1
var mirror_y := south_limit + north_limit - cur_pos_y - 1
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_action == "LightenDarken":
if ld == 0: # Lighten
@ -672,10 +671,24 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
mouse_press_pixels.append(pos_floored)
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
if vertical_mirror:
current_pixel_color = layers[current_layer_index][0].get_pixel(cur_pos_x, mirror_y)
if vertical_mirror:
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_action == "LightenDarken":
if ld == 0: # Lighten
_c = current_pixel_color.lightened(ld_amount)
else:
_c = current_pixel_color.darkened(ld_amount)
mouse_press_pixels.append(pos_floored)
mouse_press_pressure_values.append(pen_pressure)
layers[Global.current_layer][0].set_pixel(cur_pos_x, mirror_y, _c)
sprite_changed_this_frame = true
if horizontal_mirror && vertical_mirror:
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_action == "LightenDarken":
if ld == 0: # Lighten
@ -685,34 +698,21 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
mouse_press_pixels.append(pos_floored)
mouse_press_pressure_values.append(pen_pressure)
layers[current_layer_index][0].set_pixel(cur_pos_x, mirror_y, _c)
sprite_changed_this_frame = true
if horizontal_mirror && vertical_mirror:
current_pixel_color = layers[current_layer_index][0].get_pixel(mirror_x, mirror_y)
if current_pixel_color != _c: # don't draw the same pixel over and over
if current_action == "LightenDarken":
if ld == 0: # Lighten
_c = current_pixel_color.lightened(ld_amount)
else:
_c = current_pixel_color.darkened(ld_amount)
mouse_press_pixels.append(pos_floored)
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
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)
elif brush_type == Global.BRUSH_TYPES.CIRCLE || 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
var mirror_x := east_limit + west_limit - pos.x
var mirror_y := south_limit + north_limit - pos.y
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:
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:
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
@ -755,13 +755,13 @@ func draw_brush(pos : Vector2, color : Color, current_mouse_button : String, cur
mirror_y -= 1
# Use custom blend function cause of godot's issue #31124
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:
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:
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:
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
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)
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:
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:
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:
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
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
# 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 mouse_pos_floored = mouse_pos.floor()
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 y = previous_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
if e2 >= dy:
err += dy
@ -813,9 +813,9 @@ func fill_gaps(mouse_pos : Vector2, prev_mouse_pos : Vector2, color : Color, cur
y += sy
# 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()
var pixel = layers[current_layer_index][0].get_pixelv(pos)
var pixel = sprite.get_pixelv(pos)
if target_color == replace_color:
return
elif pixel != target_color:
@ -832,20 +832,20 @@ func flood_fill(pos : Vector2, target_color : Color, replace_color : Color) -> v
break
var west : 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
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
for px in range(west.x + 1, east.x):
var p := Vector2(px, n.y)
# Draw
layers[current_layer_index][0].set_pixelv(p, replace_color)
replace_color = layers[current_layer_index][0].get_pixelv(p)
sprite.set_pixelv(p, replace_color)
replace_color = sprite.get_pixelv(p)
var north := p + Vector2.UP
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)
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)
sprite_changed_this_frame = true

View file

@ -254,8 +254,8 @@ func change_theme(ID : int) -> void:
var disabled_file_name = button.texture_disabled.resource_path.get_file()
button.texture_disabled = load("res://Assets/Graphics/%s Themes/%s/%s" % [Global.theme_type, button_category, disabled_file_name])
# Make sure the frame text gets updated
Global.current_frame = Global.current_frame
# Make sure the frame text gets updated
Global.current_frame = Global.current_frame
func _on_GridWidthValue_value_changed(value : float) -> void:
Global.grid_width = value

View file

@ -1,12 +1,15 @@
extends Button
var frame := 0
var layer := 0
onready var popup_menu := $PopupMenu
func _on_FrameButton_pressed() -> void:
if Input.is_action_just_released("left_mouse"):
Global.current_frame = frame
Global.current_layer = layer
print(str(frame), str(layer))
elif Input.is_action_just_released("right_mouse"):
if Global.canvases.size() == 1:
popup_menu.set_item_disabled(0, true)
@ -30,7 +33,7 @@ func _on_PopupMenu_id_pressed(ID : int) -> void:
0: #Remove Frame
remove_frame()
1: #Clone Layer
1: # Clone Layer
var canvas : Canvas = Global.canvases[frame]
var new_canvas : Canvas = load("res://Prefabs/Canvas.tscn").instance()
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, "canvas", new_canvas)
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")
Global.undo_redo.add_do_property(frame_button, "pressed", false)
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
# Canvas related stuff
var layers := []
var current_frame := 0 setget frame_changed
var current_layer := 0
# warning-ignore:unused_class_variable
var can_draw := false
# warning-ignore:unused_class_variable
@ -223,14 +225,14 @@ var right_mirror_container : Container
var animation_timeline : Panel
var animation_timer : Timer
var frame_ids : HBoxContainer
var current_frame_label : Label
var loop_animation_button : BaseButton
var play_forward : BaseButton
var play_backwards : BaseButton
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 move_up_layer_button : BaseButton
var move_down_layer_button : BaseButton
@ -340,24 +342,23 @@ func _ready() -> void:
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")
frame_ids = find_node_by_name(animation_timeline, "FrameIDs")
current_frame_label = find_node_by_name(animation_timeline, "CurrentFrame")
loop_animation_button = find_node_by_name(animation_timeline, "LoopAnim")
play_forward = find_node_by_name(animation_timeline, "PlayForward")
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_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")
#var layer_stuff_container = find_node_by_name(animation_timeline, "LayerVBoxContainer")
layer_opacity_slider = find_node_by_name(layer_stuff_container, "OpacitySlider")
layer_opacity_spinbox = find_node_by_name(layer_stuff_container, "OpacitySpinBox")
vbox_layer_container = find_node_by_name(layer_stuff_container, "VBoxLayerContainer")
remove_layer_button = find_node_by_name(animation_timeline, "RemoveLayer")
move_up_layer_button = find_node_by_name(animation_timeline, "MoveUpLayer")
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")
edit_palette_button = find_node_by_name(root, "EditPalette")
@ -370,6 +371,10 @@ func _ready() -> void:
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
func find_node_by_name(root, node_name) -> Node:
if root.get_name() == node_name:
@ -412,7 +417,7 @@ func undo(_canvases : Array, layer_index : int = -1) -> void:
if action_name == "Add Frame":
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
if canvases.size() == 2: # Stop animating
play_forward.pressed = false
@ -421,10 +426,10 @@ func undo(_canvases : Array, layer_index : int = -1) -> void:
elif action_name == "Remove Frame":
canvas_parent.add_child(_canvases[0])
canvas_parent.move_child(_canvases[0], _canvases[0].frame)
frame_container.add_child(_canvases[0].frame_button)
frame_container.move_child(_canvases[0].frame_button, _canvases[0].frame)
layer_and_frame_container.add_child(_canvases[0].frame_button)
layer_and_frame_container.move_child(_canvases[0].frame_button, _canvases[0].frame)
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.update()
@ -448,26 +453,49 @@ func redo(_canvases : Array, layer_index : int = -1) -> void:
if action_name == "Scale":
c.camera_zoom()
if "Layer" in action_name:
var current_layer_index : int = _canvases[0].current_layer_index
_canvases[0].generate_layer_panels()
if action_name == "Change Layer Order":
_canvases[0].current_layer_index = current_layer_index
_canvases[0].get_layer_container(current_layer_index).changed_selection()
if action_name == "Add Layer":
var layer_container = load("res://Prefabs/LayerContainer.tscn").instance()
_canvases[0].layers[current_layer][2] = tr("Layer") + " %s" % current_layer
layer_container.i = current_layer
layer_container.get_child(0).get_child(1).text = _canvases[0].layers[current_layer][2]
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":
canvas_parent.add_child(_canvases[0])
if !Global.frame_container.is_a_parent_of(_canvases[0].frame_button):
Global.frame_container.add_child(_canvases[0].frame_button)
var label := Label.new()
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":
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
play_forward.pressed = false
play_backwards.pressed = false
animation_timer.stop()
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.update()
@ -491,18 +519,17 @@ func frame_changed(value : int) -> void:
c.line_2d.set_point_position(1, c.line_2d.points[0])
canvas = canvases[current_frame]
canvas.visible = true
canvas.generate_layer_panels()
#canvas.generate_layer_panels()
# Make all frame buttons unpressed
for c in canvases:
var text_color := Color.white
if theme_type == "Gold" || theme_type == "Light":
text_color = Color.black
c.frame_button.get_node("FrameButton").pressed = false
c.frame_button.get_node("FrameID").add_color_override("font_color", text_color)
c.frame_button.pressed = false
#c.frame_button.get_node("FrameID").add_color_override("font_color", text_color)
# Make only the current frame button pressed
canvas.frame_button.get_node("FrameButton").pressed = true
canvas.frame_button.get_node("FrameID").add_color_override("font_color", Color("#3c5d75"))
canvas.frame_button.pressed = true
#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:
var brush_container

View file

@ -1,16 +1,16 @@
class_name LayerContainer
extends Button
var i
var i := 0
# warning-ignore:unused_class_variable
var currently_selected := false
onready var visibility_button := $VisibilityButton
onready var visibility_button := $HBoxContainer/VisibilityButton
onready var label := $HBoxContainer/Label
onready var line_edit := $HBoxContainer/LineEdit
func _ready() -> void:
changed_selection()
#changed_selection()
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_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:
var initially_pressed := pressed
var label_initially_visible : bool = label.visible
Global.canvas.current_layer_index = i
changed_selection()
# Global.canvas.current_layer_index = i
# changed_selection()
if !initially_pressed:
if label_initially_visible:
label.visible = false
@ -44,14 +44,15 @@ func changed_selection() -> void:
var parent := get_parent()
for child in parent.get_children():
if child is Button:
#print(child.name)
child.label.visible = true
child.line_edit.visible = false
child.line_edit.editable = false
if Global.canvas.current_layer_index == child.i: # The selected layer
child.currently_selected = true
child.pressed = true
Global.layer_opacity_slider.value = Global.canvas.layers[child.i][4] * 100
Global.layer_opacity_spinbox.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][3] * 100
if Global.canvas.current_layer_index < Global.canvas.layers.size() - 1:
Global.move_up_layer_button.disabled = false
@ -86,5 +87,5 @@ func _on_VisibilityButton_pressed() -> void:
Global.canvas.update()
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

View file

@ -406,9 +406,10 @@ func _on_OpenSprite_file_selected(path : String) -> void:
Global.canvas = canvas
var width := file.get_16()
var height := file.get_16()
print(width, height)
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 layer_name := file.get_line()
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_line("END_LAYERS")
for child in canvas.get_children(): #Store guides
for child in canvas.get_children(): # Store guides
if child is Guide:
file.store_line("|")
file.store_8(child.type)
@ -554,7 +555,7 @@ func clear_canvases() -> void:
for child in Global.vbox_layer_container.get_children():
if child is PanelContainer:
child.queue_free()
for child in Global.frame_container.get_children():
for child in Global.frame_containers.get_children():
child.queue_free()
for child in Global.canvas_parent.get_children():
if child is Canvas:
@ -687,86 +688,6 @@ func _on_RightBrushSizeEdit_value_changed(value) -> void:
Global.right_brush_size = new_size
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:
var temp: Color = Global.left_color_picker.color