Explorar el Código

[HTML5] Add JavaScriptToolsEditorPlugin.

A new editor plugin, specific to HTML5, that provide some extra features
needed to make the editor usable on that platform.

For now, it adds a "Download project sources" option in the "Tool" menu,
so the user can download the work done as a zip file (from the browser
storage).
Fabio Alessandrelli hace 5 años
padre
commit
55f04952c5

+ 1 - 0
platform/javascript/SCsub

@@ -8,6 +8,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"]

+ 2 - 6
platform/javascript/api/api.cpp

@@ -31,30 +31,28 @@
 #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));
 }
 
 void unregister_javascript_api() {
-
 	memdelete(javascript_eval);
 }
 
 JavaScript *JavaScript::singleton = NULL;
 
 JavaScript *JavaScript::get_singleton() {
-
 	return singleton;
 }
 
 JavaScript::JavaScript() {
-
 	ERR_FAIL_COND_MSG(singleton != NULL, "JavaScript singleton already exist.");
 	singleton = this;
 }
@@ -62,13 +60,11 @@ JavaScript::JavaScript() {
 JavaScript::~JavaScript() {}
 
 void JavaScript::_bind_methods() {
-
 	ClassDB::bind_method(D_METHOD("eval", "code", "use_global_execution_context"), &JavaScript::eval, DEFVAL(false));
 }
 
 #if !defined(JAVASCRIPT_ENABLED) || !defined(JAVASCRIPT_EVAL_ENABLED)
 Variant JavaScript::eval(const String &p_code, bool p_use_global_exec_context) {
-
 	return Variant();
 }
 #endif

+ 123 - 0
platform/javascript/api/javascript_tools_editor_plugin.cpp

@@ -0,0 +1,123 @@
+#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::_downalod_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::_downalod_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

+ 32 - 0
platform/javascript/api/javascript_tools_editor_plugin.h

@@ -0,0 +1,32 @@
+#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 _downalod_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