HTML5-File-Exchange-for-Godot/addons/HTML5FileExchange/HTML5FileExchange.gd
2020-08-28 20:58:29 +03:00

204 lines
5.7 KiB
GDScript

extends Node
signal InFocus
func _ready():
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() {
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;
}
}
});
}
var fileDataArray = [];
var fileTypeArray = [];
var fileNameArray = [];
var numberOfFiles = 0;
function multiupload() {
canceled = true;
var input = document.createElement('INPUT');
input.setAttribute("type", "file");
input.setAttribute("accept", "image/png, image/jpeg, image/webp");
input.setAttribute("multiple","true")
input.click();
input.addEventListener('change', event => {
if (event.target.files.length > 0){
canceled = false;}
numberOfFiles = event.target.files.length
for(var i = 0; i < event.target.files.length; i++){
var file = event.target.files[i];
var reader = new FileReader();
fileTypeArray.push(file.type);
fileNameArray.push(file.name);
reader.readAsArrayBuffer(file);
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) {
fileDataArray.push(evt.target.result);
}
}
}
});
}
function download(fileName, byte) {
var buffer = Uint8Array.from(byte);
var blob = new Blob([buffer], { type: 'image/png'});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
};
""", true)
func load_image_array()->Array:
if OS.get_name() != "HTML5" or !OS.has_feature('JavaScript'):
return
JavaScript.eval("multiupload();", true)
yield(self, "InFocus")
yield(get_tree().create_timer(0.1), "timeout")
if JavaScript.eval("canceled;", true):
return
var imageDataArray = []
var imageTypeArray = []
var imageNameArray = []
for i in range(JavaScript.eval("numberOfFiles;", true)):
while true:
imageDataArray.push_back(JavaScript.eval("fileDataArray["+String(i)+"];", true))
if imageDataArray.size() == i+1:
imageTypeArray.push_back(JavaScript.eval("fileTypeArray["+String(i)+"];", true))
imageNameArray.push_back(JavaScript.eval("fileNameArray["+String(i)+"];", true))
break
yield(get_tree().create_timer(1.0), "timeout")
var imageArray = []
for i in range(imageDataArray.size()):
var image = Image.new()
var image_error
match imageTypeArray[i]:
"image/png":
image_error = image.load_png_from_buffer(imageDataArray[i])
"image/jpeg":
image_error = image.load_jpg_from_buffer(imageDataArray[i])
"image/webp":
image_error = image.load_webp_from_buffer(imageDataArray[i])
var invalidType:
return
if image_error:
return
else:
imageArray.push_back(image)
return imageArray
func load_image()->Image:
if OS.get_name() != "HTML5" or !OS.has_feature('JavaScript'):
return
#Execute js function
JavaScript.eval("upload();", true) #opens promt for choosing file
#label.text = "Wait for focus"
yield(self, "InFocus") #wait until js promt is closed
#label.text = "Timer on for loading"
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
#label.text = "Canceled prompt"
return
# use data from png data
#label.text = "Load image"
var imageData
while true:
imageData = JavaScript.eval("fileData;", true)
if imageData != null:
break
#label.text = "No image yet"
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 invalidType:
#label.text = "Unsupported file format - %s." % invalidType
return
if image_error:
#label.text = "An error occurred while trying to display the image."
return
else:
return image
# Display texture
var tex = ImageTexture.new()
tex.create_from_image(image, 0) # Flag = 0 or else export is fucked!
Sprite.texture = tex
#loadedImage = image # Keep Image for later, just in case...
#loadedImageName = imageName
#label.text = "Image %s loaded as %s." % [imageName, imageType]
return
#label.text = "Something went wrong"
func save_image(image:Image, fileName:String = "export")->void:
if OS.get_name() != "HTML5" or !OS.has_feature('JavaScript'):
return
image.clear_mipmaps()
if image.save_png("user://export_temp.png"):
#label.text = "Error saving temp file"
return
var file:File = File.new()
if file.open("user://export_temp.png", File.READ):
#label.text = "Error opening file"
return
var pngData = Array(file.get_buffer(file.get_len())) #read data as PoolByteArray and convert it to Array for JS
file.close()
var dir = Directory.new()
dir.remove("user://export_temp.png")
JavaScript.eval("download('%s', %s);" % [fileName, str(pngData)], true)
#label.text = "Saving DONE"