Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvements to copy\delete methods and (some) tag workflow #648

Merged
merged 14 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 111 additions & 56 deletions src/UI/Timeline/AnimationTimeline.gd
Original file line number Diff line number Diff line change
Expand Up @@ -77,48 +77,79 @@ 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
new_layers[l_i].linked_cels.append(frame)
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)
project.undo_redo.add_undo_method(Global, "undo_or_redo", true)

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
Expand All @@ -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")
Expand Down Expand Up @@ -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
Expand All @@ -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")
Expand All @@ -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(
Expand All @@ -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
Expand All @@ -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)

Expand Down
6 changes: 3 additions & 3 deletions src/UI/Timeline/FrameButton.gd
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,17 @@ 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


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
Expand Down