diff --git a/platform/android/doc_classes/EditorExportPlatformAndroid.xml b/platform/android/doc_classes/EditorExportPlatformAndroid.xml index 983683fd780..4c9e6630b64 100644 --- a/platform/android/doc_classes/EditorExportPlatformAndroid.xml +++ b/platform/android/doc_classes/EditorExportPlatformAndroid.xml @@ -615,6 +615,10 @@ Application version visible to the user. Falls back to [member ProjectSettings.application/config/version] if left empty. + + If [code]true[/code], [url=https://developer.android.com/design/ui/wear/guides/components/swipe-to-dismiss]Swipe to dismiss[/url] will be enabled on Wear OS. + [b]Note:[/b] This is [code]true[/code] by default. To disable this behavior, [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] is required. + The extended reality (XR) mode for this application. diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 9d2bc917044..ae7b1fd65fd 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -1005,6 +1005,57 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref &p_preset) { + const String themes_xml_path = ExportTemplateManager::get_android_build_directory(p_preset).path_join("res/values/themes.xml"); + bool enable_swipe_to_dismiss = p_preset->get("wear_os/swipe_to_dismiss"); + + if (!FileAccess::exists(themes_xml_path)) { + print_error("res/values/themes.xml does not exist."); + return; + } + + String xml_content; + Ref file = FileAccess::open(themes_xml_path, FileAccess::READ); + PackedStringArray lines = file->get_as_text().split("\n"); + file->close(); + + // Check if the line contains the existing element. + // If found and `enable_swipe_to_dismiss` is true, remove the item. + // If found and `enable_swipe_to_dismiss` is false, update its value to "false". + bool found = false; + bool modified = false; + for (int i = 0; i < lines.size(); i++) { + String line = lines[i]; + if (line.contains("")) { + lines.set(i, vformat(" %s", bool_to_string(enable_swipe_to_dismiss))); + found = true; + modified = true; + break; + } + } + + // If is not found and `enable_swipe_to_dismiss` is false: + // Add a new element before the closing tag. + if (!found && !enable_swipe_to_dismiss) { + for (int i = 0; i < lines.size(); i++) { + if (lines[i].contains("")) { + lines.insert(i, " false"); + modified = true; + break; + } + } + } + + // Reconstruct the XML content from the modified lines. + if (modified) { + xml_content = String("\n").join(lines); + store_string_at_path(themes_xml_path, xml_content); + print_verbose("Successfully modified " + themes_xml_path + ": " + "\n" + xml_content); + } else { + print_verbose("No changes needed for " + themes_xml_path); + } +} + void EditorExportPlatformAndroid::_fix_manifest(const Ref &p_preset, Vector &p_manifest, bool p_give_internet) { // Leaving the unused types commented because looking these constants up // again later would be annoying @@ -1802,6 +1853,11 @@ String EditorExportPlatformAndroid::get_export_option_warning(const EditorExport if (!is_package_name_valid(pn, &pn_err)) { return TTR("Invalid package name:") + " " + pn_err; } + } else if (p_name == "wear_os/swipe_to_dismiss") { + bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build"); + if (!bool(p_preset->get("wear_os/swipe_to_dismiss")) && !gradle_build_enabled) { + return TTR("\"Use Gradle Build\" must be enabled to disable \"Swipe to dismiss\"."); + } } else if (p_name == "gradle_build/use_gradle_build") { bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build"); String enabled_plugins_names = _get_plugins_names(Ref(p_preset)); @@ -1932,6 +1988,8 @@ void EditorExportPlatformAndroid::get_export_options(List *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,OpenXR"), XR_MODE_REGULAR, false, true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "wear_os/swipe_to_dismiss"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_small"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_normal"), true)); @@ -1969,6 +2027,7 @@ bool EditorExportPlatformAndroid::get_export_option_visibility(const EditorExpor p_option == "package/exclude_from_recents" || p_option == "package/show_in_app_library" || p_option == "package/show_as_launcher_app" || + p_option == "wear_os/swipe_to_dismiss" || p_option == "apk_expansion/enable" || p_option == "apk_expansion/SALT" || p_option == "apk_expansion/public_key") { @@ -3171,6 +3230,8 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref &p_preset, bool p_give_internet, bool p_debug); + void _fix_themes_xml(const Ref &p_preset); + void _fix_manifest(const Ref &p_preset, Vector &p_manifest, bool p_give_internet); static String _get_keystore_path(const Ref &p_preset, bool p_debug); diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml index 3c86e54df52..c97054233cb 100644 --- a/platform/android/java/app/res/values/themes.xml +++ b/platform/android/java/app/res/values/themes.xml @@ -2,7 +2,8 @@