diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index a498267b0..0eeae2bd1 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -35,7 +35,6 @@ func _ready() -> void: frame_scroll_bar.connect("value_changed", self, "_frame_scroll_changed") Global.animation_timer.wait_time = 1 / Global.current_project.fps fps_spinbox.value = Global.current_project.fps - # config loading layer_frame_h_split.split_offset = Global.config_cache.get_value("timeline", "layer_size", 0) self.cel_size = Global.config_cache.get_value("timeline", "cel_size", cel_size) # Call setter @@ -62,7 +61,6 @@ func _ready() -> void: # emit signals that were supposed to be emitted (Check if it's still required in godot 4) $"%PastPlacement".emit_signal("item_selected", 0 if past_above else 1) $"%FuturePlacement".emit_signal("item_selected", 0 if future_above else 1) - # Makes sure that the frame and tag scroll bars are in the right place: Global.layer_vbox.call_deferred("emit_signal", "resized") @@ -284,7 +282,6 @@ func _on_CopyFrame_pressed() -> void: func copy_frames(indices := [], destination := -1) -> void: var project: Project = Global.current_project - if indices.size() == 0: indices.append(project.current_frame) @@ -294,7 +291,6 @@ func copy_frames(indices := [], destination := -1) -> void: copied_indices = range(destination + 1, (destination + 1) + indices.size()) else: copied_indices = range(indices[-1] + 1, indices[-1] + 1 + indices.size()) - var new_animation_tags := project.animation_tags.duplicate() # Loop through the tags to create new classes for them, so that they won't be the same # as project.animation_tags's classes. Needed for undo/redo to work properly. @@ -305,16 +301,13 @@ func copy_frames(indices := [], destination := -1) -> void: new_animation_tags[i].from, new_animation_tags[i].to ) - project.undos += 1 project.undo_redo.create_action("Add Frame") - for f in indices: + var src_frame: Frame = project.frames[f] var new_frame := Frame.new() copied_frames.append(new_frame) - var src_frame: Frame = project.frames[f] - new_frame.duration = src_frame.duration for l in range(project.layers.size()): var src_cel: BaseCel = project.frames[f].cels[l] # Cel we're copying from, the source @@ -326,9 +319,9 @@ func copy_frames(indices := [], destination := -1) -> void: ) if src_cel.selected != null: selected_id = src_cel.selected.id - else: new_cel = src_cel.get_script().new() + if project.layers[l].new_cels_linked: if src_cel.link_set == null: src_cel.link_set = {} @@ -341,20 +334,19 @@ func copy_frames(indices := [], destination := -1) -> void: else: new_cel.set_content(src_cel.copy_content()) new_cel.opacity = src_cel.opacity + if new_cel is Cel3D: if selected_id in new_cel.object_properties.keys(): if selected_id != -1: new_cel.selected = new_cel.get_object_from_id(selected_id) new_frame.cels.append(new_cel) - # Loop through the tags to see if the frame is in one - for tag in new_animation_tags: + for tag in new_animation_tags: # Loop through the tags to see if the frame is in one if copied_indices[0] >= tag.from && copied_indices[0] <= tag.to: tag.to += 1 elif copied_indices[0] < tag.from: tag.from += 1 tag.to += 1 - project.undo_redo.add_do_method(Global, "undo_or_redo", false) project.undo_redo.add_undo_method(Global, "undo_or_redo", true) project.undo_redo.add_do_method(project, "add_frames", copied_frames, copied_indices) @@ -364,10 +356,8 @@ func copy_frames(indices := [], destination := -1) -> void: project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags) project.undo_redo.add_undo_property(project, "animation_tags", project.animation_tags) project.undo_redo.commit_action() - # Select all the new frames so that it is easier to move/offset collectively if user wants - # For ease in animation workflow, the new current frame will be the first duplicated frame - # instead of the last + # For ease in animation workflow, the new current frame will be the first duplicated frame instead of the last var range_start: int = copied_indices[-1] var range_end = copied_indices[0] var frame_diff_sign = sign(range_end - range_start) @@ -388,37 +378,6 @@ func _on_FrameTagButton_pressed() -> void: find_node("FrameTagDialog").popup_centered() -func _on_TagContainer_gui_input(event: InputEvent) -> void: - if !event is InputEventMouseButton: - return - if Input.is_action_just_released("right_mouse"): - $"%TagList".clear() - if Global.current_project.animation_tags.empty(): - return - $"%TagList".add_separator("Paste content from tag:") - for tag in Global.current_project.animation_tags: - var img = Image.new() - img.create(5, 5, true, Image.FORMAT_RGBA8) - img.fill(tag.color) - var tex = ImageTexture.new() - tex.create_from_image(img) - var title = tag.name - if title == "": - title = "(Untitled)" - $"%TagList".add_icon_item(tex, title) - if not $"%TagList".is_connected("id_pressed", self, "_on_TagList_id_pressed"): - $"%TagList".connect("id_pressed", self, "_on_TagList_id_pressed") - $"%TagList".popup(Rect2(get_global_mouse_position(), Vector2.ONE)) - - -func _on_TagList_id_pressed(id: int) -> void: - var tag: AnimationTag = Global.current_project.animation_tags[id - 1] - var frames = [] - for i in range(tag.from - 1, tag.to): - frames.append(i) - copy_frames(frames, Global.current_project.current_frame) - - func _on_MoveLeft_pressed() -> void: var frame: int = Global.current_project.current_frame if frame == 0: @@ -476,7 +435,6 @@ func _on_PlayForward_toggled(button_pressed: bool) -> void: Global.change_button_texturerect(Global.play_forward.get_child(0), "pause.png") else: Global.change_button_texturerect(Global.play_forward.get_child(0), "play.png") - play_animation(button_pressed, true) @@ -485,7 +443,6 @@ func _on_PlayBackwards_toggled(button_pressed: bool) -> void: Global.change_button_texturerect(Global.play_backwards.get_child(0), "pause.png") else: Global.change_button_texturerect(Global.play_backwards.get_child(0), "play_backwards.png") - play_animation(button_pressed, false) @@ -980,7 +937,6 @@ func project_frame_added(frame: int) -> void: frame_scroll_container.call_deferred( # Make it visible, yes 3 call_deferreds are required "call_deferred", "call_deferred", "ensure_control_visible", button ) - var layer := Global.cel_vbox.get_child_count() - 1 for cel_hbox in Global.cel_vbox.get_children(): var cel_button = project.frames[frame].cels[layer].instantiate_cel_button() diff --git a/src/UI/Timeline/AnimationTimeline.tscn b/src/UI/Timeline/AnimationTimeline.tscn index 941033220..180cc1e1d 100644 --- a/src/UI/Timeline/AnimationTimeline.tscn +++ b/src/UI/Timeline/AnimationTimeline.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=44 format=2] +[gd_scene load_steps=45 format=2] [ext_resource path="res://src/UI/Timeline/AnimationTimeline.gd" type="Script" id=1] [ext_resource path="res://assets/graphics/layers/new.png" type="Texture" id=2] @@ -11,6 +11,7 @@ [ext_resource path="res://src/UI/Nodes/ValueSlider.tscn" type="PackedScene" id=9] [ext_resource path="res://assets/graphics/misc/value_arrow.svg" type="Texture" id=10] [ext_resource path="res://src/UI/Timeline/FrameScrollContainer.gd" type="Script" id=11] +[ext_resource path="res://src/UI/Timeline/PasteTagPopup.gd" type="Script" id=12] [ext_resource path="res://assets/graphics/timeline/new_frame.png" type="Texture" id=19] [ext_resource path="res://assets/graphics/timeline/remove_frame.png" type="Texture" id=20] [ext_resource path="res://assets/graphics/timeline/go_to_first_frame.png" type="Texture" id=21] @@ -974,12 +975,12 @@ margin_bottom = 40.0 mouse_filter = 2 color = Color( 0, 0.741176, 1, 0.501961 ) -[node name="TagList" type="PopupMenu" parent="."] -unique_name_in_owner = true +[node name="PasteTagPopup" type="PopupMenu" parent="."] margin_left = 439.0 margin_top = 9.0 margin_right = 459.0 margin_bottom = 29.0 +script = ExtResource( 12 ) [connection signal="pressed" from="TimelineContainer/TimelineButtons/LayerTools/VBoxContainer/LayerButtons/AddLayer" to="." method="add_layer" binds= [ 0 ]] [connection signal="pressed" from="TimelineContainer/TimelineButtons/LayerTools/VBoxContainer/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"] @@ -1004,7 +1005,6 @@ margin_bottom = 29.0 [connection signal="pressed" from="TimelineContainer/TimelineButtons/VBoxContainer/AnimationToolsScrollContainer/AnimationTools/AnimationButtons/LoopButtons/OnionSkinning" to="." method="_on_OnionSkinning_pressed"] [connection signal="pressed" from="TimelineContainer/TimelineButtons/VBoxContainer/AnimationToolsScrollContainer/AnimationTools/AnimationButtons/LoopButtons/LoopAnim" to="." method="_on_LoopAnim_pressed"] [connection signal="value_changed" from="TimelineContainer/TimelineButtons/VBoxContainer/AnimationToolsScrollContainer/AnimationTools/AnimationButtons/LoopButtons/FPSValue" to="." method="_on_FPSValue_value_changed"] -[connection signal="gui_input" from="TimelineContainer/TimelineButtons/VBoxContainer/TagScroll/HBoxContainer/TagContainer" to="." method="_on_TagContainer_gui_input"] [connection signal="gui_input" from="TimelineContainer/PanelContainer/VBoxContainer/TimelineScroll/LayerFrameHSplit" to="." method="_on_LayerFrameSplitContainer_gui_input"] [connection signal="resized" from="TimelineContainer/PanelContainer/VBoxContainer/TimelineScroll/LayerFrameHSplit/VBoxContainer/LayerVBox" to="." method="_on_LayerVBox_resized"] [connection signal="timeout" from="AnimationTimer" to="." method="_on_AnimationTimer_timeout"] diff --git a/src/UI/Timeline/PasteTagPopup.gd b/src/UI/Timeline/PasteTagPopup.gd new file mode 100644 index 000000000..c59846509 --- /dev/null +++ b/src/UI/Timeline/PasteTagPopup.gd @@ -0,0 +1,38 @@ +extends PopupMenu + + +func _ready() -> void: + var tag_container: Control = Global.animation_timeline.find_node("TagContainer") + connect("id_pressed", self, "_on_TagList_id_pressed") + tag_container.connect("gui_input", self, "_on_TagContainer_gui_input") + + +func _on_TagContainer_gui_input(event: InputEvent) -> void: + if !event is InputEventMouseButton: + return + if Input.is_action_just_released("right_mouse"): + clear() + if Global.current_project.animation_tags.empty(): + return + add_separator("Paste content from tag:") + for tag in Global.current_project.animation_tags: + var img = Image.new() + img.create(5, 5, true, Image.FORMAT_RGBA8) + img.fill(tag.color) + var tex = ImageTexture.new() + tex.create_from_image(img) + var title = tag.name + if title == "": + title = "(Untitled)" + add_icon_item(tex, title) + var frame_idx = Global.current_project.current_frame + 2 + add_separator(str("The pasted frames will start at (Frame ", frame_idx, ")")) + popup(Rect2(get_global_mouse_position(), Vector2.ONE)) + + +func _on_TagList_id_pressed(id: int) -> void: + var tag: AnimationTag = Global.current_project.animation_tags[id - 1] + var frames = [] + for i in range(tag.from - 1, tag.to): + frames.append(i) + Global.animation_timeline.copy_frames(frames, Global.current_project.current_frame)