1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-31 07:29:49 +00:00

Replace ExportSprites with a new ExportDialog.

This commit is contained in:
novhack 2020-03-23 23:09:37 +01:00
parent b733682c3a
commit 169efa29d5
6 changed files with 733 additions and 272 deletions

View file

@ -29,7 +29,6 @@
[ext_resource path="res://Prefabs/Dialogs/SplashDialog.tscn" type="PackedScene" id=27]
[ext_resource path="res://Prefabs/Dialogs/CreateNewImage.tscn" type="PackedScene" id=28]
[ext_resource path="res://Prefabs/Dialogs/ImportSprites.tscn" type="PackedScene" id=29]
[ext_resource path="res://Prefabs/Dialogs/ExportSprites.tscn" type="PackedScene" id=30]
[ext_resource path="res://Prefabs/Dialogs/ScaleImage.tscn" type="PackedScene" id=31]
[ext_resource path="res://Prefabs/Dialogs/PreferencesDialog.tscn" type="PackedScene" id=32]
[ext_resource path="res://Prefabs/Dialogs/OutlineDialog.tscn" type="PackedScene" id=33]
@ -38,6 +37,7 @@
[ext_resource path="res://Prefabs/NewPaletteDialog.tscn" type="PackedScene" id=36]
[ext_resource path="res://Prefabs/PaletteImportFileDialog.tscn" type="PackedScene" id=37]
[ext_resource path="res://Prefabs/Dialogs/RotateImage.tscn" type="PackedScene" id=38]
[ext_resource path="res://Prefabs/Dialogs/ExportDialog.tscn" type="PackedScene" id=39]
[sub_resource type="InputEventKey" id=1]
scancode = 88
@ -1259,7 +1259,7 @@ current_path = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρι
[node name="ImportSprites" parent="." instance=ExtResource( 29 )]
[node name="ExportSprites" parent="." instance=ExtResource( 30 )]
[node name="ExportDialog" parent="." instance=ExtResource( 39 )]
[node name="ScaleImage" parent="." instance=ExtResource( 31 )]
@ -1360,7 +1360,7 @@ visible = false
[connection signal="file_selected" from="SaveSprite" to="." method="_on_SaveSprite_file_selected"]
[connection signal="popup_hide" from="SaveSprite" to="." method="_can_draw_true"]
[connection signal="popup_hide" from="ImportSprites" to="." method="_can_draw_true"]
[connection signal="popup_hide" from="ExportSprites" to="." method="_can_draw_true"]
[connection signal="popup_hide" from="ExportDialog" to="." method="_can_draw_true"]
[connection signal="popup_hide" from="ScaleImage" to="." method="_can_draw_true"]
[connection signal="popup_hide" from="PreferencesDialog" to="." method="_can_draw_true"]
[connection signal="popup_hide" from="OutlineDialog" to="." method="_can_draw_true"]

View file

