diff options
Diffstat (limited to 'platform/javascript')
21 files changed, 353 insertions, 91 deletions
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index a93c98a89f..85a633442e 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -20,6 +20,13 @@ for lib in js_libraries:      env.Append(LINKFLAGS=['--js-library', env.File(lib).path])  env.Depends(build, js_libraries) +js_modules = [ +    'id_handler.js', +] +for module in js_modules: +    env.Append(LINKFLAGS=['--pre-js', env.File(module).path]) +env.Depends(build, js_modules) +  wrapper_start = env.File('pre.js')  wrapper_end = env.File('engine.js')  js_wrapped = env.Textfile('#bin/godot', [wrapper_start, js, wrapper_end], TEXTFILESUFFIX='${PROGSUFFIX}.wrapped.js') diff --git a/platform/javascript/api/api.cpp b/platform/javascript/api/api.cpp index c7a6d53561..d4dc43d57c 100644 --- a/platform/javascript/api/api.cpp +++ b/platform/javascript/api/api.cpp @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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/api/api.h b/platform/javascript/api/api.h index 5f22f082e9..52d87528f6 100644 --- a/platform/javascript/api/api.h +++ b/platform/javascript/api/api.h @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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/api/javascript_eval.h b/platform/javascript/api/javascript_eval.h index 49d5309737..49e460fffd 100644 --- a/platform/javascript/api/javascript_eval.h +++ b/platform/javascript/api/javascript_eval.h @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp index a5b627b8dc..11104007e2 100644 --- a/platform/javascript/audio_driver_javascript.cpp +++ b/platform/javascript/audio_driver_javascript.cpp @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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       */ @@ -146,6 +146,15 @@ void AudioDriverJavaScript::start() {  	/* clang-format on */  } +void AudioDriverJavaScript::resume() { +	/* clang-format off */ +	EM_ASM({ +		if (_audioDriver_audioContext.resume) +			_audioDriver_audioContext.resume(); +	}); +	/* clang-format on */ +} +  int AudioDriverJavaScript::get_mix_rate() const {  	/* clang-format off */ @@ -200,7 +209,7 @@ Error AudioDriverJavaScript::capture_start() {  		}  		function gotMediaInputError(e) { -			console.log(e); +			out(e);  		}  		if (navigator.mediaDevices.getUserMedia) { diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h index c8aeb0b446..9dcba02c96 100644 --- a/platform/javascript/audio_driver_javascript.h +++ b/platform/javascript/audio_driver_javascript.h @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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       */ @@ -49,6 +49,7 @@ public:  	virtual Error init();  	virtual void start(); +	void resume();  	virtual int get_mix_rate() const;  	virtual SpeakerMode get_speaker_mode() const;  	virtual void lock(); diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 22b5f1f87a..145ac42863 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -1,5 +1,4 @@  import os -import sys  def is_active(): @@ -104,17 +103,19 @@ def configure(env):      ## Compile flags -    env.Append(CPPPATH=['#platform/javascript']) +    env.Prepend(CPPPATH=['#platform/javascript'])      env.Append(CPPDEFINES=['JAVASCRIPT_ENABLED', 'UNIX_ENABLED'])      # No multi-threading (SharedArrayBuffer) available yet,      # once feasible also consider memory buffer size issues.      env.Append(CPPDEFINES=['NO_THREADS']) -    # These flags help keep the file size down. -    env.Append(CCFLAGS=['-fno-exceptions', '-fno-rtti']) -    # Don't use dynamic_cast, necessary with no-rtti. -    env.Append(CPPDEFINES=['NO_SAFE_CAST']) +    # Disable exceptions and rtti on non-tools (template) builds +    if not env['tools']: +        # These flags help keep the file size down. +        env.Append(CCFLAGS=['-fno-exceptions', '-fno-rtti']) +        # Don't use dynamic_cast, necessary with no-rtti. +        env.Append(CPPDEFINES=['NO_SAFE_CAST'])      if env['javascript_eval']:          env.Append(CPPDEFINES=['JAVASCRIPT_EVAL_ENABLED']) @@ -129,10 +130,6 @@ def configure(env):      # us since we don't know requirements at compile-time.      env.Append(LINKFLAGS=['-s', 'ALLOW_MEMORY_GROWTH=1']) -    # Since we use both memory growth and MEMFS preloading, -    # this avoids unecessary copying on start-up. -    env.Append(LINKFLAGS=['--no-heap-copy']) -      # This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1.      env.Append(LINKFLAGS=['-s', 'USE_WEBGL2=1']) @@ -140,7 +137,3 @@ def configure(env):      # TODO: Reevaluate usage of this setting now that engine.js manages engine runtime.      env.Append(LINKFLAGS=['-s', 'NO_EXIT_RUNTIME=1']) - -    # TODO: Move that to opus module's config. -    if 'module_opus_enabled' in env and env['module_opus_enabled']: -        env.opus_fixed_point = 'yes' diff --git a/platform/javascript/dom_keys.inc b/platform/javascript/dom_keys.inc index a30818decc..bf99ea5d42 100644 --- a/platform/javascript/dom_keys.inc +++ b/platform/javascript/dom_keys.inc @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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/engine.js b/platform/javascript/engine.js index 91458eb4c3..860d6707ff 100644 --- a/platform/javascript/engine.js +++ b/platform/javascript/engine.js @@ -199,7 +199,8 @@  					}  					LIBS.FS.mkdirTree(dir);  				} -				LIBS.FS.createDataFile('/', file.path, new Uint8Array(file.buffer), true, true, true); +				// With memory growth, canOwn should be false. +				LIBS.FS.createDataFile(file.path, null, new Uint8Array(file.buffer), true, true, false);  			}, this);  			preloadedFiles = null; diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 7a325e81dd..487da77b10 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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       */ @@ -104,22 +104,27 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re  void EditorExportPlatformJavaScript::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { -	if (p_preset->get("texture_format/s3tc")) { +	if (p_preset->get("vram_texture_compression/for_desktop")) {  		r_features->push_back("s3tc");  	} -	if (p_preset->get("texture_format/etc")) { -		r_features->push_back("etc"); -	} -	if (p_preset->get("texture_format/etc2")) { -		r_features->push_back("etc2"); + +	if (p_preset->get("vram_texture_compression/for_mobile")) { +		String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name"); +		if (driver == "GLES2") { +			r_features->push_back("etc"); +		} else if (driver == "GLES3") { +			r_features->push_back("etc2"); +			if (ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2")) { +				r_features->push_back("etc"); +			} +		}  	}  }  void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_options) { -	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true)); -	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false)); -	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), true)); +	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_desktop"), true)); // S3TC +	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::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); @@ -155,7 +160,7 @@ bool EditorExportPlatformJavaScript::can_export(const Ref<EditorExportPreset> &p  		if (FileAccess::exists(p_preset->get("custom_template/debug"))) {  			valid = true;  		} else { -			err += "Custom debug template not found.\n"; +			err += TTR("Custom debug template not found.") + "\n";  		}  	} @@ -163,14 +168,23 @@ bool EditorExportPlatformJavaScript::can_export(const Ref<EditorExportPreset> &p  		if (FileAccess::exists(p_preset->get("custom_template/release"))) {  			valid = true;  		} else { -			err += "Custom release template not found.\n"; +			err += TTR("Custom release template not found.") + "\n"; +		} +	} + +	r_missing_templates = !valid; + +	if (p_preset->get("vram_texture_compression/for_mobile")) { +		String etc_error = test_etc2(); +		if (etc_error != String()) { +			valid = false; +			err += etc_error;  		}  	}  	if (!err.empty())  		r_error = err; -	r_missing_templates = !valid;  	return valid;  } @@ -200,6 +214,10 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese  			template_path = find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE);  	} +	if (!DirAccess::exists(p_path.get_base_dir())) { +		return ERR_FILE_BAD_PATH; +	} +  	if (template_path != String() && !FileAccess::exists(template_path)) {  		EditorNode::get_singleton()->show_warning(TTR("Template file not found:") + "\n" + template_path);  		return ERR_FILE_NOT_FOUND; @@ -349,7 +367,7 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese  	if (err) {  		return err;  	} -	OS::get_singleton()->shell_open(path); +	OS::get_singleton()->shell_open(String("file://") + path);  	return OK;  } diff --git a/platform/javascript/export/export.h b/platform/javascript/export/export.h index 2835d0723f..7ebbcd6f00 100644 --- a/platform/javascript/export/export.h +++ b/platform/javascript/export/export.h @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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/http_client.h.inc b/platform/javascript/http_client.h.inc index d75d33a33a..d707d623ab 100644 --- a/platform/javascript/http_client.h.inc +++ b/platform/javascript/http_client.h.inc @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                    http://www.godotengine.org                         */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp index ccf4f8a11b..b4bab9a999 100644 --- a/platform/javascript/http_client_javascript.cpp +++ b/platform/javascript/http_client_javascript.cpp @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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/http_request.h b/platform/javascript/http_request.h index b5ff46d7fe..4a596057da 100644 --- a/platform/javascript/http_request.h +++ b/platform/javascript/http_request.h @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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/http_request.js b/platform/javascript/http_request.js index ee1c06c623..66dacfc3d4 100644 --- a/platform/javascript/http_request.js +++ b/platform/javascript/http_request.js @@ -5,7 +5,7 @@  /*                           GODOT ENGINE                                */  /*                    http://www.godotengine.org                         */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */  /*                                                                       */  /* Permission is hereby granted, free of charge, to any person obtaining */  /* a copy of this software and associated documentation files (the       */ @@ -82,7 +82,7 @@ var GodotHTTPRequest = {  	godot_xhr_send_string: function(xhrId, strPtr) {  		if (!strPtr) { -			console.warn("Failed to send string per XHR: null pointer"); +			err("Failed to send string per XHR: null pointer");  			return;  		}  		GodotHTTPRequest.requests[xhrId].send(UTF8ToString(strPtr)); @@ -90,11 +90,11 @@ var GodotHTTPRequest = {  	godot_xhr_send_data: function(xhrId, ptr, len) {  		if (!ptr) { -			console.warn("Failed to send data per XHR: null pointer"); +			err("Failed to send data per XHR: null pointer");  			return;  		}  		if (len < 0) { -			console.warn("Failed to send data per XHR: buffer length less than 0"); +			err("Failed to send data per XHR: buffer length less than 0");  			return;  		}  		GodotHTTPRequest.requests[xhrId].send(HEAPU8.subarray(ptr, ptr + len)); diff --git a/platform/javascript/id_handler.js b/platform/javascript/id_handler.js new file mode 100644 index 0000000000..36ef5aa8ef --- /dev/null +++ b/platform/javascript/id_handler.js @@ -0,0 +1,62 @@ +/*************************************************************************/ +/*  id_handler.js                                                        */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                    http://www.godotengine.org                         */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ +/*                                                                       */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the       */ +/* "Software"), to deal in the Software without restriction, including   */ +/* without limitation the rights to use, copy, modify, merge, publish,   */ +/* distribute, sublicense, and/or sell copies of the Software, and to    */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions:                                             */ +/*                                                                       */ +/* The above copyright notice and this permission notice shall be        */ +/* included in all copies or substantial portions of the Software.       */ +/*                                                                       */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ +/*************************************************************************/ + +var IDHandler = function() { + +	var ids = {}; +	var size = 0; + +	this.has = function(id) { +		return ids.hasOwnProperty(id); +	} + +	this.add = function(obj) { +		size += 1; +		var id = crypto.getRandomValues(new Int32Array(32))[0]; +		ids[id] = obj; +		return id; +	} + +	this.get = function(id) { +		return ids[id]; +	} + +	this.remove = function(id) { +		size -= 1; +		delete ids[id]; +	} + +	this.size = function() { +		return size; +	} + +	this.ids = ids; +}; + +Module.IDHandler = new IDHandler; diff --git a/platform/javascript/javascript_eval.cpp b/platform/javascript/javascript_eval.cpp index 9b8174cc71..dd3eba74e4 100644 --- a/platform/javascript/javascript_eval.cpp +++ b/platform/javascript/javascript_eval.cpp @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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       */ @@ -69,7 +69,7 @@ Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {  				eval_ret = eval(UTF8ToString(CODE));  			}  		} catch (e) { -			console.warn(e); +			err(e);  			eval_ret = null;  		} @@ -97,7 +97,7 @@ Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {  					if (array_ptr!==0) {  						_free(array_ptr)  					} -					console.warn(e); +					err(e);  					// fall through  				}  				break; diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp index ec60571402..bdf9dfe18f 100644 --- a/platform/javascript/javascript_main.cpp +++ b/platform/javascript/javascript_main.cpp @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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 9250ca4903..c69e6f0cb8 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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       */ @@ -245,6 +245,8 @@ EM_BOOL OS_JavaScript::keydown_callback(int p_event_type, const EmscriptenKeyboa  		return false;  	}  	os->input->parse_input_event(ev); +	// Resume audio context after input in case autoplay was denied. +	os->audio_driver_javascript.resume();  	return true;  } @@ -295,6 +297,30 @@ EM_BOOL OS_JavaScript::mouse_button_callback(int p_event_type, const EmscriptenM  		default: return false;  	} +	if (ev->is_pressed()) { + +		uint64_t diff = p_event->timestamp - os->last_click_ms; + +		if (ev->get_button_index() == os->last_click_button_index) { + +			if (diff < 400 && Point2(os->last_click_pos).distance_to(ev->get_position()) < 5) { + +				os->last_click_ms = 0; +				os->last_click_pos = Point2(-100, -100); +				os->last_click_button_index = -1; +				ev->set_doubleclick(true); +			} + +		} else { +			os->last_click_button_index = ev->get_button_index(); +		} + +		if (!ev->is_doubleclick()) { +			os->last_click_ms += diff; +			os->last_click_pos = ev->get_position(); +		} +	} +  	int mask = os->input->get_mouse_button_mask();  	int button_flag = 1 << (ev->get_button_index() - 1);  	if (ev->is_pressed()) { @@ -311,6 +337,8 @@ EM_BOOL OS_JavaScript::mouse_button_callback(int p_event_type, const EmscriptenM  	ev->set_button_mask(mask);  	os->input->parse_input_event(ev); +	// Resume audio context after input in case autoplay was denied. +	os->audio_driver_javascript.resume();  	// Prevent multi-click text selection and wheel-click scrolling anchor.  	// Context menu is prevented through contextmenu event.  	return true; @@ -391,12 +419,134 @@ void OS_JavaScript::set_cursor_shape(CursorShape p_shape) {  	ERR_FAIL_INDEX(p_shape, CURSOR_MAX); +	if (get_mouse_mode() == MOUSE_MODE_VISIBLE) { +		if (cursors[p_shape] != "") { +			Vector<String> url = cursors[p_shape].split("?"); +			set_css_cursor(("url(\"" + url[0] + "\") " + url[1] + ", auto").utf8()); +		} else { +			set_css_cursor(godot2dom_cursor(p_shape)); +		} +	} +  	cursor_shape = p_shape; -	if (get_mouse_mode() != MOUSE_MODE_HIDDEN) -		set_css_cursor(godot2dom_cursor(cursor_shape));  }  void OS_JavaScript::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + +	if (p_cursor.is_valid()) { +		Ref<Texture> texture = p_cursor; +		Ref<AtlasTexture> atlas_texture = p_cursor; +		Ref<Image> image; +		Size2 texture_size; +		Rect2 atlas_rect; + +		if (texture.is_valid()) { +			image = texture->get_data(); +			if (image.is_valid()) { +				image->duplicate(); +			} +		} + +		if (!image.is_valid() && atlas_texture.is_valid()) { +			texture = atlas_texture->get_atlas(); + +			atlas_rect.size.width = texture->get_width(); +			atlas_rect.size.height = texture->get_height(); +			atlas_rect.position.x = atlas_texture->get_region().position.x; +			atlas_rect.position.y = atlas_texture->get_region().position.y; + +			texture_size.width = atlas_texture->get_region().size.x; +			texture_size.height = atlas_texture->get_region().size.y; +		} else if (image.is_valid()) { +			texture_size.width = texture->get_width(); +			texture_size.height = texture->get_height(); +		} + +		ERR_FAIL_COND(!texture.is_valid()); +		ERR_FAIL_COND(p_hotspot.x < 0 || p_hotspot.y < 0); +		ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256); +		ERR_FAIL_COND(p_hotspot.x > texture_size.width || p_hotspot.y > texture_size.height); + +		image = texture->get_data(); + +		ERR_FAIL_COND(!image.is_valid()); + +		image = image->duplicate(); + +		if (atlas_texture.is_valid()) +			image->crop_from_point( +					atlas_rect.position.x, +					atlas_rect.position.y, +					texture_size.width, +					texture_size.height); + +		if (image->get_format() != Image::FORMAT_RGBA8) { +			image->convert(Image::FORMAT_RGBA8); +		} + +		png_image png_meta; +		memset(&png_meta, 0, sizeof png_meta); +		png_meta.version = PNG_IMAGE_VERSION; +		png_meta.width = texture_size.width; +		png_meta.height = texture_size.height; +		png_meta.format = PNG_FORMAT_RGBA; + +		PoolByteArray png; +		size_t len; +		PoolByteArray::Read r = image->get_data().read(); +		ERR_FAIL_COND(!png_image_write_get_memory_size(png_meta, len, 0, r.ptr(), 0, NULL)); + +		png.resize(len); +		PoolByteArray::Write w = png.write(); +		ERR_FAIL_COND(!png_image_write_to_memory(&png_meta, w.ptr(), &len, 0, r.ptr(), 0, NULL)); +		w = PoolByteArray::Write(); + +		r = png.read(); + +		char *object_url; +		/* clang-format off */ +		EM_ASM({ +			var PNG_PTR = $0; +			var PNG_LEN = $1; +			var PTR = $2; + +			var png = new Blob([HEAPU8.slice(PNG_PTR, PNG_PTR + PNG_LEN)], { type: 'image/png' }); +			var url = URL.createObjectURL(png); +			var length_bytes = lengthBytesUTF8(url) + 1; +			var string_on_wasm_heap = _malloc(length_bytes); +			setValue(PTR, string_on_wasm_heap, '*'); +			stringToUTF8(url, string_on_wasm_heap, length_bytes); +		}, r.ptr(), len, &object_url); +		/* clang-format on */ +		r = PoolByteArray::Read(); + +		String url = String::utf8(object_url) + "?" + itos(p_hotspot.x) + " " + itos(p_hotspot.y); + +		/* clang-format off */ +		EM_ASM({ _free($0); }, object_url); +		/* clang-format on */ + +		if (cursors[p_shape] != "") { +			/* clang-format off */ +			EM_ASM({ +				URL.revokeObjectURL(UTF8ToString($0).split('?')[0]); +			}, cursors[p_shape].utf8().get_data()); +			/* clang-format on */ +			cursors[p_shape] = ""; +		} + +		cursors[p_shape] = url; + +	} else if (cursors[p_shape] != "") { +		/* clang-format off */ +		EM_ASM({ +			URL.revokeObjectURL(UTF8ToString($0).split('?')[0]); +		}, cursors[p_shape].utf8().get_data()); +		/* clang-format on */ +		cursors[p_shape] = ""; +	} + +	set_cursor_shape(cursor_shape);  }  void OS_JavaScript::set_mouse_mode(OS::MouseMode p_mode) { @@ -408,7 +558,9 @@ void OS_JavaScript::set_mouse_mode(OS::MouseMode p_mode) {  	if (p_mode == MOUSE_MODE_VISIBLE) { +		// set_css_cursor must be called before set_cursor_shape to make the cursor visible  		set_css_cursor(godot2dom_cursor(cursor_shape)); +		set_cursor_shape(cursor_shape);  		emscripten_exit_pointerlock();  	} else if (p_mode == MOUSE_MODE_HIDDEN) { @@ -422,7 +574,9 @@ void OS_JavaScript::set_mouse_mode(OS::MouseMode p_mode) {  		ERR_EXPLAIN("MOUSE_MODE_CAPTURED can only be entered from within an appropriate input callback");  		ERR_FAIL_COND(result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED);  		ERR_FAIL_COND(result != EMSCRIPTEN_RESULT_SUCCESS); +		// set_css_cursor must be called before set_cursor_shape to make the cursor visible  		set_css_cursor(godot2dom_cursor(cursor_shape)); +		set_cursor_shape(cursor_shape);  	}  } @@ -452,7 +606,6 @@ EM_BOOL OS_JavaScript::wheel_callback(int p_event_type, const EmscriptenWheelEve  	InputDefault *input = get_singleton()->input;  	Ref<InputEventMouseButton> ev;  	ev.instance(); -	ev->set_button_mask(input->get_mouse_button_mask());  	ev->set_position(input->get_mouse_position());  	ev->set_global_position(ev->get_position()); @@ -475,10 +628,14 @@ EM_BOOL OS_JavaScript::wheel_callback(int p_event_type, const EmscriptenWheelEve  	// Different browsers give wildly different delta values, and we can't  	// interpret deltaMode, so use default value for wheel events' factor. +	int button_flag = 1 << (ev->get_button_index() - 1); +  	ev->set_pressed(true); +	ev->set_button_mask(input->get_mouse_button_mask() | button_flag);  	input->parse_input_event(ev);  	ev->set_pressed(false); +	ev->set_button_mask(input->get_mouse_button_mask() & ~button_flag);  	input->parse_input_event(ev);  	return true; @@ -515,6 +672,8 @@ EM_BOOL OS_JavaScript::touch_press_callback(int p_event_type, const EmscriptenTo  		os->input->parse_input_event(ev);  	} +	// Resume audio context after input in case autoplay was denied. +	os->audio_driver_javascript.resume();  	return true;  } @@ -670,7 +829,7 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver,  				RasterizerGLES3::make_current();  				break;  			} else { -				if (GLOBAL_GET("rendering/quality/driver/driver_fallback") == "Best") { +				if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2")) {  					p_video_driver = VIDEO_DRIVER_GLES2;  					gles3 = false;  					continue; @@ -707,8 +866,21 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver,  	video_driver_index = p_video_driver;  	video_mode = p_desired; -	// Can't fulfill fullscreen request during start-up due to browser security. +	// fullscreen_change_callback will correct this if the request is successful.  	video_mode.fullscreen = false; +	// Emscripten only attempts fullscreen requests if the user input callback +	// was registered through one its own functions, so request manually for +	// start-up fullscreen. +	if (p_desired.fullscreen) { +		/* clang-format off */ +		EM_ASM({ +			(canvas.requestFullscreen || canvas.msRequestFullscreen || +				canvas.mozRequestFullScreen || canvas.mozRequestFullscreen || +				canvas.webkitRequestFullscreen +			).call(canvas); +		}); +		/* clang-format on */ +	}  	/* clang-format off */  	if (EM_ASM_INT_V({ return Module.resizeCanvasOnStart })) {  		/* clang-format on */ @@ -814,15 +986,16 @@ bool OS_JavaScript::main_loop_iterate() {  		if (sync_wait_time < 0) {  			/* clang-format off */  			EM_ASM( -				FS.syncfs(function(err) { -					if (err) { console.warn('Failed to save IDB file system: ' + err.message); } +				FS.syncfs(function(error) { +					if (error) { err('Failed to save IDB file system: ' + error.message); }  				});  			);  			/* clang-format on */  		}  	} -	process_joypads(); +	if (emscripten_sample_gamepad_data() == EMSCRIPTEN_RESULT_SUCCESS) +		process_joypads();  	if (just_exited_fullscreen) {  		if (window_maximized) { @@ -862,7 +1035,7 @@ void OS_JavaScript::finalize() {  // Miscellaneous -Error OS_JavaScript::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { +Error OS_JavaScript::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {  	ERR_EXPLAIN("OS::execute() is not available on the HTML5 platform");  	ERR_FAIL_V(ERR_UNAVAILABLE); @@ -898,16 +1071,6 @@ bool OS_JavaScript::_check_internal_feature_support(const String &p_feature) {  		return true;  #endif -	EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_get_current_context(); -	// All extensions are already automatically enabled, this function allows -	// checking WebGL extension support without inline JavaScript -	if (p_feature == "s3tc") -		return emscripten_webgl_enable_extension(ctx, "WEBGL_compressed_texture_s3tc_srgb"); -	if (p_feature == "etc") -		return emscripten_webgl_enable_extension(ctx, "WEBGL_compressed_texture_etc1"); -	if (p_feature == "etc2") -		return emscripten_webgl_enable_extension(ctx, "WEBGL_compressed_texture_etc"); -  	return false;  } @@ -996,7 +1159,7 @@ Error OS_JavaScript::shell_open(String p_uri) {  	return OK;  } -String OS_JavaScript::get_name() { +String OS_JavaScript::get_name() const {  	return "HTML5";  } @@ -1067,6 +1230,10 @@ OS_JavaScript::OS_JavaScript(int p_argc, char *p_argv[]) {  	}  	set_cmdline(p_argv[0], arguments); +	last_click_button_index = -1; +	last_click_ms = 0; +	last_click_pos = Point2(-100, -100); +  	window_maximized = false;  	entering_fullscreen = false;  	just_exited_fullscreen = false; diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 79dac5940f..a0c7c31f2d 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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       */ @@ -50,9 +50,15 @@ class OS_JavaScript : public OS_Unix {  	InputDefault *input;  	Ref<InputEventKey> deferred_key_event;  	CursorShape cursor_shape; +	String cursors[CURSOR_MAX];  	Point2 touches[32]; +	Point2i last_click_pos; +	uint64_t last_click_ms; +	int last_click_button_index; +  	MainLoop *main_loop; +	int video_driver_index;  	AudioDriverJavaScript audio_driver_javascript;  	bool idb_available; @@ -80,8 +86,6 @@ class OS_JavaScript : public OS_Unix {  	static void file_access_close_callback(const String &p_file, int p_flags); -	int video_driver_index; -  protected:  	virtual int get_current_video_driver() const; @@ -133,7 +137,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); +	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 kill(const ProcessID &p_pid);  	virtual int get_process_id() const; @@ -142,7 +146,7 @@ public:  	virtual void set_icon(const Ref<Image> &p_icon);  	String get_executable_path() const;  	virtual Error shell_open(String p_uri); -	virtual String get_name(); +	virtual String get_name() const;  	virtual bool can_draw() const;  	virtual String get_resource_dir() const; diff --git a/platform/javascript/platform_config.h b/platform/javascript/platform_config.h index af4cf07393..baba6325b3 100644 --- a/platform/javascript/platform_config.h +++ b/platform/javascript/platform_config.h @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2019 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       */  |