Compare commits

..

7 Commits
init ... master

Author SHA1 Message Date
e7a6925d91 updated 2023-12-03 10:20:42 +08:00
7df2bcb1c5 started modification to godot4 2023-09-10 11:45:25 +08:00
2332eeba0a started modification to godot4 2023-09-10 11:45:00 +08:00
93631b95e5 adapted script for Godot 4.1 2023-09-10 10:19:26 +08:00
Miks Ramāns
aab6be4dea
Delete .github directory 2022-05-09 00:15:00 +03:00
yiyuezhuo
891e6b01d1 Check sample.tscn as a upload & download example. 2022-05-09 00:13:05 +03:00
yiyuezhuo
4af1125541 Refactor using better Godot and JavaScript API and add an example 2022-05-09 00:13:05 +03:00
11 changed files with 180 additions and 87 deletions

2
.gitignore vendored
View File

@ -3,7 +3,7 @@
.import/
export.cfg
export_presets.cfg
.godot/
# Mono-specific ignores
.mono/
data_*/

View File

@ -1 +1,11 @@
# HTML5 File Exchange for Godot 3.2
# HTML5 File Exchange for Godot 3.4
## Usage
Check sample.tscn as a upload & download example.
### Without sample
* Copy addons to your project.
* Enable the plugin. (A `HTML5File` singleton should be added into autoload list).
* If the HTML5 debugging option is not enabled, add a HTML5 export item.

20
Sample.gd Normal file
View File

@ -0,0 +1,20 @@
extends TextureRect
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func _on_UploadButton_pressed():
HTML5File.load_image()
var image = await HTML5File.load_completed
var tex = ImageTexture.new()
tex.create_from_image(image) #,0
texture = tex;
func _on_DownloadButton_pressed():
var image : Image
image = get_viewport().get_texture().get_image()
HTML5File.save_image(image, "image.png")

View File

@ -1,24 +1,21 @@
extends Node
signal InFocus
signal read_completed
signal load_completed(image)
var js_callback = JavaScriptBridge.create_callback(load_handler);
var js_interface;
func _ready():
if OS.get_name() == "HTML5" and OS.has_feature('JavaScript'):
if OS.get_name() == "Web":
_define_js()
func _notification(notification:int) -> void:
if notification == MainLoop.NOTIFICATION_WM_FOCUS_IN:
emit_signal("InFocus")
js_interface = JavaScriptBridge.get_interface("_HTML5FileExchange");
func _define_js()->void:
#Define JS script
JavaScript.eval("""
var fileData;
var fileType;
var fileName;
var canceled;
function upload() {
JavaScriptBridge.eval("""
var _HTML5FileExchange = {};
_HTML5FileExchange.upload = function(gd_callback) {
canceled = true;
var input = document.createElement('INPUT');
input.setAttribute("type", "file");
@ -29,56 +26,32 @@ func _define_js()->void:
canceled = false;}
var file = event.target.files[0];
var reader = new FileReader();
fileType = file.type;
fileName = file.name;
this.fileType = file.type;
// var fileName = file.name;
reader.readAsArrayBuffer(file);
reader.onloadend = function (evt) {
reader.onloadend = (evt) => { // Since here's it's arrow function, "this" still refers to _HTML5FileExchange
if (evt.target.readyState == FileReader.DONE) {
fileData = evt.target.result;
this.result = evt.target.result;
gd_callback(); // It's hard to retrieve value from callback argument, so it's just for notification
}
}
});
}
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_handler(_args):
emit_signal("read_completed")
func load_image()->Image:
if OS.get_name() != "HTML5" or !OS.has_feature('JavaScript'):
func load_image():
if OS.get_name() != "Web" or !OS.has_feature('JavaScript'):
return
#Execute js function
JavaScript.eval("upload();", true) #opens promt for choosing file
js_interface.upload(js_callback);
await self.read_completed
#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 imageType = js_interface.fileType;
var imageData = JavaScriptBridge.eval("_HTML5FileExchange.result", true) # interface doesn't work as expected for some reason
var image = Image.new()
var image_error
@ -90,39 +63,18 @@ func load_image()->Image:
"image/webp":
image_error = image.load_webp_from_buffer(imageData)
var invalidType:
#label.text = "Unsupported file format - %s." % invalidType
print("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"
print("An error occurred while trying to display the image.")
emit_signal("load_completed", image)
func save_image(image:Image, fileName:String = "export")->void:
if OS.get_name() != "HTML5" or !OS.has_feature('JavaScript'):
func save_image(image:Image, fileName:String = "export.png")->void:
if OS.get_name() != "Web" 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"
var buffer = image.save_png_to_buffer()
JavaScriptBridge.download_buffer(buffer, fileName)

View File

@ -1,4 +1,4 @@
tool
@tool
extends EditorPlugin

7
default_env.tres Normal file
View File

@ -0,0 +1,7 @@
[gd_resource type="Environment" load_steps=2 format=3 uid="uid://baopyhxl0883"]
[sub_resource type="Sky" id="1"]
[resource]
background_mode = 2
sky = SubResource("1")

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

34
icon.png.import Normal file
View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dchvsb8f80an3"
path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.png"
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

4
makefile Normal file
View File

@ -0,0 +1,4 @@
git:
git add -A
git commit -m "$m"
git push

32
project.godot Normal file
View File

@ -0,0 +1,32 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="HTML5-File-Exchange-for-Godot"
run/main_scene="res://sample.tscn"
config/features=PackedStringArray("4.2")
config/icon="res://icon.png"
[autoload]
HTML5File="*res://addons/HTML5FileExchange/HTML5FileExchange.gd"
[editor_plugins]
enabled=PackedStringArray("res://addons/HTML5FileExchange/plugin.cfg")
[physics]
common/enable_pause_aware_picking=true
[rendering]
environment/defaults/default_environment="res://default_env.tres"

34
sample.tscn Normal file
View File

@ -0,0 +1,34 @@
[gd_scene load_steps=2 format=3 uid="uid://dk0u6daqunn2k"]
[ext_resource type="Script" path="res://Sample.gd" id="1"]
[node name="Control" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
layout_mode = 2
[node name="UploadButton" type="Button" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "Upload"
[node name="DownloadButton" type="Button" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "Download"
[node name="TextureRect" type="TextureRect" parent="VBoxContainer"]
layout_mode = 2
script = ExtResource("1")
[connection signal="pressed" from="VBoxContainer/HBoxContainer/UploadButton" to="VBoxContainer/TextureRect" method="_on_UploadButton_pressed"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/DownloadButton" to="VBoxContainer/TextureRect" method="_on_DownloadButton_pressed"]