Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HTML5] Synchronous main, better persistence, handlers fixes, optional full screen. #42178

Merged
merged 8 commits into from
Sep 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
950 changes: 467 additions & 483 deletions drivers/dummy/rasterizer_dummy.h

Large diffs are not rendered by default.

27 changes: 20 additions & 7 deletions misc/dist/html/full-size.html
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
const MAIN_PACK = '$GODOT_BASENAME.pck';
const EXTRA_ARGS = JSON.parse('$GODOT_ARGS');
const INDETERMINATE_STATUS_STEP_MS = 100;
const FULL_WINDOW = $GODOT_FULL_WINDOW;

var canvas = document.getElementById('canvas');
var statusProgress = document.getElementById('status-progress');
Expand All @@ -156,6 +157,9 @@

var initializing = true;
var statusMode = 'hidden';
var lastWidth = 0;
var lastHeight = 0;
var lastScale = 0;

var animationCallbacks = [];
function animate(time) {
Expand All @@ -165,14 +169,23 @@
requestAnimationFrame(animate);

function adjustCanvasDimensions() {
var scale = window.devicePixelRatio || 1;
var width = window.innerWidth;
var height = window.innerHeight;
canvas.width = width * scale;
canvas.height = height * scale;
const scale = window.devicePixelRatio || 1;
if (lastWidth != window.innerWidth || lastHeight != window.innerHeight || lastScale != scale) {
lastScale = scale;
lastWidth = window.innerWidth;
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) {

Expand Down
22 changes: 11 additions & 11 deletions platform/javascript/audio_driver_javascript.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,21 @@ class AudioDriverJavaScript : public AudioDriver {

static AudioDriverJavaScript *singleton;

virtual const char *get_name() const;
const char *get_name() const override;

virtual Error init();
virtual void start();
Error init() override;
void start() override;
void resume();
virtual float get_latency();
virtual int get_mix_rate() const;
virtual SpeakerMode get_speaker_mode() const;
virtual void lock();
virtual void unlock();
virtual void finish();
float get_latency() override;
int get_mix_rate() const override;
SpeakerMode get_speaker_mode() const override;
void lock() override;
void unlock() override;
void finish() override;
void finish_async();

virtual Error capture_start();
virtual Error capture_stop();
Error capture_start() override;
Error capture_stop() override;

AudioDriverJavaScript();
};
Expand Down
44 changes: 21 additions & 23 deletions platform/javascript/display_server_javascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ bool DisplayServerJavaScript::check_size_force_redraw() {
if (last_width != canvas_width || last_height != canvas_height) {
last_width = canvas_width;
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);
return true;
}
Expand Down Expand Up @@ -892,15 +892,18 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
#define SET_EM_CALLBACK(target, ev, cb) \
result = emscripten_set_##ev##_callback(target, nullptr, true, &cb); \
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) \
result = emscripten_set_##ev##_callback(nullptr, true, &cb); \
EM_CHECK(ev)
// These callbacks from Emscripten's html5.h suffice to access most
// JavaScript APIs. For APIs that are not (sufficiently) exposed, EM_ASM
// 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(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, touchstart, touch_press_callback)
SET_EM_CALLBACK(canvas_id, touchmove, touchmove_callback)
Expand All @@ -918,27 +921,25 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive

/* clang-format off */
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 send_window_event = cwrap('send_window_event', null, ['number']);
const notifications = arguments;
(['mouseover', 'mouseleave', 'focus', 'blur']).forEach(function(event, index) {
Module.listeners[event] = send_window_event.bind(null, notifications[index]);
canvas.addEventListener(event, Module.listeners[event]);
Module.listeners.add(canvas, event, send_window_event.bind(null, notifications[index]), true);
});
// Clipboard
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'));
};
window.addEventListener('paste', Module.listeners['paste'], false);
Module.listeners['dragover'] = function(ev) {
}, false);
// Drag an drop
Module.listeners.add(canvas, 'dragover', function(ev) {
// Prevent default behavior (which would try to open the file(s))
ev.preventDefault();
};
Module.listeners['drop'] = Module.drop_handler; // Defined in native/utils.js
canvas.addEventListener('dragover', Module.listeners['dragover'], false);
canvas.addEventListener('drop', Module.listeners['drop'], false);
}, false);
Module.listeners.add(canvas, 'drop', Module.drop_handler, false);
},
WINDOW_EVENT_MOUSE_ENTER,
WINDOW_EVENT_MOUSE_EXIT,
Expand All @@ -952,14 +953,7 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive

