summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <rverschelde@gmail.com>2020-10-15 10:28:59 +0200
committerGitHub <noreply@github.com>2020-10-15 10:28:59 +0200
commitcb3d5b6ddaf231664b480997b9e640cc0b695c45 (patch)
treee2f85338c45019cdc924c6ed7f9a355c1d02c7c1 /platform
parent075a8baa363e1048b31647298d7116b720511096 (diff)
parentc54de7f5899f2bd64caee65efe16975a179aa51f (diff)
Merge pull request #42789 from Faless/js/4.0_html_editor_first_iteration
[HTML5] Editor prototype
Diffstat (limited to 'platform')
-rw-r--r--platform/javascript/SCsub3
-rw-r--r--platform/javascript/api/api.cpp2
-rw-r--r--platform/javascript/api/javascript_tools_editor_plugin.cpp153
-rw-r--r--platform/javascript/api/javascript_tools_editor_plugin.h62
-rw-r--r--platform/javascript/detect.py2
-rw-r--r--platform/javascript/engine/engine.js8
-rw-r--r--platform/javascript/native/utils.js21
7 files changed, 246 insertions, 5 deletions
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index a8861124b9..7381ea13b7 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -9,6 +9,7 @@ javascript_files = [
"javascript_eval.cpp",
"javascript_main.cpp",
"os_javascript.cpp",
+ "api/javascript_tools_editor_plugin.cpp",
]
build_targets = ["#bin/godot${PROGSUFFIX}.js", "#bin/godot${PROGSUFFIX}.wasm"]
@@ -55,7 +56,7 @@ out_files = [
zip_dir.File(binary_name + ".wasm"),
zip_dir.File(binary_name + ".html"),
]
-html_file = "#misc/dist/html/full-size.html"
+html_file = "#misc/dist/html/editor.html" if env["tools"] else "#misc/dist/html/full-size.html"
in_files = [js_wrapped, build[1], html_file]
if env["threads_enabled"]:
in_files.append(build[2])
diff --git a/platform/javascript/api/api.cpp b/platform/javascript/api/api.cpp
index 9c73e5c4c4..aa0206d144 100644
--- a/platform/javascript/api/api.cpp
+++ b/platform/javascript/api/api.cpp
@@ -31,10 +31,12 @@
#include "api.h"
#include "core/engine.h"
#include "javascript_eval.h"
+#include "javascript_tools_editor_plugin.h"
static JavaScript *javascript_eval;
void register_javascript_api() {
+ JavaScriptToolsEditorPlugin::initialize();
ClassDB::register_virtual_class<JavaScript>();
javascript_eval = memnew(JavaScript);
Engine::get_singleton()->add_singleton(Engine::Singleton("JavaScript", javascript_eval));
diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp
new file mode 100644
index 0000000000..e487bf23b7
--- /dev/null
+++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp
@@ -0,0 +1,153 @@
+/*************************************************************************/
+/* javascript_tools_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* 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 */
+/* "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. */
+/*************************************************************************/
+
+#if defined(TOOLS_ENABLED) && defined(JAVASCRIPT_ENABLED)
+#include "javascript_tools_editor_plugin.h"
+
+#include "core/engine.h"
+#include "core/os/dir_access.h"
+#include "core/os/file_access.h"
+#include "core/project_settings.h"
+#include "editor/editor_node.h"
+
+#include <emscripten/emscripten.h>
+
+static void _javascript_editor_init_callback() {
+ EditorNode::get_singleton()->add_editor_plugin(memnew(JavaScriptToolsEditorPlugin(EditorNode::get_singleton())));
+}
+
+void JavaScriptToolsEditorPlugin::initialize() {
+ EditorNode::add_init_callback(_javascript_editor_init_callback);
+}
+
+JavaScriptToolsEditorPlugin::JavaScriptToolsEditorPlugin(EditorNode *p_editor) {
+ Variant v;
+ add_tool_menu_item("Download Project Source", this, "_download_zip", v);
+}
+
+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");
+ 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, NULL, &io);
+ String base_path = resource_path.substr(0, resource_path.rfind("/")) + "/";
+ _zip_recursive(resource_path, base_path, zip);
+ zipClose(zip, NULL);
+ EM_ASM({
+ const path = "/tmp/project.zip";
+ const size = FS.stat(path)["size"];
+ const buf = new Uint8Array(size);
+ const fd = FS.open(path, "r");
+ FS.read(fd, buf, 0, size);
+ FS.close(fd);
+ FS.unlink(path);
+ const blob = new Blob([buf], { type: "application/zip" });
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = "project.zip";
+ a.style.display = "none";
+ document.body.appendChild(a);
+ a.click();
+ a.remove();
+ window.URL.revokeObjectURL(url);
+ });
+}
+
+void JavaScriptToolsEditorPlugin::_bind_methods() {
+ ClassDB::bind_method("_download_zip", &JavaScriptToolsEditorPlugin::_download_zip);
+}
+
+void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, zipFile p_zip) {
+ FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
+ if (!f) {
+ WARN_PRINT("Unable to open file for zipping: " + p_path);
+ return;
+ }
+ Vector<uint8_t> data;
+ int len = f->get_len();
+ data.resize(len);
+ f->get_buffer(data.ptrw(), len);
+ f->close();
+ memdelete(f);
+
+ String path = p_path.replace_first(p_base_path, "");
+ zipOpenNewFileInZip(p_zip,
+ path.utf8().get_data(),
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION);
+ zipWriteInFileInZip(p_zip, data.ptr(), data.size());
+ zipCloseFileInZip(p_zip);
+}
+
+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);
+ return;
+ }
+ dir->list_dir_begin();
+ String cur = dir->get_next();
+ while (!cur.empty()) {
+ String cs = p_path.plus_file(cur);
+ if (cur == "." || cur == ".." || cur == ".import") {
+ // Skip
+ } else if (dir->current_is_dir()) {
+ String path = cs.replace_first(p_base_path, "") + "/";
+ zipOpenNewFileInZip(p_zip,
+ path.utf8().get_data(),
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION);
+ zipCloseFileInZip(p_zip);
+ _zip_recursive(cs, p_base_path, p_zip);
+ } else {
+ _zip_file(cs, p_base_path, p_zip);
+ }
+ cur = dir->get_next();
+ }
+}
+#endif
diff --git a/platform/javascript/api/javascript_tools_editor_plugin.h b/platform/javascript/api/javascript_tools_editor_plugin.h
new file mode 100644
index 0000000000..cc09fa4cd3
--- /dev/null
+++ b/platform/javascript/api/javascript_tools_editor_plugin.h
@@ -0,0 +1,62 @@
+/*************************************************************************/
+/* javascript_tools_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* 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 */
+/* "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. */
+/*************************************************************************/
+
+#ifndef JAVASCRIPT_TOOLS_EDITOR_PLUGIN_H
+#define JAVASCRIPT_TOOLS_EDITOR_PLUGIN_H
+
+#if defined(TOOLS_ENABLED) && defined(JAVASCRIPT_ENABLED)
+#include "core/io/zip_io.h"
+#include "editor/editor_plugin.h"
+
+class JavaScriptToolsEditorPlugin : public EditorPlugin {
+ GDCLASS(JavaScriptToolsEditorPlugin, EditorPlugin);
+
+private:
+ void _zip_file(String p_path, String p_base_path, zipFile p_zip);
+ void _zip_recursive(String p_path, String p_base_path, zipFile p_zip);
+
+protected:
+ static void _bind_methods();
+
+ void _download_zip(Variant p_v);
+
+public:
+ static void initialize();
+
+ JavaScriptToolsEditorPlugin(EditorNode *p_editor);
+};
+#else
+class JavaScriptToolsEditorPlugin {
+public:
+ static void initialize() {}
+};
+#endif
+
+#endif // JAVASCRIPT_TOOLS_EDITOR_PLUGIN_H
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index 4b5890545f..8f2961b33d 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -135,7 +135,7 @@ def configure(env):
env.Append(CPPDEFINES=["PTHREAD_NO_RENAME"])
env.Append(CCFLAGS=["-s", "USE_PTHREADS=1"])
env.Append(LINKFLAGS=["-s", "USE_PTHREADS=1"])
- env.Append(LINKFLAGS=["-s", "PTHREAD_POOL_SIZE=4"])
+ env.Append(LINKFLAGS=["-s", "PTHREAD_POOL_SIZE=8"])
env.Append(LINKFLAGS=["-s", "WASM_MEM_MAX=2048MB"])
env.extra_suffix = ".threads" + env.extra_suffix
else:
diff --git a/platform/javascript/engine/engine.js b/platform/javascript/engine/engine.js
index adcd919a6b..05a11701c0 100644
--- a/platform/javascript/engine/engine.js
+++ b/platform/javascript/engine/engine.js
@@ -121,6 +121,7 @@ Function('return this')()['Engine'] = (function() {
me.rtenv['noExitRuntime'] = true;
me.rtenv['onExecute'] = me.onExecute;
me.rtenv['onExit'] = function(code) {
+ me.rtenv['deinitFS']();
if (me.onExit)
me.onExit(code);
me.rtenv = null;
@@ -227,6 +228,12 @@ Function('return this')()['Engine'] = (function() {
this.persistentPaths = persistentPaths;
};
+ Engine.prototype.requestQuit = function() {
+ if (this.rtenv) {
+ this.rtenv['request_quit']();
+ }
+ };
+
// Closure compiler exported engine methods.
/** @export */
Engine['isWebGLAvailable'] = Utils.isWebGLAvailable;
@@ -249,5 +256,6 @@ Function('return this')()['Engine'] = (function() {
Engine.prototype['setOnExit'] = Engine.prototype.setOnExit;
Engine.prototype['copyToFS'] = Engine.prototype.copyToFS;
Engine.prototype['setPersistentPaths'] = Engine.prototype.setPersistentPaths;
+ Engine.prototype['requestQuit'] = Engine.prototype.requestQuit;
return Engine;
})();
diff --git a/platform/javascript/native/utils.js b/platform/javascript/native/utils.js
index 0b3698fd86..8d0beba454 100644
--- a/platform/javascript/native/utils.js
+++ b/platform/javascript/native/utils.js
@@ -29,8 +29,7 @@
/*************************************************************************/
Module['initFS'] = function(persistentPaths) {
- FS.mkdir('/userfs');
- FS.mount(IDBFS, {}, '/userfs');
+ Module.mount_points = ['/userfs'].concat(persistentPaths);
function createRecursive(dir) {
try {
@@ -43,13 +42,14 @@ Module['initFS'] = function(persistentPaths) {
}
}
- persistentPaths.forEach(function(path) {
+ Module.mount_points.forEach(function(path) {
createRecursive(path);
FS.mount(IDBFS, {}, path);
});
return new Promise(function(resolve, reject) {
FS.syncfs(true, function(err) {
if (err) {
+ Module.mount_points = [];
Module.idbfs = false;
console.log("IndexedDB not available: " + err.message);
} else {
@@ -60,6 +60,21 @@ Module['initFS'] = function(persistentPaths) {
});
};
+Module['deinitFS'] = function() {
+ Module.mount_points.forEach(function(path) {
+ try {
+ FS.unmount(path);
+ } catch (e) {
+ console.log("Already unmounted", e);
+ }
+ if (Module.idbfs && IDBFS.dbs[path]) {
+ IDBFS.dbs[path].close();
+ delete IDBFS.dbs[path];
+ }
+ });
+ Module.mount_points = [];
+};
+
Module['copyToFS'] = function(path, buffer) {
var p = path.lastIndexOf("/");
var dir = "/";