From 53338e4310bf8f7c90ffcc7fd8fcc9f9ef995877 Mon Sep 17 00:00:00 2001 From: OverloadedOrama <35376950+OverloadedOrama@users.noreply.github.com> Date: Thu, 2 Apr 2020 03:29:14 +0300 Subject: [PATCH] Basic UI for animation frame tags You can add tags by right clicking on a cel and selecting "Add Frame Tag". No tag modifying and deletion is implemented yet. I'm using a different ScrollContainer for the tags, which gets updated everytime the main timeline ScrollContainer gets updated. I hide its sliders from its theme, wish there was a more straightforward way. --- Changelog.md | 3 +- Prefabs/AnimationTag.tscn | 24 ++++ Prefabs/AnimationTimeline.tscn | 200 ++++++++++++++++++++++-------- Prefabs/Dialogs/SplashDialog.tscn | 3 +- Prefabs/FrameButton.tscn | 2 +- Scripts/AnimationTimeline.gd | 28 +++++ Scripts/FrameButton.gd | 10 +- Scripts/Global.gd | 25 ++++ Translations/Translations.pot | 6 + 9 files changed, 241 insertions(+), 60 deletions(-) create mode 100644 Prefabs/AnimationTag.tscn diff --git a/Changelog.md b/Changelog.md index d2f2320ec..c21c137af 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Cels are now in the timeline. Each cel refers to a specific layer AND a frame. Frames are a collection of cels for every layer. - Cel linking is now possible. This way, layers can be "shared" in multiple frames. +- You can now group multiple frames with tags. - Pattern filling is now possible. If the user chooses a brush that is not the pixel or a circle brush and uses the bucket tool, the brush image is used as a pattern that fills the area. - Importing .pngs as palettes is now possible - thanks to Martin Novák (novhack)! - A confirmation message now appears when the user quits Pixelorama, if there are unsaved changes - thanks to Schweini07! @@ -27,7 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Layer visibility is taken into account when exporting the drawing as a .png file. This means that invisible layers will not be included in the final .png file. - Visual change, added border outlines to all window dialogs. - Animation now loops by default. -- Onion skinning settings have been moved to a popup window, and 2 new buttons were added. One that enables it, and one that opens the settings window. +- Onion skinning settings have been moved to a popup window, and 2 new buttons were added. One that toggles onion skinning, and one that opens the settings window. - The splash screen is no longer purple, it now gets affected by the chosen theme. ### Fixed diff --git a/Prefabs/AnimationTag.tscn b/Prefabs/AnimationTag.tscn new file mode 100644 index 000000000..8265c8435 --- /dev/null +++ b/Prefabs/AnimationTag.tscn @@ -0,0 +1,24 @@ +[gd_scene format=2] + +[node name="AnimationTag" type="VBoxContainer"] +margin_right = 39.0 +margin_bottom = 32.0 +rect_min_size = Vector2( 39, 32 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Line2D" type="Line2D" parent="."] +points = PoolVector2Array( 0, 32, 0, 0, 39, 0, 39, 32 ) +width = 1.0 +texture_mode = 1313163520 + +[node name="Label" type="Label" parent="."] +margin_left = 7.0 +margin_right = 32.0 +margin_bottom = 32.0 +size_flags_horizontal = 4 +size_flags_vertical = 3 +text = "Idle" +align = 1 +valign = 1 diff --git a/Prefabs/AnimationTimeline.tscn b/Prefabs/AnimationTimeline.tscn index a4e7cdeb3..9b01fe51b 100644 --- a/Prefabs/AnimationTimeline.tscn +++ b/Prefabs/AnimationTimeline.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=52 format=2] +[gd_scene load_steps=58 format=2] [ext_resource path="res://Scripts/AnimationTimeline.gd" type="Script" id=1] [ext_resource path="res://Assets/Graphics/Dark Themes/Layers/New_Layer.png" type="Texture" id=2] @@ -84,6 +84,27 @@ scancode = 16777230 [sub_resource type="ShortCut" id=12] shortcut = SubResource( 11 ) +[sub_resource type="StyleBoxEmpty" id=13] + +[sub_resource type="StyleBoxEmpty" id=14] + +[sub_resource type="StyleBoxEmpty" id=15] + +[sub_resource type="StyleBoxEmpty" id=16] + +[sub_resource type="StyleBoxEmpty" id=17] + +[sub_resource type="Theme" id=18] +HScrollBar/icons/decrement = null +HScrollBar/icons/decrement_highlight = null +HScrollBar/icons/increment = null +HScrollBar/icons/increment_highlight = null +HScrollBar/styles/grabber = SubResource( 13 ) +HScrollBar/styles/grabber_highlight = SubResource( 14 ) +HScrollBar/styles/grabber_pressed = SubResource( 15 ) +HScrollBar/styles/scroll = SubResource( 16 ) +HScrollBar/styles/scroll_focus = SubResource( 17 ) + [node name="AnimationTimeline" type="Panel"] margin_top = 438.0 margin_right = 704.0 @@ -210,26 +231,6 @@ size_flags_horizontal = 3 [node name="SpacerControl" type="Control" parent="AnimationContainer/TimelineContainer"] margin_right = 604.0 -[node name="AnimationTags" type="VBoxContainer" parent="AnimationContainer/TimelineContainer"] -visible = false -margin_right = 471.0 -margin_bottom = 32.0 - -[node name="Line2D" type="Line2D" parent="AnimationContainer/TimelineContainer/AnimationTags"] -points = PoolVector2Array( 0, 32, 0, 0, 110, 0, 110, 32 ) -width = 1.0 -texture_mode = 1313163520 - -[node name="Label" type="Label" parent="AnimationContainer/TimelineContainer/AnimationTags"] -margin_right = 110.0 -margin_bottom = 32.0 -rect_min_size = Vector2( 110, 32 ) -size_flags_horizontal = 0 -size_flags_vertical = 0 -text = "Animation Tags" -align = 1 -valign = 1 - [node name="AnimationButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"] margin_top = 4.0 margin_right = 604.0 @@ -238,15 +239,16 @@ rect_min_size = Vector2( 0, 24 ) [node name="CurrentFrame" type="Label" parent="AnimationContainer/TimelineContainer/AnimationButtons"] margin_top = 5.0 -margin_right = 117.0 +margin_right = 150.0 margin_bottom = 19.0 +rect_min_size = Vector2( 150, 0 ) 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_left = 154.0 +margin_right = 174.0 margin_bottom = 20.0 hint_tooltip = "Add a new frame" mouse_default_cursor_shape = 2 @@ -256,8 +258,8 @@ texture_normal = ExtResource( 19 ) texture_hover = ExtResource( 20 ) [node name="PlaybackButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/AnimationButtons"] -margin_left = 234.0 -margin_right = 374.0 +margin_left = 251.0 +margin_right = 391.0 margin_bottom = 24.0 size_flags_horizontal = 6 @@ -398,55 +400,72 @@ margin_top = 32.0 margin_right = 604.0 margin_bottom = 36.0 -[node name="OpacityContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"] +[node name="OpacityAndTagContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"] margin_top = 40.0 margin_right = 604.0 -margin_bottom = 64.0 +margin_bottom = 72.0 custom_constants/separation = 2 -[node name="OpacityLabel" type="Label" parent="AnimationContainer/TimelineContainer/OpacityContainer"] +[node name="OpacityContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer"] +margin_right = 214.0 +margin_bottom = 32.0 +rect_min_size = Vector2( 214, 0 ) + +[node name="OpacityLabel" type="Label" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"] margin_right = 53.0 -margin_bottom = 24.0 +margin_bottom = 32.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 ) +[node name="OpacitySlider" type="HSlider" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"] +margin_left = 57.0 +margin_right = 136.0 +margin_bottom = 32.0 mouse_default_cursor_shape = 2 +size_flags_horizontal = 3 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 +[node name="OpacitySpinBox" type="SpinBox" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"] +margin_left = 140.0 +margin_top = 4.0 +margin_right = 214.0 +margin_bottom = 28.0 mouse_default_cursor_shape = 2 size_flags_vertical = 4 value = 100.0 align = 1 +[node name="TagScroll" type="ScrollContainer" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer"] +margin_left = 216.0 +margin_right = 604.0 +margin_bottom = 32.0 +rect_min_size = Vector2( 0, 32 ) +size_flags_horizontal = 3 +theme = SubResource( 18 ) +scroll_vertical_enabled = false + +[node name="TagContainer" type="Control" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/TagScroll"] + [node name="TimelineScroll" type="ScrollContainer" parent="AnimationContainer/TimelineContainer"] -margin_top = 68.0 +margin_top = 76.0 margin_right = 604.0 margin_bottom = 200.0 size_flags_vertical = 3 [node name="LayersAndFrames" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll"] margin_right = 252.0 -margin_bottom = 132.0 +margin_bottom = 124.0 size_flags_vertical = 3 -[node name="VBoxContainer" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames"] +[node name="LayerVBoxCont" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames"] margin_right = 212.0 -margin_bottom = 132.0 +margin_bottom = 124.0 -[node name="LayerLabel" type="Label" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/VBoxContainer"] +[node name="LayerLabel" type="Label" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont"] margin_right = 212.0 margin_bottom = 16.0 rect_min_size = Vector2( 0, 16 ) @@ -454,31 +473,31 @@ text = "Layers" align = 1 valign = 1 -[node name="LayersContainer" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/VBoxContainer"] +[node name="LayersContainer" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont"] margin_top = 20.0 margin_right = 212.0 margin_bottom = 56.0 -[node name="LayerContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/VBoxContainer/LayersContainer" instance=ExtResource( 18 )] +[node name="LayerContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont/LayersContainer" instance=ExtResource( 18 )] margin_right = 212.0 -[node name="VBoxContainer2" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames"] +[node name="FrameButtonsAndIds" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames"] margin_left = 216.0 margin_right = 252.0 -margin_bottom = 132.0 +margin_bottom = 124.0 -[node name="FrameIDs" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/VBoxContainer2"] +[node name="FrameIDs" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"] margin_right = 36.0 margin_bottom = 14.0 -[node name="Label" type="Label" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/VBoxContainer2/FrameIDs"] +[node name="Label" type="Label" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds/FrameIDs"] margin_right = 36.0 margin_bottom = 14.0 rect_min_size = Vector2( 36, 0 ) text = "1" align = 1 -[node name="FramesContainer" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/VBoxContainer2"] +[node name="FramesContainer" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"] margin_top = 18.0 margin_right = 36.0 margin_bottom = 18.0 @@ -544,6 +563,78 @@ margin_right = 132.0 margin_bottom = 116.0 mouse_default_cursor_shape = 2 text = "Blue-Red Mode" + +[node name="TagDialog" type="ConfirmationDialog" parent="."] +margin_right = 83.0 +margin_bottom = 58.0 +window_title = "Frame Tag Properties" +resizable = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="GridContainer" type="GridContainer" parent="TagDialog"] +margin_left = 8.0 +margin_top = 8.0 +margin_right = 192.0 +margin_bottom = 124.0 +custom_constants/vseparation = 8 +custom_constants/hseparation = 8 +columns = 2 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="NameLabel" type="Label" parent="TagDialog/GridContainer"] +margin_top = 5.0 +margin_right = 42.0 +margin_bottom = 19.0 +text = "Name:" + +[node name="NameLineEdit" type="LineEdit" parent="TagDialog/GridContainer"] +margin_left = 50.0 +margin_right = 124.0 +margin_bottom = 24.0 + +[node name="ColorLabel" type="Label" parent="TagDialog/GridContainer"] +margin_top = 35.0 +margin_right = 42.0 +margin_bottom = 49.0 +text = "Color:" + +[node name="ColorPickerButton" type="ColorPickerButton" parent="TagDialog/GridContainer"] +margin_left = 50.0 +margin_top = 32.0 +margin_right = 124.0 +margin_bottom = 52.0 + +[node name="FromLabel" type="Label" parent="TagDialog/GridContainer"] +margin_top = 65.0 +margin_right = 42.0 +margin_bottom = 79.0 +text = "From:" + +[node name="FromSpinBox" type="SpinBox" parent="TagDialog/GridContainer"] +margin_left = 50.0 +margin_top = 60.0 +margin_right = 124.0 +margin_bottom = 84.0 +min_value = 1.0 +value = 1.0 + +[node name="ToLabel" type="Label" parent="TagDialog/GridContainer"] +margin_top = 97.0 +margin_right = 42.0 +margin_bottom = 111.0 +text = "To:" + +[node name="ToSpinBox" type="SpinBox" parent="TagDialog/GridContainer"] +margin_left = 50.0 +margin_top = 92.0 +margin_right = 124.0 +margin_bottom = 116.0 +min_value = 1.0 +value = 1.0 [connection signal="pressed" from="AnimationContainer/ForLayerButtons/LayerButtons/AddLayer" to="." method="add_layer" binds= [ true ]] [connection signal="pressed" from="AnimationContainer/ForLayerButtons/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"] [connection signal="pressed" from="AnimationContainer/ForLayerButtons/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ 1 ]] @@ -561,9 +652,12 @@ text = "Blue-Red Mode" [connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/OnionSkinning" to="." method="_on_OnionSkinning_pressed"] [connection signal="pressed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/LoopAnim" to="." method="_on_LoopAnim_pressed"] [connection signal="value_changed" from="AnimationContainer/TimelineContainer/AnimationButtons/LoopButtons/FPSValue" to="." method="_on_FPSValue_value_changed"] -[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="value_changed" from="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer/OpacitySlider" to="." method="_on_OpacitySlider_value_changed"] +[connection signal="value_changed" from="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer/OpacitySpinBox" to="." method="_on_OpacitySlider_value_changed"] [connection signal="timeout" from="AnimationTimer" to="." method="_on_AnimationTimer_timeout"] +[connection signal="popup_hide" from="OnionSkinningSettings" to="." method="_on_OnionSkinningSettings_popup_hide"] [connection signal="value_changed" from="OnionSkinningSettings/OnionSkinningButtons/PastOnionSkinning" to="." method="_on_PastOnionSkinning_value_changed"] [connection signal="value_changed" from="OnionSkinningSettings/OnionSkinningButtons/FutureOnionSkinning" to="." method="_on_FutureOnionSkinning_value_changed"] [connection signal="toggled" from="OnionSkinningSettings/OnionSkinningButtons/BlueRedMode" to="." method="_on_BlueRedMode_toggled"] +[connection signal="confirmed" from="TagDialog" to="." method="_on_TagDialog_confirmed"] +[connection signal="popup_hide" from="TagDialog" to="." method="_on_TagDialog_popup_hide"] diff --git a/Prefabs/Dialogs/SplashDialog.tscn b/Prefabs/Dialogs/SplashDialog.tscn index 6afda10eb..948efc5f1 100644 --- a/Prefabs/Dialogs/SplashDialog.tscn +++ b/Prefabs/Dialogs/SplashDialog.tscn @@ -9,7 +9,6 @@ [ext_resource path="res://Assets/Fonts/Roboto-Small.tres" type="DynamicFont" id=7] [node name="SplashDialog" type="WindowDialog"] -visible = true margin_right = 600.0 margin_bottom = 400.0 rect_min_size = Vector2( 600, 560 ) @@ -137,7 +136,7 @@ margin_bottom = 260.0 rect_min_size = Vector2( 0, 260 ) [node name="Label" type="Label" parent="Contents/PatronsArtNews/ChangelogContainer/ChangelogScroll"] -margin_right = 130.0 +margin_right = 142.0 margin_bottom = 2921.0 size_flags_horizontal = 3 size_flags_vertical = 3 diff --git a/Prefabs/FrameButton.tscn b/Prefabs/FrameButton.tscn index 44403fb8c..59936b75a 100644 --- a/Prefabs/FrameButton.tscn +++ b/Prefabs/FrameButton.tscn @@ -35,7 +35,7 @@ __meta__ = { 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, "Unlink Cel", null, 0, false, true, 4, 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, "Add Frame Tag", null, 0, false, false, 4, 0, null, "", false, "Unlink Cel", null, 0, false, true, 5, 0, null, "", false ] [node name="LinkedIndicator" type="Polygon2D" parent="."] visible = false diff --git a/Scripts/AnimationTimeline.gd b/Scripts/AnimationTimeline.gd index 109d457fb..a80449347 100644 --- a/Scripts/AnimationTimeline.gd +++ b/Scripts/AnimationTimeline.gd @@ -4,6 +4,18 @@ var fps := 6.0 var animation_loop := 1 # 0 is no loop, 1 is cycle loop, 2 is ping-pong loop var animation_forward := true +onready var timeline_scroll : ScrollContainer = $AnimationContainer/TimelineContainer/TimelineScroll +onready var tag_scroll_container : ScrollContainer = $AnimationContainer/TimelineContainer/OpacityAndTagContainer/TagScroll + +func _ready() -> void: + timeline_scroll.get_h_scrollbar().connect("value_changed", self, "_h_scroll_changed") + + +func _h_scroll_changed(value : float) -> void: + # Let the main timeline ScrollContainer affect the tag ScrollContainer too + tag_scroll_container.get_child(0).rect_min_size.x = timeline_scroll.get_child(0).rect_size.x - 212 + tag_scroll_container.scroll_horizontal = value + func add_frame() -> void: var new_canvas : Canvas = load("res://Prefabs/Canvas.tscn").instance() @@ -291,3 +303,19 @@ func _on_OpacitySlider_value_changed(value) -> void: Global.layer_opacity_spinbox.value = value Global.canvas.update() + +func _on_TagDialog_confirmed() -> void: + var tag_name : String = Global.tag_dialog.get_node("GridContainer/NameLineEdit").text + var tag_color : Color = Global.tag_dialog.get_node("GridContainer/ColorPickerButton").color + var tag_from : int = Global.tag_dialog.get_node("GridContainer/FromSpinBox").value + var tag_to : int = Global.tag_dialog.get_node("GridContainer/ToSpinBox").value + Global.animation_tags.append([tag_name, tag_color, tag_from, tag_to]) + Global.animation_tags = Global.animation_tags # To execute animation_tags_changed() + + +func _on_OnionSkinningSettings_popup_hide() -> void: + Global.can_draw = true + + +func _on_TagDialog_popup_hide() -> void: + Global.can_draw = true diff --git a/Scripts/FrameButton.gd b/Scripts/FrameButton.gd index 430dd0b97..c67eddbbd 100644 --- a/Scripts/FrameButton.gd +++ b/Scripts/FrameButton.gd @@ -9,10 +9,10 @@ func _ready() -> void: hint_tooltip = "Frame: %s, Layer: %s" % [frame, layer] if Global.canvases[frame] in Global.layers[layer][5]: get_node("LinkedIndicator").visible = true - popup_menu.set_item_disabled(4, false) # Unlink cel + popup_menu.set_item_disabled(5, false) # Unlink cel else: get_node("LinkedIndicator").visible = false - popup_menu.set_item_disabled(4, true) # Unlink cel + popup_menu.set_item_disabled(5, true) # Unlink cel func _on_FrameButton_pressed() -> void: if Input.is_action_just_released("left_mouse"): @@ -87,7 +87,11 @@ func _on_PopupMenu_id_pressed(ID : int) -> void: change_frame_order(-1) 3: # Move Right change_frame_order(1) - 4: # Unlink Cel + 4: # Add Frame Tag + Global.tag_dialog.popup_centered() + Global.tag_dialog.get_node("GridContainer/FromSpinBox").value = frame + 1 + Global.tag_dialog.get_node("GridContainer/ToSpinBox").value = frame + 1 + 5: # Unlink Cel var cel_index : int = Global.layers[layer][5].find(Global.canvases[frame]) Global.layers[layer][5].remove(cel_index) _ready() diff --git a/Scripts/Global.gd b/Scripts/Global.gd index d03a98f2a..50957ce3c 100644 --- a/Scripts/Global.gd +++ b/Scripts/Global.gd @@ -33,6 +33,7 @@ var transparent_background : ImageTexture # warning-ignore:unused_class_variable var selected_pixels := [] var image_clipboard : Image +var animation_tags := [] setget animation_tags_changed # [Name, Color, From, To] # warning-ignore:unused_class_variable var theme_type := "Dark" @@ -232,6 +233,8 @@ var play_backwards : BaseButton var timeline_seconds : Control var layers_container : VBoxContainer var frames_container : VBoxContainer +var tag_container : Control +var tag_dialog : ConfirmationDialog var remove_layer_button : BaseButton var move_up_layer_button : BaseButton @@ -346,6 +349,8 @@ func _ready() -> void: 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") + tag_container = find_node_by_name(animation_timeline, "TagContainer") + tag_dialog = find_node_by_name(animation_timeline, "TagDialog") remove_layer_button = find_node_by_name(animation_timeline, "RemoveLayer") move_up_layer_button = find_node_by_name(animation_timeline, "MoveUpLayer") @@ -370,6 +375,7 @@ func _ready() -> void: # will new frames be linked boolean (4), Array of linked frames (5)] layers.append([tr("Layer") + " 0", true, false, HBoxContainer.new(), false, []]) + # 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: @@ -609,6 +615,25 @@ func layer_changed(value : int) -> void: yield(get_tree().create_timer(0.01), "timeout") self.current_frame = current_frame # Call frame_changed to update UI + +func animation_tags_changed(value : Array) -> void: + animation_tags = value + var tag : Container = load("res://Prefabs/AnimationTag.tscn").instance() + tag_container.add_child(tag) + var tag_position := tag_container.get_child_count() - 1 + tag_container.move_child(tag, tag_position) + tag.get_node("Label").text = animation_tags[tag_position][0] + tag.get_node("Label").modulate = animation_tags[tag_position][1] + tag.get_node("Line2D").default_color = animation_tags[tag_position][1] + + tag.rect_position.x = (animation_tags[tag_position][2] - 1) * 39 + animation_tags[tag_position][2] + + var size : int = animation_tags[tag_position][3] - animation_tags[tag_position][2] + tag.rect_min_size.x = (size + 1) * 39 + tag.get_node("Line2D").points[2] = Vector2(tag.rect_min_size.x, 0) + tag.get_node("Line2D").points[3] = Vector2(tag.rect_min_size.x, 32) + + func create_brush_button(brush_img : Image, brush_type := Brush_Types.CUSTOM, hint_tooltip := "") -> void: var brush_container var brush_button = load("res://Prefabs/BrushButton.tscn").instance() diff --git a/Translations/Translations.pot b/Translations/Translations.pot index da04d4735..972d227e9 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -630,6 +630,12 @@ msgstr "" msgid "Move Right" msgstr "" +msgid "Add Frame Tag" +msgstr "" + +msgid "Unlink Cel" +msgstr "" + msgid "Layer" msgstr ""