mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-18 17:19:50 +00:00
[Continuation] Auto select cloned frames, reuse tag animations (#861)
* Duplicated frames
* Added Clone Tag feature
* fix remaining tag issues
* Update AnimationTimeline.gd
formatting
* formatting
* formatting
* add icon and other remaining stuff
* formatting
* formatting
* Update AnimationTimeline.gd
* Update AnimationTimeline.gd
* some bug fixes
* some bug fixes
* make empty tags appear as (Untitled)
* linting
* Delete copy_frame.png
* Delete copy_tag.png
* Add files via upload
* removed separate button and use tag button
* UI improvements to
"Paste content from tag"
* remove some lines that appeared
during resolving conflicts
* Update AnimationTimeline.gd
* moved paste tag code to it's own script
to reduce lines to 1000 in animation timeline.gd
* formatting
* Add files via upload
* test lint disabling
* Update AnimationTimeline.gd
* increase max file lines to 2000
* Removed accidental changes by commit:.....
1902938b98
(Due to my bad habit of dragging and dropping files instead of using git)
This commit is contained in:
parent
98cef503c2
commit
b75903286c
|
@ -1,3 +1,5 @@
|
||||||
disable:
|
disable:
|
||||||
- no-elif-return
|
- no-elif-return
|
||||||
- no-else-return
|
- no-else-return
|
||||||
|
|
||||||
|
max-file-lines: 2000
|
||||||
|
|
|
@ -35,7 +35,6 @@ func _ready() -> void:
|
||||||
frame_scroll_bar.connect("value_changed", self, "_frame_scroll_changed")
|
frame_scroll_bar.connect("value_changed", self, "_frame_scroll_changed")
|
||||||
Global.animation_timer.wait_time = 1 / Global.current_project.fps
|
Global.animation_timer.wait_time = 1 / Global.current_project.fps
|
||||||
fps_spinbox.value = Global.current_project.fps
|
fps_spinbox.value = Global.current_project.fps
|
||||||
|
|
||||||
# config loading
|
# config loading
|
||||||
layer_frame_h_split.split_offset = Global.config_cache.get_value("timeline", "layer_size", 0)
|
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
|
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)
|
# 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)
|
$"%PastPlacement".emit_signal("item_selected", 0 if past_above else 1)
|
||||||
$"%FuturePlacement".emit_signal("item_selected", 0 if future_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:
|
# Makes sure that the frame and tag scroll bars are in the right place:
|
||||||
Global.layer_vbox.call_deferred("emit_signal", "resized")
|
Global.layer_vbox.call_deferred("emit_signal", "resized")
|
||||||
|
|
||||||
|
@ -151,10 +149,8 @@ func add_frame() -> void:
|
||||||
var project: Project = Global.current_project
|
var project: Project = Global.current_project
|
||||||
var frame_add_index := project.current_frame + 1
|
var frame_add_index := project.current_frame + 1
|
||||||
var frame: Frame = project.new_empty_frame()
|
var frame: Frame = project.new_empty_frame()
|
||||||
|
|
||||||
project.undos += 1
|
project.undos += 1
|
||||||
project.undo_redo.create_action("Add Frame")
|
project.undo_redo.create_action("Add Frame")
|
||||||
|
|
||||||
for l in range(project.layers.size()):
|
for l in range(project.layers.size()):
|
||||||
if project.layers[l].new_cels_linked: # If the link button is pressed
|
if project.layers[l].new_cels_linked: # If the link button is pressed
|
||||||
var prev_cel: BaseCel = project.frames[project.current_frame].cels[l]
|
var prev_cel: BaseCel = project.frames[project.current_frame].cels[l]
|
||||||
|
@ -282,15 +278,19 @@ func _on_CopyFrame_pressed() -> void:
|
||||||
copy_frames(indices)
|
copy_frames(indices)
|
||||||
|
|
||||||
|
|
||||||
func copy_frames(indices := []) -> void:
|
func copy_frames(indices := [], destination := -1) -> void:
|
||||||
var project: Project = Global.current_project
|
var project: Project = Global.current_project
|
||||||
|
|
||||||
if indices.size() == 0:
|
if indices.size() == 0:
|
||||||
indices.append(project.current_frame)
|
indices.append(project.current_frame)
|
||||||
|
|
||||||
var copied_frames := []
|
var copied_frames := []
|
||||||
var copied_indices := range(indices[-1] + 1, indices[-1] + 1 + indices.size())
|
var copied_indices := [] # the indices of newly copied frames
|
||||||
|
|
||||||
|
if destination != -1:
|
||||||
|
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()
|
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
|
# 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.
|
# as project.animation_tags's classes. Needed for undo/redo to work properly.
|
||||||
|
@ -301,16 +301,13 @@ func copy_frames(indices := []) -> void:
|
||||||
new_animation_tags[i].from,
|
new_animation_tags[i].from,
|
||||||
new_animation_tags[i].to
|
new_animation_tags[i].to
|
||||||
)
|
)
|
||||||
|
|
||||||
project.undos += 1
|
project.undos += 1
|
||||||
project.undo_redo.create_action("Add Frame")
|
project.undo_redo.create_action("Add Frame")
|
||||||
|
|
||||||
for f in indices:
|
for f in indices:
|
||||||
|
var src_frame: Frame = project.frames[f]
|
||||||
var new_frame := Frame.new()
|
var new_frame := Frame.new()
|
||||||
copied_frames.append(new_frame)
|
copied_frames.append(new_frame)
|
||||||
|
|
||||||
var src_frame: Frame = project.frames[f]
|
|
||||||
|
|
||||||
new_frame.duration = src_frame.duration
|
new_frame.duration = src_frame.duration
|
||||||
for l in range(project.layers.size()):
|
for l in range(project.layers.size()):
|
||||||
var src_cel: BaseCel = project.frames[f].cels[l] # Cel we're copying from, the source
|
var src_cel: BaseCel = project.frames[f].cels[l] # Cel we're copying from, the source
|
||||||
|
@ -322,9 +319,9 @@ func copy_frames(indices := []) -> void:
|
||||||
)
|
)
|
||||||
if src_cel.selected != null:
|
if src_cel.selected != null:
|
||||||
selected_id = src_cel.selected.id
|
selected_id = src_cel.selected.id
|
||||||
|
|
||||||
else:
|
else:
|
||||||
new_cel = src_cel.get_script().new()
|
new_cel = src_cel.get_script().new()
|
||||||
|
|
||||||
if project.layers[l].new_cels_linked:
|
if project.layers[l].new_cels_linked:
|
||||||
if src_cel.link_set == null:
|
if src_cel.link_set == null:
|
||||||
src_cel.link_set = {}
|
src_cel.link_set = {}
|
||||||
|
@ -337,29 +334,44 @@ func copy_frames(indices := []) -> void:
|
||||||
else:
|
else:
|
||||||
new_cel.set_content(src_cel.copy_content())
|
new_cel.set_content(src_cel.copy_content())
|
||||||
new_cel.opacity = src_cel.opacity
|
new_cel.opacity = src_cel.opacity
|
||||||
|
|
||||||
if new_cel is Cel3D:
|
if new_cel is Cel3D:
|
||||||
if selected_id in new_cel.object_properties.keys():
|
if selected_id in new_cel.object_properties.keys():
|
||||||
if selected_id != -1:
|
if selected_id != -1:
|
||||||
new_cel.selected = new_cel.get_object_from_id(selected_id)
|
new_cel.selected = new_cel.get_object_from_id(selected_id)
|
||||||
new_frame.cels.append(new_cel)
|
new_frame.cels.append(new_cel)
|
||||||
|
|
||||||
# Loop through the tags to see if the frame is in one
|
for tag in new_animation_tags: # Loop through the tags to see if the frame is in one
|
||||||
for tag in new_animation_tags:
|
if copied_indices[0] >= tag.from && copied_indices[0] <= tag.to:
|
||||||
if indices[-1] + 1 >= tag.from && indices[-1] + 1 <= tag.to:
|
|
||||||
tag.to += 1
|
tag.to += 1
|
||||||
elif indices[-1] + 1 < tag.from:
|
elif copied_indices[0] < tag.from:
|
||||||
tag.from += 1
|
tag.from += 1
|
||||||
tag.to += 1
|
tag.to += 1
|
||||||
|
|
||||||
project.undo_redo.add_do_method(Global, "undo_or_redo", false)
|
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_undo_method(Global, "undo_or_redo", true)
|
||||||
project.undo_redo.add_do_method(project, "add_frames", copied_frames, copied_indices)
|
project.undo_redo.add_do_method(project, "add_frames", copied_frames, copied_indices)
|
||||||
project.undo_redo.add_undo_method(project, "remove_frames", copied_indices)
|
project.undo_redo.add_undo_method(project, "remove_frames", copied_indices)
|
||||||
project.undo_redo.add_do_method(project, "change_cel", indices[-1] + 1)
|
project.undo_redo.add_do_method(project, "change_cel", copied_indices[0])
|
||||||
project.undo_redo.add_undo_method(project, "change_cel", indices[-1])
|
project.undo_redo.add_undo_method(project, "change_cel", project.current_frame)
|
||||||
project.undo_redo.add_do_property(project, "animation_tags", new_animation_tags)
|
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.add_undo_property(project, "animation_tags", project.animation_tags)
|
||||||
project.undo_redo.commit_action()
|
project.undo_redo.commit_action()
|
||||||
|
# Select all the new frames so that it is easier to move/offset collectively if user wants
|
||||||
|
# To ease animation workflow, new current frame is the first copied 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)
|
||||||
|
if frame_diff_sign == 0:
|
||||||
|
frame_diff_sign = 1
|
||||||
|
for i in range(range_start, range_end + frame_diff_sign, frame_diff_sign):
|
||||||
|
for j in range(0, Global.current_project.layers.size()):
|
||||||
|
var frame_layer := [i, j]
|
||||||
|
if !Global.current_project.selected_cels.has(frame_layer):
|
||||||
|
Global.current_project.selected_cels.append(frame_layer)
|
||||||
|
Global.current_project.change_cel(range_end, -1)
|
||||||
|
yield(get_tree(), "idle_frame")
|
||||||
|
yield(get_tree(), "idle_frame")
|
||||||
|
adjust_scroll_container()
|
||||||
|
|
||||||
|
|
||||||
func _on_FrameTagButton_pressed() -> void:
|
func _on_FrameTagButton_pressed() -> void:
|
||||||
|
@ -423,7 +435,6 @@ func _on_PlayForward_toggled(button_pressed: bool) -> void:
|
||||||
Global.change_button_texturerect(Global.play_forward.get_child(0), "pause.png")
|
Global.change_button_texturerect(Global.play_forward.get_child(0), "pause.png")
|
||||||
else:
|
else:
|
||||||
Global.change_button_texturerect(Global.play_forward.get_child(0), "play.png")
|
Global.change_button_texturerect(Global.play_forward.get_child(0), "play.png")
|
||||||
|
|
||||||
play_animation(button_pressed, true)
|
play_animation(button_pressed, true)
|
||||||
|
|
||||||
|
|
||||||
|
@ -432,7 +443,6 @@ func _on_PlayBackwards_toggled(button_pressed: bool) -> void:
|
||||||
Global.change_button_texturerect(Global.play_backwards.get_child(0), "pause.png")
|
Global.change_button_texturerect(Global.play_backwards.get_child(0), "pause.png")
|
||||||
else:
|
else:
|
||||||
Global.change_button_texturerect(Global.play_backwards.get_child(0), "play_backwards.png")
|
Global.change_button_texturerect(Global.play_backwards.get_child(0), "play_backwards.png")
|
||||||
|
|
||||||
play_animation(button_pressed, false)
|
play_animation(button_pressed, false)
|
||||||
|
|
||||||
|
|
||||||
|
@ -932,7 +942,6 @@ func project_frame_added(frame: int) -> void:
|
||||||
frame_scroll_container.call_deferred( # Make it visible, yes 3 call_deferreds are required
|
frame_scroll_container.call_deferred( # Make it visible, yes 3 call_deferreds are required
|
||||||
"call_deferred", "call_deferred", "ensure_control_visible", button
|
"call_deferred", "call_deferred", "ensure_control_visible", button
|
||||||
)
|
)
|
||||||
|
|
||||||
var layer := Global.cel_vbox.get_child_count() - 1
|
var layer := Global.cel_vbox.get_child_count() - 1
|
||||||
for cel_hbox in Global.cel_vbox.get_children():
|
for cel_hbox in Global.cel_vbox.get_children():
|
||||||
var cel_button = project.frames[frame].cels[layer].instantiate_cel_button()
|
var cel_button = project.frames[frame].cels[layer].instantiate_cel_button()
|
||||||
|
|
|
@ -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://src/UI/Timeline/AnimationTimeline.gd" type="Script" id=1]
|
||||||
[ext_resource path="res://assets/graphics/layers/new.png" type="Texture" id=2]
|
[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://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://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/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/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/remove_frame.png" type="Texture" id=20]
|
||||||
[ext_resource path="res://assets/graphics/timeline/go_to_first_frame.png" type="Texture" id=21]
|
[ext_resource path="res://assets/graphics/timeline/go_to_first_frame.png" type="Texture" id=21]
|
||||||
|
@ -432,9 +433,6 @@ margin_top = -7.0
|
||||||
margin_right = 7.0
|
margin_right = 7.0
|
||||||
margin_bottom = 7.0
|
margin_bottom = 7.0
|
||||||
texture = ExtResource( 28 )
|
texture = ExtResource( 28 )
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="MoveLeft" type="Button" parent="TimelineContainer/TimelineButtons/VBoxContainer/AnimationToolsScrollContainer/AnimationTools/AnimationButtons/FrameButtons" groups=["UIButtons"]]
|
[node name="MoveLeft" type="Button" parent="TimelineContainer/TimelineButtons/VBoxContainer/AnimationToolsScrollContainer/AnimationTools/AnimationButtons/FrameButtons" groups=["UIButtons"]]
|
||||||
margin_left = 96.0
|
margin_left = 96.0
|
||||||
|
@ -980,6 +978,11 @@ margin_bottom = 40.0
|
||||||
mouse_filter = 2
|
mouse_filter = 2
|
||||||
color = Color( 0, 0.741176, 1, 0.501961 )
|
color = Color( 0, 0.741176, 1, 0.501961 )
|
||||||
|
|
||||||
|
[node name="PasteTagPopup" type="PopupMenu" parent="."]
|
||||||
|
margin_right = 20.0
|
||||||
|
margin_bottom = 20.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/AddLayer" to="." method="add_layer" binds= [ 0 ]]
|
||||||
[connection signal="pressed" from="TimelineContainer/TimelineButtons/LayerTools/VBoxContainer/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"]
|
[connection signal="pressed" from="TimelineContainer/TimelineButtons/LayerTools/VBoxContainer/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"]
|
||||||
[connection signal="pressed" from="TimelineContainer/TimelineButtons/LayerTools/VBoxContainer/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ true ]]
|
[connection signal="pressed" from="TimelineContainer/TimelineButtons/LayerTools/VBoxContainer/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ true ]]
|
||||||
|
|
38
src/UI/Timeline/PasteTagPopup.gd
Normal file
38
src/UI/Timeline/PasteTagPopup.gd
Normal file
|
@ -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)
|
Loading…
Reference in a new issue