diff --git a/base/sources/backends/data/wasm/index.html b/base/sources/backends/data/wasm/index.html index ebc2bfe3..29d61bde 100644 --- a/base/sources/backends/data/wasm/index.html +++ b/base/sources/backends/data/wasm/index.html @@ -20,7 +20,7 @@ - + diff --git a/base/sources/backends/data/wasm/start.js b/base/sources/backends/data/wasm/start.js index 9347333e..eeac8c5b 100644 --- a/base/sources/backends/data/wasm/start.js +++ b/base/sources/backends/data/wasm/start.js @@ -1,15 +1,18 @@ -let memory = null; -let heapu8 = null; -let heapu16 = null; -let heapu32 = null; -let heapi32 = null; -let heapf32 = null; -let heapf64 = null; -let module = null; -let instance = null; -let wgpu_objects = [ null ]; -let wgpu_free_ids = []; +let memory = null; +let heapu8 = null; +let heapu16 = null; +let heapu32 = null; +let heapi32 = null; +let heapf32 = null; +let heapf64 = null; +let module = null; +let instance = null; +let wgpu_objects = [ null ]; +let wgpu_free_ids = []; +let file_buffer = null; +let file_buffer_pos = 0; +let config_json = ""; function ptr_to_id(ptr) { if (ptr === null) { @@ -139,23 +142,19 @@ async function init() { let adapter = await navigator.gpu.requestAdapter(); let device = await adapter.requestDevice(); - let canvas = document.getElementById('iron'); - canvas.width = window.innerWidth; + let canvas = document.getElementById('iron'); + canvas.width = window.innerWidth; canvas.height = window.innerHeight; window.addEventListener('resize', () => { - canvas.width = window.innerWidth; + canvas.width = window.innerWidth; canvas.height = window.innerHeight; - // ... }); let context = canvas.getContext('webgpu'); let format = navigator.gpu.getPreferredCanvasFormat(); context.configure({device, format}); - let file_buffer = null; - let file_buffer_pos = 0; - let result = await WebAssembly.instantiate(wasm_bytes, { env : {memory}, imports : { @@ -621,11 +620,18 @@ async function init() { console.log(read_string(format)); }, js_fopen : function(filename) { - let req = new XMLHttpRequest(); - req.open("GET", read_string(filename), false); - req.overrideMimeType("text/plain; charset=x-user-defined"); - req.send(); - let str = req.response; + let str; + if (read_string(filename) === "/./data/config.json" || + read_string(filename) === "/./data//config.json") { //// + str = config_json; + } + else { + let req = new XMLHttpRequest(); + req.open("GET", read_string(filename), false); + req.overrideMimeType("text/plain; charset=x-user-defined"); + req.send(); + str = req.response; + } file_buffer_pos = 0; file_buffer = new ArrayBuffer(str.length); let buf_view = new Uint8Array(file_buffer); @@ -650,6 +656,9 @@ async function init() { } return count; }, + js_fwrite : function(ptr, size, count, stream) { + config_json = read_string_n(ptr, count); //// + }, js_time : function() { return window.performance.now(); }, @@ -695,6 +704,30 @@ async function init() { }, js_canvas_h : function() { return canvas.height; + }, + js_mouse_set_cursor : function(i) { + if (i == 0) // arrow + canvas.style.cursor = 'default'; + else if (i == 1) // hand + canvas.style.cursor = 'pointer'; + else if (i == 2) // ibeam + canvas.style.cursor = 'text'; + else if (i == 3) // sizewe + canvas.style.cursor = 'ew-resize'; + else if (i == 4) // sizens + canvas.style.cursor = 'ns-resize'; + }, + js_mouse_show : function() { + canvas.style.cursor = 'default'; + }, + js_mouse_hide : function() { + canvas.style.cursor = 'none'; + }, + js_window_set_title : function(str) { + document.title = read_string(str); + }, + js_load_url : function(str) { + window.open(read_string(str), "_blank"); } } }); @@ -709,37 +742,168 @@ async function init() { } window.requestAnimationFrame(update); - canvas.addEventListener('contextmenu', (event) => { - event.preventDefault(); - }); - canvas.addEventListener('mousedown', (event) => { - instance.exports.wasm_mousedown(button_to_iron_button(event.button), event.clientX, event.clientY); - }); - canvas.addEventListener('mouseup', (event) => { - instance.exports.wasm_mouseup(button_to_iron_button(event.button), event.clientX, event.clientY); - }); - canvas.addEventListener('mousemove', (event) => { - instance.exports.wasm_mousemove(event.clientX, event.clientY); - }); - canvas.addEventListener('wheel', (event) => { - instance.exports.wasm_wheel(event.deltaY); - }); + canvas.addEventListener('contextmenu', (event) => { event.preventDefault(); }); + canvas.addEventListener('mousedown', (event) => { instance.exports.wasm_mousedown(button_to_iron_button(event.button), event.clientX, event.clientY); }); + canvas.addEventListener('mouseup', (event) => { instance.exports.wasm_mouseup(button_to_iron_button(event.button), event.clientX, event.clientY); }); + canvas.addEventListener('mousemove', (event) => { instance.exports.wasm_mousemove(event.clientX, event.clientY); }); + canvas.addEventListener('wheel', (event) => { instance.exports.wasm_wheel(event.deltaY); }); canvas.addEventListener('keydown', (event) => { if (event.repeat) { event.preventDefault(); return; } - instance.exports.wasm_keydown(event.keyCode); + instance.exports.wasm_keydown(key_to_iron_key(event.key)); + instance.exports.wasm_keypress(key_to_iron_key(event.key, true)); }); canvas.addEventListener('keyup', (event) => { if (event.repeat) { event.preventDefault(); return; } - instance.exports.wasm_keyup(event.keyCode); + instance.exports.wasm_keyup(key_to_iron_key(event.key)); }); } +function key_to_iron_key(key, is_press = false) { + if (key === ":") + return 58; + if (key === ";") + return 59; + if (key === "<") + return 60; + if (key === "=") + return 61; + if (key === ">") + return 62; + if (key === "?") + return 63; + if (key === "@") + return 64; + if (key === "^") + return 160; + if (key === "!") + return 161; + if (key === '"') + return 162; + if (key === "#") + return 163; + if (key === "$") + return 164; + if (key === "%") + return 165; + if (key === "&") + return 166; + if (key === "_") + return 167; + if (key === "(") + return 168; + if (key === ")") + return 169; + if (key === "*") + return 170; + if (key === "+") + return 171; + if (key === "|") + return 172; + if (key === "-") + return 173; + if (key === "{") + return 174; + if (key === "}") + return 175; + if (key === "~") + return 176; + if (key === ",") + return 188; + if (key === ".") + return 190; + if (key === "/") + return 191; + if (key === "`") + return 192; + if (key === "[") + return 219; + if (key === "\\") + return 220; + if (key === "]") + return 221; + if (key === "'") + return 222; + if (key === " ") + return 32; + if (key.length === 1 && is_press) + return key.charCodeAt(0); + if (key.length === 1) + return key.toUpperCase().charCodeAt(0); + if (key === "Backspace") + return 8; + if (key === "Tab") + return 9; + if (key === "Enter") + return 13; + if (key === "Shift") + return 16; + if (key === "Control") + return 17; + if (key === "Alt") + return 18; + if (key === "CapsLock") + return 20; + if (key === "Escape") + return 27; + if (key === "PageUp") + return 33; + if (key === "PageDown") + return 34; + if (key === "End") + return 35; + if (key === "Home") + return 36; + if (key === "ArrowLeft") + return 37; + if (key === "ArrowUp") + return 38; + if (key === "ArrowRight") + return 39; + if (key === "ArrowDown") + return 40; + if (key === "PrintScreen") + return 44; + if (key === "Insert") + return 45; + if (key === "Delete") + return 46; + if (key === "Meta") + return 224; + if (key === "AltGraph") + return 225; + if (key === "F1") + return 112; + if (key === "F2") + return 113; + if (key === "F3") + return 114; + if (key === "F4") + return 115; + if (key === "F5") + return 116; + if (key === "F6") + return 117; + if (key === "F7") + return 118; + if (key === "F8") + return 119; + if (key === "F9") + return 120; + if (key === "F10") + return 121; + if (key === "F11") + return 122; + if (key === "F12") + return 123; + return -1; +} + function button_to_iron_button(button) { if (button === 1) return 2; diff --git a/base/sources/backends/wasm_system.c b/base/sources/backends/wasm_system.c index e1b354aa..0b96240d 100644 --- a/base/sources/backends/wasm_system.c +++ b/base/sources/backends/wasm_system.c @@ -7,6 +7,17 @@ #include #include +__attribute__((import_module("imports"), import_name("js_time"))) int js_time(); +__attribute__((import_module("imports"), import_name("js_canvas_w"))) int js_canvas_w(); +__attribute__((import_module("imports"), import_name("js_canvas_h"))) int js_canvas_h(); +__attribute__((import_module("imports"), import_name("js_mouse_set_cursor"))) void js_mouse_set_cursor(int i); +__attribute__((import_module("imports"), import_name("js_mouse_show"))) void js_mouse_show(); +__attribute__((import_module("imports"), import_name("js_mouse_hide"))) void js_mouse_hide(); +__attribute__((import_module("imports"), import_name("js_window_set_title"))) void js_window_set_title(const char *title); +__attribute__((import_module("imports"), import_name("js_load_url"))) void js_load_url(const char *url); + +static bool mouse_hidden = false; + void iron_display_init(void) {} int iron_primary_display(void) { @@ -33,16 +44,25 @@ bool iron_mouse_can_lock(void) { return false; } -void iron_mouse_show() {} -void iron_mouse_hide() {} -void iron_mouse_set_cursor(iron_cursor_t cursor_index) {} +void iron_mouse_show() { + js_mouse_show(); +} +void iron_mouse_hide() { + js_mouse_hide(); +} + +void iron_mouse_set_cursor(iron_cursor_t cursor_index) { + if (mouse_hidden) { + return; + } + js_mouse_set_cursor(cursor_index); +} + void iron_mouse_set_position(int x, int y) {} void iron_mouse_get_position(int *x, int *y) {} void iron_keyboard_show() {} void iron_keyboard_hide() {} -__attribute__((import_module("imports"), import_name("js_time"))) int js_time(); - void iron_init(iron_window_options_t *win) { gpu_init(win->depth_bits, true); } @@ -66,7 +86,7 @@ double iron_time(void) { } int iron_hardware_threads(void) { - return 4; + return 1; } void iron_internal_shutdown(void) {} @@ -105,6 +125,10 @@ __attribute__((export_name("wasm_keyup"))) void wasm_keyup(int key) { iron_internal_keyboard_trigger_key_up(key); } +__attribute__((export_name("wasm_keypress"))) void wasm_keypress(int key) { + iron_internal_keyboard_trigger_key_press(key); +} + iron_window_mode_t iron_internal_window_mode = IRON_WINDOW_MODE_WINDOW; int iron_window_x() { @@ -115,9 +139,6 @@ int iron_window_y() { return 0; } -__attribute__((import_module("imports"), import_name("js_canvas_w"))) int js_canvas_w(); -__attribute__((import_module("imports"), import_name("js_canvas_h"))) int js_canvas_h(); - int iron_window_width() { return js_canvas_w(); } @@ -148,7 +169,11 @@ void iron_window_change_mode(iron_window_mode_t mode) { void iron_window_destroy() {} void iron_window_show() {} void iron_window_hide() {} -void iron_window_set_title(const char *title) {} + +void iron_window_set_title(const char *title) { + js_window_set_title(title); +} + void iron_window_create(iron_window_options_t *win) {} void iron_window_set_resize_callback(void (*callback)(int x, int y, void *data), void *data) {} void iron_window_set_close_callback(bool (*callback)(void *), void *data) {} @@ -172,8 +197,15 @@ const char *iron_language() { return "en"; } -void iron_load_url(const char *url) {} +void iron_load_url(const char *url) { + js_load_url(url); +} const char *iron_system_id() { return "wasm"; } + +// void iron_internal_drop_files_callback(char *); +// char *iron_internal_cut_callback(void); +// char *iron_internal_copy_callback(void); +// void iron_internal_paste_callback(char *); diff --git a/base/sources/libs/kong/dir.c b/base/sources/libs/kong/dir.c index 8833718a..7a17f089 100644 --- a/base/sources/libs/kong/dir.c +++ b/base/sources/libs/kong/dir.c @@ -49,6 +49,7 @@ void close_dir(directory *dir) { directory open_dir(const char *dirname) { directory dir; + dir.handle = NULL; return dir; } diff --git a/base/sources/libs/miniclib/stdio.c b/base/sources/libs/miniclib/stdio.c index 81492f7b..2138dbac 100644 --- a/base/sources/libs/miniclib/stdio.c +++ b/base/sources/libs/miniclib/stdio.c @@ -8,6 +8,7 @@ __attribute__((import_module("imports"), import_name("js_fopen"))) FILE *js_f __attribute__((import_module("imports"), import_name("js_ftell"))) long int js_ftell(FILE *stream); __attribute__((import_module("imports"), import_name("js_fseek"))) int js_fseek(FILE *stream, long int offset, int origin); __attribute__((import_module("imports"), import_name("js_fread"))) size_t js_fread(void *ptr, size_t size, size_t count, FILE *stream); +__attribute__((import_module("imports"), import_name("js_fwrite"))) size_t js_fwrite(void *ptr, size_t size, size_t count, FILE *stream); #endif FILE *stdout = NULL, *stderr = NULL; @@ -57,6 +58,9 @@ int vsnprintf(char *s, size_t n, const char *format, va_list arg) { } size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream) { +#ifdef IRON_WASM + js_fwrite(ptr, size, count, stream); +#endif return 0; } diff --git a/base/sources/ts/file.ts b/base/sources/ts/file.ts index a9286daf..d21522f6 100644 --- a/base/sources/ts/file.ts +++ b/base/sources/ts/file.ts @@ -21,7 +21,7 @@ let file_cloud_sizes: map_t = null; let _file_init_cloud_bytes_done: () => void; -/// if arm_android +/// if (arm_android || arm_wasm) let file_internal: map_t = null; // .apk contents /// end @@ -37,7 +37,13 @@ function file_read_directory(path: string): string[] { } } - /// if arm_android + /// if arm_wasm + if (starts_with(path, "/./")) { + path = substring(path, 2, path.length); + } + /// end + + /// if (arm_android || arm_wasm) path = string_replace_all(path, "//", "/"); if (file_internal == null) { let s: string = sys_buffer_to_string(data_get_blob("data_list.json")); @@ -49,6 +55,10 @@ function file_read_directory(path: string): string[] { /// end let files: string[] = string_split(iron_read_directory(path), "\n"); + if (files.length == 1 && files[0] == ""){ + array_pop(files); + return files; + } array_sort(files, null); // Folders first diff --git a/paint/project.js b/paint/project.js index c330d938..6945d733 100644 --- a/paint/project.js +++ b/paint/project.js @@ -25,6 +25,7 @@ if (platform == "wasm") { flags.with_plugins = false; flags.with_raytrace = false; flags.idle_sleep = false; + flags.export_data_list = true; } let project = new Project(flags.name);