diff options
Diffstat (limited to 'platform/javascript')
-rw-r--r-- | platform/javascript/audio_driver_javascript.cpp | 6 | ||||
-rw-r--r-- | platform/javascript/detect.py | 5 | ||||
-rw-r--r-- | platform/javascript/export/export.cpp | 55 | ||||
-rw-r--r-- | platform/javascript/http_request.js | 3 | ||||
-rw-r--r-- | platform/javascript/id_handler.js | 5 | ||||
-rw-r--r-- | platform/javascript/os_javascript.cpp | 70 | ||||
-rw-r--r-- | platform/javascript/os_javascript.h | 2 |
7 files changed, 93 insertions, 53 deletions
diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp index 4144eb3499..f1bc7c4382 100644 --- a/platform/javascript/audio_driver_javascript.cpp +++ b/platform/javascript/audio_driver_javascript.cpp @@ -63,7 +63,7 @@ void AudioDriverJavaScript::mix_to_js() { void AudioDriverJavaScript::process_capture(float sample) { int32_t sample32 = int32_t(sample * 32768.f) * (1U << 16); - capture_buffer_write(sample32); + input_buffer_write(sample32); } Error AudioDriverJavaScript::init() { @@ -198,7 +198,7 @@ void AudioDriverJavaScript::finish() { Error AudioDriverJavaScript::capture_start() { - capture_buffer_init(buffer_length); + input_buffer_init(buffer_length); /* clang-format off */ EM_ASM({ @@ -245,6 +245,8 @@ Error AudioDriverJavaScript::capture_stop() { }); /* clang-format on */ + input_buffer.clear(); + return OK; } diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 7bf3e1bc1d..1766833364 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -131,6 +131,11 @@ def configure(env): env.Append(LINKFLAGS=['-s', 'BINARYEN=1']) + # Only include the JavaScript support code for the web environment + # (i.e. exclude Node.js and other unused environments). + # This makes the JavaScript support code about 4 KB smaller. + env.Append(LINKFLAGS=['-s', 'ENVIRONMENT=web']) + # This needs to be defined for Emscripten using 'fastcomp' (default pre-1.39.0) # and undefined if using 'upstream'. And to make things simple, earlier # Emscripten versions didn't include 'fastcomp' in their path, so we check diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 9b93d4f140..c1cb8bcb58 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -86,7 +86,7 @@ public: ERR_FAIL_COND_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", "Invalid method or HTTP version."); String filepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export"); - String basereq = "/tmp_js_export"; + const String basereq = "/tmp_js_export"; String ctype = ""; if (req[1] == basereq + ".html") { filepath += ".html"; @@ -97,8 +97,13 @@ public: } else if (req[1] == basereq + ".pck") { filepath += ".pck"; ctype = "application/octet-stream"; - } else if (req[1] == basereq + ".png") { - filepath += ".png"; + } else if (req[1] == basereq + ".png" || req[1] == "/favicon.png") { + // Also allow serving the generated favicon for a smoother loading experience. + if (req[1] == "/favicon.png") { + filepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("favicon.png"); + } else { + filepath += ".png"; + } ctype = "image/png"; } else if (req[1] == basereq + ".wasm") { filepath += ".wasm"; @@ -470,11 +475,10 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese } Ref<Image> splash; - String splash_path = GLOBAL_GET("application/boot_splash/image"); - splash_path = splash_path.strip_edges(); + const String splash_path = String(GLOBAL_GET("application/boot_splash/image")).strip_edges(); if (!splash_path.empty()) { splash.instance(); - Error err = splash->load(splash_path); + const Error err = splash->load(splash_path); if (err) { EditorNode::get_singleton()->show_warning(TTR("Could not read boot splash image file:") + "\n" + splash_path + "\n" + TTR("Using default boot splash image.")); splash.unref(); @@ -483,11 +487,32 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese if (splash.is_null()) { splash = Ref<Image>(memnew(Image(boot_splash_png))); } - String png_path = p_path.get_base_dir().plus_file(p_path.get_file().get_basename() + ".png"); - if (splash->save_png(png_path) != OK) { - EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + png_path); + const String splash_png_path = p_path.get_base_dir().plus_file(p_path.get_file().get_basename() + ".png"); + if (splash->save_png(splash_png_path) != OK) { + EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + splash_png_path); return ERR_FILE_CANT_WRITE; } + + // Save a favicon that can be accessed without waiting for the project to finish loading. + // This way, the favicon can be displayed immediately when loading the page. + Ref<Image> favicon; + const String favicon_path = String(GLOBAL_GET("application/config/icon")).strip_edges(); + if (!favicon_path.empty()) { + favicon.instance(); + const Error err = favicon->load(favicon_path); + if (err) { + favicon.unref(); + } + } + + if (favicon.is_valid()) { + const String favicon_png_path = p_path.get_base_dir().plus_file("favicon.png"); + if (favicon->save_png(favicon_png_path) != OK) { + EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + favicon_png_path); + return ERR_FILE_CANT_WRITE; + } + } + return OK; } @@ -536,9 +561,8 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese return OK; } - String basepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export"); - String path = basepath + ".html"; - Error err = export_project(p_preset, true, path, p_debug_flags); + const String basepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export"); + Error err = export_project(p_preset, true, basepath + ".html", p_debug_flags); if (err != OK) { // Export generates several files, clean them up on failure. DirAccess::remove_file_or_error(basepath + ".html"); @@ -546,13 +570,14 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese DirAccess::remove_file_or_error(basepath + ".pck"); DirAccess::remove_file_or_error(basepath + ".png"); DirAccess::remove_file_or_error(basepath + ".wasm"); + DirAccess::remove_file_or_error(EditorSettings::get_singleton()->get_cache_dir().plus_file("favicon.png")); return err; } - IP_Address bind_ip; - uint16_t bind_port = EDITOR_GET("export/web/http_port"); + const uint16_t bind_port = EDITOR_GET("export/web/http_port"); // Resolve host if needed. - String bind_host = EDITOR_GET("export/web/http_host"); + const String bind_host = EDITOR_GET("export/web/http_host"); + IP_Address bind_ip; if (bind_host.is_valid_ip_address()) { bind_ip = bind_host; } else { diff --git a/platform/javascript/http_request.js b/platform/javascript/http_request.js index c112039d0b..f621689f9d 100644 --- a/platform/javascript/http_request.js +++ b/platform/javascript/http_request.js @@ -3,9 +3,10 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/platform/javascript/id_handler.js b/platform/javascript/id_handler.js index 36ef5aa8ef..3851123ed1 100644 --- a/platform/javascript/id_handler.js +++ b/platform/javascript/id_handler.js @@ -3,9 +3,10 @@ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ -/* http://www.godotengine.org */ +/* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 592def8011..34dce90b6b 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -49,6 +49,7 @@ #define DOM_BUTTON_RIGHT 2 #define DOM_BUTTON_XBUTTON1 3 #define DOM_BUTTON_XBUTTON2 4 +#define GODOT_CANVAS_SELECTOR "#canvas" // Window (canvas) @@ -70,18 +71,23 @@ static bool is_canvas_focused() { /* clang-format on */ } -static Point2 correct_canvas_position(int x, int y) { +static Point2 compute_position_in_canvas(int x, int y) { + int canvas_x = EM_ASM_INT({ + return document.getElementById('canvas').getBoundingClientRect().x; + }); + int canvas_y = EM_ASM_INT({ + return document.getElementById('canvas').getBoundingClientRect().y; + }); int canvas_width; int canvas_height; - emscripten_get_canvas_element_size(NULL, &canvas_width, &canvas_height); + emscripten_get_canvas_element_size(GODOT_CANVAS_SELECTOR, &canvas_width, &canvas_height); double element_width; double element_height; - emscripten_get_element_css_size(NULL, &element_width, &element_height); + emscripten_get_element_css_size(GODOT_CANVAS_SELECTOR, &element_width, &element_height); - x = (int)(canvas_width / element_width * x); - y = (int)(canvas_height / element_height * y); - return Point2(x, y); + return Point2((int)(canvas_width / element_width * (x - canvas_x)), + (int)(canvas_height / element_height * (y - canvas_y))); } static bool cursor_inside_canvas = true; @@ -135,14 +141,14 @@ void OS_JavaScript::set_window_size(const Size2 p_size) { emscripten_exit_soft_fullscreen(); window_maximized = false; } - emscripten_set_canvas_element_size(NULL, p_size.x, p_size.y); + emscripten_set_canvas_element_size(GODOT_CANVAS_SELECTOR, p_size.x, p_size.y); } } Size2 OS_JavaScript::get_window_size() const { int canvas[2]; - emscripten_get_canvas_element_size(NULL, canvas, canvas + 1); + emscripten_get_canvas_element_size(GODOT_CANVAS_SELECTOR, canvas, canvas + 1); return Size2(canvas[0], canvas[1]); } @@ -162,7 +168,7 @@ void OS_JavaScript::set_window_maximized(bool p_enabled) { strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.canvasResizedCallback = NULL; - emscripten_enter_soft_fullscreen(NULL, &strategy); + emscripten_enter_soft_fullscreen(GODOT_CANVAS_SELECTOR, &strategy); window_maximized = p_enabled; } } @@ -191,7 +197,7 @@ void OS_JavaScript::set_window_fullscreen(bool p_enabled) { strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.canvasResizedCallback = NULL; - EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(NULL, false, &strategy); + EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(GODOT_CANVAS_SELECTOR, false, &strategy); ERR_FAIL_COND_MSG(result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED, "Enabling fullscreen is only possible from an input callback for the HTML5 platform."); ERR_FAIL_COND_MSG(result != EMSCRIPTEN_RESULT_SUCCESS, "Enabling fullscreen is only possible from an input callback for the HTML5 platform."); // Not fullscreen yet, so prevent "windowed" canvas dimensions from @@ -298,7 +304,7 @@ EM_BOOL OS_JavaScript::mouse_button_callback(int p_event_type, const EmscriptenM Ref<InputEventMouseButton> ev; ev.instance(); ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_MOUSEDOWN); - ev->set_position(correct_canvas_position(p_event->canvasX, p_event->canvasY)); + ev->set_position(compute_position_in_canvas(p_event->clientX, p_event->clientY)); ev->set_global_position(ev->get_position()); dom2godot_mod(p_event, ev); @@ -363,7 +369,7 @@ EM_BOOL OS_JavaScript::mousemove_callback(int p_event_type, const EmscriptenMous OS_JavaScript *os = get_singleton(); int input_mask = os->input->get_mouse_button_mask(); - Point2 pos = correct_canvas_position(p_event->canvasX, p_event->canvasY); + Point2 pos = compute_position_in_canvas(p_event->clientX, p_event->clientY); // For motion outside the canvas, only read mouse movement if dragging // started inside the canvas; imitating desktop app behaviour. if (!cursor_inside_canvas && !input_mask) @@ -697,7 +703,7 @@ EM_BOOL OS_JavaScript::touch_press_callback(int p_event_type, const EmscriptenTo if (!touch.isChanged) continue; ev->set_index(touch.identifier); - ev->set_position(correct_canvas_position(touch.canvasX, touch.canvasY)); + ev->set_position(compute_position_in_canvas(touch.clientX, touch.clientY)); os->touches[i] = ev->get_position(); ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_TOUCHSTART); @@ -722,7 +728,7 @@ EM_BOOL OS_JavaScript::touchmove_callback(int p_event_type, const EmscriptenTouc if (!touch.isChanged) continue; ev->set_index(touch.identifier); - ev->set_position(correct_canvas_position(touch.canvasX, touch.canvasY)); + ev->set_position(compute_position_in_canvas(touch.clientX, touch.clientY)); Point2 &prev = os->touches[i]; ev->set_relative(ev->get_position() - prev); prev = ev->get_position(); @@ -921,7 +927,7 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, } } - EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(NULL, &attributes); + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(GODOT_CANVAS_SELECTOR, &attributes); if (emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS) { gl_initialization_error = true; } @@ -974,7 +980,7 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, EMSCRIPTEN_RESULT result; #define EM_CHECK(ev) \ if (result != EMSCRIPTEN_RESULT_SUCCESS) \ - ERR_PRINTS("Error while setting " #ev " callback: Code " + itos(result)) + ERR_PRINT("Error while setting " #ev " callback: Code " + itos(result)); #define SET_EM_CALLBACK(target, ev, cb) \ result = emscripten_set_##ev##_callback(target, NULL, true, &cb); \ EM_CHECK(ev) @@ -984,21 +990,21 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, // 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("#window", mousemove, mousemove_callback) - SET_EM_CALLBACK("#canvas", mousedown, mouse_button_callback) - SET_EM_CALLBACK("#window", mouseup, mouse_button_callback) - SET_EM_CALLBACK("#window", wheel, wheel_callback) - SET_EM_CALLBACK("#window", touchstart, touch_press_callback) - SET_EM_CALLBACK("#window", touchmove, touchmove_callback) - SET_EM_CALLBACK("#window", touchend, touch_press_callback) - SET_EM_CALLBACK("#window", touchcancel, touch_press_callback) - SET_EM_CALLBACK("#canvas", keydown, keydown_callback) - SET_EM_CALLBACK("#canvas", keypress, keypress_callback) - SET_EM_CALLBACK("#canvas", keyup, keyup_callback) - SET_EM_CALLBACK(NULL, fullscreenchange, fullscreen_change_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mousemove, mousemove_callback) + SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, mousedown, mouse_button_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mouseup, mouse_button_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, wheel, wheel_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchstart, touch_press_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchmove, touchmove_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchend, touch_press_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchcancel, touch_press_callback) + SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keydown, keydown_callback) + SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keypress, keypress_callback) + SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keyup, keyup_callback) + SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, fullscreenchange, fullscreen_change_callback) SET_EM_CALLBACK_NOTARGET(gamepadconnected, gamepad_change_callback) SET_EM_CALLBACK_NOTARGET(gamepaddisconnected, gamepad_change_callback) -#undef SET_EM_CALLBACK_NODATA +#undef SET_EM_CALLBACK_NOTARGET #undef SET_EM_CALLBACK #undef EM_CHECK @@ -1079,15 +1085,15 @@ bool OS_JavaScript::main_loop_iterate() { strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.canvasResizedCallback = NULL; - emscripten_enter_soft_fullscreen(NULL, &strategy); + emscripten_enter_soft_fullscreen(GODOT_CANVAS_SELECTOR, &strategy); } else { - emscripten_set_canvas_element_size(NULL, windowed_size.width, windowed_size.height); + emscripten_set_canvas_element_size(GODOT_CANVAS_SELECTOR, windowed_size.width, windowed_size.height); } just_exited_fullscreen = false; } int canvas[2]; - emscripten_get_canvas_element_size(NULL, canvas, canvas + 1); + emscripten_get_canvas_element_size(GODOT_CANVAS_SELECTOR, canvas, canvas + 1); video_mode.width = canvas[0]; video_mode.height = canvas[1]; if (!window_maximized && !video_mode.fullscreen && !just_exited_fullscreen && !entering_fullscreen) { diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 2d1c765e76..5c02a292ee 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -141,7 +141,7 @@ public: void run_async(); bool main_loop_iterate(); - virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL); + virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL); virtual Error kill(const ProcessID &p_pid); virtual int get_process_id() const; |