From bec30112f6e3d0aaaed046606c177c0b5eae06dd Mon Sep 17 00:00:00 2001 From: Variable <77773850+Variable-ind@users.noreply.github.com> Date: Mon, 28 Feb 2022 06:31:17 +0500 Subject: [PATCH] improvements to copy\delete methods and (some) tag workflow (#648) * improvements to copy and delete methods To allow cloning/deleting an array of frames * formatting * adapt to the new copy/delete methods * Update AnimationTimeline.gd * removed some bugs * changed old tag behaviour tags ahead get further by 1 frame on add_frame() * modified tag behaviour * formatting * removed tag interaction --- src/UI/Timeline/AnimationTimeline.gd | 167 ++++++++++++++++++--------- src/UI/Timeline/FrameButton.gd | 6 +- 2 files changed, 114 insertions(+), 59 deletions(-) diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index aec872daf..04e553ad3 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -77,10 +77,11 @@ func cel_size_changed(value: int) -> void: func add_frame() -> void: var project: Project = Global.current_project + var frame_add_index := project.current_frame + 1 var frame: Frame = project.new_empty_frame() var new_frames: Array = project.frames.duplicate() var new_layers: Array = project.duplicate_layers() - new_frames.insert(project.current_frame + 1, frame) + new_frames.insert(frame_add_index, frame) for l_i in range(new_layers.size()): if new_layers[l_i].new_cels_linked: # If the link button is pressed @@ -88,6 +89,25 @@ func add_frame() -> void: frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture + # Code to PUSH AHEAD tags starting after the frame + var new_animation_tags := Global.current_project.animation_tags.duplicate() + # Loop through the tags to create new classes for them, so that they won't be the same + # as Global.current_project.animation_tags's classes. Needed for undo/redo to work properly. + for i in new_animation_tags.size(): + new_animation_tags[i] = AnimationTag.new( + new_animation_tags[i].name, + new_animation_tags[i].color, + new_animation_tags[i].from, + new_animation_tags[i].to + ) + # Loop through the tags to see if the frame is in one + for tag in new_animation_tags: + if frame_add_index >= tag.from && frame_add_index <= tag.to: + tag.to += 1 + elif (frame_add_index) < tag.from: + tag.from += 1 + tag.to += 1 + project.undos += 1 project.undo_redo.create_action("Add Frame") project.undo_redo.add_do_method(Global, "undo_or_redo", false) @@ -95,30 +115,41 @@ func add_frame() -> void: project.undo_redo.add_do_property(project, "frames", new_frames) project.undo_redo.add_do_property(project, "current_frame", project.current_frame + 1) + Global.current_project.undo_redo.add_do_property( + Global.current_project, "animation_tags", new_animation_tags + ) project.undo_redo.add_do_property(project, "layers", new_layers) project.undo_redo.add_undo_property(project, "frames", project.frames) project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) + Global.current_project.undo_redo.add_undo_property( + Global.current_project, "animation_tags", Global.current_project.animation_tags + ) project.undo_redo.add_undo_property(project, "layers", project.layers) project.undo_redo.commit_action() func _on_DeleteFrame_pressed(frame := -1) -> void: - delete_frame(frame) + var frames := [] + for cel in Global.current_project.selected_cels: + frame = cel[0] + if not frame in frames: + frames.append(frame) + frames.sort() + delete_frames(frames) -func delete_frame(frame := -1) -> void: +func delete_frames(frames := []) -> void: if Global.current_project.frames.size() == 1: return - if frame == -1: - frame = Global.current_project.current_frame - var frame_to_delete: Frame = Global.current_project.frames[frame] + if frames.size() == 0: + frames.append(Global.current_project.current_frame) + var new_frames: Array = Global.current_project.frames.duplicate() - new_frames.erase(frame_to_delete) var current_frame := Global.current_project.current_frame - if current_frame > 0 && current_frame == new_frames.size(): # If it's the last frame - current_frame -= 1 + var new_layers: Array = Global.current_project.duplicate_layers() + var frame_correction := 0 # Only needed for tag adjustment var new_animation_tags := Global.current_project.animation_tags.duplicate() # Loop through the tags to create new classes for them, so that they won't be the same @@ -131,26 +162,37 @@ func delete_frame(frame := -1) -> void: new_animation_tags[i].to ) - # Loop through the tags to see if the frame is in one - for tag in new_animation_tags: - if frame + 1 >= tag.from && frame + 1 <= tag.to: - if tag.from == tag.to: # If we're deleting the only frame in the tag - new_animation_tags.erase(tag) - else: + for frame in frames: + if new_frames.size() == 1: # If only 1 frame + break + var frame_to_delete: Frame = Global.current_project.frames[frame] + new_frames.erase(frame_to_delete) + if current_frame > 0 && current_frame == new_frames.size(): # If it's the last frame + current_frame -= 1 + + # Check if one of the cels of the frame is linked + # if they are, unlink them too + # this prevents removed cels being kept in linked memory + for layer in new_layers: + for linked in layer.linked_cels: + if linked == Global.current_project.frames[frame]: + layer.linked_cels.erase(linked) + + # Loop through the tags to see if the frame is in one + frame -= frame_correction # Erasing made frames indexes 1 step ahead their intended tags + var tag_correction := 0 # needed when tag is erased + for tag_ind in new_animation_tags.size(): + var tag = new_animation_tags[tag_ind - tag_correction] + if frame + 1 >= tag.from && frame + 1 <= tag.to: + if tag.from == tag.to: # If we're deleting the only frame in the tag + new_animation_tags.erase(tag) + tag_correction += 1 + else: + tag.to -= 1 + elif frame + 1 < tag.from: + tag.from -= 1 tag.to -= 1 - elif frame + 1 < tag.from: - tag.from -= 1 - tag.to -= 1 - - # Check if one of the cels of the frame is linked - # if they are, unlink them too - # this prevents removed cels being kept in linked memory - var new_layers: Array = Global.current_project.duplicate_layers() - - for layer in new_layers: - for linked in layer.linked_cels: - if linked == Global.current_project.frames[frame]: - layer.linked_cels.erase(linked) + frame_correction += 1 # Compensation for the next batch Global.current_project.undos += 1 Global.current_project.undo_redo.create_action("Remove Frame") @@ -183,33 +225,23 @@ func delete_frame(frame := -1) -> void: func _on_CopyFrame_pressed(frame := -1) -> void: - copy_frame(frame) + var frames := [] + for cel in Global.current_project.selected_cels: + frame = cel[0] + if not frame in frames: + frames.append(frame) + frames.sort() + copy_frames(frames) -func copy_frame(frame := -1) -> void: +func copy_frames(frames := []) -> void: Global.canvas.selection.transform_content_confirm() - if frame == -1: - frame = Global.current_project.current_frame - var new_frame := Frame.new() + if frames.size() == 0: + frames.append(Global.current_project.current_frame) + var new_frames := Global.current_project.frames.duplicate() var new_layers: Array = Global.current_project.duplicate_layers() - new_frames.insert(frame + 1, new_frame) - - var prev_frame: Frame = Global.current_project.frames[frame] - for cel in prev_frame.cels: # Copy every cel - var sprite := Image.new() - sprite.copy_from(cel.image) - var sprite_texture := ImageTexture.new() - sprite_texture.create_from_image(sprite, 0) - new_frame.cels.append(Cel.new(sprite, cel.opacity, sprite_texture)) - - new_frame.duration = prev_frame.duration - for l_i in range(new_layers.size()): - if new_layers[l_i].new_cels_linked: # If the link button is pressed - new_layers[l_i].linked_cels.append(new_frame) - new_frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image - new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture var new_animation_tags := Global.current_project.animation_tags.duplicate() # Loop through the tags to create new classes for them, so that they won't be the same @@ -222,10 +254,33 @@ func copy_frame(frame := -1) -> void: new_animation_tags[i].to ) - # Loop through the tags to see if the frame is in one - for tag in new_animation_tags: - if frame + 1 >= tag.from && frame + 1 <= tag.to: - tag.to += 1 + for frm in frames.size(): + var frame = frames[(frames.size() - 1) - frm] + var new_frame := Frame.new() + new_frames.insert(frames[-1] + 1, new_frame) + + var prev_frame: Frame = Global.current_project.frames[frame] + for cel in prev_frame.cels: # Copy every cel + var sprite := Image.new() + sprite.copy_from(cel.image) + var sprite_texture := ImageTexture.new() + sprite_texture.create_from_image(sprite, 0) + new_frame.cels.append(Cel.new(sprite, cel.opacity, sprite_texture)) + + new_frame.duration = prev_frame.duration + for l_i in range(new_layers.size()): + if new_layers[l_i].new_cels_linked: # If the link button is pressed + new_layers[l_i].linked_cels.append(new_frame) + new_frame.cels[l_i].image = new_layers[l_i].linked_cels[0].cels[l_i].image + new_frame.cels[l_i].image_texture = new_layers[l_i].linked_cels[0].cels[l_i].image_texture + + # Loop through the tags to see if the frame is in one + for tag in new_animation_tags: + if frames[-1] + 1 >= tag.from && frames[-1] + 1 <= tag.to: + tag.to += 1 + elif frames[-1] + 1 < tag.from: + tag.from += 1 + tag.to += 1 Global.current_project.undos += 1 Global.current_project.undo_redo.create_action("Add Frame") @@ -234,7 +289,7 @@ func copy_frame(frame := -1) -> void: Global.current_project.undo_redo.add_do_property(Global.current_project, "frames", new_frames) Global.current_project.undo_redo.add_do_property( - Global.current_project, "current_frame", frame + 1 + Global.current_project, "current_frame", frames[-1] + 1 ) Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) Global.current_project.undo_redo.add_do_property( @@ -245,7 +300,7 @@ func copy_frame(frame := -1) -> void: Global.current_project, "frames", Global.current_project.frames ) Global.current_project.undo_redo.add_undo_property( - Global.current_project, "current_frame", frame + Global.current_project, "current_frame", frames[-1] ) Global.current_project.undo_redo.add_undo_property( Global.current_project, "layers", Global.current_project.layers @@ -269,7 +324,7 @@ func _on_MoveLeft_pressed() -> void: func _on_MoveRight_pressed() -> void: var frame: int = Global.current_project.current_frame - if frame == last_frame: + if frame == Global.current_project.frames.size() - 1: # using last_frame caused problems return Global.frame_ids.get_child(frame).change_frame_order(1) diff --git a/src/UI/Timeline/FrameButton.gd b/src/UI/Timeline/FrameButton.gd index 732c84369..bd86ce0d7 100644 --- a/src/UI/Timeline/FrameButton.gd +++ b/src/UI/Timeline/FrameButton.gd @@ -61,7 +61,7 @@ func _button_pressed() -> void: pressed = !pressed elif Input.is_action_just_released("middle_mouse"): pressed = !pressed - Global.animation_timeline.delete_frame(frame) + Global.animation_timeline.delete_frames([frame]) else: # An example of this would be Space pressed = !pressed @@ -69,9 +69,9 @@ func _button_pressed() -> void: func _on_PopupMenu_id_pressed(id: int) -> void: match id: 0: # Remove Frame - Global.animation_timeline.delete_frame(frame) + Global.animation_timeline.delete_frames([frame]) 1: # Clone Frame - Global.animation_timeline.copy_frame(frame) + Global.animation_timeline.copy_frames([frame]) 2: # Move Left change_frame_order(-1) 3: # Move Right