summaryrefslogtreecommitdiffstats
path: root/platform/javascript/export/export.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/javascript/export/export.cpp')
-rw-r--r--platform/javascript/export/export.cpp101
1 files changed, 70 insertions, 31 deletions
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index f3e8d6911a..c1cb8bcb58 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-2019 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* 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 */
@@ -86,17 +86,28 @@ 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";
+ ctype = "text/html";
} else if (req[1] == basereq + ".js") {
filepath += ".js";
+ ctype = "application/javascript";
} else if (req[1] == basereq + ".pck") {
filepath += ".pck";
- } else if (req[1] == basereq + ".png") {
- filepath += ".png";
+ ctype = "application/octet-stream";
+ } 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";
+ ctype = "application/wasm";
} else {
String s = "HTTP/1.1 404 Not Found\r\n";
s += "Connection: Close\r\n";
@@ -109,10 +120,14 @@ public:
ERR_FAIL_COND(!f);
String s = "HTTP/1.1 200 OK\r\n";
s += "Connection: Close\r\n";
+ s += "Content-Type: " + ctype + "\r\n";
s += "\r\n";
CharString cs = s.utf8();
Error err = connection->put_data((const uint8_t *)cs.get_data(), cs.size() - 1);
- ERR_FAIL_COND(err != OK);
+ if (err != OK) {
+ memdelete(f);
+ ERR_FAIL();
+ }
while (true) {
uint8_t bytes[4096];
@@ -121,8 +136,12 @@ public:
break;
}
err = connection->put_data(bytes, read);
- ERR_FAIL_COND(err != OK);
+ if (err != OK) {
+ memdelete(f);
+ ERR_FAIL();
+ }
}
+ memdelete(f);
}
void poll() {
@@ -288,32 +307,32 @@ Ref<Texture> EditorExportPlatformJavaScript::get_logo() const {
bool EditorExportPlatformJavaScript::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
- bool valid = false;
String err;
+ bool valid = false;
+
+ // Look for export templates (first official, and if defined custom templates).
- if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE) != "")
- valid = true;
- else if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG) != "")
- valid = true;
+ bool dvalid = exists_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG, &err);
+ bool rvalid = exists_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE, &err);
if (p_preset->get("custom_template/debug") != "") {
- if (FileAccess::exists(p_preset->get("custom_template/debug"))) {
- valid = true;
- } else {
+ dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+ if (!dvalid) {
err += TTR("Custom debug template not found.") + "\n";
}
}
-
if (p_preset->get("custom_template/release") != "") {
- if (FileAccess::exists(p_preset->get("custom_template/release"))) {
- valid = true;
- } else {
+ rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+ if (!rvalid) {
err += TTR("Custom release template not found.") + "\n";
}
}
+ valid = dvalid || rvalid;
r_missing_templates = !valid;
+ // Validate the rest of the configuration.
+
if (p_preset->get("vram_texture_compression/for_mobile")) {
String etc_error = test_etc2();
if (etc_error != String()) {
@@ -456,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();
@@ -469,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;
}
@@ -522,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");
@@ -532,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 {