|
@@ -37,8 +37,6 @@
|
|
#include "editor/editor_settings.h"
|
|
#include "editor/editor_settings.h"
|
|
#include "platform/windows/logo.gen.h"
|
|
#include "platform/windows/logo.gen.h"
|
|
|
|
|
|
-static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size);
|
|
|
|
-
|
|
|
|
class EditorExportPlatformWindows : public EditorExportPlatformPC {
|
|
class EditorExportPlatformWindows : public EditorExportPlatformPC {
|
|
Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path);
|
|
Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path);
|
|
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
|
|
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
|
|
@@ -47,6 +45,7 @@ public:
|
|
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
|
|
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
|
|
virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
|
|
virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
|
|
virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
|
|
virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
|
|
|
|
+ virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size);
|
|
virtual void get_export_options(List<ExportOption> *r_options);
|
|
virtual void get_export_options(List<ExportOption> *r_options);
|
|
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
|
|
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const;
|
|
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const;
|
|
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const;
|
|
@@ -62,10 +61,9 @@ Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPres
|
|
|
|
|
|
Error EditorExportPlatformWindows::modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
|
|
Error EditorExportPlatformWindows::modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
|
|
if (p_preset->get("application/modify_resources")) {
|
|
if (p_preset->get("application/modify_resources")) {
|
|
- return _rcedit_add_data(p_preset, p_path);
|
|
|
|
- } else {
|
|
|
|
- return OK;
|
|
|
|
|
|
+ _rcedit_add_data(p_preset, p_path);
|
|
}
|
|
}
|
|
|
|
+ return OK;
|
|
}
|
|
}
|
|
|
|
|
|
Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
|
|
Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
|
|
@@ -76,12 +74,15 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
|
|
|
|
|
|
Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, pck_path, p_flags);
|
|
Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, pck_path, p_flags);
|
|
if (p_preset->get("codesign/enable") && err == OK) {
|
|
if (p_preset->get("codesign/enable") && err == OK) {
|
|
- err = _code_sign(p_preset, pck_path);
|
|
|
|
|
|
+ _code_sign(p_preset, pck_path);
|
|
}
|
|
}
|
|
|
|
|
|
if (p_preset->get("binary_format/embed_pck") && err == OK) {
|
|
if (p_preset->get("binary_format/embed_pck") && err == OK) {
|
|
DirAccessRef tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
|
|
DirAccessRef tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
|
|
err = tmp_dir->rename(pck_path, p_path);
|
|
err = tmp_dir->rename(pck_path, p_path);
|
|
|
|
+ if (err != OK) {
|
|
|
|
+ add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), vformat(TTR("Failed to rename temporary file \"%s\"."), pck_path));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
return err;
|
|
return err;
|
|
@@ -123,7 +124,7 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
|
|
String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit");
|
|
String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit");
|
|
|
|
|
|
if (rcedit_path != String() && !FileAccess::exists(rcedit_path)) {
|
|
if (rcedit_path != String() && !FileAccess::exists(rcedit_path)) {
|
|
- ERR_PRINT("Could not find rcedit executable at " + rcedit_path + ", aborting.");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("Could not find rcedit executable at \"%s\"."), rcedit_path));
|
|
return ERR_FILE_NOT_FOUND;
|
|
return ERR_FILE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -136,7 +137,7 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
|
|
String wine_path = EditorSettings::get_singleton()->get("export/windows/wine");
|
|
String wine_path = EditorSettings::get_singleton()->get("export/windows/wine");
|
|
|
|
|
|
if (wine_path != String() && !FileAccess::exists(wine_path)) {
|
|
if (wine_path != String() && !FileAccess::exists(wine_path)) {
|
|
- ERR_PRINT("Could not find wine executable at " + wine_path + ", aborting.");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("Could not find wine executable at \"%s\"."), wine_path));
|
|
return ERR_FILE_NOT_FOUND;
|
|
return ERR_FILE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -203,10 +204,14 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset
|
|
|
|
|
|
String str;
|
|
String str;
|
|
Error err = OS::get_singleton()->execute(rcedit_path, args, true, nullptr, &str, nullptr, true);
|
|
Error err = OS::get_singleton()->execute(rcedit_path, args, true, nullptr, &str, nullptr, true);
|
|
- ERR_FAIL_COND_V_MSG(err != OK, err, "Could not start rcedit executable, configure rcedit path in the Editor Settings (Export > Windows > Rcedit).");
|
|
|
|
|
|
+ if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) {
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable, configure rcedit path in the Editor Settings (Export > Windows > Rcedit)."));
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
print_line("rcedit (" + p_path + "): " + str);
|
|
print_line("rcedit (" + p_path + "): " + str);
|
|
|
|
|
|
if (str.find("Fatal error") != -1) {
|
|
if (str.find("Fatal error") != -1) {
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), vformat(TTR("rcedit failed to modify executable:\n%s"), str));
|
|
return FAILED;
|
|
return FAILED;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -219,7 +224,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|
#ifdef WINDOWS_ENABLED
|
|
#ifdef WINDOWS_ENABLED
|
|
String signtool_path = EditorSettings::get_singleton()->get("export/windows/signtool");
|
|
String signtool_path = EditorSettings::get_singleton()->get("export/windows/signtool");
|
|
if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
|
|
if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
|
|
- ERR_PRINT("Could not find signtool executable at " + signtool_path + ", aborting.");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Could not find signtool executable at \"%s\"."), signtool_path));
|
|
return ERR_FILE_NOT_FOUND;
|
|
return ERR_FILE_NOT_FOUND;
|
|
}
|
|
}
|
|
if (signtool_path == String()) {
|
|
if (signtool_path == String()) {
|
|
@@ -228,7 +233,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|
#else
|
|
#else
|
|
String signtool_path = EditorSettings::get_singleton()->get("export/windows/osslsigncode");
|
|
String signtool_path = EditorSettings::get_singleton()->get("export/windows/osslsigncode");
|
|
if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
|
|
if (signtool_path != String() && !FileAccess::exists(signtool_path)) {
|
|
- ERR_PRINT("Could not find osslsigncode executable at " + signtool_path + ", aborting.");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Could not find osslsigncode executable at \"%s\"."), signtool_path));
|
|
return ERR_FILE_NOT_FOUND;
|
|
return ERR_FILE_NOT_FOUND;
|
|
}
|
|
}
|
|
if (signtool_path == String()) {
|
|
if (signtool_path == String()) {
|
|
@@ -248,7 +253,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|
args.push_back("/f");
|
|
args.push_back("/f");
|
|
args.push_back(p_preset->get("codesign/identity"));
|
|
args.push_back(p_preset->get("codesign/identity"));
|
|
} else {
|
|
} else {
|
|
- EditorNode::add_io_error("codesign: no identity found");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("No identity found."));
|
|
return FAILED;
|
|
return FAILED;
|
|
}
|
|
}
|
|
} else if (id_type == 2) { //Windows certificate store
|
|
} else if (id_type == 2) { //Windows certificate store
|
|
@@ -256,11 +261,11 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|
args.push_back("/sha1");
|
|
args.push_back("/sha1");
|
|
args.push_back(p_preset->get("codesign/identity"));
|
|
args.push_back(p_preset->get("codesign/identity"));
|
|
} else {
|
|
} else {
|
|
- EditorNode::add_io_error("codesign: no identity found");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("No identity found."));
|
|
return FAILED;
|
|
return FAILED;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- EditorNode::add_io_error("codesign: invalid identity type");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Invalid identity type."));
|
|
return FAILED;
|
|
return FAILED;
|
|
}
|
|
}
|
|
#else
|
|
#else
|
|
@@ -268,7 +273,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|
args.push_back("-pkcs12");
|
|
args.push_back("-pkcs12");
|
|
args.push_back(p_preset->get("codesign/identity"));
|
|
args.push_back(p_preset->get("codesign/identity"));
|
|
} else {
|
|
} else {
|
|
- EditorNode::add_io_error("codesign: no identity found");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("No identity found."));
|
|
return FAILED;
|
|
return FAILED;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
@@ -300,7 +305,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|
args.push_back(p_preset->get("codesign/timestamp_server_url"));
|
|
args.push_back(p_preset->get("codesign/timestamp_server_url"));
|
|
#endif
|
|
#endif
|
|
} else {
|
|
} else {
|
|
- EditorNode::add_io_error("codesign: invalid timestamp server");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Invalid timestamp server."));
|
|
return FAILED;
|
|
return FAILED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -347,7 +352,10 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|
|
|
|
|
String str;
|
|
String str;
|
|
Error err = OS::get_singleton()->execute(signtool_path, args, true, nullptr, &str, nullptr, true);
|
|
Error err = OS::get_singleton()->execute(signtool_path, args, true, nullptr, &str, nullptr, true);
|
|
- ERR_FAIL_COND_V_MSG(err != OK, err, "Could not start signtool executable, configure signtool path in the Editor Settings (Export > Windows > Signtool).");
|
|
|
|
|
|
+ if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) {
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start signtool executable, configure signtool path in the Editor Settings (Export > Windows > Signtool)."));
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
|
|
print_line("codesign (" + p_path + "): " + str);
|
|
print_line("codesign (" + p_path + "): " + str);
|
|
#ifndef WINDOWS_ENABLED
|
|
#ifndef WINDOWS_ENABLED
|
|
@@ -355,6 +363,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|
#else
|
|
#else
|
|
if (str.find("Failed") != -1) {
|
|
if (str.find("Failed") != -1) {
|
|
#endif
|
|
#endif
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Signtool failed to sign executable:\n%s"), str));
|
|
return FAILED;
|
|
return FAILED;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -362,10 +371,16 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
|
|
DirAccessRef tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
|
|
DirAccessRef tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
|
|
|
|
|
|
err = tmp_dir->remove(p_path);
|
|
err = tmp_dir->remove(p_path);
|
|
- ERR_FAIL_COND_V(err != OK, err);
|
|
|
|
|
|
+ if (err != OK) {
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Failed to remove temporary file \"%s\"."), p_path));
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
|
|
err = tmp_dir->rename(p_path + "_signed", p_path);
|
|
err = tmp_dir->rename(p_path + "_signed", p_path);
|
|
- ERR_FAIL_COND_V(err != OK, err);
|
|
|
|
|
|
+ if (err != OK) {
|
|
|
|
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Failed to rename temporary file \"%s\"."), p_path + "_signed"));
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
#endif
|
|
#endif
|
|
|
|
|
|
return OK;
|
|
return OK;
|
|
@@ -414,49 +429,17 @@ bool EditorExportPlatformWindows::can_export(const Ref<EditorExportPreset> &p_pr
|
|
return valid;
|
|
return valid;
|
|
}
|
|
}
|
|
|
|
|
|
-void register_windows_exporter() {
|
|
|
|
- EDITOR_DEF("export/windows/rcedit", "");
|
|
|
|
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/rcedit", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
|
|
|
|
-#ifdef WINDOWS_ENABLED
|
|
|
|
- EDITOR_DEF("export/windows/signtool", "");
|
|
|
|
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/signtool", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
|
|
|
|
-#else
|
|
|
|
- EDITOR_DEF("export/windows/osslsigncode", "");
|
|
|
|
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/osslsigncode", PROPERTY_HINT_GLOBAL_FILE));
|
|
|
|
- // On non-Windows we need WINE to run rcedit
|
|
|
|
- EDITOR_DEF("export/windows/wine", "");
|
|
|
|
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/wine", PROPERTY_HINT_GLOBAL_FILE));
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- Ref<EditorExportPlatformWindows> platform;
|
|
|
|
- platform.instance();
|
|
|
|
-
|
|
|
|
- Ref<Image> img = memnew(Image(_windows_logo));
|
|
|
|
- Ref<ImageTexture> logo;
|
|
|
|
- logo.instance();
|
|
|
|
- logo->create_from_image(img);
|
|
|
|
- platform->set_logo(logo);
|
|
|
|
- platform->set_name("Windows Desktop");
|
|
|
|
- platform->set_extension("exe");
|
|
|
|
- platform->set_release_32("windows_32_release.exe");
|
|
|
|
- platform->set_debug_32("windows_32_debug.exe");
|
|
|
|
- platform->set_release_64("windows_64_release.exe");
|
|
|
|
- platform->set_debug_64("windows_64_debug.exe");
|
|
|
|
- platform->set_os_name("Windows");
|
|
|
|
- platform->set_fixup_embedded_pck_func(&fixup_embedded_pck);
|
|
|
|
-
|
|
|
|
- EditorExport::get_singleton()->add_export_platform(platform);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
|
|
|
|
|
|
+Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) {
|
|
// Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data
|
|
// Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data
|
|
|
|
|
|
if (p_embedded_size + p_embedded_start >= 0x100000000) { // Check for total executable size
|
|
if (p_embedded_size + p_embedded_start >= 0x100000000) { // Check for total executable size
|
|
- ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Windows executables cannot be >= 4 GiB.");
|
|
|
|
|
|
+ add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("Windows executables cannot be >= 4 GiB."));
|
|
|
|
+ return ERR_INVALID_DATA;
|
|
}
|
|
}
|
|
|
|
|
|
FileAccess *f = FileAccess::open(p_path, FileAccess::READ_WRITE);
|
|
FileAccess *f = FileAccess::open(p_path, FileAccess::READ_WRITE);
|
|
if (!f) {
|
|
if (!f) {
|
|
|
|
+ add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), vformat(TTR("Failed to open executable file \"%s\"."), p_path));
|
|
return ERR_CANT_OPEN;
|
|
return ERR_CANT_OPEN;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -469,6 +452,7 @@ static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start,
|
|
uint32_t magic = f->get_32();
|
|
uint32_t magic = f->get_32();
|
|
if (magic != 0x00004550) {
|
|
if (magic != 0x00004550) {
|
|
f->close();
|
|
f->close();
|
|
|
|
+ add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("Executable file header corrupted."));
|
|
return ERR_FILE_CORRUPT;
|
|
return ERR_FILE_CORRUPT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -520,5 +504,42 @@ static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start,
|
|
|
|
|
|
f->close();
|
|
f->close();
|
|
|
|
|
|
- return found ? OK : ERR_FILE_CORRUPT;
|
|
|
|
|
|
+ if (!found) {
|
|
|
|
+ add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("Executable \"pck\" section not found."));
|
|
|
|
+ return ERR_FILE_CORRUPT;
|
|
|
|
+ }
|
|
|
|
+ return OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void register_windows_exporter() {
|
|
|
|
+ EDITOR_DEF("export/windows/rcedit", "");
|
|
|
|
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/rcedit", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
|
|
|
|
+#ifdef WINDOWS_ENABLED
|
|
|
|
+ EDITOR_DEF("export/windows/signtool", "");
|
|
|
|
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/signtool", PROPERTY_HINT_GLOBAL_FILE, "*.exe"));
|
|
|
|
+#else
|
|
|
|
+ EDITOR_DEF("export/windows/osslsigncode", "");
|
|
|
|
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/osslsigncode", PROPERTY_HINT_GLOBAL_FILE));
|
|
|
|
+ // On non-Windows we need WINE to run rcedit
|
|
|
|
+ EDITOR_DEF("export/windows/wine", "");
|
|
|
|
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/wine", PROPERTY_HINT_GLOBAL_FILE));
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ Ref<EditorExportPlatformWindows> platform;
|
|
|
|
+ platform.instance();
|
|
|
|
+
|
|
|
|
+ Ref<Image> img = memnew(Image(_windows_logo));
|
|
|
|
+ Ref<ImageTexture> logo;
|
|
|
|
+ logo.instance();
|
|
|
|
+ logo->create_from_image(img);
|
|
|
|
+ platform->set_logo(logo);
|
|
|
|
+ platform->set_name("Windows Desktop");
|
|
|
|
+ platform->set_extension("exe");
|
|
|
|
+ platform->set_release_32("windows_32_release.exe");
|
|
|
|
+ platform->set_debug_32("windows_32_debug.exe");
|
|
|
|
+ platform->set_release_64("windows_64_release.exe");
|
|
|
|
+ platform->set_debug_64("windows_64_debug.exe");
|
|
|
|
+ platform->set_os_name("Windows");
|
|
|
|
+
|
|
|
|
+ EditorExport::get_singleton()->add_export_platform(platform);
|
|
}
|
|
}
|