diff options
Diffstat (limited to 'platform/javascript')
-rw-r--r-- | platform/javascript/README.md | 15 | ||||
-rw-r--r-- | platform/javascript/api/javascript_tools_editor_plugin.cpp | 32 | ||||
-rw-r--r-- | platform/javascript/display_server_javascript.cpp | 21 | ||||
-rw-r--r-- | platform/javascript/export/export_plugin.h | 2 | ||||
-rw-r--r-- | platform/javascript/os_javascript.cpp | 4 |
5 files changed, 64 insertions, 10 deletions
diff --git a/platform/javascript/README.md b/platform/javascript/README.md new file mode 100644 index 0000000000..f181bea9e0 --- /dev/null +++ b/platform/javascript/README.md @@ -0,0 +1,15 @@ +# HTML5 platform port + +This folder contains the C++ and JavaScript code for the HTML5/WebAssembly platform port, +compiled using [Emscripten](https://emscripten.org/). + +It also contains a ESLint linting setup (see [`package.json`](package.json)). + +See also [`misc/dist/html`](/misc/dist/html) folder for files used by this platform +such as the HTML5 shell. + +## Artwork license + +[`logo.png`](logo.png) and [`run_icon.png`](run_icon.png) are licensed under +[Creative Commons Attribution 3.0 Unported](https://www.w3.org/html/logo/faq.html#how-licenced) +per the HTML5 logo usage guidelines. diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp index 54f541f607..45a2cd595a 100644 --- a/platform/javascript/api/javascript_tools_editor_plugin.cpp +++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp @@ -35,6 +35,7 @@ #include "core/config/project_settings.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" +#include "core/os/time.h" #include "editor/editor_node.h" #include <emscripten/emscripten.h> @@ -58,23 +59,40 @@ JavaScriptToolsEditorPlugin::JavaScriptToolsEditorPlugin(EditorNode *p_editor) { void JavaScriptToolsEditorPlugin::_download_zip(Variant p_v) { if (!Engine::get_singleton() || !Engine::get_singleton()->is_editor_hint()) { - WARN_PRINT("Project download is only available in Editor mode"); + ERR_PRINT("Downloading the project as a ZIP archive is only available in Editor mode."); return; } String resource_path = ProjectSettings::get_singleton()->get_resource_path(); FileAccess *src_f; zlib_filefunc_def io = zipio_create_io_from_file(&src_f); - zipFile zip = zipOpen2("/tmp/project.zip", APPEND_STATUS_CREATE, nullptr, &io); - String base_path = resource_path.substr(0, resource_path.rfind("/")) + "/"; + + // Name the downloded ZIP file to contain the project name and download date for easier organization. + // Replace characters not allowed (or risky) in Windows file names with safe characters. + // In the project name, all invalid characters become an empty string so that a name + // like "Platformer 2: Godette's Revenge" becomes "platformer_2-_godette-s_revenge". + const String project_name = GLOBAL_GET("application/config/name"); + const String project_name_safe = project_name.to_lower().replace(" ", "_"); + const String datetime_safe = + Time::get_singleton()->get_datetime_string_from_system(false, true).replace(" ", "_"); + const String output_name = OS::get_singleton()->get_safe_dir_name(vformat("%s_%s.zip")); + const String output_path = String("/tmp").plus_file(output_name); + + zipFile zip = zipOpen2(output_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io); + const String base_path = resource_path.substr(0, resource_path.rfind("/")) + "/"; _zip_recursive(resource_path, base_path, zip); zipClose(zip, nullptr); - FileAccess *f = FileAccess::open("/tmp/project.zip", FileAccess::READ); - ERR_FAIL_COND_MSG(!f, "Unable to create zip file"); + FileAccess *f = FileAccess::open(output_path, FileAccess::READ); + ERR_FAIL_COND_MSG(!f, "Unable to create ZIP file."); Vector<uint8_t> buf; buf.resize(f->get_length()); f->get_buffer(buf.ptrw(), buf.size()); - godot_js_os_download_buffer(buf.ptr(), buf.size(), "project.zip", "application/zip"); + godot_js_os_download_buffer(buf.ptr(), buf.size(), output_name.utf8().get_data(), "application/zip"); + + f->close(); + memdelete(f); + // Remove the temporary file since it was sent to the user's native filesystem as a download. + DirAccess::remove_file_or_error(output_path); } void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, zipFile p_zip) { @@ -108,7 +126,7 @@ void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, z void JavaScriptToolsEditorPlugin::_zip_recursive(String p_path, String p_base_path, zipFile p_zip) { DirAccess *dir = DirAccess::open(p_path); if (!dir) { - WARN_PRINT("Unable to open dir for zipping: " + p_path); + WARN_PRINT("Unable to open directory for zipping: " + p_path); return; } dir->list_dir_begin(); diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index fda18a5c19..b43614eb99 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -158,6 +158,10 @@ EM_BOOL DisplayServerJavaScript::keydown_callback(int p_event_type, const Emscri return false; } Input::get_singleton()->parse_input_event(ev); + + // Make sure to flush all events so we can call restricted APIs inside the event. + Input::get_singleton()->flush_buffered_events(); + return true; } @@ -165,6 +169,10 @@ EM_BOOL DisplayServerJavaScript::keypress_callback(int p_event_type, const Emscr DisplayServerJavaScript *display = get_singleton(); display->deferred_key_event->set_unicode(p_event->charCode); Input::get_singleton()->parse_input_event(display->deferred_key_event); + + // Make sure to flush all events so we can call restricted APIs inside the event. + Input::get_singleton()->flush_buffered_events(); + return true; } @@ -172,6 +180,10 @@ EM_BOOL DisplayServerJavaScript::keyup_callback(int p_event_type, const Emscript Ref<InputEventKey> ev = setup_key_event(p_event); ev->set_pressed(false); Input::get_singleton()->parse_input_event(ev); + + // Make sure to flush all events so we can call restricted APIs inside the event. + Input::get_singleton()->flush_buffered_events(); + return ev->get_keycode() != KEY_UNKNOWN && ev->get_keycode() != (Key)0; } @@ -245,6 +257,10 @@ EM_BOOL DisplayServerJavaScript::mouse_button_callback(int p_event_type, const E ev->set_button_mask(mask); input->parse_input_event(ev); + + // Make sure to flush all events so we can call restricted APIs inside the event. + Input::get_singleton()->flush_buffered_events(); + // Prevent multi-click text selection and wheel-click scrolling anchor. // Context menu is prevented through contextmenu event. return true; @@ -507,6 +523,10 @@ EM_BOOL DisplayServerJavaScript::touch_press_callback(int p_event_type, const Em Input::get_singleton()->parse_input_event(ev); } + + // Make sure to flush all events so we can call restricted APIs inside the event. + Input::get_singleton()->flush_buffered_events(); + // Resume audio context after input in case autoplay was denied. return true; } @@ -1019,6 +1039,7 @@ bool DisplayServerJavaScript::can_any_window_draw() const { } void DisplayServerJavaScript::process_events() { + Input::get_singleton()->flush_buffered_events(); if (godot_js_display_gamepad_sample() == OK) { process_joypads(); } diff --git a/platform/javascript/export/export_plugin.h b/platform/javascript/export/export_plugin.h index 736edfe3a8..bdd1235259 100644 --- a/platform/javascript/export/export_plugin.h +++ b/platform/javascript/export/export_plugin.h @@ -134,7 +134,7 @@ public: virtual void get_platform_features(List<String> *r_features) override { r_features->push_back("web"); - r_features->push_back(get_os_name()); + r_features->push_back(get_os_name().to_lower()); } virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override { diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 76102d941b..95c5909d50 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -137,12 +137,12 @@ int OS_JavaScript::get_processor_count() const { } bool OS_JavaScript::_check_internal_feature_support(const String &p_feature) { - if (p_feature == "HTML5" || p_feature == "web") { + if (p_feature == "html5" || p_feature == "web") { return true; } #ifdef JAVASCRIPT_EVAL_ENABLED - if (p_feature == "JavaScript") { + if (p_feature == "javascript") { return true; } #endif |