diff options
Diffstat (limited to 'platform/web/js')
-rw-r--r-- | platform/web/js/libs/library_godot_input.js | 135 | ||||
-rw-r--r-- | platform/web/js/libs/library_godot_webgl2.externs.js | 16 | ||||
-rw-r--r-- | platform/web/js/libs/library_godot_webgl2.js | 17 |
3 files changed, 167 insertions, 1 deletions
diff --git a/platform/web/js/libs/library_godot_input.js b/platform/web/js/libs/library_godot_input.js index eaff40f89c..1292c468f5 100644 --- a/platform/web/js/libs/library_godot_input.js +++ b/platform/web/js/libs/library_godot_input.js @@ -29,6 +29,110 @@ /**************************************************************************/ /* + * IME API helper. + */ + +const GodotIME = { + $GodotIME__deps: ['$GodotRuntime', '$GodotEventListeners'], + $GodotIME__postset: 'GodotOS.atexit(function(resolve, reject) { GodotIME.clear(); resolve(); });', + $GodotIME: { + ime: null, + active: false, + + getModifiers: function (evt) { + return (evt.shiftKey + 0) + ((evt.altKey + 0) << 1) + ((evt.ctrlKey + 0) << 2) + ((evt.metaKey + 0) << 3); + }, + + ime_active: function (active) { + function focus_timer() { + GodotIME.active = true; + GodotIME.ime.focus(); + } + + if (GodotIME.ime) { + if (active) { + GodotIME.ime.style.display = 'block'; + setInterval(focus_timer, 100); + } else { + GodotIME.ime.style.display = 'none'; + GodotConfig.canvas.focus(); + GodotIME.active = false; + } + } + }, + + ime_position: function (x, y) { + if (GodotIME.ime) { + GodotIME.ime.style.left = `${x}px`; + GodotIME.ime.style.top = `${y}px`; + } + }, + + init: function (ime_cb, key_cb, code, key) { + function key_event_cb(pressed, evt) { + const modifiers = GodotIME.getModifiers(evt); + GodotRuntime.stringToHeap(evt.code, code, 32); + GodotRuntime.stringToHeap(evt.key, key, 32); + key_cb(pressed, evt.repeat, modifiers); + evt.preventDefault(); + } + function ime_event_cb(event) { + if (GodotIME.ime) { + if (event.type === 'compositionstart') { + ime_cb(0, null); + GodotIME.ime.innerHTML = ''; + } else if (event.type === 'compositionupdate') { + const ptr = GodotRuntime.allocString(event.data); + ime_cb(1, ptr); + GodotRuntime.free(ptr); + } else if (event.type === 'compositionend') { + const ptr = GodotRuntime.allocString(event.data); + ime_cb(2, ptr); + GodotRuntime.free(ptr); + GodotIME.ime.innerHTML = ''; + } + } + } + + const ime = document.createElement('div'); + ime.className = 'ime'; + ime.style.background = 'none'; + ime.style.opacity = 0.0; + ime.style.position = 'fixed'; + ime.style.left = '0px'; + ime.style.top = '0px'; + ime.style.width = '2px'; + ime.style.height = '2px'; + ime.style.display = 'none'; + ime.contentEditable = 'true'; + + GodotEventListeners.add(ime, 'compositionstart', ime_event_cb, false); + GodotEventListeners.add(ime, 'compositionupdate', ime_event_cb, false); + GodotEventListeners.add(ime, 'compositionend', ime_event_cb, false); + GodotEventListeners.add(ime, 'keydown', key_event_cb.bind(null, 1), false); + GodotEventListeners.add(ime, 'keyup', key_event_cb.bind(null, 0), false); + + ime.onblur = function () { + this.style.display = 'none'; + GodotConfig.canvas.focus(); + GodotIME.active = false; + }; + + GodotConfig.canvas.parentElement.appendChild(ime); + GodotIME.ime = ime; + }, + + clear: function () { + if (GodotIME.ime) { + GodotIME.ime.remove(); + GodotIME.ime = null; + } + }, + }, +}; +mergeInto(LibraryManager.library, GodotIME); + +/* * Gamepad API helper. */ const GodotInputGamepads = { @@ -338,7 +442,7 @@ mergeInto(LibraryManager.library, GodotInputDragDrop); * Godot exposed input functions. */ const GodotInput = { - $GodotInput__deps: ['$GodotRuntime', '$GodotConfig', '$GodotEventListeners', '$GodotInputGamepads', '$GodotInputDragDrop'], + $GodotInput__deps: ['$GodotRuntime', '$GodotConfig', '$GodotEventListeners', '$GodotInputGamepads', '$GodotInputDragDrop', '$GodotIME'], $GodotInput: { getModifiers: function (evt) { return (evt.shiftKey + 0) + ((evt.altKey + 0) << 1) + ((evt.ctrlKey + 0) << 2) + ((evt.metaKey + 0) << 3); @@ -462,6 +566,35 @@ const GodotInput = { }, /* + * IME API + */ + godot_js_set_ime_active__proxy: 'sync', + godot_js_set_ime_active__sig: 'vi', + godot_js_set_ime_active: function (p_active) { + GodotIME.ime_active(p_active); + }, + + godot_js_set_ime_position__proxy: 'sync', + godot_js_set_ime_position__sig: 'vii', + godot_js_set_ime_position: function (p_x, p_y) { + GodotIME.ime_position(p_x, p_y); + }, + + godot_js_set_ime_cb__proxy: 'sync', + godot_js_set_ime_cb__sig: 'viiii', + godot_js_set_ime_cb: function (p_ime_cb, p_key_cb, code, key) { + const ime_cb = GodotRuntime.get_func(p_ime_cb); + const key_cb = GodotRuntime.get_func(p_key_cb); + GodotIME.init(ime_cb, key_cb, code, key); + }, + + godot_js_is_ime_focused__proxy: 'sync', + godot_js_is_ime_focused__sig: 'i', + godot_js_is_ime_focused: function () { + return GodotIME.active; + }, + + /* * Gamepad API */ godot_js_input_gamepad_cb__proxy: 'sync', diff --git a/platform/web/js/libs/library_godot_webgl2.externs.js b/platform/web/js/libs/library_godot_webgl2.externs.js index 18d8d0815a..99190ab009 100644 --- a/platform/web/js/libs/library_godot_webgl2.externs.js +++ b/platform/web/js/libs/library_godot_webgl2.externs.js @@ -34,3 +34,19 @@ OVR_multiview2.prototype.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR; * @return {void} */ OVR_multiview2.prototype.framebufferTextureMultiviewOVR = function(target, attachment, texture, level, baseViewIndex, numViews) {}; + +/** + * @constructor OCULUS_multiview + */ +function OCULUS_multiview() {} + +/** + * @param {number} target + * @param {number} attachment + * @param {WebGLTexture} texture + * @param {number} level + * @param {number} baseViewIndex + * @param {number} numViews + * @return {void} + */ +OCULUS_multiview.prototype.framebufferTextureMultisampleMultiviewOVR = function(target, attachment, texture, level, samples, baseViewIndex, numViews) {}; diff --git a/platform/web/js/libs/library_godot_webgl2.js b/platform/web/js/libs/library_godot_webgl2.js index dbaec9f01b..005b4b7917 100644 --- a/platform/web/js/libs/library_godot_webgl2.js +++ b/platform/web/js/libs/library_godot_webgl2.js @@ -61,6 +61,23 @@ const GodotWebGL2 = { const /** OVR_multiview2 */ ext = context.multiviewExt; ext.framebufferTextureMultiviewOVR(target, attachment, GL.textures[texture], level, base_view_index, num_views); }, + + godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR__deps: ['emscripten_webgl_get_current_context'], + godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR__proxy: 'sync', + godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR__sig: 'viiiiiii', + godot_webgl2_glFramebufferTextureMultisampleMultiviewOVR: function (target, attachment, texture, level, samples, base_view_index, num_views) { + const context = GL.currentContext; + if (typeof context.oculusMultiviewExt === 'undefined') { + const /** OCULUS_multiview */ ext = context.GLctx.getExtension('OCULUS_multiview'); + if (!ext) { + GodotRuntime.error('Trying to call glFramebufferTextureMultisampleMultiviewOVR() without the OCULUS_multiview extension'); + return; + } + context.oculusMultiviewExt = ext; + } + const /** OCULUS_multiview */ ext = context.oculusMultiviewExt; + ext.framebufferTextureMultisampleMultiviewOVR(target, attachment, GL.textures[texture], level, samples, base_view_index, num_views); + }, }; autoAddDeps(GodotWebGL2, '$GodotWebGL2'); |