Merge pull request #42178 from Faless/js/sync_fs_size_handlers
[HTML5] Synchronous main, better persistence, handlers fixes, optional full screen.
This commit is contained in:
commit
c10e8ac1de
11 changed files with 739 additions and 678 deletions
File diff suppressed because it is too large
Load diff
27
misc/dist/html/full-size.html
vendored
27
misc/dist/html/full-size.html
vendored
|
@ -147,6 +147,7 @@ $GODOT_HEAD_INCLUDE
|
||||||
const MAIN_PACK = '$GODOT_BASENAME.pck';
|
const MAIN_PACK = '$GODOT_BASENAME.pck';
|
||||||
const EXTRA_ARGS = JSON.parse('$GODOT_ARGS');
|
const EXTRA_ARGS = JSON.parse('$GODOT_ARGS');
|
||||||
const INDETERMINATE_STATUS_STEP_MS = 100;
|
const INDETERMINATE_STATUS_STEP_MS = 100;
|
||||||
|
const FULL_WINDOW = $GODOT_FULL_WINDOW;
|
||||||
|
|
||||||
var canvas = document.getElementById('canvas');
|
var canvas = document.getElementById('canvas');
|
||||||
var statusProgress = document.getElementById('status-progress');
|
var statusProgress = document.getElementById('status-progress');
|
||||||
|
@ -156,6 +157,9 @@ $GODOT_HEAD_INCLUDE
|
||||||
|
|
||||||
var initializing = true;
|
var initializing = true;
|
||||||
var statusMode = 'hidden';
|
var statusMode = 'hidden';
|
||||||
|
var lastWidth = 0;
|
||||||
|
var lastHeight = 0;
|
||||||
|
var lastScale = 0;
|
||||||
|
|
||||||
var animationCallbacks = [];
|
var animationCallbacks = [];
|
||||||
function animate(time) {
|
function animate(time) {
|
||||||
|
@ -165,14 +169,23 @@ $GODOT_HEAD_INCLUDE
|
||||||
requestAnimationFrame(animate);
|
requestAnimationFrame(animate);
|
||||||
|
|
||||||
function adjustCanvasDimensions() {
|
function adjustCanvasDimensions() {
|
||||||
var scale = window.devicePixelRatio || 1;
|
const scale = window.devicePixelRatio || 1;
|
||||||
var width = window.innerWidth;
|
if (lastWidth != window.innerWidth || lastHeight != window.innerHeight || lastScale != scale) {
|
||||||
var height = window.innerHeight;
|
lastScale = scale;
|
||||||
canvas.width = width * scale;
|
lastWidth = window.innerWidth;
|
||||||
canvas.height = height * scale;
|
lastHeight = window.innerHeight;
|
||||||
|
canvas.width = Math.floor(lastWidth * scale);
|
||||||
|
canvas.height = Math.floor(lastHeight * scale);
|
||||||
|
canvas.style.width = lastWidth + "px";
|
||||||
|
canvas.style.height = lastHeight + "px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FULL_WINDOW) {
|
||||||
|
animationCallbacks.push(adjustCanvasDimensions);
|
||||||
|
adjustCanvasDimensions();
|
||||||
|
} else {
|
||||||
|
engine.setCanvasResizedOnStart(true);
|
||||||
}
|
}
|
||||||
animationCallbacks.push(adjustCanvasDimensions);
|
|
||||||
adjustCanvasDimensions();
|
|
||||||
|
|
||||||
setStatusMode = function setStatusMode(mode) {
|
setStatusMode = function setStatusMode(mode) {
|
||||||
|
|
||||||
|
|
|
@ -46,21 +46,21 @@ public:
|
||||||
|
|
||||||
static AudioDriverJavaScript *singleton;
|
static AudioDriverJavaScript *singleton;
|
||||||
|
|
||||||
virtual const char *get_name() const;
|
const char *get_name() const override;
|
||||||
|
|
||||||
virtual Error init();
|
Error init() override;
|
||||||
virtual void start();
|
void start() override;
|
||||||
void resume();
|
void resume();
|
||||||
virtual float get_latency();
|
float get_latency() override;
|
||||||
virtual int get_mix_rate() const;
|
int get_mix_rate() const override;
|
||||||
virtual SpeakerMode get_speaker_mode() const;
|
SpeakerMode get_speaker_mode() const override;
|
||||||
virtual void lock();
|
void lock() override;
|
||||||
virtual void unlock();
|
void unlock() override;
|
||||||
virtual void finish();
|
void finish() override;
|
||||||
void finish_async();
|
void finish_async();
|
||||||
|
|
||||||
virtual Error capture_start();
|
Error capture_start() override;
|
||||||
virtual Error capture_stop();
|
Error capture_stop() override;
|
||||||
|
|
||||||
AudioDriverJavaScript();
|
AudioDriverJavaScript();
|
||||||
};
|
};
|
||||||
|
|
|
@ -75,7 +75,7 @@ bool DisplayServerJavaScript::check_size_force_redraw() {
|
||||||
if (last_width != canvas_width || last_height != canvas_height) {
|
if (last_width != canvas_width || last_height != canvas_height) {
|
||||||
last_width = canvas_width;
|
last_width = canvas_width;
|
||||||
last_height = canvas_height;
|
last_height = canvas_height;
|
||||||
// Update the framebuffer size and for redraw.
|
// Update the framebuffer size for redraw.
|
||||||
emscripten_set_canvas_element_size(DisplayServerJavaScript::canvas_id, canvas_width, canvas_height);
|
emscripten_set_canvas_element_size(DisplayServerJavaScript::canvas_id, canvas_width, canvas_height);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -892,15 +892,18 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
|
||||||
#define SET_EM_CALLBACK(target, ev, cb) \
|
#define SET_EM_CALLBACK(target, ev, cb) \
|
||||||
result = emscripten_set_##ev##_callback(target, nullptr, true, &cb); \
|
result = emscripten_set_##ev##_callback(target, nullptr, true, &cb); \
|
||||||
EM_CHECK(ev)
|
EM_CHECK(ev)
|
||||||
|
#define SET_EM_WINDOW_CALLBACK(ev, cb) \
|
||||||
|
result = emscripten_set_##ev##_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, false, &cb); \
|
||||||
|
EM_CHECK(ev)
|
||||||
#define SET_EM_CALLBACK_NOTARGET(ev, cb) \
|
#define SET_EM_CALLBACK_NOTARGET(ev, cb) \
|
||||||
result = emscripten_set_##ev##_callback(nullptr, true, &cb); \
|
result = emscripten_set_##ev##_callback(nullptr, true, &cb); \
|
||||||
EM_CHECK(ev)
|
EM_CHECK(ev)
|
||||||
// These callbacks from Emscripten's html5.h suffice to access most
|
// These callbacks from Emscripten's html5.h suffice to access most
|
||||||
// JavaScript APIs. For APIs that are not (sufficiently) exposed, EM_ASM
|
// JavaScript APIs. For APIs that are not (sufficiently) exposed, EM_ASM
|
||||||
// is used below.
|
// is used below.
|
||||||
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mousemove, mousemove_callback)
|
|
||||||
SET_EM_CALLBACK(canvas_id, mousedown, mouse_button_callback)
|
SET_EM_CALLBACK(canvas_id, mousedown, mouse_button_callback)
|
||||||
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mouseup, mouse_button_callback)
|
SET_EM_WINDOW_CALLBACK(mousemove, mousemove_callback)
|
||||||
|
SET_EM_WINDOW_CALLBACK(mouseup, mouse_button_callback)
|
||||||
SET_EM_CALLBACK(canvas_id, wheel, wheel_callback)
|
SET_EM_CALLBACK(canvas_id, wheel, wheel_callback)
|
||||||
SET_EM_CALLBACK(canvas_id, touchstart, touch_press_callback)
|
SET_EM_CALLBACK(canvas_id, touchstart, touch_press_callback)
|
||||||
SET_EM_CALLBACK(canvas_id, touchmove, touchmove_callback)
|
SET_EM_CALLBACK(canvas_id, touchmove, touchmove_callback)
|
||||||
|
@ -918,27 +921,25 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
EM_ASM_ARGS({
|
EM_ASM_ARGS({
|
||||||
Module.listeners = {};
|
// Bind native event listeners.
|
||||||
|
// Module.listeners, and Module.drop_handler are defined in native/utils.js
|
||||||
const canvas = Module['canvas'];
|
const canvas = Module['canvas'];
|
||||||
const send_window_event = cwrap('send_window_event', null, ['number']);
|
const send_window_event = cwrap('send_window_event', null, ['number']);
|
||||||
const notifications = arguments;
|
const notifications = arguments;
|
||||||
(['mouseover', 'mouseleave', 'focus', 'blur']).forEach(function(event, index) {
|
(['mouseover', 'mouseleave', 'focus', 'blur']).forEach(function(event, index) {
|
||||||
Module.listeners[event] = send_window_event.bind(null, notifications[index]);
|
Module.listeners.add(canvas, event, send_window_event.bind(null, notifications[index]), true);
|
||||||
canvas.addEventListener(event, Module.listeners[event]);
|
|
||||||
});
|
});
|
||||||
// Clipboard
|
// Clipboard
|
||||||
const update_clipboard = cwrap('update_clipboard', null, ['string']);
|
const update_clipboard = cwrap('update_clipboard', null, ['string']);
|
||||||
Module.listeners['paste'] = function(evt) {
|
Module.listeners.add(window, 'paste', function(evt) {
|
||||||
update_clipboard(evt.clipboardData.getData('text'));
|
update_clipboard(evt.clipboardData.getData('text'));
|
||||||
};
|
}, false);
|
||||||
window.addEventListener('paste', Module.listeners['paste'], false);
|
// Drag an drop
|
||||||
Module.listeners['dragover'] = function(ev) {
|
Module.listeners.add(canvas, 'dragover', function(ev) {
|
||||||
// Prevent default behavior (which would try to open the file(s))
|
// Prevent default behavior (which would try to open the file(s))
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
};
|
}, false);
|
||||||
Module.listeners['drop'] = Module.drop_handler; // Defined in native/utils.js
|
Module.listeners.add(canvas, 'drop', Module.drop_handler, false);
|
||||||
canvas.addEventListener('dragover', Module.listeners['dragover'], false);
|
|
||||||
canvas.addEventListener('drop', Module.listeners['drop'], false);
|
|
||||||
},
|
},
|
||||||
WINDOW_EVENT_MOUSE_ENTER,
|
WINDOW_EVENT_MOUSE_ENTER,
|
||||||
WINDOW_EVENT_MOUSE_EXIT,
|
WINDOW_EVENT_MOUSE_EXIT,
|
||||||
|
@ -952,14 +953,7 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
|
||||||
|
|
||||||
DisplayServerJavaScript::~DisplayServerJavaScript() {
|
DisplayServerJavaScript::~DisplayServerJavaScript() {
|
||||||
EM_ASM({
|
EM_ASM({
|
||||||
Object.entries(Module.listeners).forEach(function(kv) {
|
Module.listeners.clear();
|
||||||
if (kv[0] == 'paste') {
|
|
||||||
window.removeEventListener(kv[0], kv[1], true);
|
|
||||||
} else {
|
|
||||||
Module['canvas'].removeEventListener(kv[0], kv[1]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Module.listeners = {};
|
|
||||||
});
|
});
|
||||||
//emscripten_webgl_commit_frame();
|
//emscripten_webgl_commit_frame();
|
||||||
//emscripten_webgl_destroy_context(webgl_ctx);
|
//emscripten_webgl_destroy_context(webgl_ctx);
|
||||||
|
@ -1109,7 +1103,11 @@ Size2i DisplayServerJavaScript::window_get_min_size(WindowID p_window) const {
|
||||||
void DisplayServerJavaScript::window_set_size(const Size2i p_size, WindowID p_window) {
|
void DisplayServerJavaScript::window_set_size(const Size2i p_size, WindowID p_window) {
|
||||||
last_width = p_size.x;
|
last_width = p_size.x;
|
||||||
last_height = p_size.y;
|
last_height = p_size.y;
|
||||||
emscripten_set_canvas_element_size(canvas_id, p_size.x, p_size.y);
|
double scale = EM_ASM_DOUBLE({
|
||||||
|
return window.devicePixelRatio || 1;
|
||||||
|
});
|
||||||
|
emscripten_set_canvas_element_size(canvas_id, p_size.x * scale, p_size.y * scale);
|
||||||
|
emscripten_set_element_css_size(canvas_id, p_size.x, p_size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Size2i DisplayServerJavaScript::window_get_size(WindowID p_window) const {
|
Size2i DisplayServerJavaScript::window_get_size(WindowID p_window) const {
|
||||||
|
|
|
@ -93,7 +93,7 @@ class DisplayServerJavaScript : public DisplayServer {
|
||||||
static void _dispatch_input_event(const Ref<InputEvent> &p_event);
|
static void _dispatch_input_event(const Ref<InputEvent> &p_event);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int get_current_video_driver() const;
|
int get_current_video_driver() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Override return type to make writing static callbacks less tedious.
|
// Override return type to make writing static callbacks less tedious.
|
||||||
|
@ -113,92 +113,92 @@ public:
|
||||||
bool check_size_force_redraw();
|
bool check_size_force_redraw();
|
||||||
|
|
||||||
// from DisplayServer
|
// from DisplayServer
|
||||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
||||||
virtual bool has_feature(Feature p_feature) const;
|
bool has_feature(Feature p_feature) const override;
|
||||||
virtual String get_name() const;
|
String get_name() const override;
|
||||||
|
|
||||||
// cursor
|
// cursor
|
||||||
virtual void cursor_set_shape(CursorShape p_shape);
|
void cursor_set_shape(CursorShape p_shape) override;
|
||||||
virtual CursorShape cursor_get_shape() const;
|
CursorShape cursor_get_shape() const override;
|
||||||
virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
|
void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
|
||||||
|
|
||||||
// mouse
|
// mouse
|
||||||
virtual void mouse_set_mode(MouseMode p_mode);
|
void mouse_set_mode(MouseMode p_mode) override;
|
||||||
virtual MouseMode mouse_get_mode() const;
|
MouseMode mouse_get_mode() const override;
|
||||||
|
|
||||||
// touch
|
// touch
|
||||||
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||||
|
|
||||||
// clipboard
|
// clipboard
|
||||||
virtual void clipboard_set(const String &p_text);
|
void clipboard_set(const String &p_text) override;
|
||||||
virtual String clipboard_get() const;
|
String clipboard_get() const override;
|
||||||
|
|
||||||
// screen
|
// screen
|
||||||
virtual int get_screen_count() const;
|
int get_screen_count() const override;
|
||||||
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||||
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||||
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||||
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||||
|
|
||||||
// windows
|
// windows
|
||||||
virtual Vector<DisplayServer::WindowID> get_window_list() const;
|
Vector<DisplayServer::WindowID> get_window_list() const override;
|
||||||
virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
|
WindowID get_window_at_screen_position(const Point2i &p_position) const override;
|
||||||
|
|
||||||
virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID);
|
void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
|
ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
|
|
||||||
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
|
|
||||||
virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
|
|
||||||
virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
|
|
||||||
virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
|
|
||||||
virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const;
|
int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
|
|
||||||
virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const;
|
Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
|
|
||||||
virtual void window_set_transient(WindowID p_window, WindowID p_parent);
|
void window_set_transient(WindowID p_window, WindowID p_parent) override;
|
||||||
|
|
||||||
virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const;
|
Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
|
|
||||||
virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const;
|
Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
|
|
||||||
virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const;
|
Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const; // FIXME: Find clearer name for this.
|
Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
|
|
||||||
virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const;
|
WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
|
|
||||||
virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const;
|
bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
|
|
||||||
virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
|
void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const;
|
bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
|
|
||||||
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID);
|
void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
|
void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
|
|
||||||
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
|
bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||||
|
|
||||||
virtual bool can_any_window_draw() const;
|
bool can_any_window_draw() const override;
|
||||||
|
|
||||||
// events
|
// events
|
||||||
virtual void process_events();
|
void process_events() override;
|
||||||
|
|
||||||
// icon
|
// icon
|
||||||
virtual void set_icon(const Ref<Image> &p_icon);
|
void set_icon(const Ref<Image> &p_icon) override;
|
||||||
|
|
||||||
// others
|
// others
|
||||||
virtual bool get_swap_cancel_ok();
|
bool get_swap_cancel_ok() override;
|
||||||
virtual void swap_buffers();
|
void swap_buffers() override;
|
||||||
|
|
||||||
static void register_javascript_driver();
|
static void register_javascript_driver();
|
||||||
DisplayServerJavaScript(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
|
DisplayServerJavaScript(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
|
||||||
|
|
|
@ -33,6 +33,7 @@ Function('return this')()['Engine'] = (function() {
|
||||||
this.resizeCanvasOnStart = false;
|
this.resizeCanvasOnStart = false;
|
||||||
this.onExecute = null;
|
this.onExecute = null;
|
||||||
this.onExit = null;
|
this.onExit = null;
|
||||||
|
this.persistentPaths = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
Engine.prototype.init = /** @param {string=} basePath */ function(basePath) {
|
Engine.prototype.init = /** @param {string=} basePath */ function(basePath) {
|
||||||
|
@ -56,12 +57,14 @@ Function('return this')()['Engine'] = (function() {
|
||||||
config['locateFile'] = Utils.createLocateRewrite(loadPath);
|
config['locateFile'] = Utils.createLocateRewrite(loadPath);
|
||||||
config['instantiateWasm'] = Utils.createInstantiatePromise(loadPromise);
|
config['instantiateWasm'] = Utils.createInstantiatePromise(loadPromise);
|
||||||
Godot(config).then(function(module) {
|
Godot(config).then(function(module) {
|
||||||
me.rtenv = module;
|
module['initFS'](me.persistentPaths).then(function(fs_err) {
|
||||||
if (unloadAfterInit) {
|
me.rtenv = module;
|
||||||
unload();
|
if (unloadAfterInit) {
|
||||||
}
|
unload();
|
||||||
resolve();
|
}
|
||||||
config = null;
|
resolve();
|
||||||
|
config = null;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return initPromise;
|
return initPromise;
|
||||||
|
@ -220,6 +223,10 @@ Function('return this')()['Engine'] = (function() {
|
||||||
this.rtenv['copyToFS'](path, buffer);
|
this.rtenv['copyToFS'](path, buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Engine.prototype.setPersistentPaths = function(persistentPaths) {
|
||||||
|
this.persistentPaths = persistentPaths;
|
||||||
|
};
|
||||||
|
|
||||||
// Closure compiler exported engine methods.
|
// Closure compiler exported engine methods.
|
||||||
/** @export */
|
/** @export */
|
||||||
Engine['isWebGLAvailable'] = Utils.isWebGLAvailable;
|
Engine['isWebGLAvailable'] = Utils.isWebGLAvailable;
|
||||||
|
@ -241,5 +248,6 @@ Function('return this')()['Engine'] = (function() {
|
||||||
Engine.prototype['setOnExecute'] = Engine.prototype.setOnExecute;
|
Engine.prototype['setOnExecute'] = Engine.prototype.setOnExecute;
|
||||||
Engine.prototype['setOnExit'] = Engine.prototype.setOnExit;
|
Engine.prototype['setOnExit'] = Engine.prototype.setOnExit;
|
||||||
Engine.prototype['copyToFS'] = Engine.prototype.copyToFS;
|
Engine.prototype['copyToFS'] = Engine.prototype.copyToFS;
|
||||||
|
Engine.prototype['setPersistentPaths'] = Engine.prototype.setPersistentPaths;
|
||||||
return Engine;
|
return Engine;
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -258,6 +258,7 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re
|
||||||
current_line = current_line.replace("$GODOT_BASENAME", p_name);
|
current_line = current_line.replace("$GODOT_BASENAME", p_name);
|
||||||
current_line = current_line.replace("$GODOT_PROJECT_NAME", ProjectSettings::get_singleton()->get_setting("application/config/name"));
|
current_line = current_line.replace("$GODOT_PROJECT_NAME", ProjectSettings::get_singleton()->get_setting("application/config/name"));
|
||||||
current_line = current_line.replace("$GODOT_HEAD_INCLUDE", p_preset->get("html/head_include"));
|
current_line = current_line.replace("$GODOT_HEAD_INCLUDE", p_preset->get("html/head_include"));
|
||||||
|
current_line = current_line.replace("$GODOT_FULL_WINDOW", p_preset->get("html/full_window_size") ? "true" : "false");
|
||||||
current_line = current_line.replace("$GODOT_DEBUG_ENABLED", p_debug ? "true" : "false");
|
current_line = current_line.replace("$GODOT_DEBUG_ENABLED", p_debug ? "true" : "false");
|
||||||
current_line = current_line.replace("$GODOT_ARGS", flags_json);
|
current_line = current_line.replace("$GODOT_ARGS", flags_json);
|
||||||
str_export += current_line + "\n";
|
str_export += current_line + "\n";
|
||||||
|
@ -291,6 +292,7 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_mobile"), false)); // ETC or ETC2, depending on renderer
|
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_mobile"), false)); // ETC or ETC2, depending on renderer
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), ""));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), ""));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/full_window_size"), true));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,17 @@
|
||||||
static OS_JavaScript *os = nullptr;
|
static OS_JavaScript *os = nullptr;
|
||||||
static uint64_t target_ticks = 0;
|
static uint64_t target_ticks = 0;
|
||||||
|
|
||||||
|
extern "C" EMSCRIPTEN_KEEPALIVE void _request_quit_callback(char *p_filev[], int p_filec) {
|
||||||
|
DisplayServerJavaScript *ds = DisplayServerJavaScript::get_singleton();
|
||||||
|
if (ds) {
|
||||||
|
Variant event = int(DisplayServer::WINDOW_EVENT_CLOSE_REQUEST);
|
||||||
|
Variant *eventp = &event;
|
||||||
|
Variant ret;
|
||||||
|
Callable::CallError ce;
|
||||||
|
ds->window_event_callback.call((const Variant **)&eventp, 1, ret, ce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void exit_callback() {
|
void exit_callback() {
|
||||||
emscripten_cancel_main_loop(); // After this, we can exit!
|
emscripten_cancel_main_loop(); // After this, we can exit!
|
||||||
Main::cleanup();
|
Main::cleanup();
|
||||||
|
@ -77,12 +88,27 @@ void main_loop_callback() {
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
os->get_main_loop()->finish();
|
os->get_main_loop()->finish();
|
||||||
os->finalize_async(); // Will add all the async finish functions.
|
os->finalize_async(); // Will add all the async finish functions.
|
||||||
|
/* clang-format off */
|
||||||
EM_ASM({
|
EM_ASM({
|
||||||
Promise.all(Module.async_finish).then(function() {
|
Promise.all(Module.async_finish).then(function() {
|
||||||
Module.async_finish = [];
|
Module.async_finish = [];
|
||||||
|
return new Promise(function(accept, reject) {
|
||||||
|
if (!Module.idbfs) {
|
||||||
|
accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FS.syncfs(function(error) {
|
||||||
|
if (error) {
|
||||||
|
err('Failed to save IDB file system: ' + error.message);
|
||||||
|
}
|
||||||
|
accept();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).then(function() {
|
||||||
ccall("cleanup_after_sync", null, []);
|
ccall("cleanup_after_sync", null, []);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
/* clang-format on */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,31 +116,8 @@ extern "C" EMSCRIPTEN_KEEPALIVE void cleanup_after_sync() {
|
||||||
emscripten_set_main_loop(exit_callback, -1, false);
|
emscripten_set_main_loop(exit_callback, -1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" EMSCRIPTEN_KEEPALIVE void main_after_fs_sync(char *p_idbfs_err) {
|
/// When calling main, it is assumed FS is setup and synced.
|
||||||
String idbfs_err = String::utf8(p_idbfs_err);
|
|
||||||
if (!idbfs_err.empty()) {
|
|
||||||
print_line("IndexedDB not available: " + idbfs_err);
|
|
||||||
}
|
|
||||||
os->set_idb_available(idbfs_err.empty());
|
|
||||||
// TODO: Check error return value.
|
|
||||||
Main::setup2(); // Manual second phase.
|
|
||||||
// Ease up compatibility.
|
|
||||||
ResourceLoader::set_abort_on_missing_resources(false);
|
|
||||||
Main::start();
|
|
||||||
os->get_main_loop()->init();
|
|
||||||
// Immediately run the first iteration.
|
|
||||||
// We are inside an animation frame, we want to immediately draw on the newly setup canvas.
|
|
||||||
main_loop_callback();
|
|
||||||
emscripten_resume_main_loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
// Create and mount userfs immediately.
|
|
||||||
EM_ASM({
|
|
||||||
FS.mkdir('/userfs');
|
|
||||||
FS.mount(IDBFS, {}, '/userfs');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Configure locale.
|
// Configure locale.
|
||||||
char locale_ptr[16];
|
char locale_ptr[16];
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
@ -132,26 +135,30 @@ int main(int argc, char *argv[]) {
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
os = new OS_JavaScript();
|
os = new OS_JavaScript();
|
||||||
|
os->set_idb_available((bool)EM_ASM_INT({ return Module.idbfs }));
|
||||||
|
|
||||||
// We must override main when testing is enabled
|
// We must override main when testing is enabled
|
||||||
TEST_MAIN_OVERRIDE
|
TEST_MAIN_OVERRIDE
|
||||||
|
|
||||||
Main::setup(argv[0], argc - 1, &argv[1], false);
|
Main::setup(argv[0], argc - 1, &argv[1]);
|
||||||
emscripten_set_main_loop(main_loop_callback, -1, false);
|
|
||||||
emscripten_pause_main_loop(); // Will need to wait for FS sync.
|
|
||||||
|
|
||||||
// Sync from persistent state into memory and then
|
// Ease up compatibility.
|
||||||
// run the 'main_after_fs_sync' function.
|
ResourceLoader::set_abort_on_missing_resources(false);
|
||||||
|
|
||||||
|
Main::start();
|
||||||
|
os->get_main_loop()->init();
|
||||||
|
// Expose method for requesting quit.
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
EM_ASM({
|
EM_ASM({
|
||||||
FS.syncfs(true, function(err) {
|
Module['request_quit'] = function() {
|
||||||
requestAnimationFrame(function() {
|
ccall("_request_quit_callback", null, []);
|
||||||
ccall('main_after_fs_sync', null, ['string'], [err ? err.message : ""]);
|
};
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
emscripten_set_main_loop(main_loop_callback, -1, false);
|
||||||
|
// Immediately run the first iteration.
|
||||||
|
// We are inside an animation frame, we want to immediately draw on the newly setup canvas.
|
||||||
|
main_loop_callback();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
// Continued async in main_after_fs_sync() from the syncfs() callback.
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,38 @@
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
|
Module['initFS'] = function(persistentPaths) {
|
||||||
|
FS.mkdir('/userfs');
|
||||||
|
FS.mount(IDBFS, {}, '/userfs');
|
||||||
|
|
||||||
|
function createRecursive(dir) {
|
||||||
|
try {
|
||||||
|
FS.stat(dir);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.errno !== ERRNO_CODES.ENOENT) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
FS.mkdirTree(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
persistentPaths.forEach(function(path) {
|
||||||
|
createRecursive(path);
|
||||||
|
FS.mount(IDBFS, {}, path);
|
||||||
|
});
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
FS.syncfs(true, function(err) {
|
||||||
|
if (err) {
|
||||||
|
Module.idbfs = false;
|
||||||
|
console.log("IndexedDB not available: " + err.message);
|
||||||
|
} else {
|
||||||
|
Module.idbfs = true;
|
||||||
|
}
|
||||||
|
resolve(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Module['copyToFS'] = function(path, buffer) {
|
Module['copyToFS'] = function(path, buffer) {
|
||||||
var p = path.lastIndexOf("/");
|
var p = path.lastIndexOf("/");
|
||||||
var dir = "/";
|
var dir = "/";
|
||||||
|
@ -37,7 +69,7 @@ Module['copyToFS'] = function(path, buffer) {
|
||||||
try {
|
try {
|
||||||
FS.stat(dir);
|
FS.stat(dir);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.errno !== ERRNO_CODES.ENOENT) { // 'ENOENT', see https://github.com/emscripten-core/emscripten/blob/master/system/lib/libc/musl/arch/emscripten/bits/errno.h
|
if (e.errno !== ERRNO_CODES.ENOENT) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
FS.mkdirTree(dir);
|
FS.mkdirTree(dir);
|
||||||
|
@ -202,3 +234,44 @@ Module.drop_handler = (function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
function EventHandlers() {
|
||||||
|
function Handler(target, event, method, capture) {
|
||||||
|
this.target = target;
|
||||||
|
this.event = event;
|
||||||
|
this.method = method;
|
||||||
|
this.capture = capture;
|
||||||
|
}
|
||||||
|
|
||||||
|
var listeners = [];
|
||||||
|
|
||||||
|
function has(target, event, method, capture) {
|
||||||
|
return listeners.findIndex(function(e) {
|
||||||
|
return e.target === target && e.event === event && e.method === method && e.capture == capture;
|
||||||
|
}) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.add = function(target, event, method, capture) {
|
||||||
|
if (has(target, event, method, capture)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listeners.push(new Handler(target, event, method, capture));
|
||||||
|
target.addEventListener(event, method, capture);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.remove = function(target, event, method, capture) {
|
||||||
|
if (!has(target, event, method, capture)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
target.removeEventListener(event, method, capture);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.clear = function() {
|
||||||
|
listeners.forEach(function(h) {
|
||||||
|
h.target.removeEventListener(h.event, h.method, h.capture);
|
||||||
|
});
|
||||||
|
listeners.length = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Module.listeners = new EventHandlers();
|
||||||
|
|
|
@ -46,24 +46,6 @@
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
bool OS_JavaScript::has_touchscreen_ui_hint() const {
|
|
||||||
/* clang-format off */
|
|
||||||
return EM_ASM_INT_V(
|
|
||||||
return 'ontouchstart' in window;
|
|
||||||
);
|
|
||||||
/* clang-format on */
|
|
||||||
}
|
|
||||||
|
|
||||||
// Audio
|
|
||||||
|
|
||||||
int OS_JavaScript::get_audio_driver_count() const {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *OS_JavaScript::get_audio_driver_name(int p_driver) const {
|
|
||||||
return "JavaScript";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
void OS_JavaScript::initialize() {
|
void OS_JavaScript::initialize() {
|
||||||
OS_Unix::initialize_core();
|
OS_Unix::initialize_core();
|
||||||
|
@ -90,27 +72,24 @@ MainLoop *OS_JavaScript::get_main_loop() const {
|
||||||
return main_loop;
|
return main_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_JavaScript::main_loop_callback() {
|
extern "C" EMSCRIPTEN_KEEPALIVE void _idb_synced() {
|
||||||
get_singleton()->main_loop_iterate();
|
OS_JavaScript::get_singleton()->idb_is_syncing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OS_JavaScript::main_loop_iterate() {
|
bool OS_JavaScript::main_loop_iterate() {
|
||||||
if (is_userfs_persistent() && sync_wait_time >= 0) {
|
if (is_userfs_persistent() && idb_needs_sync && !idb_is_syncing) {
|
||||||
int64_t current_time = get_ticks_msec();
|
idb_is_syncing = true;
|
||||||
int64_t elapsed_time = current_time - last_sync_check_time;
|
idb_needs_sync = false;
|
||||||
last_sync_check_time = current_time;
|
/* clang-format off */
|
||||||
|
EM_ASM({
|
||||||
sync_wait_time -= elapsed_time;
|
FS.syncfs(function(error) {
|
||||||
|
if (error) {
|
||||||
if (sync_wait_time < 0) {
|
err('Failed to save IDB file system: ' + error.message);
|
||||||
/* clang-format off */
|
}
|
||||||
EM_ASM(
|
ccall("_idb_synced", 'void', [], []);
|
||||||
FS.syncfs(function(error) {
|
});
|
||||||
if (error) { err('Failed to save IDB file system: ' + error.message); }
|
});
|
||||||
});
|
/* clang-format on */
|
||||||
);
|
|
||||||
/* clang-format on */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayServer::get_singleton()->process_events();
|
DisplayServer::get_singleton()->process_events();
|
||||||
|
@ -201,10 +180,6 @@ String OS_JavaScript::get_name() const {
|
||||||
return "HTML5";
|
return "HTML5";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OS_JavaScript::can_draw() const {
|
|
||||||
return true; // Always?
|
|
||||||
}
|
|
||||||
|
|
||||||
String OS_JavaScript::get_user_data_dir() const {
|
String OS_JavaScript::get_user_data_dir() const {
|
||||||
return "/userfs";
|
return "/userfs";
|
||||||
};
|
};
|
||||||
|
@ -222,11 +197,17 @@ String OS_JavaScript::get_data_path() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_JavaScript::file_access_close_callback(const String &p_file, int p_flags) {
|
void OS_JavaScript::file_access_close_callback(const String &p_file, int p_flags) {
|
||||||
OS_JavaScript *os = get_singleton();
|
OS_JavaScript *os = OS_JavaScript::get_singleton();
|
||||||
if (os->is_userfs_persistent() && p_file.begins_with("/userfs") && p_flags & FileAccess::WRITE) {
|
if (!(os->is_userfs_persistent() && (p_flags & FileAccess::WRITE))) {
|
||||||
os->last_sync_check_time = OS::get_singleton()->get_ticks_msec();
|
return; // FS persistence is not working or we are not writing.
|
||||||
// Wait five seconds in case more files are about to be closed.
|
}
|
||||||
os->sync_wait_time = 5000;
|
bool is_file_persistent = p_file.begins_with("/userfs");
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
// Hack for editor persistence (can we track).
|
||||||
|
is_file_persistent = is_file_persistent || p_file.begins_with("/home/web_user/");
|
||||||
|
#endif
|
||||||
|
if (is_file_persistent) {
|
||||||
|
os->idb_needs_sync = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,57 +44,52 @@ class OS_JavaScript : public OS_Unix {
|
||||||
|
|
||||||
bool finalizing = false;
|
bool finalizing = false;
|
||||||
bool idb_available = false;
|
bool idb_available = false;
|
||||||
int64_t sync_wait_time = -1;
|
bool idb_needs_sync = false;
|
||||||
int64_t last_sync_check_time = -1;
|
|
||||||
|
|
||||||
static void main_loop_callback();
|
static void main_loop_callback();
|
||||||
|
|
||||||
static void file_access_close_callback(const String &p_file, int p_flags);
|
static void file_access_close_callback(const String &p_file, int p_flags);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void initialize();
|
void initialize() override;
|
||||||
|
|
||||||
virtual void set_main_loop(MainLoop *p_main_loop);
|
void set_main_loop(MainLoop *p_main_loop) override;
|
||||||
virtual void delete_main_loop();
|
void delete_main_loop() override;
|
||||||
|
|
||||||
virtual void finalize();
|
void finalize() override;
|
||||||
|
|
||||||
virtual bool _check_internal_feature_support(const String &p_feature);
|
bool _check_internal_feature_support(const String &p_feature) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool idb_is_syncing = false;
|
||||||
|
|
||||||
// Override return type to make writing static callbacks less tedious.
|
// Override return type to make writing static callbacks less tedious.
|
||||||
static OS_JavaScript *get_singleton();
|
static OS_JavaScript *get_singleton();
|
||||||
|
|
||||||
virtual void initialize_joypads();
|
void initialize_joypads() override;
|
||||||
|
|
||||||
virtual bool has_touchscreen_ui_hint() const;
|
MainLoop *get_main_loop() const override;
|
||||||
|
|
||||||
virtual int get_audio_driver_count() const;
|
|
||||||
virtual const char *get_audio_driver_name(int p_driver) const;
|
|
||||||
|
|
||||||
virtual MainLoop *get_main_loop() const;
|
|
||||||
void finalize_async();
|
void finalize_async();
|
||||||
bool main_loop_iterate();
|
bool main_loop_iterate();
|
||||||
|
|
||||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr);
|
Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr) override;
|
||||||
virtual Error kill(const ProcessID &p_pid);
|
Error kill(const ProcessID &p_pid) override;
|
||||||
virtual int get_process_id() const;
|
int get_process_id() const override;
|
||||||
|
|
||||||
String get_executable_path() const;
|
String get_executable_path() const override;
|
||||||
virtual Error shell_open(String p_uri);
|
Error shell_open(String p_uri) override;
|
||||||
virtual String get_name() const;
|
String get_name() const override;
|
||||||
// Override default OS implementation which would block the main thread with delay_usec.
|
// Override default OS implementation which would block the main thread with delay_usec.
|
||||||
// Implemented in javascript_main.cpp loop callback instead.
|
// Implemented in javascript_main.cpp loop callback instead.
|
||||||
virtual void add_frame_delay(bool p_can_draw) {}
|
void add_frame_delay(bool p_can_draw) override {}
|
||||||
virtual bool can_draw() const;
|
|
||||||
|
|
||||||
virtual String get_cache_path() const;
|
String get_cache_path() const override;
|
||||||
virtual String get_config_path() const;
|
String get_config_path() const override;
|
||||||
virtual String get_data_path() const;
|
String get_data_path() const override;
|
||||||
virtual String get_user_data_dir() const;
|
String get_user_data_dir() const override;
|
||||||
|
|
||||||
void set_idb_available(bool p_idb_available);
|
void set_idb_available(bool p_idb_available);
|
||||||
virtual bool is_userfs_persistent() const;
|
bool is_userfs_persistent() const override;
|
||||||
|
|
||||||
void resume_audio();
|
void resume_audio();
|
||||||
bool is_finalizing() { return finalizing; }
|
bool is_finalizing() { return finalizing; }
|
||||||
|
|
Loading…
Reference in a new issue