diff --git a/main/main.cpp b/main/main.cpp index 44201522af14..1cbd732747bf 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2896,7 +2896,7 @@ Error Main::setup2() { MAIN_PRINT("Main: Setup Logo"); -#if !defined(TOOLS_ENABLED) && (defined(WEB_ENABLED) || defined(ANDROID_ENABLED)) +#if !defined(TOOLS_ENABLED) && defined(WEB_ENABLED) bool show_logo = false; #else bool show_logo = true; diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index eebef3f96914..ad00659257de 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -212,11 +212,6 @@ static const char *android_perms[] = { static const char *MISMATCHED_VERSIONS_MESSAGE = "Android build version mismatch:\n| Template installed: %s\n| Requested version: %s\nPlease reinstall Android build template from 'Project' menu."; -static const char *SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi/splash.png"; -static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v4/splash.png"; -static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png"; -static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png"; -static const char *SPLASH_CONFIG_PATH = "res/drawable/splash_drawable.xml"; static const char *GDEXTENSION_LIBS_PATH = "libs/gdextensionlibs.json"; static const int icon_densities_count = 6; @@ -1642,67 +1637,6 @@ void EditorExportPlatformAndroid::_process_launcher_icons(const String &p_file_n } } -String EditorExportPlatformAndroid::load_splash_refs(Ref &splash_image, Ref &splash_bg_color_image) { - bool scale_splash = GLOBAL_GET("application/boot_splash/fullsize"); - bool apply_filter = GLOBAL_GET("application/boot_splash/use_filter"); - bool show_splash_image = GLOBAL_GET("application/boot_splash/show_image"); - String project_splash_path = GLOBAL_GET("application/boot_splash/image"); - - // Setup the splash bg color. - bool bg_color_valid = false; - Color bg_color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color", &bg_color_valid); - if (!bg_color_valid) { - bg_color = boot_splash_bg_color; - } - - if (show_splash_image) { - if (!project_splash_path.is_empty()) { - splash_image.instantiate(); - print_verbose("Loading splash image: " + project_splash_path); - const Error err = ImageLoader::load_image(project_splash_path, splash_image); - if (err) { - if (OS::get_singleton()->is_stdout_verbose()) { - print_error("- unable to load splash image from " + project_splash_path + " (" + itos(err) + ")"); - } - splash_image.unref(); - } - } - } else { - splash_image.instantiate(); - splash_image->initialize_data(1, 1, false, Image::FORMAT_RGBA8); - splash_image->set_pixel(0, 0, bg_color); - } - - if (splash_image.is_null()) { - // Use the default - print_verbose("Using default splash image."); - splash_image = Ref(memnew(Image(boot_splash_png))); - } - - if (scale_splash) { - Size2 screen_size = Size2(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height")); - int width, height; - if (screen_size.width > screen_size.height) { - // scale horizontally - height = screen_size.height; - width = splash_image->get_width() * screen_size.height / splash_image->get_height(); - } else { - // scale vertically - width = screen_size.width; - height = splash_image->get_height() * screen_size.width / splash_image->get_width(); - } - splash_image->resize(width, height); - } - - print_verbose("Creating splash background color image."); - splash_bg_color_image.instantiate(); - splash_bg_color_image->initialize_data(splash_image->get_width(), splash_image->get_height(), false, splash_image->get_format()); - splash_bg_color_image->fill(bg_color); - - String processed_splash_config_xml = vformat(SPLASH_CONFIG_XML_CONTENT, bool_to_string(apply_filter)); - return processed_splash_config_xml; -} - void EditorExportPlatformAndroid::load_icon_refs(const Ref &p_preset, Ref &icon, Ref &foreground, Ref &background) { String project_icon_path = GLOBAL_GET("application/config/icon"); @@ -1739,61 +1673,34 @@ void EditorExportPlatformAndroid::load_icon_refs(const Ref & } void EditorExportPlatformAndroid::_copy_icons_to_gradle_project(const Ref &p_preset, - const String &processed_splash_config_xml, - const Ref &splash_image, - const Ref &splash_bg_color_image, - const Ref &main_image, - const Ref &foreground, - const Ref &background) { + const Ref &p_main_image, + const Ref &p_foreground, + const Ref &p_background) { String gradle_build_dir = ExportTemplateManager::get_android_build_directory(p_preset); - // Store the splash configuration - if (!processed_splash_config_xml.is_empty()) { - print_verbose("Storing processed splash configuration: " + String("\n") + processed_splash_config_xml); - store_string_at_path(gradle_build_dir.path_join(SPLASH_CONFIG_PATH), processed_splash_config_xml); - } - - // Store the splash image - if (splash_image.is_valid() && !splash_image->is_empty()) { - String splash_export_path = gradle_build_dir.path_join(SPLASH_IMAGE_EXPORT_PATH); - print_verbose("Storing splash image in " + splash_export_path); - Vector data; - _load_image_data(splash_image, data); - store_file_at_path(splash_export_path, data); - } - - // Store the splash bg color image - if (splash_bg_color_image.is_valid() && !splash_bg_color_image->is_empty()) { - String splash_bg_color_path = gradle_build_dir.path_join(SPLASH_BG_COLOR_PATH); - print_verbose("Storing splash background image in " + splash_bg_color_path); - Vector data; - _load_image_data(splash_bg_color_image, data); - store_file_at_path(splash_bg_color_path, data); - } - // 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->is_empty()) { + if (p_main_image.is_valid() && !p_main_image->is_empty()) { print_verbose("Processing launcher icon for dimension " + itos(launcher_icons[i].dimensions) + " into " + launcher_icons[i].export_path); Vector data; - _process_launcher_icons(launcher_icons[i].export_path, main_image, launcher_icons[i].dimensions, data); + _process_launcher_icons(launcher_icons[i].export_path, p_main_image, launcher_icons[i].dimensions, data); store_file_at_path(gradle_build_dir.path_join(launcher_icons[i].export_path), data); } - if (foreground.is_valid() && !foreground->is_empty()) { - print_verbose("Processing launcher adaptive icon foreground for dimension " + itos(launcher_adaptive_icon_foregrounds[i].dimensions) + " into " + launcher_adaptive_icon_foregrounds[i].export_path); + if (p_foreground.is_valid() && !p_foreground->is_empty()) { + print_verbose("Processing launcher adaptive icon p_foreground for dimension " + itos(launcher_adaptive_icon_foregrounds[i].dimensions) + " into " + launcher_adaptive_icon_foregrounds[i].export_path); Vector data; - _process_launcher_icons(launcher_adaptive_icon_foregrounds[i].export_path, foreground, + _process_launcher_icons(launcher_adaptive_icon_foregrounds[i].export_path, p_foreground, launcher_adaptive_icon_foregrounds[i].dimensions, data); store_file_at_path(gradle_build_dir.path_join(launcher_adaptive_icon_foregrounds[i].export_path), data); } - if (background.is_valid() && !background->is_empty()) { - print_verbose("Processing launcher adaptive icon background for dimension " + itos(launcher_adaptive_icon_backgrounds[i].dimensions) + " into " + launcher_adaptive_icon_backgrounds[i].export_path); + if (p_background.is_valid() && !p_background->is_empty()) { + print_verbose("Processing launcher adaptive icon p_background for dimension " + itos(launcher_adaptive_icon_backgrounds[i].dimensions) + " into " + launcher_adaptive_icon_backgrounds[i].export_path); Vector data; - _process_launcher_icons(launcher_adaptive_icon_backgrounds[i].export_path, background, + _process_launcher_icons(launcher_adaptive_icon_backgrounds[i].export_path, p_background, launcher_adaptive_icon_backgrounds[i].dimensions, data); store_file_at_path(gradle_build_dir.path_join(launcher_adaptive_icon_backgrounds[i].export_path), data); } @@ -3093,10 +3000,6 @@ Error EditorExportPlatformAndroid::export_project_helper(const Refget_include_filter()); print_verbose("- exclude filter: " + p_preset->get_exclude_filter()); - Ref splash_image; - Ref splash_bg_color_image; - String processed_splash_config_xml = load_splash_refs(splash_image, splash_bg_color_image); - Ref main_image; Ref foreground; Ref background; @@ -3172,7 +3075,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Refis_empty()) { - _load_image_data(splash_image, data); - } - - // Process the splash bg color image - if ((file == SPLASH_BG_COLOR_PATH || file == LEGACY_BUILD_SPLASH_BG_COLOR_PATH) && splash_bg_color_image.is_valid() && !splash_bg_color_image->is_empty()) { - _load_image_data(splash_bg_color_image, data); - } - if (file.ends_with(".png") && file.contains("mipmap")) { for (int i = 0; i < icon_densities_count; ++i) { if (main_image.is_valid() && !main_image->is_empty()) { diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index 679afdc50f73..97bbd0c7bcc5 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -39,18 +39,6 @@ #include "core/os/os.h" #include "editor/export/editor_export_platform.h" -const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH( - - - - - - -)SPLASH"; - // Optional environment variables for defining confidential information. If any // of these is set, they will override the values set in the credentials file. const String ENV_ANDROID_KEYSTORE_DEBUG_PATH = "GODOT_ANDROID_KEYSTORE_DEBUG_PATH"; @@ -179,17 +167,12 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { void _process_launcher_icons(const String &p_file_name, const Ref &p_source_image, int dimension, Vector &p_data); - String load_splash_refs(Ref &splash_image, Ref &splash_bg_color_image); - void load_icon_refs(const Ref &p_preset, Ref &icon, Ref &foreground, Ref &background); void _copy_icons_to_gradle_project(const Ref &p_preset, - const String &processed_splash_config_xml, - const Ref &splash_image, - const Ref &splash_bg_color_image, - const Ref &main_image, - const Ref &foreground, - const Ref &background); + const Ref &p_main_image, + const Ref &p_foreground, + const Ref &p_background); static void _create_editor_debug_keystore_if_needed(); diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle index bde6a93c860b..01d5d9ef9294 100644 --- a/platform/android/java/app/build.gradle +++ b/platform/android/java/app/build.gradle @@ -32,6 +32,7 @@ configurations { dependencies { implementation "androidx.fragment:fragment:$versions.fragmentVersion" + implementation "androidx.core:core-splashscreen:$versions.splashscreenVersion" if (rootProject.findProject(":lib")) { implementation project(":lib") diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index c404af34d819..01759a1b2fd0 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -11,7 +11,8 @@ ext.versions = [ nexusPublishVersion: '1.3.0', javaVersion : JavaVersion.VERSION_17, // Also update 'platform/android/detect.py#get_ndk_version()' when this is updated. - ndkVersion : '23.2.8568313' + ndkVersion : '23.2.8568313', + splashscreenVersion: '1.0.1' ] diff --git a/platform/android/java/app/res/drawable-nodpi/splash.png b/platform/android/java/app/res/drawable-nodpi/splash.png deleted file mode 100644 index 7bddd4325a8e..000000000000 Binary files a/platform/android/java/app/res/drawable-nodpi/splash.png and /dev/null differ diff --git a/platform/android/java/app/res/drawable-nodpi/splash_bg_color.png b/platform/android/java/app/res/drawable-nodpi/splash_bg_color.png deleted file mode 100644 index 004b6fd50831..000000000000 Binary files a/platform/android/java/app/res/drawable-nodpi/splash_bg_color.png and /dev/null differ diff --git a/platform/android/java/app/res/drawable/splash_drawable.xml b/platform/android/java/app/res/drawable/splash_drawable.xml deleted file mode 100644 index 30627b998c23..000000000000 --- a/platform/android/java/app/res/drawable/splash_drawable.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml index d64b50ca4561..3ab840192876 100644 --- a/platform/android/java/app/res/values/themes.xml +++ b/platform/android/java/app/res/values/themes.xml @@ -3,8 +3,17 @@ diff --git a/platform/android/java/app/src/com/godot/game/GodotApp.java b/platform/android/java/app/src/com/godot/game/GodotApp.java index 9142d767b4bd..22e617f6e738 100644 --- a/platform/android/java/app/src/com/godot/game/GodotApp.java +++ b/platform/android/java/app/src/com/godot/game/GodotApp.java @@ -34,6 +34,8 @@ import org.godotengine.godot.GodotActivity; import android.os.Bundle; +import androidx.core.splashscreen.SplashScreen; + /** * Template activity for Godot Android builds. * Feel free to extend and modify this class for your custom logic. @@ -41,7 +43,7 @@ import android.os.Bundle; public class GodotApp extends GodotActivity { @Override public void onCreate(Bundle savedInstanceState) { - setTheme(R.style.GodotAppMainTheme); + SplashScreen.installSplashScreen(this); super.onCreate(savedInstanceState); } } diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle index c5ef08615206..55fe2a22feaa 100644 --- a/platform/android/java/editor/build.gradle +++ b/platform/android/java/editor/build.gradle @@ -10,6 +10,8 @@ dependencies { implementation project(":lib") implementation "androidx.window:window:1.2.0" + implementation "androidx.core:core-splashscreen:$versions.splashscreenVersion" + implementation "androidx.constraintlayout:constraintlayout:2.1.4" } ext { @@ -92,6 +94,10 @@ android { targetSdkVersion versions.targetSdk missingDimensionStrategy 'products', 'editor' + manifestPlaceholders += [ + editorAppName: "Godot Editor 4", + editorBuildSuffix: "" + ] } base { @@ -124,11 +130,13 @@ android { dev { initWith debug applicationIdSuffix ".dev" + manifestPlaceholders += [editorBuildSuffix: " (dev)"] } debug { initWith release applicationIdSuffix ".debug" + manifestPlaceholders += [editorBuildSuffix: " (debug)"] signingConfig signingConfigs.debug } diff --git a/platform/android/java/editor/src/debug/res/values/strings.xml b/platform/android/java/editor/src/debug/res/values/strings.xml deleted file mode 100644 index 09ee2d77e19d..000000000000 --- a/platform/android/java/editor/src/debug/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Godot Editor 4 (debug) - diff --git a/platform/android/java/editor/src/dev/res/values/strings.xml b/platform/android/java/editor/src/dev/res/values/strings.xml deleted file mode 100644 index 215f2c7d0ac1..000000000000 --- a/platform/android/java/editor/src/dev/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Godot Editor 4 (dev) - diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml index f646ef3f51bc..c7d14a3f4914 100644 --- a/platform/android/java/editor/src/main/AndroidManifest.xml +++ b/platform/android/java/editor/src/main/AndroidManifest.xml @@ -13,12 +13,15 @@ android:glEsVersion="0x00030000" android:required="true" /> - - - + + @@ -26,39 +29,44 @@ + android:label="${editorAppName}${editorBuildSuffix}" + android:requestLegacyExternalStorage="true" + android:theme="@style/GodotEditorSplashScreenTheme" + tools:ignore="GoogleAppIndexingWarning"> + - + android:screenOrientation="userLandscape"> + + - - + - diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt index 52acd63674b4..5515347bd61b 100644 --- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt +++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt @@ -38,8 +38,10 @@ import android.content.Intent import android.content.pm.PackageManager import android.os.* import android.util.Log +import android.view.View import android.widget.Toast import androidx.annotation.CallSuper +import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.window.layout.WindowMetricsCalculator import org.godotengine.godot.GodotActivity import org.godotengine.godot.GodotLib @@ -88,8 +90,13 @@ open class GodotEditor : GodotActivity() { } private val commandLineParams = ArrayList() + private val editorLoadingIndicator: View? by lazy { findViewById(R.id.editor_loading_indicator) } + + override fun getGodotAppLayout() = R.layout.godot_editor_layout override fun onCreate(savedInstanceState: Bundle?) { + installSplashScreen() + // We exclude certain permissions from the set we request at startup, as they'll be // requested on demand based on use-cases. PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO)) @@ -121,6 +128,14 @@ open class GodotEditor : GodotActivity() { } } + override fun onGodotMainLoopStarted() { + super.onGodotMainLoopStarted() + runOnUiThread { + // Hide the loading indicator + editorLoadingIndicator?.visibility = View.GONE + } + } + /** * Check for project permissions to enable */ diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt index aa4d02b5b252..8e4e08921192 100644 --- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt +++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt @@ -34,6 +34,9 @@ package org.godotengine.editor * Drives the 'run project' window of the Godot Editor. */ class GodotGame : GodotEditor() { + + override fun getGodotAppLayout() = org.godotengine.godot.R.layout.godot_app_layout + override fun overrideOrientationRequest() = false override fun enableLongPressGestures() = false diff --git a/platform/android/java/editor/src/main/res/layout/godot_editor_layout.xml b/platform/android/java/editor/src/main/res/layout/godot_editor_layout.xml new file mode 100644 index 000000000000..431a468f2904 --- /dev/null +++ b/platform/android/java/editor/src/main/res/layout/godot_editor_layout.xml @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/platform/android/java/editor/src/main/res/values/strings.xml b/platform/android/java/editor/src/main/res/values/strings.xml index 216d02d9c749..909711ab180d 100644 --- a/platform/android/java/editor/src/main/res/values/strings.xml +++ b/platform/android/java/editor/src/main/res/values/strings.xml @@ -1,6 +1,4 @@ - Godot Editor 4 - Missing storage access permission! diff --git a/platform/android/java/editor/src/main/res/values/themes.xml b/platform/android/java/editor/src/main/res/values/themes.xml index fda04d6dc7d1..2b352247db4c 100644 --- a/platform/android/java/editor/src/main/res/values/themes.xml +++ b/platform/android/java/editor/src/main/res/values/themes.xml @@ -2,4 +2,10 @@ + + diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt index 7b8fad895293..4c5e857b7ac2 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt @@ -36,6 +36,7 @@ import android.content.pm.PackageManager import android.os.Bundle import android.util.Log import androidx.annotation.CallSuper +import androidx.annotation.LayoutRes import androidx.fragment.app.FragmentActivity import org.godotengine.godot.utils.PermissionsUtil import org.godotengine.godot.utils.ProcessPhoenix @@ -65,7 +66,7 @@ abstract class GodotActivity : FragmentActivity(), GodotHost { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.godot_app_layout) + setContentView(getGodotAppLayout()) handleStartIntent(intent, true) @@ -80,6 +81,9 @@ abstract class GodotActivity : FragmentActivity(), GodotHost { } } + @LayoutRes + protected open fun getGodotAppLayout() = R.layout.godot_app_layout + override fun onDestroy() { Log.v(TAG, "Destroying Godot app...") super.onDestroy()