@ -0,0 +1,309 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Scripts/Dialogs/ExportDialog.gd" type="Script" id=1]
[node name="ExportDialog" type="AcceptDialog"]
margin_right = 456.0
margin_bottom = 530.0
rect_min_size = Vector2( 456, 530 )
window_title = "Export..."
resizable = true
dialog_hide_on_ok = false
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="VBoxContainer" type="VBoxContainer" parent="."]
margin_left = 8.0
margin_top = 8.0
margin_right = 448.0
margin_bottom = 494.0
rect_min_size = Vector2( 330, 0 )
size_flags_vertical = 3
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Tabs" type="Tabs" parent="VBoxContainer"]
margin_right = 440.0
margin_bottom = 24.0
size_flags_vertical = 0
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
margin_top = 28.0
margin_right = 440.0
margin_bottom = 32.0
[node name="PreviewLabel" type="Label" parent="VBoxContainer"]
margin_top = 36.0
margin_right = 440.0
margin_bottom = 50.0
text = "Preview:"
[node name="PreviewScroll" type="ScrollContainer" parent="VBoxContainer"]
margin_top = 54.0
margin_right = 440.0
margin_bottom = 358.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="Previews" type="GridContainer" parent="VBoxContainer/PreviewScroll"]
margin_right = 440.0
margin_bottom = 304.0
size_flags_horizontal = 3
size_flags_vertical = 3
columns = 3
[node name="FrameOptions" type="VBoxContainer" parent="VBoxContainer"]
visible = false
margin_top = 334.0
margin_right = 440.0
margin_bottom = 358.0
[node name="FrameNumber" type="HBoxContainer" parent="VBoxContainer/FrameOptions"]
margin_right = 440.0
margin_bottom = 24.0
[node name="FrameNumberLabel" type="Label" parent="VBoxContainer/FrameOptions/FrameNumber"]
margin_top = 5.0
margin_right = 44.0
margin_bottom = 19.0
text = "Frame:"
[node name="FrameNumber" type="SpinBox" parent="VBoxContainer/FrameOptions/FrameNumber"]
margin_left = 48.0
margin_right = 440.0
margin_bottom = 24.0
rect_min_size = Vector2( 100, 0 )
size_flags_horizontal = 3
min_value = 1.0
page = 1.0
value = 1.0
rounded = true
align = 2
[node name="SpritesheetOptions" type="VBoxContainer" parent="VBoxContainer"]
margin_top = 362.0
margin_right = 440.0
margin_bottom = 386.0
[node name="Orientation" type="HBoxContainer" parent="VBoxContainer/SpritesheetOptions"]
margin_right = 440.0
margin_bottom = 24.0
alignment = 1
[node name="OrientationLabel" type="Label" parent="VBoxContainer/SpritesheetOptions/Orientation"]
margin_top = 5.0
margin_right = 77.0
margin_bottom = 19.0
text = "Orientation:"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Orientation" type="OptionButton" parent="VBoxContainer/SpritesheetOptions/Orientation"]
margin_left = 81.0
margin_right = 226.0
margin_bottom = 24.0
size_flags_horizontal = 3
text = "Rows"
items = [ "Rows", null, false, 0, null, "Columns", null, false, 1, null ]
selected = 0
[node name="LinesCountLabel" type="Label" parent="VBoxContainer/SpritesheetOptions/Orientation"]
margin_left = 230.0
margin_top = 5.0
margin_right = 290.0
margin_bottom = 19.0
text = "Columns:"
[node name="LinesCount" type="SpinBox" parent="VBoxContainer/SpritesheetOptions/Orientation"]
margin_left = 294.0
margin_right = 440.0
margin_bottom = 24.0
size_flags_horizontal = 3
min_value = 1.0
max_value = 1000.0
value = 1.0
align = 2
[node name="AnimationOptions" type="VBoxContainer" parent="VBoxContainer"]
visible = false
margin_top = 366.0
margin_right = 440.0
margin_bottom = 386.0
[node name="AnimationType" type="OptionButton" parent="VBoxContainer/AnimationOptions"]
margin_right = 440.0
margin_bottom = 20.0
size_flags_horizontal = 3
disabled = true
text = "All frames as multiple files"
items = [ "All frames as multiple files", null, false, 0, null ]
selected = 0
[node name="HSeparator2" type="HSeparator" parent="VBoxContainer"]
margin_top = 390.0
margin_right = 440.0
margin_bottom = 394.0
[node name="Options" type="HBoxContainer" parent="VBoxContainer"]
margin_top = 398.0
margin_right = 440.0
margin_bottom = 422.0
[node name="ResizeLabel" type="Label" parent="VBoxContainer/Options"]
margin_top = 5.0
margin_right = 46.0
margin_bottom = 19.0
rect_min_size = Vector2( 30, 0 )
text = "Resize:"
align = 2
[node name="Resize" type="SpinBox" parent="VBoxContainer/Options"]
margin_left = 50.0
margin_right = 197.0
margin_bottom = 24.0
size_flags_horizontal = 3
min_value = 10.0
max_value = 1000.0
step = 100.0
value = 100.0
align = 2
suffix = "%"
[node name="InterpolationLabel" type="Label" parent="VBoxContainer/Options"]
margin_left = 201.0
margin_top = 5.0
margin_right = 288.0
margin_bottom = 19.0
rect_min_size = Vector2( 30, 0 )
text = "Interpolation:"
align = 2
[node name="Interpolation" type="OptionButton" parent="VBoxContainer/Options"]
margin_left = 292.0
margin_right = 440.0
margin_bottom = 24.0
size_flags_horizontal = 3
text = "Nearest"
align = 2
items = [ "Nearest", null, false, 0, null, "Bilinear", null, false, 1, null, "Cubic", null, false, 2, null, "Trilinear", null, false, 3, null, "Lanczos", null, false, 4, null ]
selected = 0
[node name="HSeparator3" type="HSeparator" parent="VBoxContainer"]
margin_top = 426.0
margin_right = 440.0
margin_bottom = 430.0
[node name="Path" type="HBoxContainer" parent="VBoxContainer"]
margin_top = 434.0
margin_right = 440.0
margin_bottom = 458.0
[node name="Label" type="Label" parent="VBoxContainer/Path"]
margin_top = 5.0
margin_right = 32.0
margin_bottom = 19.0
rect_min_size = Vector2( 30, 0 )
text = "Path:"
[node name="PathLineEdit" type="LineEdit" parent="VBoxContainer/Path"]
margin_left = 36.0
margin_right = 377.0
margin_bottom = 24.0
size_flags_horizontal = 3
align = 2
[node name="PathButton" type="Button" parent="VBoxContainer/Path"]
margin_left = 381.0
margin_right = 440.0
margin_bottom = 24.0
text = "Browse"
[node name="File" type="HBoxContainer" parent="VBoxContainer"]
margin_top = 462.0
margin_right = 440.0
margin_bottom = 486.0
[node name="Label" type="Label" parent="VBoxContainer/File"]
margin_top = 5.0
margin_right = 30.0
margin_bottom = 19.0
rect_min_size = Vector2( 30, 0 )
text = "File:"
[node name="FileLineEdit" type="LineEdit" parent="VBoxContainer/File"]
margin_left = 34.0
margin_right = 296.0
margin_bottom = 24.0
size_flags_horizontal = 3
align = 2
[node name="FileFormat" type="OptionButton" parent="VBoxContainer/File"]
margin_left = 300.0
margin_right = 440.0
margin_bottom = 24.0
rect_min_size = Vector2( 130, 0 )
disabled = true
text = ".png ; PNG Image"
items = [ ".png ; PNG Image", null, false, 0, null, ".gif ; GIF Image", null, true, 1, null ]
selected = 0
[node name="Popups" type="Node" parent="."]
[node name="PathDialog" type="FileDialog" parent="Popups"]
margin_left = 8.0
margin_top = 8.0
margin_right = 448.0
margin_bottom = 494.0
rect_min_size = Vector2( 440, 300 )
size_flags_horizontal = 0
size_flags_vertical = 0
window_title = "Open a Directory"
resizable = true
mode = 2
access = 2
current_dir = "/home/novhack/Pixelorama"
current_path = "/home/novhack/Pixelorama/"
[node name="PathValidationAlert" type="AcceptDialog" parent="Popups"]
margin_left = 8.0
margin_top = 180.0
margin_right = 448.0
margin_bottom = 280.0
size_flags_horizontal = 0
size_flags_vertical = 0
dialog_text = "Directory path or file name is not valid!"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="FileExistsAlert" type="AcceptDialog" parent="Popups"]
margin_left = 8.0
margin_top = 180.0
margin_right = 448.0
margin_bottom = 280.0
size_flags_horizontal = 0
size_flags_vertical = 0
dialog_text = "File %s already exists. Overwrite?"
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="about_to_show" from="." to="." method="_on_ExportDialog_about_to_show"]
[connection signal="confirmed" from="." to="." method="_on_ExportDialog_confirmed"]
[connection signal="custom_action" from="." to="." method="_on_ExportDialog_custom_action"]
[connection signal="tab_clicked" from="VBoxContainer/Tabs" to="." method="_on_Tabs_tab_clicked"]
[connection signal="value_changed" from="VBoxContainer/FrameOptions/FrameNumber/FrameNumber" to="." method="_on_Frame_value_changed"]
[connection signal="item_selected" from="VBoxContainer/SpritesheetOptions/Orientation/Orientation" to="." method="_on_Orientation_item_selected"]
[connection signal="value_changed" from="VBoxContainer/SpritesheetOptions/Orientation/LinesCount" to="." method="_on_LinesCount_value_changed"]
[connection signal="value_changed" from="VBoxContainer/Options/Resize" to="." method="_on_Resize_value_changed"]
[connection signal="item_selected" from="VBoxContainer/Options/Interpolation" to="." method="_on_Interpolation_item_selected"]
[connection signal="text_changed" from="VBoxContainer/Path/PathLineEdit" to="." method="_on_PathLineEdit_text_changed"]
[connection signal="pressed" from="VBoxContainer/Path/PathButton" to="." method="_on_PathButton_pressed"]
[connection signal="text_changed" from="VBoxContainer/File/FileLineEdit" to="." method="_on_FileLineEdit_text_changed"]
[connection signal="item_selected" from="VBoxContainer/File/FileFormat" to="." method="_on_FileFormat_item_selected"]
[connection signal="dir_selected" from="Popups/PathDialog" to="." method="_on_FileDialog_dir_selected"]
[connection signal="confirmed" from="Popups/FileExistsAlert" to="." method="_on_FileExistsAlert_confirmed"]
[connection signal="custom_action" from="Popups/FileExistsAlert" to="." method="_on_FileExistsAlert_custom_action"]

