[Export] Respect icon/splash screen import settings.

This commit is contained in:
Pāvels Nadtočajevs 2025-01-28 08:07:20 +02:00
parent 9ee1873ae1
commit b3f7c8f5d3
8 changed files with 69 additions and 44 deletions

View file

@ -35,6 +35,7 @@
#include "core/extension/gdextension.h" #include "core/extension/gdextension.h"
#include "core/io/file_access_encrypted.h" #include "core/io/file_access_encrypted.h"
#include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION #include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
#include "core/io/image_loader.h"
#include "core/io/resource_uid.h" #include "core/io/resource_uid.h"
#include "core/io/zip_io.h" #include "core/io/zip_io.h"
#include "core/version.h" #include "core/version.h"
@ -82,6 +83,28 @@ static int _get_pad(int p_alignment, int p_n) {
#define PCK_PADDING 16 #define PCK_PADDING 16
Ref<Image> EditorExportPlatform::_load_icon_or_splash_image(const String &p_path, Error *r_error) const {
Ref<Image> image;
if (!p_path.is_empty() && ResourceLoader::exists(p_path) && !ResourceLoader::get_resource_type(p_path).is_empty()) {
Ref<Texture2D> texture = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_REUSE, r_error);
if (texture.is_valid()) {
image = texture->get_image();
if (image.is_valid() && image->is_compressed()) {
image->decompress();
}
}
}
if (image.is_null()) {
image.instantiate();
Error err = ImageLoader::load_image(p_path, image);
if (r_error) {
*r_error = err;
}
}
return image;
}
bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) { bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) {
bool has_messages = false; bool has_messages = false;

View file

@ -202,6 +202,8 @@ protected:
Error _load_patches(const Vector<String> &p_patches); Error _load_patches(const Vector<String> &p_patches);
void _unload_patches(); void _unload_patches();
Ref<Image> _load_icon_or_splash_image(const String &p_path, Error *r_error) const;
public: public:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const = 0; virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const = 0;

View file

@ -1723,18 +1723,18 @@ void EditorExportPlatformAndroid::_process_launcher_icons(const String &p_file_n
void EditorExportPlatformAndroid::load_icon_refs(const Ref<EditorExportPreset> &p_preset, Ref<Image> &icon, Ref<Image> &foreground, Ref<Image> &background, Ref<Image> &monochrome) { void EditorExportPlatformAndroid::load_icon_refs(const Ref<EditorExportPreset> &p_preset, Ref<Image> &icon, Ref<Image> &foreground, Ref<Image> &background, Ref<Image> &monochrome) {
String project_icon_path = GLOBAL_GET("application/config/icon"); String project_icon_path = GLOBAL_GET("application/config/icon");
icon.instantiate(); Error err = OK;
foreground.instantiate();
background.instantiate();
monochrome.instantiate();
// Regular icon: user selection -> project icon -> default. // Regular icon: user selection -> project icon -> default.
String path = static_cast<String>(p_preset->get(LAUNCHER_ICON_OPTION)).strip_edges(); String path = static_cast<String>(p_preset->get(LAUNCHER_ICON_OPTION)).strip_edges();
print_verbose("Loading regular icon from " + path); print_verbose("Loading regular icon from " + path);
if (path.is_empty() || ImageLoader::load_image(path, icon) != OK) { if (!path.is_empty()) {
icon = _load_icon_or_splash_image(path, &err);
}
if (path.is_empty() || err != OK || icon.is_null() || icon->is_empty()) {
print_verbose("- falling back to project icon: " + project_icon_path); print_verbose("- falling back to project icon: " + project_icon_path);
if (!project_icon_path.is_empty()) { if (!project_icon_path.is_empty()) {
ImageLoader::load_image(project_icon_path, icon); icon = _load_icon_or_splash_image(project_icon_path, &err);
} else { } else {
ERR_PRINT("No project icon specified. Please specify one in the Project Settings under Application -> Config -> Icon"); ERR_PRINT("No project icon specified. Please specify one in the Project Settings under Application -> Config -> Icon");
} }
@ -1743,7 +1743,10 @@ void EditorExportPlatformAndroid::load_icon_refs(const Ref<EditorExportPreset> &
// Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default). // Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default).
path = static_cast<String>(p_preset->get(LAUNCHER_ADAPTIVE_ICON_FOREGROUND_OPTION)).strip_edges(); path = static_cast<String>(p_preset->get(LAUNCHER_ADAPTIVE_ICON_FOREGROUND_OPTION)).strip_edges();
print_verbose("Loading adaptive foreground icon from " + path); print_verbose("Loading adaptive foreground icon from " + path);
if (path.is_empty() || ImageLoader::load_image(path, foreground) != OK) { if (!path.is_empty()) {
foreground = _load_icon_or_splash_image(path, &err);
}
if (path.is_empty() || err != OK || foreground.is_null() || foreground->is_empty()) {
print_verbose("- falling back to using the regular icon"); print_verbose("- falling back to using the regular icon");
foreground = icon; foreground = icon;
} }
@ -1752,14 +1755,14 @@ void EditorExportPlatformAndroid::load_icon_refs(const Ref<EditorExportPreset> &
path = static_cast<String>(p_preset->get(LAUNCHER_ADAPTIVE_ICON_BACKGROUND_OPTION)).strip_edges(); path = static_cast<String>(p_preset->get(LAUNCHER_ADAPTIVE_ICON_BACKGROUND_OPTION)).strip_edges();
if (!path.is_empty()) { if (!path.is_empty()) {
print_verbose("Loading adaptive background icon from " + path); print_verbose("Loading adaptive background icon from " + path);
ImageLoader::load_image(path, background); background = _load_icon_or_splash_image(path, &err);
} }
// Adaptive monochrome: user selection -> default. // Adaptive monochrome: user selection -> default.
path = static_cast<String>(p_preset->get(LAUNCHER_ADAPTIVE_ICON_MONOCHROME_OPTION)).strip_edges(); path = static_cast<String>(p_preset->get(LAUNCHER_ADAPTIVE_ICON_MONOCHROME_OPTION)).strip_edges();
if (!path.is_empty()) { if (!path.is_empty()) {
print_verbose("Loading adaptive monochrome icon from " + path); print_verbose("Loading adaptive monochrome icon from " + path);
ImageLoader::load_image(path, monochrome); monochrome = _load_icon_or_splash_image(path, &err);
} }
} }

View file

@ -982,9 +982,9 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
} }
// Resize main app icon. // Resize main app icon.
icon_path = GLOBAL_GET("application/config/icon"); icon_path = GLOBAL_GET("application/config/icon");
Ref<Image> img = memnew(Image); Error err = OK;
Error err = ImageLoader::load_image(icon_path, img); Ref<Image> img = _load_icon_or_splash_image(icon_path, &err);
if (err != OK) { if (err != OK || img.is_null() || img->is_empty()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path)); add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path));
return ERR_UNCONFIGURED; return ERR_UNCONFIGURED;
} else if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) { } else if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
@ -1003,9 +1003,9 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
} }
} else { } else {
// Load custom icon and resize if required. // Load custom icon and resize if required.
Ref<Image> img = memnew(Image); Error err = OK;
Error err = ImageLoader::load_image(icon_path, img); Ref<Image> img = _load_icon_or_splash_image(icon_path, &err);
if (err != OK) { if (err != OK || img.is_null() || img->is_empty()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path)); add_message(EXPORT_MESSAGE_ERROR, TTR("Export Icons"), vformat("Invalid icon (%s): '%s'.", info.preset_key, icon_path));
return ERR_UNCONFIGURED; return ERR_UNCONFIGURED;
} else if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) { } else if (info.force_opaque && img->detect_alpha() != Image::ALPHA_NONE) {
@ -1089,13 +1089,11 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
const String custom_launch_image_3x = p_preset->get("storyboard/custom_image@3x"); const String custom_launch_image_3x = p_preset->get("storyboard/custom_image@3x");
if (custom_launch_image_2x.length() > 0 && custom_launch_image_3x.length() > 0) { if (custom_launch_image_2x.length() > 0 && custom_launch_image_3x.length() > 0) {
Ref<Image> image;
String image_path = p_dest_dir.path_join("splash@2x.png"); String image_path = p_dest_dir.path_join("splash@2x.png");
image.instantiate(); Error err = OK;
Error err = ImageLoader::load_image(custom_launch_image_2x, image); Ref<Image> image = _load_icon_or_splash_image(custom_launch_image_2x, &err);
if (err) { if (err != OK || image.is_null() || image->is_empty()) {
image.unref();
return err; return err;
} }
@ -1103,13 +1101,10 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
return ERR_FILE_CANT_WRITE; return ERR_FILE_CANT_WRITE;
} }
image.unref();
image_path = p_dest_dir.path_join("splash@3x.png"); image_path = p_dest_dir.path_join("splash@3x.png");
image.instantiate(); image = _load_icon_or_splash_image(custom_launch_image_3x, &err);
err = ImageLoader::load_image(custom_launch_image_3x, image);
if (err) { if (err != OK || image.is_null() || image->is_empty()) {
image.unref();
return err; return err;
} }
@ -1117,19 +1112,16 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
return ERR_FILE_CANT_WRITE; return ERR_FILE_CANT_WRITE;
} }
} else { } else {
Error err = OK;
Ref<Image> splash; Ref<Image> splash;
const String splash_path = GLOBAL_GET("application/boot_splash/image"); const String splash_path = GLOBAL_GET("application/boot_splash/image");
if (!splash_path.is_empty()) { if (!splash_path.is_empty()) {
splash.instantiate(); splash = _load_icon_or_splash_image(splash_path, &err);
const Error err = ImageLoader::load_image(splash_path, splash);
if (err) {
splash.unref();
}
} }
if (splash.is_null()) { if (err != OK || splash.is_null() || splash->is_empty()) {
splash.instantiate(boot_splash_png); splash.instantiate(boot_splash_png);
} }

View file

@ -1883,10 +1883,8 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
icon->get_buffer(&data.write[0], icon->get_length()); icon->get_buffer(&data.write[0], icon->get_length());
} }
} else { } else {
Ref<Image> icon; Ref<Image> icon = _load_icon_or_splash_image(icon_path, &err);
icon.instantiate(); if (err == OK && icon.is_valid() && !icon->is_empty()) {
err = ImageLoader::load_image(icon_path, icon);
if (err == OK && !icon->is_empty()) {
_make_icon(p_preset, icon, data); _make_icon(p_preset, icon, data);
} }
} }

