mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-18 17:19:50 +00:00
Saving .png files is now possible in HTML5
Addresses #280. Huge thanks to https://github.com/Pukkah/HTML5-File-Exchange-for-Godot
This commit is contained in:
parent
6b26bb5b10
commit
fb7c1a1874
|
@ -97,6 +97,7 @@ Global="*res://src/Autoload/Global.gd"
|
||||||
Import="*res://src/Autoload/Import.gd"
|
Import="*res://src/Autoload/Import.gd"
|
||||||
OpenSave="*res://src/Autoload/OpenSave.gd"
|
OpenSave="*res://src/Autoload/OpenSave.gd"
|
||||||
DrawingAlgos="*res://src/Autoload/DrawingAlgos.gd"
|
DrawingAlgos="*res://src/Autoload/DrawingAlgos.gd"
|
||||||
|
Html5FileExchange="*res://src/Autoload/HTML5FileExchange.gd"
|
||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
|
|
||||||
|
|
105
src/Autoload/HTML5FileExchange.gd
Normal file
105
src/Autoload/HTML5FileExchange.gd
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
extends Node
|
||||||
|
# Code taken and modified from https://github.com/Pukkah/HTML5-File-Exchange-for-Godot
|
||||||
|
# Thanks to Pukkah from GitHub for providing the original code
|
||||||
|
|
||||||
|
signal InFocus
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if OS.get_name() == "HTML5" and OS.has_feature('JavaScript'):
|
||||||
|
_define_js()
|
||||||
|
|
||||||
|
|
||||||
|
func _notification(notification:int) -> void:
|
||||||
|
if notification == MainLoop.NOTIFICATION_WM_FOCUS_IN:
|
||||||
|
emit_signal("InFocus")
|
||||||
|
|
||||||
|
func _define_js() -> void:
|
||||||
|
# Define JS script
|
||||||
|
JavaScript.eval("""
|
||||||
|
var fileData;
|
||||||
|
var fileType;
|
||||||
|
var fileName;
|
||||||
|
var canceled;
|
||||||
|
function upload_image() {
|
||||||
|
canceled = true;
|
||||||
|
var input = document.createElement('INPUT');
|
||||||
|
input.setAttribute("type", "file");
|
||||||
|
input.setAttribute("accept", "image/png, image/jpeg, image/webp");
|
||||||
|
input.click();
|
||||||
|
input.addEventListener('change', event => {
|
||||||
|
if (event.target.files.length > 0){
|
||||||
|
canceled = false;}
|
||||||
|
var file = event.target.files[0];
|
||||||
|
var reader = new FileReader();
|
||||||
|
fileType = file.type;
|
||||||
|
fileName = file.name;
|
||||||
|
reader.readAsArrayBuffer(file);
|
||||||
|
reader.onloadend = function (evt) {
|
||||||
|
if (evt.target.readyState == FileReader.DONE) {
|
||||||
|
fileData = evt.target.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function download(fileName, byte, type) {
|
||||||
|
var buffer = Uint8Array.from(byte);
|
||||||
|
var blob = new Blob([buffer], { type: type});
|
||||||
|
var link = document.createElement('a');
|
||||||
|
link.href = window.URL.createObjectURL(blob);
|
||||||
|
link.download = fileName;
|
||||||
|
link.click();
|
||||||
|
};
|
||||||
|
""", true)
|
||||||
|
|
||||||
|
|
||||||
|
func load_image() -> Image:
|
||||||
|
if OS.get_name() != "HTML5" or !OS.has_feature('JavaScript'):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Execute js function
|
||||||
|
JavaScript.eval("upload_image();", true) # opens prompt for choosing file
|
||||||
|
|
||||||
|
yield(self, "InFocus") # wait until js prompt is closed
|
||||||
|
|
||||||
|
yield(get_tree().create_timer(0.1), "timeout") #give some time for async js data load
|
||||||
|
|
||||||
|
if JavaScript.eval("canceled;", true): # if File Dialog closed w/o file
|
||||||
|
return
|
||||||
|
|
||||||
|
# use data from png data
|
||||||
|
var imageData
|
||||||
|
while true:
|
||||||
|
imageData = JavaScript.eval("fileData;", true)
|
||||||
|
if imageData != null:
|
||||||
|
break
|
||||||
|
yield(get_tree().create_timer(1.0), "timeout") # need more time to load data
|
||||||
|
|
||||||
|
var imageType = JavaScript.eval("fileType;", true)
|
||||||
|
var imageName = JavaScript.eval("fileName;", true)
|
||||||
|
|
||||||
|
var image = Image.new()
|
||||||
|
var image_error
|
||||||
|
match imageType:
|
||||||
|
"image/png":
|
||||||
|
image_error = image.load_png_from_buffer(imageData)
|
||||||
|
"image/jpeg":
|
||||||
|
image_error = image.load_jpg_from_buffer(imageData)
|
||||||
|
"image/webp":
|
||||||
|
image_error = image.load_webp_from_buffer(imageData)
|
||||||
|
var invalid_type:
|
||||||
|
print(invalid_type)
|
||||||
|
return
|
||||||
|
if image_error:
|
||||||
|
print("An error occurred while trying to display the image.")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
func save_image(image : Image, file_name : String = "export") -> void:
|
||||||
|
if OS.get_name() != "HTML5" or !OS.has_feature('JavaScript'):
|
||||||
|
return
|
||||||
|
|
||||||
|
var png_data = Array(image.get_data())
|
||||||
|
JavaScript.eval("download('%s', %s, 'image/png');" % [file_name, str(png_data)], true)
|
|
@ -77,6 +77,11 @@ func _ready() -> void:
|
||||||
$VBoxContainer/AnimationOptions/AnimationType.selected = AnimationType.MULTIPLE_FILES
|
$VBoxContainer/AnimationOptions/AnimationType.selected = AnimationType.MULTIPLE_FILES
|
||||||
$VBoxContainer/AnimationOptions/AnimationType.disabled = true
|
$VBoxContainer/AnimationOptions/AnimationType.disabled = true
|
||||||
|
|
||||||
|
# If we're on HTML5, don't let the user change the directory path
|
||||||
|
if OS.get_name() == "HTML5":
|
||||||
|
$VBoxContainer/Path.visible = false
|
||||||
|
directory_path = "user://"
|
||||||
|
|
||||||
|
|
||||||
func show_tab() -> void:
|
func show_tab() -> void:
|
||||||
$VBoxContainer/FrameOptions.hide()
|
$VBoxContainer/FrameOptions.hide()
|
||||||
|
@ -348,9 +353,12 @@ func export_processed_images(ignore_overwrites : bool) -> void:
|
||||||
$GifExporter.end_export()
|
$GifExporter.end_export()
|
||||||
else:
|
else:
|
||||||
for i in range(processed_images.size()):
|
for i in range(processed_images.size()):
|
||||||
var err = processed_images[i].save_png(export_paths[i])
|
if OS.get_name() == "HTML5":
|
||||||
if err != OK:
|
Html5FileExchange.save_image(processed_images[i], export_paths[i].get_file())
|
||||||
OS.alert("Can't save file")
|
else:
|
||||||
|
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
|
# Store settings for quick export and when the dialog is opened again
|
||||||
was_exported = true
|
was_exported = true
|
||||||
|
|
Loading…
Reference in a new issue