DisplayServerJavaScript::~DisplayServerJavaScript() {
EM_ASM({
Object.entries(Module.listeners).forEach(function(kv) {
if (kv[0] == 'paste') {
window.removeEventListener(kv[0], kv[1], true);
} else {
Module['canvas'].removeEventListener(kv[0], kv[1]);
}
});
Module.listeners = {};
Module.listeners.clear();
});
//emscripten_webgl_commit_frame();
//emscripten_webgl_destroy_context(webgl_ctx);
Expand Down Expand Up @@ -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) {
last_width = p_size.x;
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 {
Expand Down
104 changes: 52 additions & 52 deletions platform/javascript/display_server_javascript.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class DisplayServerJavaScript : public DisplayServer {
static void _dispatch_input_event(const Ref<InputEvent> &p_event);

protected:
virtual int get_current_video_driver() const;
int get_current_video_driver() const;

public:
// Override return type to make writing static callbacks less tedious.
Expand All @@ -113,92 +113,92 @@ class DisplayServerJavaScript : public DisplayServer {
bool check_size_force_redraw();

// from DisplayServer
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual bool has_feature(Feature p_feature) const;
virtual String get_name() const;
void alert(const String &p_alert, const String &p_title = "ALERT!") override;
bool has_feature(Feature p_feature) const override;
String get_name() const override;

// cursor
virtual void cursor_set_shape(CursorShape p_shape);
virtual CursorShape cursor_get_shape() const;
virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
void cursor_set_shape(CursorShape p_shape) override;
CursorShape cursor_get_shape() const override;
void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;

// mouse
virtual void mouse_set_mode(MouseMode p_mode);
virtual MouseMode mouse_get_mode() const;
void mouse_set_mode(MouseMode p_mode) override;
MouseMode mouse_get_mode() const override;

// 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
virtual void clipboard_set(const String &p_text);
virtual String clipboard_get() const;
void clipboard_set(const String &p_text) override;
String clipboard_get() const override;

// screen
virtual int get_screen_count() const;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
int get_screen_count() const override;
Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;

// windows
virtual Vector<DisplayServer::WindowID> get_window_list() const;
virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
Vector<DisplayServer::WindowID> get_window_list() const override;
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);
virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
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);
virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_input_text_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;
void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
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;
virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID);
int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
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;
virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID);
Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
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);
virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const;
void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
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);
virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const;
void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
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);
virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const;
virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const; // FIXME: Find clearer name for this.
void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
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);
virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const;
void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
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);
virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const;
void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
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);
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
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
virtual void process_events();
void process_events() override;

// icon
virtual void set_icon(const Ref<Image> &p_icon);
void set_icon(const Ref<Image> &p_icon) override;

// others
virtual bool get_swap_cancel_ok();
virtual void swap_buffers();
bool get_swap_cancel_ok() override;
void swap_buffers() override;

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);
Expand Down
20 changes: 14 additions & 6 deletions platform/javascript/engine/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Function('return this')()['Engine'] = (function() {
this.resizeCanvasOnStart = false;
this.onExecute = null;
this.onExit = null;
this.persistentPaths = [];
};

Engine.prototype.init = /** @param {string=} basePath */ function(basePath) {
Expand All @@ -56,12 +57,14 @@ Function('return this')()['Engine'] = (function() {
config['locateFile'] = Utils.createLocateRewrite(loadPath);
config['instantiateWasm'] = Utils.createInstantiatePromise(loadPromise);
Godot(config).then(function(module) {
me.rtenv = module;
if (unloadAfterInit) {
unload();
}
resolve();
config = null;
module['initFS'](me.persistentPaths).then(function(fs_err) {
me.rtenv = module;
if (unloadAfterInit) {
unload();
}
resolve();
config = null;
});
});
});
return initPromise;
Expand Down Expand Up @@ -220,6 +223,10 @@ Function('return this')()['Engine'] = (function() {
this.rtenv['copyToFS'](path, buffer);
};

Engine.prototype.setPersistentPaths = function(persistentPaths) {
this.persistentPaths = persistentPaths;
};

// Closure compiler exported engine methods.
/** @export */
Engine['isWebGLAvailable'] = Utils.isWebGLAvailable;
Expand All @@ -241,5 +248,6 @@ Function('return this')()['Engine'] = (function() {
Engine.prototype['setOnExecute'] = Engine.prototype.setOnExecute;
Engine.prototype['setOnExit'] = Engine.prototype.setOnExit;
Engine.prototype['copyToFS'] = Engine.prototype.copyToFS;
Engine.prototype['setPersistentPaths'] = Engine.prototype.setPersistentPaths;
return Engine;
})();
2 changes: 2 additions & 0 deletions platform/javascript/export/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_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_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_ARGS", flags_json);
str_export += current_line + "\n";
Expand Down Expand Up @@ -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::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::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/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
}
Expand Down
Loading