View file

@ -1,95 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Scripts/Dialogs/ExportSprites.gd" type="Script" id=1]
[node name="ExportSprites" type="FileDialog"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -512.0
margin_top = -300.0
margin_right = 3.0
margin_bottom = 48.0
window_title = "Export Sprite as .png"
resizable = true
access = 2
filters = PoolStringArray( "*.png ; PNG Image" )
current_dir = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama"
current_path = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama/"
script = ExtResource( 1 )
[node name="ExportOption" type="OptionButton" parent="."]
margin_left = 8.0
margin_top = 8.0
margin_right = 507.0
margin_bottom = 312.0
text = "EXPORT_CURRENT_FRAME_LABEL"
items = [ "EXPORT_CURRENT_FRAME_LABEL", null, false, 0, null, "EXPORT_FRAMES_AS_MULTIPLE_FILES_LABEL", null, false, 1, null, "EXPORT_FRAMES_AS_SPRITESHEET_LABEL", null, false, 2, null ]
selected = 0
[node name="Resize" type="HBoxContainer" parent="."]
margin_left = 8.0
margin_top = 8.0
margin_right = 507.0
margin_bottom = 312.0
[node name="Label" type="Label" parent="Resize"]
margin_top = 145.0
margin_right = 46.0
margin_bottom = 159.0
text = "Resize:"
[node name="ResizeValue" type="SpinBox" parent="Resize"]
margin_left = 50.0
margin_right = 124.0
margin_bottom = 304.0
mouse_default_cursor_shape = 2
min_value = 10.0
max_value = 1000.0
step = 10.0
value = 100.0
suffix = "%"
[node name="Label2" type="Label" parent="Resize"]
margin_left = 128.0
margin_top = 145.0
margin_right = 215.0
margin_bottom = 159.0
text = "Interpolation:"
[node name="Interpolation" type="OptionButton" parent="Resize"]
margin_left = 219.0
margin_right = 298.0
margin_bottom = 304.0
text = "Nearest"
items = [ "Nearest", null, false, 0, null, "Bilinear", null, false, 1, null, "Cubic", null, false, 2, null, "Trilinear", null, false, 3, null, "Lanczos", null, false, 4, null ]
selected = 0
[node name="Spritesheet" type="HBoxContainer" parent="."]
visible = false
margin_left = 8.0
margin_top = 8.0
margin_right = 507.0
margin_bottom = 312.0
[node name="ColumnsOrRows" type="OptionButton" parent="Spritesheet"]
margin_right = 97.0
margin_bottom = 304.0
text = "Columns"
items = [ "Columns", null, false, 0, null, "Rows", null, false, 1, null ]
selected = 0
[node name="Frames" type="SpinBox" parent="Spritesheet"]
margin_left = 101.0
margin_right = 175.0
margin_bottom = 304.0
mouse_default_cursor_shape = 2
min_value = 1.0
value = 1.0
[connection signal="file_selected" from="." to="." method="_on_ExportSprites_file_selected"]
[connection signal="item_selected" from="ExportOption" to="." method="_on_ExportOption_item_selected"]
[connection signal="value_changed" from="Resize/ResizeValue" to="." method="_on_ResizeValue_value_changed"]
[connection signal="item_selected" from="Resize/Interpolation" to="." method="_on_Interpolation_item_selected"]
[connection signal="item_selected" from="Spritesheet/ColumnsOrRows" to="." method="_on_ColumnsOrRows_item_selected"]
[connection signal="value_changed" from="Spritesheet/Frames" to="." method="_on_Frames_value_changed"]

View file

@ -0,0 +1,406 @@
extends AcceptDialog
enum ExportTab { Frame = 0, Spritesheet = 1, Animation = 2 }
var current_tab : int = ExportTab.Frame
# All canvases and their layers processed/blended into images
var processed_images = [] # Image[]
# Frame options
var frame_number := 0
# Spritesheet options
enum Orientation { Rows = 0, Columns = 1 }
var orientation : int = Orientation.Rows
# How many rows/columns before new line is added
var lines_count := 1
# Animation options
enum AnimationType { MultipleFiles = 0 }
var animation_type : int = AnimationType.MultipleFiles
# Options
var resize := 100
var interpolation := 0 # Image.Interpolation
# Export directory path and export file name
var directory_path := ""
var file_name := ""
var file_format := ".png"
var file_exists_alert = "File %s already exists. Overwrite?"
# Store all settings after export, enables a quick re-export with same settings
var was_exported : bool = false
var exported_tab : int
var exported_frame_number : int
var exported_orientation : int
var exported_lines_count : int
var exported_animation_type : int
var exported_resize : int
var exported_interpolation : int
var exported_directory_path : String
var exported_file_name : String
var exported_file_format : String
# Export coroutine signal
signal resume_export_function()
var stop_export = false
func _ready():
$VBoxContainer/Tabs.add_tab("Frame")
$VBoxContainer/Tabs.add_tab("Spritesheet")
$VBoxContainer/Tabs.add_tab("Animation")
add_button("Cancel", false, "cancel")
$Popups/FileExistsAlert.add_button("Cancel Export", false, "cancel")
func show_tab():
$VBoxContainer/FrameOptions.hide()
$VBoxContainer/SpritesheetOptions.hide()
$VBoxContainer/AnimationOptions.hide()
match current_tab:
ExportTab.Frame:
if not was_exported:
frame_number = Global.current_frame + 1
$VBoxContainer/FrameOptions/FrameNumber/FrameNumber.max_value = Global.canvases.size() + 1
$VBoxContainer/FrameOptions/FrameNumber/FrameNumber.value = frame_number
process_frame()
$VBoxContainer/FrameOptions.show()
ExportTab.Spritesheet:
if not was_exported:
orientation = Orientation.Rows
lines_count = int(ceil(sqrt(Global.canvases.size())))
$VBoxContainer/SpritesheetOptions/Orientation/Orientation.selected = orientation
$VBoxContainer/SpritesheetOptions/Orientation/LinesCount.max_value = Global.canvases.size()
$VBoxContainer/SpritesheetOptions/Orientation/LinesCount.value = lines_count
$VBoxContainer/SpritesheetOptions/Orientation/LinesCountLabel.text = "Columns:"
process_spritesheet()
$VBoxContainer/SpritesheetOptions.show()
ExportTab.Animation:
process_animation()
$VBoxContainer/AnimationOptions.show()
set_preview()
$VBoxContainer/Tabs.current_tab = current_tab
func external_export() -> void:
restore_previous_export_settings()
match current_tab:
ExportTab.Frame:
process_frame()
ExportTab.Spritesheet:
process_spritesheet()
ExportTab.Animation:
process_animation()
export_processed_images(true)
func process_frame() -> void:
var canvas = Global.canvases[frame_number - 1]
var image := Image.new()
image.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
blend_layers(image, canvas)
processed_images.clear()
processed_images.append(image)
func process_spritesheet() -> void:
# If rows mode selected calculate columns count and vice versa
var spritesheet_columns = lines_count if orientation == Orientation.Rows else frames_divided_by_spritesheet_lines()
var spritesheet_rows = lines_count if orientation == Orientation.Columns else frames_divided_by_spritesheet_lines()
var width = Global.canvas.size.x * spritesheet_columns
var height = Global.canvas.size.y * spritesheet_rows
var whole_image := Image.new()
whole_image.create(width, height, false, Image.FORMAT_RGBA8)
whole_image.lock()
var origin := Vector2.ZERO
var hh := 0
var vv := 0
for canvas in Global.canvases:
if orientation == Orientation.Rows:
if vv < spritesheet_columns:
origin.x = canvas.size.x * vv
vv += 1
else:
hh += 1
origin.x = 0
vv = 1
origin.y = canvas.size.y * hh
else:
if hh < spritesheet_rows:
origin.y = canvas.size.y * hh
hh += 1
else:
vv += 1
origin.y = 0
hh = 1
origin.x = canvas.size.x * vv
blend_layers(whole_image, canvas, origin)
processed_images.clear()
processed_images.append(whole_image)
func process_animation() -> void:
processed_images.clear()
for canvas in Global.canvases:
var image := Image.new()
image.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
blend_layers(image, canvas)
processed_images.append(image)
func set_preview() -> void:
remove_previews()
if processed_images.size() == 1 and current_tab != ExportTab.Animation:
$VBoxContainer/PreviewScroll/Previews.columns = 1
add_preview(processed_images[0])
else:
$VBoxContainer/PreviewScroll/Previews.columns = ceil(sqrt(processed_images.size()))
for i in range(processed_images.size()):
add_preview(processed_images[i], i + 1)
func add_preview(image: Image, canvas_number: int = -1):
var container = VBoxContainer.new()
container.size_flags_horizontal = SIZE_EXPAND_FILL
container.size_flags_vertical = SIZE_EXPAND_FILL
container.rect_min_size = Vector2(0, 128)
var preview = TextureRect.new()
preview.expand = true
preview.size_flags_horizontal = SIZE_EXPAND_FILL
preview.size_flags_vertical = SIZE_EXPAND_FILL
preview.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
preview.texture = ImageTexture.new()
preview.texture.create_from_image(image, 0)
container.add_child(preview)
if canvas_number != -1:
var label = Label.new()
label.align = Label.ALIGN_CENTER
label.text = String(canvas_number)
container.add_child(label)
$VBoxContainer/PreviewScroll/Previews.add_child(container)
func remove_previews():
for child in $VBoxContainer/PreviewScroll/Previews.get_children():
child.queue_free()
func export_processed_images(ignore_overwrites: bool) -> void:
# Stop export if directory path or file name are not valid
var dir = Directory.new()
if not dir.dir_exists(directory_path) or not file_name.is_valid_filename():
$Popups/PathValidationAlert.popup_centered()
return
# Check export paths
var export_paths = []
for i in range(processed_images.size()):
stop_export = false
var export_path = create_export_path(true if current_tab == ExportTab.Animation else false, i + 1)
# Check if the file already exists
var fileCheck = File.new()
if fileCheck.file_exists(export_path):
# Ask user if he want's to overwrite the file
if not was_exported or (was_exported and not ignore_overwrites):
# Overwrite existing file?
$Popups/FileExistsAlert.dialog_text = file_exists_alert % export_path
$Popups/FileExistsAlert.popup_centered()
# Stops the function until the user decides if he want's to overwrite
yield(self, "resume_export_function")
if stop_export:
# User decided to stop export
return
export_paths.append(export_path)
# Scale images that are to export
scale_processed_images()
for i in range(processed_images.size()):
var err = processed_images[i].save_png(export_paths[i])
if err != OK:
OS.alert("Can't save file")
# Store settings for quick export and when the dialog is opened again
was_exported = true
store_export_settings()
Global.file_menu.get_popup().set_item_text(5, tr("Export") + " %s" % (file_name + file_format))
Global.notification_label("File(s) exported")
hide()
# Blends canvas layers into passed image starting from the origin position
func blend_layers(image: Image, canvas: Canvas, origin: Vector2 = Vector2(0, 0)):
image.lock()
var layer_i := 0
for layer in canvas.layers:
if Global.layers[layer_i][1]:
var layer_image : Image = layer[0]
layer_image.lock()
if layer[2] < 1: # If we have layer transparency
for xx in layer_image.get_size().x:
for yy in layer_image.get_size().y:
var pixel_color := layer_image.get_pixel(xx, yy)
var alpha : float = pixel_color.a * layer[4]
layer_image.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
canvas.blend_rect(image, layer_image, Rect2(canvas.position, canvas.size), origin)
layer_i += 1
image.unlock()
func scale_processed_images():
for processed_image in processed_images:
if resize != 100:
processed_image.unlock()
processed_image.resize(processed_image.get_size().x * resize / 100, processed_image.get_size().y * resize / 100, interpolation)
func create_export_path(multifile: bool, frame: int = 0) -> String:
var path = file_name
# Only append frame number when there are multiple files exported
if multifile:
path += "_" + String(frame)
return directory_path.plus_file(path + file_format)
func frames_divided_by_spritesheet_lines() -> int:
return int(ceil(Global.canvases.size() / float(lines_count)))
func store_export_settings():
exported_tab = current_tab
exported_frame_number = frame_number
exported_orientation = orientation
exported_lines_count = lines_count
exported_animation_type = animation_type
exported_resize = resize
exported_interpolation = interpolation
exported_directory_path = directory_path
exported_file_name = file_name
exported_file_format = file_format
# Fill the dialog with previous export settings
func restore_previous_export_settings():
current_tab = exported_tab
frame_number = exported_frame_number if exported_frame_number <= Global.canvases.size() else Global.canvases.size()
orientation = exported_orientation
lines_count = exported_lines_count
animation_type = exported_animation_type
resize = exported_resize
interpolation = exported_interpolation
directory_path = exported_directory_path
file_name = exported_file_name
file_format = exported_file_format
func _on_ExportDialog_about_to_show():
# If export already occured - fill the dialog with previous export settings
if was_exported:
restore_previous_export_settings()
if directory_path.empty():
directory_path = OS.get_system_dir(OS.SYSTEM_DIR_DESKTOP)
# If export already occured - sets gui to show previous settings
$VBoxContainer/Options/Resize.value = resize
$VBoxContainer/Options/Interpolation.selected = interpolation
$VBoxContainer/Path/PathLineEdit.text = directory_path
$VBoxContainer/File/FileLineEdit.text = file_name
$VBoxContainer/File/FileFormat.text = file_format
show_tab()
func _on_Tabs_tab_clicked(tab):
current_tab = tab
show_tab()
func _on_Frame_value_changed(value: float):
frame_number = value
process_frame()
set_preview()
func _on_Orientation_item_selected(id):
orientation = id
if orientation == Orientation.Rows:
$VBoxContainer/SpritesheetOptions/Orientation/LinesCountLabel.text = "Columns:"
else:
$VBoxContainer/SpritesheetOptions/Orientation/LinesCountLabel.text = "Rows:"
$VBoxContainer/SpritesheetOptions/Orientation/LinesCount.value = frames_divided_by_spritesheet_lines()
process_spritesheet()
set_preview()
func _on_LinesCount_value_changed(value):
lines_count = value
process_spritesheet()
set_preview()
func _on_Resize_value_changed(value: float) -> void:
resize = value
func _on_Interpolation_item_selected(id: int) -> void:
interpolation = id
func _on_ExportDialog_confirmed():
export_processed_images(false)
func _on_ExportDialog_custom_action(action):
if action == "cancel":
hide()
func _on_PathButton_pressed():
$Popups/PathDialog.popup_centered()
func _on_PathLineEdit_text_changed(new_text):
directory_path = new_text
func _on_FileLineEdit_text_changed(new_text):
file_name = new_text
func _on_FileDialog_dir_selected(dir: String):
$VBoxContainer/Path/PathLineEdit.text = dir
directory_path = dir
func _on_FileFormat_item_selected(id):
match id:
0: # PNG
file_format = '.png';
1: # GIF
file_format = '.gif';
func _on_FileExistsAlert_confirmed():
# Overwrite existing file
$Popups/FileExistsAlert.dialog_text = file_exists_alert
stop_export = false
emit_signal("resume_export_function")
func _on_FileExistsAlert_custom_action(action):
if action == "cancel":
# Cancel export
$Popups/FileExistsAlert.dialog_text = file_exists_alert
stop_export = true
emit_signal("resume_export_function")
$Popups/FileExistsAlert.hide()

View file

@ -1,159 +0,0 @@
extends FileDialog
var current_export_path := ""
var export_option := 0
var resize := 100
var interpolation = Image.INTERPOLATE_NEAREST
var frames_spinbox : SpinBox
var per_rows := false
var spritesheet_rows = 1
var spritesheet_columns = 1
func _ready() -> void:
frames_spinbox = Global.find_node_by_name(self, "Frames")
var children := []
for i in range(get_child_count()):
if i > 7:
children.append(get_child(i))
for child in children:
remove_child(child)
get_vbox().add_child(child)
func _on_ExportOption_item_selected(ID : int) -> void:
export_option = ID
var spritesheet_container = Global.find_node_by_name(self, "Spritesheet")
if ID > 1:
spritesheet_container.visible = true
else:
spritesheet_container.visible = false
func _on_ResizeValue_value_changed(value) -> void:
resize = value
func _on_Interpolation_item_selected(ID : int) -> void:
interpolation = ID
func _on_ColumnsOrRows_item_selected(ID) -> void:
per_rows = bool(ID)
# Update spritesheet_rows/columns variable
_on_Frames_value_changed(frames_spinbox.value)
func _on_Frames_value_changed(value):
value = min(value, Global.canvases.size())
if per_rows:
spritesheet_rows = value
frames_spinbox.value = spritesheet_rows
else:
spritesheet_columns = value
frames_spinbox.value = spritesheet_columns
func _on_ExportSprites_file_selected(path : String) -> void:
current_export_path = path
Global.file_menu.get_popup().set_item_text(5, tr("Export") + " %s" % path.get_file())
export_project()
func export_project() -> void:
if export_option == 0: # Export current frame
save_sprite(Global.canvas, current_export_path)
elif export_option == 1: # Export all frames as multiple files
var i := 1
for canvas in Global.canvases:
var path := "%s_%s" % [current_export_path, str(i)]
path = path.replace(".png", "")
path = "%s.png" % path
save_sprite(canvas, path)
i += 1
elif export_option == 2: # Export all frames as a spritesheet (single file)
save_spritesheet()
Global.notification_label("File exported")
func save_sprite(canvas : Canvas, path : String) -> void:
var whole_image := Image.new()
whole_image.create(canvas.size.x, canvas.size.y, false, Image.FORMAT_RGBA8)
whole_image.lock()
var layer_i := 0
for layer in canvas.layers:
if Global.layers[layer_i][1]: # If layer is visible
var img : Image = layer[0]
img.lock()
if layer[2] < 1: # If we have layer transparency
for xx in img.get_size().x:
for yy in img.get_size().y:
var pixel_color := img.get_pixel(xx, yy)
var alpha : float = pixel_color.a * layer[4]
img.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
canvas.blend_rect(whole_image, img, Rect2(canvas.position, canvas.size), Vector2.ZERO)
layer[0].lock()
layer_i += 1
if resize != 100:
whole_image.unlock()
whole_image.resize(whole_image.get_size().x * resize / 100, whole_image.get_size().y * resize / 100, interpolation)
var err = whole_image.save_png(path)
if err != OK:
OS.alert("Can't save file")
func save_spritesheet() -> void:
if per_rows:
spritesheet_columns = ceil(Global.canvases.size() / spritesheet_rows)
else:
spritesheet_rows = ceil(Global.canvases.size() / spritesheet_columns)
var width = Global.canvas.size.x * spritesheet_rows
var height = Global.canvas.size.y * spritesheet_columns
var whole_image := Image.new()
whole_image.create(width, height, false, Image.FORMAT_RGBA8)
whole_image.lock()
var dst := Vector2.ZERO
var hh := 0
var vv := 0
for canvas in Global.canvases:
if per_rows:
if vv < spritesheet_columns:
dst.y = canvas.size.y * vv
vv += 1
else:
hh += 1
dst.y = 0
vv = 1
dst.x = canvas.size.x * hh
else:
if hh < spritesheet_rows:
dst.x = canvas.size.x * hh
hh += 1
else:
vv += 1
dst.x = 0
hh = 1
dst.y = canvas.size.y * vv
var layer_i := 0
for layer in canvas.layers:
if Global.layers[layer_i][1]: # If layer is visible
var img : Image = layer[0]
img.lock()
if layer[2] < 1: # If we have layer transparency
for xx in img.get_size().x:
for yy in img.get_size().y:
var pixel_color := img.get_pixel(xx, yy)
var alpha : float = pixel_color.a * layer[4]
img.set_pixel(xx, yy, Color(pixel_color.r, pixel_color.g, pixel_color.b, alpha))
canvas.blend_rect(whole_image, img, Rect2(canvas.position, canvas.size), dst)
layer[0].lock()
layer_i += 1
if resize != 100:
whole_image.unlock()
whole_image.resize(width * resize / 100, height * resize / 100, interpolation)
var err = whole_image.save_png(current_export_path)
if err != OK:
OS.alert("Can't save file")

View file

@ -45,9 +45,9 @@ func _ready() -> void:
"Open..." : KEY_MASK_CMD + KEY_O,
"Save..." : KEY_MASK_CMD + KEY_S,
"Save as..." : KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S,
"Import PNG..." : KEY_MASK_CMD + KEY_I,
"Export PNG..." : KEY_MASK_CMD + KEY_E,
"Export PNG as..." : KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_E,
"Import..." : KEY_MASK_CMD + KEY_I,
"Export..." : KEY_MASK_CMD + KEY_E,
"Export as..." : KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_E,
"Quit" : KEY_MASK_CMD + KEY_Q
}
var edit_menu_items := {
@ -238,13 +238,13 @@ func file_menu_id_pressed(id : int) -> void:
Global.can_draw = false
opensprite_file_selected = false
5: # Export
if $ExportSprites.current_export_path == "":
$ExportSprites.popup_centered()
if $ExportDialog.was_exported == false:
$ExportDialog.popup_centered()
Global.can_draw = false
else:
$ExportSprites.export_project()
$ExportDialog.external_export()
6: # Export as
$ExportSprites.popup_centered()
$ExportDialog.popup_centered()
Global.can_draw = false
7: # Quit
show_quit_dialog()
@ -510,20 +510,21 @@ func _on_OpenSprite_file_selected(path : String) -> void:
current_save_path = path
$SaveSprite.current_path = path
$ExportSprites.current_export_path = path.trim_suffix(".pxo") + ".png"
$ExportSprites.current_path = $ExportSprites.current_export_path
$ExportDialog.file_name = path.get_file().trim_suffix(".pxo")
$ExportDialog.directory_path = path.get_base_dir()
$ExportDialog.was_exported = false
file_menu.set_item_text(2, tr("Save") + " %s" % path.get_file())
file_menu.set_item_text(5, tr("Export") + " %s" % $ExportSprites.current_path.get_file())
file_menu.set_item_text(5, tr("Export"))
Global.window_title = path.get_file() + " - Pixelorama"
func _on_SaveSprite_file_selected(path : String) -> void:
current_save_path = path
$ExportSprites.current_export_path = path.trim_suffix(".pxo") + ".png"
$ExportSprites.current_path = $ExportSprites.current_export_path
$ExportDialog.file_name = path.get_file().trim_suffix(".pxo")
$ExportDialog.directory_path = path.get_base_dir()
$ExportDialog.was_exported = false
file_menu.set_item_text(2, tr("Save") + " %s" % path.get_file())
file_menu.set_item_text(5, tr("Export") + " %s" % $ExportSprites.current_path.get_file())
var file := File.new()
var err := file.open(path, File.WRITE)
if err == OK:
@ -593,9 +594,8 @@ func clear_canvases() -> void:
child.queue_free()
Global.canvases.clear()
current_save_path = ""
$ExportSprites.current_export_path = ""
file_menu.set_item_text(2, "Save")
file_menu.set_item_text(5, "Export PNG...")
file_menu.set_item_text(5, "Export...")
Global.window_title = "(" + tr("untitled") + ") - Pixelorama"
Global.undo_redo.clear_history(false)