From 7f6b034adb65b4a75d7051a4380f1257dcfc86c7 Mon Sep 17 00:00:00 2001 From: laame <63640344+Pukkah@users.noreply.github.com> Date: Wed, 3 Jun 2020 20:03:57 +0300 Subject: [PATCH] Add files via upload --- addons/HTML5FileExchange/HTML5FileExchange.gd | 128 ++++++++++++++++++ addons/HTML5FileExchange/plugin.cfg | 15 ++ addons/HTML5FileExchange/plugin.gd | 10 ++ 3 files changed, 153 insertions(+) create mode 100644 addons/HTML5FileExchange/HTML5FileExchange.gd create mode 100644 addons/HTML5FileExchange/plugin.cfg create mode 100644 addons/HTML5FileExchange/plugin.gd diff --git a/addons/HTML5FileExchange/HTML5FileExchange.gd b/addons/HTML5FileExchange/HTML5FileExchange.gd new file mode 100644 index 0000000..3d7ba80 --- /dev/null +++ b/addons/HTML5FileExchange/HTML5FileExchange.gd @@ -0,0 +1,128 @@ +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; + } + } + }); + } + 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()->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" diff --git a/addons/HTML5FileExchange/plugin.cfg b/addons/HTML5FileExchange/plugin.cfg new file mode 100644 index 0000000..1354542 --- /dev/null +++ b/addons/HTML5FileExchange/plugin.cfg @@ -0,0 +1,15 @@ +[plugin] + +name="HTML5 File Exchange" +description="Open/Import and Save/Export files in HTML5 environment. +Supported input - *.png, *.jpeg, *.webp +Supported output - *.png + +Usage: +Get file from User - +var image:Image = yield(HTML5File.get_image(), \"completed\") +Send file to User - +HTML5File.save_image(image:Image, fileName:String = \"export\")" +author="laame" +version="0.1.1" +script="plugin.gd" diff --git a/addons/HTML5FileExchange/plugin.gd b/addons/HTML5FileExchange/plugin.gd new file mode 100644 index 0000000..2d9467f --- /dev/null +++ b/addons/HTML5FileExchange/plugin.gd @@ -0,0 +1,10 @@ +tool +extends EditorPlugin + + +func _enter_tree(): + add_autoload_singleton("HTML5File", "res://addons/HTML5FileExchange/HTML5FileExchange.gd") + + +func _exit_tree(): + remove_autoload_singleton("HTML5File")