diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index fbdeae9b5..539a78c16 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -216,16 +216,16 @@ func export_gif(args: Dictionary) -> void: match direction: AnimationDirection.FORWARD: for i in range(processed_images.size()): - write_frame_to_gif(processed_images[i], Global.current_project.frame_duration[i] * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) + write_frame_to_gif(processed_images[i], Global.current_project.frames[i].duration * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) AnimationDirection.BACKWARDS: for i in range(processed_images.size() - 1, -1, -1): - write_frame_to_gif(processed_images[i], Global.current_project.frame_duration[i] * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) + write_frame_to_gif(processed_images[i], Global.current_project.frames[i].duration * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) AnimationDirection.PING_PONG: export_progress_fraction = 100 / (processed_images.size() * 2) for i in range(0, processed_images.size()): - write_frame_to_gif(processed_images[i], Global.current_project.frame_duration[i] * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) + write_frame_to_gif(processed_images[i], Global.current_project.frames[i].duration * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) for i in range(processed_images.size() - 2, 0, -1): - write_frame_to_gif(processed_images[i], Global.current_project.frame_duration[i] * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) + write_frame_to_gif(processed_images[i], Global.current_project.frames[i].duration * (1 / Global.animation_timeline.fps), exporter, args["export_dialog"]) if OS.get_name() == "HTML5": Html5FileExchange.save_gif(exporter.export_file_data(), args["export_paths"][0]) diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index a56631fbe..0992d6ef1 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -218,8 +218,6 @@ func open_old_pxo_file(file : File, new_project : Project, first_line : String) new_project.size = Vector2(width, height) new_project.frames.append(frame_class) - if frame >= new_project.frame_duration.size(): - new_project.frame_duration.append(1) frame_line = file.get_line() frame += 1 @@ -386,7 +384,6 @@ func open_image_as_spritesheet(path : String, image : Image, horizontal : int, v frame.cels.append(Cel.new(empty_sprite, 1)) project.frames.append(frame) - project.frame_duration.append(1) set_new_tab(project, path) @@ -395,7 +392,6 @@ func open_image_as_new_frame(image : Image, layer_index := 0) -> void: var project = Global.current_project image.crop(project.size.x, project.size.y) var new_frames : Array = project.frames.duplicate() - var frame_duration : Array = Global.current_project.frame_duration.duplicate() var frame := Frame.new() for i in project.layers.size(): @@ -410,7 +406,6 @@ func open_image_as_new_frame(image : Image, layer_index := 0) -> void: frame.cels.append(Cel.new(empty_image, 1)) new_frames.append(frame) - frame_duration.append(1) project.undos += 1 project.undo_redo.create_action("Add Frame") @@ -420,12 +415,10 @@ func open_image_as_new_frame(image : Image, layer_index := 0) -> void: project.undo_redo.add_do_property(project, "frames", new_frames) project.undo_redo.add_do_property(project, "current_frame", new_frames.size() - 1) project.undo_redo.add_do_property(project, "current_layer", layer_index) - Global.current_project.undo_redo.add_do_property(Global.current_project, "frame_duration", frame_duration) # Add an 1 in the list of frame_duration project.undo_redo.add_undo_property(project, "frames", project.frames) project.undo_redo.add_undo_property(project, "current_frame", project.current_frame) project.undo_redo.add_undo_property(project, "current_layer", project.current_layer) - Global.current_project.undo_redo.add_undo_property(Global.current_project, "frame_duration", Global.current_project.frame_duration) project.undo_redo.commit_action() diff --git a/src/Classes/Frame.gd b/src/Classes/Frame.gd index ed7bd62e0..db5a97e09 100644 --- a/src/Classes/Frame.gd +++ b/src/Classes/Frame.gd @@ -4,7 +4,9 @@ class_name Frame extends Reference var cels : Array # An array of Cels +var duration := 1.0 -func _init(_cels := []) -> void: +func _init(_cels := [], _duration := 1.0) -> void: cels = _cels + duration = _duration diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 9565127b6..b4a85310e 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -9,7 +9,6 @@ var tile_mode : int = Global.Tile_Mode.NONE var undos := 0 # The number of times we added undo properties var has_changed := false setget has_changed_changed var frames := [] setget frames_changed # Array of Frames (that contain Cels) -var frame_duration := [] var layers := [] setget layers_changed # Array of Layers var current_frame := 0 setget frame_changed var current_layer := 0 setget layer_changed @@ -41,7 +40,6 @@ func _init(_frames := [], _name := tr("untitled"), _size := Vector2(64, 64)) -> frames = _frames name = _name size = _size - frame_duration.append(1) select_all_pixels() undo_redo = UndoRedo.new() @@ -259,7 +257,8 @@ func serialize() -> Dictionary: # "image_data" : cel.image.get_data() }) frame_data.append({ - "cels" : cel_data + "cels" : cel_data, + "duration" : frame.duration }) var brush_data := [] for brush in brushes: @@ -283,7 +282,6 @@ func serialize() -> Dictionary: "export_directory_path" : directory_path, "export_file_name" : file_name, "export_file_format" : file_format, - "frame_duration" : frame_duration, } return project_data @@ -299,11 +297,20 @@ func deserialize(dict : Dictionary) -> void: if dict.has("save_path"): OpenSave.current_save_paths[Global.projects.find(self)] = dict.save_path if dict.has("frames"): + var frame_i := 0 for frame in dict.frames: var cels := [] for cel in frame.cels: cels.append(Cel.new(Image.new(), cel.opacity)) - frames.append(Frame.new(cels)) + var duration := 1.0 + if frame.has("duration"): + duration = frame.duration + elif dict.has("frame_duration"): + duration = dict.frame_duration[frame_i] + + frames.append(Frame.new(cels, duration)) + frame_i += 1 + if dict.has("layers"): var layer_i := 0 for saved_layer in dict.layers: @@ -345,13 +352,6 @@ func deserialize(dict : Dictionary) -> void: file_name = dict.export_file_name if dict.has("export_file_format"): file_format = dict.export_file_format - if dict.has("frame_duration"): - frame_duration = dict.frame_duration - else: - for i in frames.size(): - if i < frame_duration.size(): - continue - frame_duration.append(1) func name_changed(value : String) -> void: diff --git a/src/UI/Canvas/CanvasPreview.gd b/src/UI/Canvas/CanvasPreview.gd index c9db8107f..c7379d60e 100644 --- a/src/UI/Canvas/CanvasPreview.gd +++ b/src/UI/Canvas/CanvasPreview.gd @@ -9,7 +9,7 @@ func _draw() -> void: if frame >= current_project.frames.size(): frame = current_project.current_frame - $AnimationTimer.wait_time = current_project.frame_duration[frame] * (1 / Global.animation_timeline.fps) + $AnimationTimer.wait_time = current_project.frames[frame].duration * (1 / Global.animation_timeline.fps) if animation_timer.is_stopped(): frame = current_project.current_frame @@ -30,6 +30,6 @@ func _on_AnimationTimer_timeout() -> void: frame = 0 $AnimationTimer.set_one_shot(true) - $AnimationTimer.wait_time = Global.current_project.frame_duration[frame] * (1 / Global.animation_timeline.fps) + $AnimationTimer.wait_time = Global.current_project.frames[frame].duration * (1 / Global.animation_timeline.fps) $AnimationTimer.start() update() diff --git a/src/UI/Dialogs/ExportDialog.gd b/src/UI/Dialogs/ExportDialog.gd index 1276a39cb..20a3e5a11 100644 --- a/src/UI/Dialogs/ExportDialog.gd +++ b/src/UI/Dialogs/ExportDialog.gd @@ -149,7 +149,7 @@ func add_animated_preview() -> void: previews.add_child(container) frame_timer.set_one_shot(true) #The wait_time it can't change correctly if it is playing - frame_timer.wait_time = Global.current_project.frame_duration[animated_preview_current_frame] * (1 / Global.animation_timeline.fps) + frame_timer.wait_time = Global.current_project.frames[animated_preview_current_frame].duration * (1 / Global.animation_timeline.fps) frame_timer.start() @@ -363,14 +363,14 @@ func _on_FrameTimer_timeout() -> void: animated_preview_current_frame = 0 else: animated_preview_current_frame += 1 - frame_timer.wait_time = Global.current_project.frame_duration[(animated_preview_current_frame - 1) % (animated_preview_frames.size())] * (1 / Global.animation_timeline.fps) + frame_timer.wait_time = Global.current_project.frames[(animated_preview_current_frame - 1) % (animated_preview_frames.size())].duration * (1 / Global.animation_timeline.fps) frame_timer.start() Export.AnimationDirection.BACKWARDS: if animated_preview_current_frame == 0: animated_preview_current_frame = Export.processed_images.size() - 1 else: animated_preview_current_frame -= 1 - frame_timer.wait_time = Global.current_project.frame_duration[(animated_preview_current_frame + 1) % (animated_preview_frames.size())] * (1 / Global.animation_timeline.fps) + frame_timer.wait_time = Global.current_project.frames[(animated_preview_current_frame + 1) % (animated_preview_frames.size())].duration * (1 / Global.animation_timeline.fps) frame_timer.start() Export.AnimationDirection.PING_PONG: match pingpong_direction: @@ -382,7 +382,7 @@ func _on_FrameTimer_timeout() -> void: animated_preview_current_frame = 0 else: animated_preview_current_frame += 1 - frame_timer.wait_time = Global.current_project.frame_duration[(animated_preview_current_frame - 1) % (animated_preview_frames.size())] * (1 / Global.animation_timeline.fps) + frame_timer.wait_time = Global.current_project.frames[(animated_preview_current_frame - 1) % (animated_preview_frames.size())].duration * (1 / Global.animation_timeline.fps) frame_timer.start() Export.AnimationDirection.BACKWARDS: if animated_preview_current_frame == 0: @@ -392,7 +392,7 @@ func _on_FrameTimer_timeout() -> void: pingpong_direction = Export.AnimationDirection.FORWARD else: animated_preview_current_frame -= 1 - frame_timer.wait_time = Global.current_project.frame_duration[(animated_preview_current_frame + 1) % (animated_preview_frames.size())] * (1 / Global.animation_timeline.fps) + frame_timer.wait_time = Global.current_project.frames[(animated_preview_current_frame + 1) % (animated_preview_frames.size())].duration * (1 / Global.animation_timeline.fps) frame_timer.start() diff --git a/src/UI/Timeline/AnimationTimeline.gd b/src/UI/Timeline/AnimationTimeline.gd index 2ff32db0f..b2238e3af 100644 --- a/src/UI/Timeline/AnimationTimeline.gd +++ b/src/UI/Timeline/AnimationTimeline.gd @@ -24,11 +24,9 @@ func _h_scroll_changed(value : float) -> void: func add_frame() -> void: - var frame_duration : Array = Global.current_project.frame_duration.duplicate() var frame : Frame = Global.canvas.new_empty_frame() var new_frames : Array = Global.current_project.frames.duplicate() var new_layers : Array = Global.current_project.layers.duplicate() - frame_duration.insert(Global.current_project.current_frame + 1, 1) new_frames.insert(Global.current_project.current_frame + 1, frame) # Loop through the array to create new classes for each element, so that they # won't be the same as the original array's classes. Needed for undo/redo to work properly. @@ -50,12 +48,10 @@ func add_frame() -> 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", Global.current_project.current_frame + 1) Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - Global.current_project.undo_redo.add_do_property(Global.current_project, "frame_duration", frame_duration) # Add an 1 in the list of frame_duration Global.current_project.undo_redo.add_undo_property(Global.current_project, "frames", Global.current_project.frames) Global.current_project.undo_redo.add_undo_property(Global.current_project, "current_frame", Global.current_project.current_frame ) Global.current_project.undo_redo.add_undo_property(Global.current_project, "layers", Global.current_project.layers) - Global.current_project.undo_redo.add_undo_property(Global.current_project, "frame_duration", Global.current_project.frame_duration) Global.current_project.undo_redo.commit_action() @@ -65,8 +61,6 @@ func _on_DeleteFrame_pressed(frame := -1) -> void: if frame == -1: frame = Global.current_project.current_frame - var frame_duration : Array = Global.current_project.frame_duration.duplicate() - frame_duration.remove(frame) var frame_to_delete : Frame = Global.current_project.frames[frame] var new_frames : Array = Global.current_project.frames.duplicate() new_frames.erase(frame_to_delete) @@ -113,13 +107,11 @@ func _on_DeleteFrame_pressed(frame := -1) -> void: Global.current_project.undo_redo.add_do_property(Global.current_project, "current_frame", current_frame) Global.current_project.undo_redo.add_do_property(Global.current_project, "animation_tags", new_animation_tags) Global.current_project.undo_redo.add_do_property(Global.current_project, "layers", new_layers) - Global.current_project.undo_redo.add_do_property(Global.current_project, "frame_duration", frame_duration) #Remove the element of the list of the frame selected Global.current_project.undo_redo.add_undo_property(Global.current_project, "frames", Global.current_project.frames) Global.current_project.undo_redo.add_undo_property(Global.current_project, "current_frame", Global.current_project.current_frame) Global.current_project.undo_redo.add_undo_property(Global.current_project, "animation_tags", Global.current_project.animation_tags) Global.current_project.undo_redo.add_undo_property(Global.current_project, "layers", Global.current_project.layers) - Global.current_project.undo_redo.add_undo_property(Global.current_project, "frame_duration", Global.current_project.frame_duration) Global.current_project.undo_redo.add_do_method(Global, "redo") Global.current_project.undo_redo.add_undo_method(Global, "undo") @@ -131,8 +123,6 @@ func _on_CopyFrame_pressed(frame := -1) -> void: frame = Global.current_project.current_frame var new_frame := Frame.new() - var frame_duration : Array = Global.current_project.frame_duration.duplicate() - frame_duration.insert(frame + 1, 1) var new_frames := Global.current_project.frames.duplicate() new_frames.insert(frame + 1, new_frame) @@ -161,7 +151,6 @@ func _on_CopyFrame_pressed(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.undo_redo.add_do_property(Global.current_project, "animation_tags", new_animation_tags) - Global.current_project.undo_redo.add_do_property(Global.current_project, "frame_duration", frame_duration) for i in range(Global.current_project.layers.size()): for child in Global.current_project.layers[i].frame_container.get_children(): Global.current_project.undo_redo.add_do_property(child, "pressed", false) @@ -170,7 +159,6 @@ func _on_CopyFrame_pressed(frame := -1) -> void: Global.current_project.undo_redo.add_undo_property(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.undo_redo.add_undo_property(Global.current_project, "animation_tags", Global.current_project.animation_tags) - Global.current_project.undo_redo.add_undo_property(Global.current_project, "frame_duration", Global.current_project.frame_duration) Global.current_project.undo_redo.commit_action() @@ -245,8 +233,8 @@ func _on_AnimationTimer_timeout() -> void: if animation_forward: if Global.current_project.current_frame < last_frame: Global.current_project.current_frame += 1 - Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1/fps) - Global.animation_timer.start() #Change the frame, change the wait time and start a cycle, this is the best way to do it + Global.animation_timer.wait_time = Global.current_project.frames[Global.current_project.current_frame].duration * (1/fps) + Global.animation_timer.start() # Change the frame, change the wait time and start a cycle, this is the best way to do it else: match animation_loop: 0: # No loop @@ -255,7 +243,7 @@ func _on_AnimationTimer_timeout() -> void: Global.animation_timer.stop() 1: # Cycle loop Global.current_project.current_frame = first_frame - Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1/fps) + Global.animation_timer.wait_time = Global.current_project.frames[Global.current_project.current_frame].duration * (1/fps) Global.animation_timer.start() 2: # Ping pong loop animation_forward = false @@ -264,7 +252,7 @@ func _on_AnimationTimer_timeout() -> void: else: if Global.current_project.current_frame > first_frame: Global.current_project.current_frame -= 1 - Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1/fps) + Global.animation_timer.wait_time = Global.current_project.frames[Global.current_project.current_frame].duration * (1/fps) Global.animation_timer.start() else: match animation_loop: @@ -274,7 +262,7 @@ func _on_AnimationTimer_timeout() -> void: Global.animation_timer.stop() 1: # Cycle loop Global.current_project.current_frame = last_frame - Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1/fps) + Global.animation_timer.wait_time = Global.current_project.frames[Global.current_project.current_frame].duration * (1/fps) Global.animation_timer.start() 2: # Ping pong loop animation_forward = true @@ -309,8 +297,9 @@ func play_animation(play : bool, forward_dir : bool) -> void: Global.play_forward.connect("toggled", self, "_on_PlayForward_toggled") if play: - Global.animation_timer.set_one_shot(true) #The wait_time it can't change correctly if it is playing - Global.animation_timer.wait_time = Global.current_project.frame_duration[Global.current_project.current_frame] * (1 / fps) + Global.animation_timer.set_one_shot(true) # The wait_time can't change correctly if it is playing + var duration : float = Global.current_project.frames[Global.current_project.current_frame].duration + Global.animation_timer.wait_time = duration * (1 / fps) Global.animation_timer.start() animation_forward = forward_dir else: diff --git a/src/UI/Timeline/CelButton.gd b/src/UI/Timeline/CelButton.gd index 7c95c7e75..0510e9a31 100644 --- a/src/UI/Timeline/CelButton.gd +++ b/src/UI/Timeline/CelButton.gd @@ -105,18 +105,10 @@ func _on_PopupMenu_id_pressed(ID : int) -> void: Global.frame_properties.popup_centered() Global.dialog_open(true) Global.frame_properties.set_frame_label(frame) - Global.frame_properties.set_frame_dur(Global.current_project.frame_duration[frame]) + Global.frame_properties.set_frame_dur(Global.current_project.frames[frame].duration) func change_frame_order(rate : int) -> void: var change = frame + rate - var frame_duration : Array = Global.current_project.frame_duration.duplicate() - if rate > 0: #There is no function in the class Array in godot to make this quickly and this is the fastest way to swap positions I think of - frame_duration.insert(change + 1, frame_duration[frame]) - frame_duration.remove(frame) - else: - frame_duration.insert(change, frame_duration[frame]) - frame_duration.remove(frame + 1) - var new_frames : Array = Global.current_project.frames.duplicate() var temp = new_frames[frame] new_frames[frame] = new_frames[change] @@ -124,14 +116,12 @@ func change_frame_order(rate : int) -> void: Global.current_project.undo_redo.create_action("Change Frame Order") 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, "frame_duration", frame_duration) if Global.current_project.current_frame == frame: Global.current_project.undo_redo.add_do_property(Global.current_project, "current_frame", change) Global.current_project.undo_redo.add_undo_property(Global.current_project, "current_frame", Global.current_project.current_frame) Global.current_project.undo_redo.add_undo_property(Global.current_project, "frames", Global.current_project.frames) - Global.current_project.undo_redo.add_undo_property(Global.current_project, "frame_duration", Global.current_project.frame_duration) Global.current_project.undo_redo.add_undo_method(Global, "undo") Global.current_project.undo_redo.add_do_method(Global, "redo") diff --git a/src/UI/Timeline/FrameProperties.gd b/src/UI/Timeline/FrameProperties.gd index d7aa56e10..a9c456d72 100644 --- a/src/UI/Timeline/FrameProperties.gd +++ b/src/UI/Timeline/FrameProperties.gd @@ -13,16 +13,16 @@ func _on_FrameProperties_popup_hide() -> void: Global.dialog_open(false) func _on_FrameProperties_confirmed(): - var frame : int = int(frame_num.get_text()) + var frame : int = int(frame_num.get_text()) - 1 var duration : float = frame_dur.get_value() - var frame_duration = Global.current_project.frame_duration.duplicate() - frame_duration[frame - 1] = duration + var new_duration = Global.current_project.frames[frame].duration + new_duration = duration Global.current_project.undos += 1 Global.current_project.undo_redo.create_action("Change frame duration") - Global.current_project.undo_redo.add_do_property(Global.current_project, "frame_duration", frame_duration) - Global.current_project.undo_redo.add_undo_property(Global.current_project, "frame_duration", Global.current_project.frame_duration) + Global.current_project.undo_redo.add_do_property(Global.current_project.frames[frame], "duration", new_duration) + Global.current_project.undo_redo.add_undo_property(Global.current_project.frames[frame], "duration", Global.current_project.frames[frame].duration) Global.current_project.undo_redo.add_do_method(Global, "redo") Global.current_project.undo_redo.add_undo_method(Global, "undo")