View file

@ -192,9 +192,9 @@ Error EditorExportPlatformWeb::_add_manifest_icon(const String &p_path, const St
Ref<Image> icon; Ref<Image> icon;
if (!p_icon.is_empty()) { if (!p_icon.is_empty()) {
icon.instantiate(); Error err = OK;
const Error err = ImageLoader::load_image(p_icon, icon); icon = _load_icon_or_splash_image(p_icon, &err);
if (err != OK) { if (err != OK || icon.is_null() || icon->is_empty()) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Icon Creation"), vformat(TTR("Could not read file: \"%s\"."), p_icon)); add_message(EXPORT_MESSAGE_ERROR, TTR("Icon Creation"), vformat(TTR("Could not read file: \"%s\"."), p_icon));
return err; return err;
} }

View file

@ -77,20 +77,28 @@ class EditorExportPlatformWeb : public EditorExportPlatform {
} }
Ref<Image> _get_project_icon() const { Ref<Image> _get_project_icon() const {
Error err = OK;
Ref<Image> icon; Ref<Image> icon;
icon.instantiate(); icon.instantiate();
const String icon_path = String(GLOBAL_GET("application/config/icon")).strip_edges(); const String icon_path = String(GLOBAL_GET("application/config/icon")).strip_edges();
if (icon_path.is_empty() || ImageLoader::load_image(icon_path, icon) != OK) { if (!icon_path.is_empty()) {
icon = _load_icon_or_splash_image(icon_path, &err);
}
if (icon_path.is_empty() || err != OK || icon.is_null() || icon->is_empty()) {
return EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("DefaultProjectIcon"), EditorStringName(EditorIcons))->get_image(); return EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("DefaultProjectIcon"), EditorStringName(EditorIcons))->get_image();
} }
return icon; return icon;
} }
Ref<Image> _get_project_splash() const { Ref<Image> _get_project_splash() const {
Error err = OK;
Ref<Image> splash; Ref<Image> splash;
splash.instantiate(); splash.instantiate();
const String splash_path = String(GLOBAL_GET("application/boot_splash/image")).strip_edges(); const String splash_path = String(GLOBAL_GET("application/boot_splash/image")).strip_edges();
if (splash_path.is_empty() || ImageLoader::load_image(splash_path, splash) != OK) { if (!splash_path.is_empty()) {
splash = _load_icon_or_splash_image(splash_path, &err);
}
if (splash_path.is_empty() || err != OK || splash.is_null() || splash->is_empty()) {
return Ref<Image>(memnew(Image(boot_splash_png))); return Ref<Image>(memnew(Image(boot_splash_png)));
} }
return splash; return splash;

View file

@ -93,10 +93,9 @@ Error EditorExportPlatformWindows::_process_icon(const Ref<EditorExportPreset> &
f->seek(prev_offset); f->seek(prev_offset);
} }
} else { } else {
Ref<Image> src_image; Ref<Image> src_image = _load_icon_or_splash_image(p_src_path, &err);
src_image.instantiate(); ERR_FAIL_COND_V(err != OK || src_image.is_null() || src_image->is_empty(), ERR_CANT_OPEN);
err = ImageLoader::load_image(p_src_path, src_image);
ERR_FAIL_COND_V(err != OK || src_image->is_empty(), ERR_CANT_OPEN);
for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) { for (size_t i = 0; i < sizeof(icon_size) / sizeof(icon_size[0]); ++i) {
int size = (icon_size[i] == 0) ? 256 : icon_size[i]; int size = (icon_size[i] == 0) ? 256 : icon_size[i];