mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-02-22 13:33:13 +00:00
Minor refactor of Export & ExportDialog to combine processed_images and durations into a single ProcessedImage class
This commit is contained in:
parent
cd2787b373
commit
cb58cf7163
2 changed files with 37 additions and 35 deletions
|
@ -30,8 +30,7 @@ var custom_exporter_generators := {}
|
||||||
|
|
||||||
var current_tab := ExportTab.IMAGE
|
var current_tab := ExportTab.IMAGE
|
||||||
## All frames and their layers processed/blended into images
|
## All frames and their layers processed/blended into images
|
||||||
var processed_images: Array[Image] = []
|
var processed_images: Array[ProcessedImage] = []
|
||||||
var durations: PackedFloat32Array = []
|
|
||||||
|
|
||||||
# Spritesheet options
|
# Spritesheet options
|
||||||
var orientation := Orientation.COLUMNS
|
var orientation := Orientation.COLUMNS
|
||||||
|
@ -58,6 +57,15 @@ var export_progress := 0.0
|
||||||
@onready var gif_export_thread := Thread.new()
|
@onready var gif_export_thread := Thread.new()
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessedImage:
|
||||||
|
var image: Image
|
||||||
|
var duration: float
|
||||||
|
|
||||||
|
func _init(_image: Image, _duration := 1.0) -> void:
|
||||||
|
image = _image
|
||||||
|
duration = _duration
|
||||||
|
|
||||||
|
|
||||||
func _exit_tree() -> void:
|
func _exit_tree() -> void:
|
||||||
if gif_export_thread.is_started():
|
if gif_export_thread.is_started():
|
||||||
gif_export_thread.wait_to_finish()
|
gif_export_thread.wait_to_finish()
|
||||||
|
@ -225,18 +233,17 @@ func process_spritesheet(project := Global.current_project) -> void:
|
||||||
tag_origins[0] += 1
|
tag_origins[0] += 1
|
||||||
_blend_layers(whole_image, frame, origin)
|
_blend_layers(whole_image, frame, origin)
|
||||||
|
|
||||||
processed_images.append(whole_image)
|
processed_images.append(ProcessedImage.new(whole_image))
|
||||||
|
|
||||||
|
|
||||||
func process_animation(project := Global.current_project) -> void:
|
func process_animation(project := Global.current_project) -> void:
|
||||||
processed_images.clear()
|
processed_images.clear()
|
||||||
durations.clear()
|
|
||||||
var frames := _calculate_frames(project)
|
var frames := _calculate_frames(project)
|
||||||
for frame in frames:
|
for frame in frames:
|
||||||
var image := Image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
|
var image := Image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
|
||||||
_blend_layers(image, frame)
|
_blend_layers(image, frame)
|
||||||
processed_images.append(image)
|
var duration := frame.duration * (1.0 / project.fps)
|
||||||
durations.append(frame.duration * (1.0 / project.fps))
|
processed_images.append(ProcessedImage.new(image, duration))
|
||||||
|
|
||||||
|
|
||||||
func _calculate_frames(project := Global.current_project) -> Array[Frame]:
|
func _calculate_frames(project := Global.current_project) -> Array[Frame]:
|
||||||
|
@ -320,7 +327,6 @@ func export_processed_images(
|
||||||
var result := true
|
var result := true
|
||||||
var details := {
|
var details := {
|
||||||
"processed_images": processed_images,
|
"processed_images": processed_images,
|
||||||
"durations": durations,
|
|
||||||
"export_dialog": export_dialog,
|
"export_dialog": export_dialog,
|
||||||
"export_paths": export_paths,
|
"export_paths": export_paths,
|
||||||
"project": project
|
"project": project
|
||||||
|
@ -368,19 +374,19 @@ func export_processed_images(
|
||||||
if OS.has_feature("web"):
|
if OS.has_feature("web"):
|
||||||
if project.file_format == FileFormat.PNG:
|
if project.file_format == FileFormat.PNG:
|
||||||
JavaScriptBridge.download_buffer(
|
JavaScriptBridge.download_buffer(
|
||||||
processed_images[i].save_png_to_buffer(),
|
processed_images[i].image.save_png_to_buffer(),
|
||||||
export_paths[i].get_file(),
|
export_paths[i].get_file(),
|
||||||
"image/png"
|
"image/png"
|
||||||
)
|
)
|
||||||
elif project.file_format == FileFormat.WEBP:
|
elif project.file_format == FileFormat.WEBP:
|
||||||
JavaScriptBridge.download_buffer(
|
JavaScriptBridge.download_buffer(
|
||||||
processed_images[i].save_webp_to_buffer(),
|
processed_images[i].image.save_webp_to_buffer(),
|
||||||
export_paths[i].get_file(),
|
export_paths[i].get_file(),
|
||||||
"image/webp"
|
"image/webp"
|
||||||
)
|
)
|
||||||
elif project.file_format == FileFormat.JPEG:
|
elif project.file_format == FileFormat.JPEG:
|
||||||
JavaScriptBridge.download_buffer(
|
JavaScriptBridge.download_buffer(
|
||||||
processed_images[i].save_jpg_to_buffer(),
|
processed_images[i].image.save_jpg_to_buffer(),
|
||||||
export_paths[i].get_file(),
|
export_paths[i].get_file(),
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
)
|
)
|
||||||
|
@ -388,11 +394,11 @@ func export_processed_images(
|
||||||
else:
|
else:
|
||||||
var err: Error
|
var err: Error
|
||||||
if project.file_format == FileFormat.PNG:
|
if project.file_format == FileFormat.PNG:
|
||||||
err = processed_images[i].save_png(export_paths[i])
|
err = processed_images[i].image.save_png(export_paths[i])
|
||||||
elif project.file_format == FileFormat.WEBP:
|
elif project.file_format == FileFormat.WEBP:
|
||||||
err = processed_images[i].save_webp(export_paths[i])
|
err = processed_images[i].image.save_webp(export_paths[i])
|
||||||
elif project.file_format == FileFormat.JPEG:
|
elif project.file_format == FileFormat.JPEG:
|
||||||
err = processed_images[i].save_jpg(export_paths[i])
|
err = processed_images[i].image.save_jpg(export_paths[i])
|
||||||
if err != OK:
|
if err != OK:
|
||||||
Global.popup_error(
|
Global.popup_error(
|
||||||
tr("File failed to save. Error code %s (%s)") % [err, error_string(err)]
|
tr("File failed to save. Error code %s (%s)") % [err, error_string(err)]
|
||||||
|
@ -425,9 +431,9 @@ func export_video(export_paths: PackedStringArray) -> bool:
|
||||||
for i in range(processed_images.size()):
|
for i in range(processed_images.size()):
|
||||||
var temp_file_name := str(i + 1).pad_zeros(number_of_digits) + ".png"
|
var temp_file_name := str(i + 1).pad_zeros(number_of_digits) + ".png"
|
||||||
var temp_file_path := temp_path_real.path_join(temp_file_name)
|
var temp_file_path := temp_path_real.path_join(temp_file_name)
|
||||||
processed_images[i].save_png(temp_file_path)
|
processed_images[i].image.save_png(temp_file_path)
|
||||||
input_file.store_line("file '" + temp_file_name + "'")
|
input_file.store_line("file '" + temp_file_name + "'")
|
||||||
input_file.store_line("duration %s" % durations[i])
|
input_file.store_line("duration %s" % processed_images[i].duration)
|
||||||
input_file.close()
|
input_file.close()
|
||||||
var ffmpeg_execute: PackedStringArray = [
|
var ffmpeg_execute: PackedStringArray = [
|
||||||
"-y", "-f", "concat", "-i", input_file_path, export_paths[0]
|
"-y", "-f", "concat", "-i", input_file_path, export_paths[0]
|
||||||
|
@ -464,8 +470,8 @@ func export_animated(args: Dictionary) -> void:
|
||||||
var frames := []
|
var frames := []
|
||||||
for i in range(processed_images.size()):
|
for i in range(processed_images.size()):
|
||||||
var frame: AImgIOFrame = AImgIOFrame.new()
|
var frame: AImgIOFrame = AImgIOFrame.new()
|
||||||
frame.content = processed_images[i]
|
frame.content = processed_images[i].image
|
||||||
frame.duration = durations[i]
|
frame.duration = processed_images[i].duration
|
||||||
frames.push_back(frame)
|
frames.push_back(frame)
|
||||||
|
|
||||||
# Export and save GIF/APNG
|
# Export and save GIF/APNG
|
||||||
|
@ -489,13 +495,12 @@ func _increase_export_progress(export_dialog: Node) -> void:
|
||||||
|
|
||||||
|
|
||||||
func _scale_processed_images() -> void:
|
func _scale_processed_images() -> void:
|
||||||
|
var resize_f := resize / 100.0
|
||||||
for processed_image in processed_images:
|
for processed_image in processed_images:
|
||||||
if resize != 100:
|
if is_equal_approx(resize, 1.0):
|
||||||
processed_image.resize(
|
continue
|
||||||
processed_image.get_size().x * resize / 100,
|
var image := processed_image.image
|
||||||
processed_image.get_size().y * resize / 100,
|
image.resize(image.get_size().x * resize_f, image.get_size().y * resize_f, interpolation)
|
||||||
interpolation
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func file_format_string(format_enum: int) -> String:
|
func file_format_string(format_enum: int) -> String:
|
||||||
|
|
|
@ -2,7 +2,7 @@ extends ConfirmationDialog
|
||||||
|
|
||||||
## Called when user resumes export after filename collision
|
## Called when user resumes export after filename collision
|
||||||
signal resume_export_function
|
signal resume_export_function
|
||||||
signal about_to_preview(Dictionary)
|
signal about_to_preview(dict: Dictionary)
|
||||||
|
|
||||||
var preview_current_frame := 0
|
var preview_current_frame := 0
|
||||||
var preview_frames: Array[Texture2D] = []
|
var preview_frames: Array[Texture2D] = []
|
||||||
|
@ -24,8 +24,7 @@ var spritesheet_exports: Array[Export.FileFormat] = [
|
||||||
Export.FileFormat.PNG, Export.FileFormat.WEBP, Export.FileFormat.JPEG
|
Export.FileFormat.PNG, Export.FileFormat.WEBP, Export.FileFormat.JPEG
|
||||||
]
|
]
|
||||||
|
|
||||||
var _preview_images: Array[Image]
|
var _preview_images: Array[Export.ProcessedImage]
|
||||||
var _preview_durations: PackedFloat32Array
|
|
||||||
|
|
||||||
@onready var tabs: TabBar = $VBoxContainer/TabBar
|
@onready var tabs: TabBar = $VBoxContainer/TabBar
|
||||||
@onready var checker: ColorRect = $"%TransparentChecker"
|
@onready var checker: ColorRect = $"%TransparentChecker"
|
||||||
|
@ -97,19 +96,17 @@ func show_tab() -> void:
|
||||||
|
|
||||||
|
|
||||||
func set_preview() -> void:
|
func set_preview() -> void:
|
||||||
_preview_images = Export.processed_images.duplicate()
|
_preview_images = Export.processed_images
|
||||||
_preview_durations = Export.durations.duplicate()
|
|
||||||
var preview_data = {
|
var preview_data = {
|
||||||
"exporter_id": Global.current_project.file_format,
|
"exporter_id": Global.current_project.file_format,
|
||||||
"export_tab": Export.current_tab,
|
"export_tab": Export.current_tab,
|
||||||
"preview_images": _preview_images,
|
"preview_images": _preview_images,
|
||||||
"durations": _preview_durations
|
|
||||||
}
|
}
|
||||||
about_to_preview.emit(preview_data)
|
about_to_preview.emit(preview_data)
|
||||||
remove_previews()
|
remove_previews()
|
||||||
if _preview_images.size() == 1:
|
if _preview_images.size() == 1:
|
||||||
previews.columns = 1
|
previews.columns = 1
|
||||||
add_image_preview(_preview_images[0])
|
add_image_preview(_preview_images[0].image)
|
||||||
else:
|
else:
|
||||||
if Export.is_single_file_format():
|
if Export.is_single_file_format():
|
||||||
previews.columns = 1
|
previews.columns = 1
|
||||||
|
@ -117,7 +114,7 @@ func set_preview() -> void:
|
||||||
else:
|
else:
|
||||||
previews.columns = ceili(sqrt(_preview_images.size()))
|
previews.columns = ceili(sqrt(_preview_images.size()))
|
||||||
for i in range(_preview_images.size()):
|
for i in range(_preview_images.size()):
|
||||||
add_image_preview(_preview_images[i], i + 1)
|
add_image_preview(_preview_images[i].image, i + 1)
|
||||||
|
|
||||||
|
|
||||||
func add_image_preview(image: Image, canvas_number: int = -1) -> void:
|
func add_image_preview(image: Image, canvas_number: int = -1) -> void:
|
||||||
|
@ -140,7 +137,7 @@ func add_animated_preview() -> void:
|
||||||
preview_frames = []
|
preview_frames = []
|
||||||
|
|
||||||
for processed_image in _preview_images:
|
for processed_image in _preview_images:
|
||||||
var texture := ImageTexture.create_from_image(processed_image)
|
var texture := ImageTexture.create_from_image(processed_image.image)
|
||||||
preview_frames.push_back(texture)
|
preview_frames.push_back(texture)
|
||||||
|
|
||||||
var container := create_preview_container()
|
var container := create_preview_container()
|
||||||
|
@ -152,7 +149,7 @@ func add_animated_preview() -> void:
|
||||||
|
|
||||||
previews.add_child(container)
|
previews.add_child(container)
|
||||||
frame_timer.set_one_shot(true) # wait_time can't change correctly if the timer is playing
|
frame_timer.set_one_shot(true) # wait_time can't change correctly if the timer is playing
|
||||||
frame_timer.wait_time = _preview_durations[preview_current_frame]
|
frame_timer.wait_time = _preview_images[preview_current_frame].duration
|
||||||
frame_timer.start()
|
frame_timer.start()
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,7 +236,7 @@ func create_layer_list() -> void:
|
||||||
|
|
||||||
func update_dimensions_label() -> void:
|
func update_dimensions_label() -> void:
|
||||||
if _preview_images.size() > 0:
|
if _preview_images.size() > 0:
|
||||||
var new_size: Vector2 = _preview_images[0].get_size() * (Export.resize / 100.0)
|
var new_size: Vector2 = _preview_images[0].image.get_size() * (Export.resize / 100.0)
|
||||||
dimension_label.text = str(new_size.x, "×", new_size.y)
|
dimension_label.text = str(new_size.x, "×", new_size.y)
|
||||||
|
|
||||||
|
|
||||||
|
@ -413,7 +410,7 @@ func _on_FrameTimer_timeout() -> void:
|
||||||
else:
|
else:
|
||||||
preview_current_frame += 1
|
preview_current_frame += 1
|
||||||
|
|
||||||
frame_timer.wait_time = _preview_durations[preview_current_frame - 1]
|
frame_timer.wait_time = _preview_images[preview_current_frame - 1].duration
|
||||||
frame_timer.start()
|
frame_timer.start()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue