From 90f7df0f5d68413a84ed6cd24eb0636661f653c4 Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas Date: Thu, 7 Mar 2024 16:08:20 +0200 Subject: [PATCH] Exporting each layer as a different file is now possible --- Translations/Translations.pot | 4 +++ src/Autoload/Export.gd | 36 ++++++++++++++++------- src/UI/Dialogs/ExportDialog.gd | 5 ++++ src/UI/Dialogs/ExportDialog.tscn | 50 ++++++++++++++++++-------------- 4 files changed, 62 insertions(+), 33 deletions(-) diff --git a/Translations/Translations.pot b/Translations/Translations.pot index c3a375386..55e38ccf1 100644 --- a/Translations/Translations.pot +++ b/Translations/Translations.pot @@ -2368,6 +2368,10 @@ msgstr "" msgid "minute(s)" msgstr "" +#. A setting found in the export dialog. When enabled, each layer is being exported as a different file, or as different frames if the target format is gif/apng/video. +msgid "Split layers" +msgstr "" + #. Found in the export dialog. msgid "Include frame tags in the file name" msgstr "" diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index ec8370229..8318ef5e9 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -31,6 +31,7 @@ var custom_exporter_generators := {} var current_tab := ExportTab.IMAGE ## All frames and their layers processed/blended into images var processed_images: Array[ProcessedImage] = [] +var split_layers := false # Spritesheet options var orientation := Orientation.COLUMNS @@ -240,10 +241,17 @@ func process_animation(project := Global.current_project) -> void: processed_images.clear() var frames := _calculate_frames(project) for frame in frames: - var image := Image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) - _blend_layers(image, frame) - var duration := frame.duration * (1.0 / project.fps) - processed_images.append(ProcessedImage.new(image, duration)) + if split_layers: + for cel in frame.cels: + var image := Image.new() + image.copy_from(cel.get_image()) + var duration := frame.duration * (1.0 / project.fps) + processed_images.append(ProcessedImage.new(image, duration)) + else: + var image := Image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) + _blend_layers(image, frame) + var duration := frame.duration * (1.0 / project.fps) + processed_images.append(ProcessedImage.new(image, duration)) func _calculate_frames(project := Global.current_project) -> Array[Frame]: @@ -290,7 +298,12 @@ func export_processed_images( var paths_of_existing_files := "" for i in range(processed_images.size()): stop_export = false - var export_path := _create_export_path(multiple_files, project, i + 1) + var frame_index := i + 1 + var layer_index := -1 + if split_layers: + frame_index = i / project.layers.size() + 1 + layer_index = posmod(i, project.layers.size()) + var export_path := _create_export_path(multiple_files, project, frame_index, layer_index) # If the user wants to create a new directory for each animation tag then check # if directories exist, and create them if not if multiple_files and new_dir_for_each_frame_tag: @@ -583,11 +596,15 @@ func is_ffmpeg_installed() -> bool: return false -func _create_export_path(multifile: bool, project: Project, frame := 0) -> String: +func _create_export_path(multifile: bool, project: Project, frame := 0, layer := -1) -> String: var path := project.file_name # Only append frame number when there are multiple files exported if multifile: - var path_extras := separator_character + str(frame).pad_zeros(number_of_digits) + var path_extras := "" + if layer > -1: + var layer_name := project.layers[layer].name + path_extras += "(%s) " % layer_name + path_extras += separator_character + str(frame).pad_zeros(number_of_digits) var frame_tag_and_start_id := _get_proccessed_image_animation_tag_and_start_id( project, frame - 1 ) @@ -622,10 +639,7 @@ func _get_proccessed_image_animation_tag_and_start_id( for animation_tag in project.animation_tags: # Check if processed image is in frame tag and assign frame tag and start id if yes # Then stop - if ( - (processed_image_id + 1) >= animation_tag.from - and (processed_image_id + 1) <= animation_tag.to - ): + if animation_tag.has_frame(processed_image_id): result_animation_tag_and_start_id = [animation_tag.name, animation_tag.from] break return result_animation_tag_and_start_id diff --git a/src/UI/Dialogs/ExportDialog.gd b/src/UI/Dialogs/ExportDialog.gd index 916e09b91..f793ecf47 100644 --- a/src/UI/Dialogs/ExportDialog.gd +++ b/src/UI/Dialogs/ExportDialog.gd @@ -418,6 +418,11 @@ func _on_ExportDialog_popup_hide() -> void: frame_timer.stop() +func _on_split_layers_toggled(toggled_on: bool) -> void: + Export.split_layers = toggled_on + show_tab() + + func _on_IncludeTagsInFilename_toggled(button_pressed: bool) -> void: Export.include_tag_in_filename = button_pressed diff --git a/src/UI/Dialogs/ExportDialog.tscn b/src/UI/Dialogs/ExportDialog.tscn index 0af91bfe8..14b481860 100644 --- a/src/UI/Dialogs/ExportDialog.tscn +++ b/src/UI/Dialogs/ExportDialog.tscn @@ -235,24 +235,24 @@ mouse_default_cursor_shape = 2 [node name="HSeparator3" type="HSeparator" parent="VBoxContainer/VSplitContainer/VBoxContainer"] layout_mode = 2 -[node name="CollapsibleContainer" type="VBoxContainer" parent="VBoxContainer/VSplitContainer/VBoxContainer"] +[node name="AdvancedOptions" type="VBoxContainer" parent="VBoxContainer/VSplitContainer/VBoxContainer"] layout_mode = 2 theme_type_variation = &"CollapsibleContainer" script = ExtResource("3") text = "Advanced options" -[node name="GridContainer" type="GridContainer" parent="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer"] +[node name="GridContainer" type="GridContainer" parent="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions"] visible = false layout_mode = 2 columns = 2 -[node name="InterpolationLabel" type="Label" parent="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer"] +[node name="InterpolationLabel" type="Label" parent="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer"] custom_minimum_size = Vector2(30, 0) layout_mode = 2 size_flags_horizontal = 3 text = "Interpolation:" -[node name="Interpolation" type="OptionButton" parent="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer"] +[node name="Interpolation" type="OptionButton" parent="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -270,29 +270,34 @@ popup/item_3/id = 3 popup/item_4/text = "Lanczos" popup/item_4/id = 4 -[node name="IncludeTagsInFilename" type="CheckBox" parent="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer" groups=["ExportImageOptions", "ExportMultipleFilesOptions"]] -layout_mode = 2 -mouse_default_cursor_shape = 2 -text = "Include frame tags in the file name" - -[node name="MultipleAnimationsDirectories" type="CheckBox" parent="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer" groups=["ExportImageOptions", "ExportMultipleFilesOptions"]] -visible = false -layout_mode = 2 -tooltip_text = "Creates multiple files but every file is stored in different folder that corresponds to its frame tag" -mouse_default_cursor_shape = 2 -text = "Create new folder for each frame tag" - -[node name="SeparatorCharacterLabel" type="Label" parent="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer" groups=["ExportImageOptions"]] +[node name="SeparatorCharacterLabel" type="Label" parent="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer" groups=["ExportImageOptions"]] custom_minimum_size = Vector2(30, 0) layout_mode = 2 size_flags_horizontal = 3 text = "Separator character(s):" -[node name="SeparatorCharacter" type="LineEdit" parent="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer" groups=["ExportImageOptions", "ExportMultipleFilesEditableOptions"]] +[node name="SeparatorCharacter" type="LineEdit" parent="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer" groups=["ExportImageOptions", "ExportMultipleFilesEditableOptions"]] layout_mode = 2 tooltip_text = "The character(s) that separate the file name and the frame number" text = "_" +[node name="SplitLayers" type="CheckBox" parent="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer" groups=["ExportImageOptions"]] +layout_mode = 2 +mouse_default_cursor_shape = 2 +text = "Split layers" + +[node name="IncludeTagsInFilename" type="CheckBox" parent="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer" groups=["ExportImageOptions", "ExportMultipleFilesOptions"]] +layout_mode = 2 +mouse_default_cursor_shape = 2 +text = "Include frame tags in the file name" + +[node name="MultipleAnimationsDirectories" type="CheckBox" parent="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer" groups=["ExportImageOptions", "ExportMultipleFilesOptions"]] +visible = false +layout_mode = 2 +tooltip_text = "Creates multiple files but every file is stored in different folder that corresponds to its frame tag" +mouse_default_cursor_shape = 2 +text = "Create new folder for each frame tag" + [node name="PathDialog" type="FileDialog" parent="." groups=["FileDialogs"]] mode = 2 title = "Open a Directory" @@ -341,10 +346,11 @@ size_flags_horizontal = 3 [connection signal="pressed" from="VBoxContainer/VSplitContainer/VBoxContainer/FilePath/PathButton" to="." method="_on_PathButton_pressed"] [connection signal="text_changed" from="VBoxContainer/VSplitContainer/VBoxContainer/FilePath/FileLineEdit" to="." method="_on_FileLineEdit_text_changed"] [connection signal="item_selected" from="VBoxContainer/VSplitContainer/VBoxContainer/FilePath/FileFormat" to="." method="_on_FileFormat_item_selected"] -[connection signal="item_selected" from="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer/Interpolation" to="." method="_on_Interpolation_item_selected"] -[connection signal="toggled" from="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer/IncludeTagsInFilename" to="." method="_on_IncludeTagsInFilename_toggled"] -[connection signal="toggled" from="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer/MultipleAnimationsDirectories" to="." method="_on_MultipleAnimationsDirectories_toggled"] -[connection signal="text_changed" from="VBoxContainer/VSplitContainer/VBoxContainer/CollapsibleContainer/GridContainer/SeparatorCharacter" to="." method="_on_SeparatorCharacter_text_changed"] +[connection signal="item_selected" from="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer/Interpolation" to="." method="_on_Interpolation_item_selected"] +[connection signal="text_changed" from="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer/SeparatorCharacter" to="." method="_on_SeparatorCharacter_text_changed"] +[connection signal="toggled" from="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer/SplitLayers" to="." method="_on_split_layers_toggled"] +[connection signal="toggled" from="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer/IncludeTagsInFilename" to="." method="_on_IncludeTagsInFilename_toggled"] +[connection signal="toggled" from="VBoxContainer/VSplitContainer/VBoxContainer/AdvancedOptions/GridContainer/MultipleAnimationsDirectories" to="." method="_on_MultipleAnimationsDirectories_toggled"] [connection signal="dir_selected" from="PathDialog" to="." method="_on_FileDialog_dir_selected"] [connection signal="confirmed" from="FileExistsAlert" to="." method="_on_FileExistsAlert_confirmed"] [connection signal="custom_action" from="FileExistsAlert" to="." method="_on_FileExistsAlert_custom_action"]