Add file picking function for web build

This commit is contained in:
Luke Hubmayer-Werner 2023-12-05 20:23:55 +10:30
parent 7b7b0a1876
commit 060ccd22e3
3 changed files with 65 additions and 0 deletions

27
data/html5_file_picker.js Normal file
View File

@ -0,0 +1,27 @@
var _FilePicker = {};
var _FilePickerData = {};
_FilePicker.upload = function(gd_callback) {
// canceled = true;
var input = document.createElement('INPUT');
input.setAttribute("type", "file");
input.setAttribute("accept", ".sfc,.srm,.gba,.bin,.iso");
input.setAttribute("multiple", "");
input.click();
input.addEventListener('change', event => {
for (const file of event.target.files) {
var reader = new FileReader();
// this.filename = file.name;
// this.file_type = file.type;
reader.readAsArrayBuffer(file);
reader.onloadend = (evt) => {
if (evt.target.readyState == FileReader.DONE) {
// Godot's JavaScriptObject API is very very poorly documented.
// It might be possible to unwrap JavaScriptObject<ArrayBuffer> to PoolByteArray
// without a bytewise for loop, but I can't work it out by trial and error.
_FilePickerData[file.name] = evt.target.result;
gd_callback(file.name, file.type);
}
}
}
});
}

View File

@ -31,6 +31,7 @@ RomLoader="*res://scripts/loaders/RomLoader.gd"
SaveLoader="*res://scripts/loaders/SaveLoader.gd"
ThemeManager="*res://scripts/managers/ThemeManager.gd"
StringLoader="*res://scripts/loaders/StringLoader.gd"
HTML5="*res://scripts/managers/HTML5.gd"
[debug]
@ -63,6 +64,7 @@ texture={
[rendering]
quality/driver/driver_name="GLES2"
2d/snapping/use_gpu_pixel_snap=true
environment/default_clear_color=Color( 0, 0, 0, 1 )
environment/default_environment="res://default_env.tres"

36
scripts/managers/HTML5.gd Normal file
View File

@ -0,0 +1,36 @@
extends Node
signal uploaded_file(filename, file_type, data)
var js_callback: JavaScriptObject
var js_interface: JavaScriptObject
func _ready() -> void:
if OS.get_name() != 'HTML5' or !OS.has_feature('JavaScript'):
return
var file := File.new()
match file.open('res://data/html5_file_picker.js', File.READ):
OK:
JavaScript.eval(file.get_as_text(), true)
var error:
print_stack()
return
js_callback = JavaScript.create_callback(self, '_upload_handler')
js_interface = JavaScript.get_interface('_FilePicker')
func _upload_handler(_args):
var filename = _args[0]
var file_type = _args[1]
# Workaround for JavaScriptObject being seemingly impossible to unwrap (no docs)
var data_key: String = '_FilePickerData["%s"]' % filename
var data = JavaScript.eval(data_key, true)
JavaScript.eval('delete '+data_key, true)
print(_args)
emit_signal('uploaded_file', filename, file_type, data)
func upload_file() -> void:
if OS.get_name() != 'HTML5' or !OS.has_feature('JavaScript'):
return
js_interface.upload(js_callback)