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")