Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy project icons to Gradle project directory during Android Custom Build. #40348

Merged
merged 1 commit into from
Jul 23, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 100 additions & 53 deletions platform/android/export/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/*************************************************************************/

#include "export.h"
#include "gradle_export_util.h"
amanj120 marked this conversation as resolved.
Show resolved Hide resolved

#include "core/io/image_loader.h"
#include "core/io/marshalls.h"
Expand Down Expand Up @@ -1408,23 +1409,81 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
//printf("end\n");
}

void _process_launcher_icons(const String &p_processing_file_name, const Ref<Image> &p_source_image, const LauncherIcon p_icon, Vector<uint8_t> &p_data) {
if (p_processing_file_name == p_icon.export_path) {
Ref<Image> working_image = p_source_image;
void _process_launcher_icons(const String &p_file_name, const Ref<Image> &p_source_image, int dimension, Vector<uint8_t> &p_data) {
Ref<Image> working_image = p_source_image;

if (p_source_image->get_width() != p_icon.dimensions || p_source_image->get_height() != p_icon.dimensions) {
working_image = p_source_image->duplicate();
working_image->resize(p_icon.dimensions, p_icon.dimensions, Image::Interpolation::INTERPOLATE_LANCZOS);
if (p_source_image->get_width() != dimension || p_source_image->get_height() != dimension) {
working_image = p_source_image->duplicate();
working_image->resize(dimension, dimension, Image::Interpolation::INTERPOLATE_LANCZOS);
}

Vector<uint8_t> png_buffer;
Error err = PNGDriverCommon::image_to_png(working_image, png_buffer);
if (err == OK) {
p_data.resize(png_buffer.size());
memcpy(p_data.ptrw(), png_buffer.ptr(), p_data.size());
} else {
String err_str = String("Failed to convert resized icon (") + p_file_name + ") to png.";
WARN_PRINT(err_str.utf8().get_data());
}
}

void load_icon_refs(const Ref<EditorExportPreset> &p_preset, Ref<Image> &icon, Ref<Image> &foreground, Ref<Image> &background) {
String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon");

icon.instance();
foreground.instance();
background.instance();

// Regular icon: user selection -> project icon -> default.
String path = static_cast<String>(p_preset->get(launcher_icon_option)).strip_edges();
if (path.empty() || ImageLoader::load_image(path, icon) != OK) {
ImageLoader::load_image(project_icon_path, icon);
}

// 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();
if (path.empty() || ImageLoader::load_image(path, foreground) != OK) {
foreground = icon;
}

// Adaptive background: user selection -> default.
path = static_cast<String>(p_preset->get(launcher_adaptive_icon_background_option)).strip_edges();
if (!path.empty()) {
ImageLoader::load_image(path, background);
}
}

void store_image(const LauncherIcon launcher_icon, const Vector<uint8_t> &data) {
String img_path = launcher_icon.export_path;
img_path = img_path.insert(0, "res://android/build/");
store_file_at_path(img_path, data);
}

void _copy_icons_to_gradle_project(const Ref<EditorExportPreset> &p_preset, const Ref<Image> &main_image,
const Ref<Image> &foreground, const Ref<Image> &background) {
// Prepare images to be resized for the icons. If some image ends up being uninitialized,
// the default image from the export template will be used.

for (int i = 0; i < icon_densities_count; ++i) {
if (main_image.is_valid() && !main_image->empty()) {
Vector<uint8_t> data;
_process_launcher_icons(launcher_icons[i].export_path, main_image, launcher_icons[i].dimensions, data);
store_image(launcher_icons[i], data);
}

Vector<uint8_t> png_buffer;
Error err = PNGDriverCommon::image_to_png(working_image, png_buffer);
if (err == OK) {
p_data.resize(png_buffer.size());
memcpy(p_data.ptrw(), png_buffer.ptr(), p_data.size());
} else {
String err_str = String("Failed to convert resized icon (") + p_processing_file_name + ") to png.";
WARN_PRINT(err_str.utf8().get_data());
if (foreground.is_valid() && !foreground->empty()) {
Vector<uint8_t> data;
_process_launcher_icons(launcher_adaptive_icon_foregrounds[i].export_path, foreground,
launcher_adaptive_icon_foregrounds[i].dimensions, data);
store_image(launcher_adaptive_icon_foregrounds[i], data);
}

if (background.is_valid() && !background->empty()) {
Vector<uint8_t> data;
_process_launcher_icons(launcher_adaptive_icon_backgrounds[i].export_path, background,
launcher_adaptive_icon_backgrounds[i].dimensions, data);
store_image(launcher_adaptive_icon_backgrounds[i], data);
}
}
}
Expand Down Expand Up @@ -2006,6 +2065,12 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {

bool use_custom_build = bool(p_preset->get("custom_template/use_custom_build"));
amanj120 marked this conversation as resolved.
Show resolved Hide resolved

Ref<Image> main_image;
Ref<Image> foreground;
Ref<Image> background;

load_icon_refs(p_preset, main_image, foreground, background);

if (use_custom_build) {
//re-generate build.gradle and AndroidManifest.xml
{ //test that installed build version is alright
Expand All @@ -2028,6 +2093,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
if (err != OK) {
EditorNode::add_io_error("Unable to overwrite res://android/build/res/*.xml files with project name");
}
// Copies the project icon files into the appropriate Gradle project directory
_copy_icons_to_gradle_project(p_preset, main_image, foreground, background);

//build project if custom build is enabled
String sdk_path = EDITOR_GET("export/android/custom_build_sdk_path");

Expand Down Expand Up @@ -2157,34 +2225,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {

Vector<String> enabled_abis = get_enabled_abis(p_preset);

String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon");

// Prepare images to be resized for the icons. If some image ends up being uninitialized, the default image from the export template will be used.
Ref<Image> launcher_icon_image;
Ref<Image> launcher_adaptive_icon_foreground_image;
Ref<Image> launcher_adaptive_icon_background_image;

launcher_icon_image.instance();
launcher_adaptive_icon_foreground_image.instance();
launcher_adaptive_icon_background_image.instance();

// Regular icon: user selection -> project icon -> default.
String path = static_cast<String>(p_preset->get(launcher_icon_option)).strip_edges();
if (path.empty() || ImageLoader::load_image(path, launcher_icon_image) != OK) {
ImageLoader::load_image(project_icon_path, launcher_icon_image);
}

// 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();
if (path.empty() || ImageLoader::load_image(path, launcher_adaptive_icon_foreground_image) != OK) {
launcher_adaptive_icon_foreground_image = launcher_icon_image;
}

// Adaptive background: user selection -> default.
path = static_cast<String>(p_preset->get(launcher_adaptive_icon_background_option)).strip_edges();
if (!path.empty()) {
ImageLoader::load_image(path, launcher_adaptive_icon_background_image);
}

Vector<String> invalid_abis(enabled_abis);
while (ret == UNZ_OK) {
Expand All @@ -2211,21 +2252,27 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
_fix_manifest(p_preset, data, p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG));
}

if (file == "resources.arsc") {
if (!use_custom_build) {
if (!use_custom_build) {
if (file == "resources.arsc") {
_fix_resources(p_preset, data);
}
}

for (int i = 0; i < icon_densities_count; ++i) {
if (launcher_icon_image.is_valid() && !launcher_icon_image->empty()) {
_process_launcher_icons(file, launcher_icon_image, launcher_icons[i], data);
}
if (launcher_adaptive_icon_foreground_image.is_valid() && !launcher_adaptive_icon_foreground_image->empty()) {
_process_launcher_icons(file, launcher_adaptive_icon_foreground_image, launcher_adaptive_icon_foregrounds[i], data);
}
if (launcher_adaptive_icon_background_image.is_valid() && !launcher_adaptive_icon_background_image->empty()) {
_process_launcher_icons(file, launcher_adaptive_icon_background_image, launcher_adaptive_icon_backgrounds[i], data);
for (int i = 0; i < icon_densities_count; ++i) {
if (main_image.is_valid() && !main_image->empty()) {
if (file == launcher_icons[i].export_path) {
_process_launcher_icons(file, main_image, launcher_icons[i].dimensions, data);
}
}
if (foreground.is_valid() && !foreground->empty()) {
if (file == launcher_adaptive_icon_foregrounds[i].export_path) {
_process_launcher_icons(file, foreground, launcher_adaptive_icon_foregrounds[i].dimensions, data);
}
}
if (background.is_valid() && !background->empty()) {
if (file == launcher_adaptive_icon_backgrounds[i].export_path) {
_process_launcher_icons(file, background, launcher_adaptive_icon_backgrounds[i].dimensions, data);
}
}
}
}

Expand Down