From d17811c8142920635faafa972cb9de58ac5b4e05 Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio Date: Sun, 2 Jul 2023 11:14:29 -0700 Subject: [PATCH] Re-architect how Android plugins are packaged and handled at export time The previous packaging format for Godot Android plugins consisted of the plugin's `gdap` config file accompanied by binaries defined in the `gdap` file. This format is now deprecated (starting with Godot 4.2), and instead Godot Android plugins are now packaged as `EditorExportPlugin` plugins. The `EditorExportPlugin` class has been updated with the following methods to provide the necessary set of functionality: - `_supports_platform`: returns true if the plugin supports the given platform - `_get_android_dependencies`: retrieve the set of android dependencies (e.g: `org.godot.example:my-plugin:0.0.0`) provided by the plugin - `_get_android_dependencies_maven_repos`: retrieve the urls of the maven repos for the provided android dependencies - `_get_android_libraries`: retrieve the local paths of the android libraries (AAR files) provided by the plugin - `_get_android_manifest_activity_element_contents`: update the contents of the `` element in the generated Android manifest - `_get_android_manifest_application_element_contents`: update the contents of the `` element in the generated Android manifest - `_get_android_manifest_element_contents`: update the contents of the `` element in the generated Android manifest --- doc/classes/EditorExportPlugin.xml | 75 ++++++++ doc/classes/EditorPlugin.xml | 6 + editor/editor_node.cpp | 6 + editor/editor_plugin.cpp | 9 + editor/editor_plugin.h | 3 + editor/export/editor_export_platform.cpp | 24 ++- editor/export/editor_export_plugin.cpp | 81 ++++++++- editor/export/editor_export_plugin.h | 27 ++- editor/export/editor_export_preset.cpp | 21 ++- editor/export/export_template_manager.cpp | 7 +- .../plugins/dedicated_server_export_plugin.h | 2 +- editor/plugins/gdextension_export_plugin.h | 2 +- modules/gdscript/register_types.cpp | 2 +- platform/android/export/export_plugin.cpp | 165 +++++++++++++++--- platform/android/export/export_plugin.h | 36 ++-- .../android/export/godot_plugin_config.cpp | 36 ++-- platform/android/export/godot_plugin_config.h | 12 +- .../android/export/gradle_export_util.cpp | 45 +++-- platform/android/export/gradle_export_util.h | 6 +- 19 files changed, 457 insertions(+), 108 deletions(-) diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml index fa824478940..75641a44869 100644 --- a/doc/classes/EditorExportPlugin.xml +++ b/doc/classes/EditorExportPlugin.xml @@ -8,6 +8,7 @@ To use [EditorExportPlugin], register it using the [method EditorPlugin.add_export_plugin] method first. + $DOCS_URL/tutorials/platform/android/android_plugin.html @@ -84,6 +85,64 @@ Calling [method skip] inside this callback will make the file not included in the export. + + + + + + Virtual method to be overridden by the user. This is called to retrieve the set of Android dependencies provided by this plugin. Each returned Android dependency should have the format of an Android remote binary dependency: [code]org.godot.example:my-plugin:0.0.0[/code] + For more information see [url=https://developer.android.com/build/dependencies?agpversion=4.1#dependency-types]Android documentation on dependencies[/url]. + [b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled. + + + + + + + + Virtual method to be overridden by the user. This is called to retrieve the URLs of Maven repositories for the set of Android dependencies provided by this plugin. + For more information see [url=https://docs.gradle.org/current/userguide/dependency_management.html#sec:maven_repo]Gradle documentation on dependency management[/url]. + [b]Note:[/b] Google's Maven repo and the Maven Central repo are already included by default. + [b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled. + + + + + + + + Virtual method to be overridden by the user. This is called to retrieve the local paths of the Android libraries archive (AAR) files provided by this plugin. + [b]Note:[/b] Relative paths **must** be relative to Godot's [code]res://addons/[/code] directory. For example, an AAR file located under [code]res://addons/hello_world_plugin/HelloWorld.release.aar[/code] can be returned as an absolute path using [code]res://addons/hello_world_plugin/HelloWorld.release.aar[/code] or a relative path using [code]hello_world_plugin/HelloWorld.release.aar[/code]. + [b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled. + + + + + + + + Virtual method to be overridden by the user. This is used at export time to update the contents of the [code]activity[/code] element in the generated Android manifest. + [b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled. + + + + + + + + Virtual method to be overridden by the user. This is used at export time to update the contents of the [code]application[/code] element in the generated Android manifest. + [b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled. + + + + + + + + Virtual method to be overridden by the user. This is used at export time to update the contents of the [code]manifest[/code] element in the generated Android manifest. + [b]Note:[/b] Only supported on Android and requires [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] to be enabled. + + @@ -99,6 +158,15 @@ Return a [PackedStringArray] of additional features this preset, for the given [param platform], should have. + + + + + + Check the requirements for the given [param option] and return a non-empty warning string if they are not met. + [b]Note:[/b] Use [method get_option] to check the value of the export options. + + @@ -124,6 +192,13 @@ Return [code]true[/code], if the result of [method _get_export_options] has changed and the export options of preset corresponding to [param platform] should be updated. + + + + + Return [code]true[/code] if the plugin supports the given [param platform]. + + diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 5b22d1e4ff9..3429062328b 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -569,6 +569,12 @@ Returns the [PopupMenu] under [b]Scene > Export As...[/b]. + + + + Provide the version of the plugin declared in the [code]plugin.cfg[/code] config file. + + diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index d61682c7363..5029a122645 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -3363,6 +3363,11 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, return; } + String plugin_version; + if (cf->has_section_key("plugin", "version")) { + plugin_version = cf->get_value("plugin", "version"); + } + if (!cf->has_section_key("plugin", "script")) { show_warning(vformat(TTR("Unable to find script field for addon plugin at: '%s'."), addon_path)); return; @@ -3408,6 +3413,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, EditorPlugin *ep = memnew(EditorPlugin); ep->set_script(scr); + ep->set_plugin_version(plugin_version); addon_name_to_plugin[addon_path] = ep; add_editor_plugin(ep, p_config_changed); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 1fe18880f70..2d4c07b2636 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -307,6 +307,14 @@ const Ref EditorPlugin::get_icon() const { return icon; } +String EditorPlugin::get_plugin_version() const { + return plugin_version; +} + +void EditorPlugin::set_plugin_version(const String &p_version) { + plugin_version = p_version; +} + bool EditorPlugin::has_main_screen() const { bool success = false; GDVIRTUAL_CALL(_has_main_screen, success); @@ -583,6 +591,7 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("get_script_create_dialog"), &EditorPlugin::get_script_create_dialog); ClassDB::bind_method(D_METHOD("add_debugger_plugin", "script"), &EditorPlugin::add_debugger_plugin); ClassDB::bind_method(D_METHOD("remove_debugger_plugin", "script"), &EditorPlugin::remove_debugger_plugin); + ClassDB::bind_method(D_METHOD("get_plugin_version"), &EditorPlugin::get_plugin_version); GDVIRTUAL_BIND(_forward_canvas_gui_input, "event"); GDVIRTUAL_BIND(_forward_canvas_draw_over_viewport, "viewport_control"); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 2bcdd387ff3..7dcf62144d6 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -61,6 +61,7 @@ class EditorPlugin : public Node { bool force_draw_over_forwarding_enabled = false; String last_main_screen_name; + String plugin_version; void _editor_project_settings_changed(); @@ -168,6 +169,8 @@ public: virtual String get_name() const; virtual const Ref get_icon() const; + virtual String get_plugin_version() const; + virtual void set_plugin_version(const String &p_version); virtual bool has_main_screen() const; virtual void make_visible(bool p_visible); virtual void selected_notify() {} //notify that it was raised by the user, not the editor diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index 79a27bd3376..5ee9b187a22 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -990,7 +990,7 @@ Error EditorExportPlatform::export_project_files(const Ref & struct SortByName { bool operator()(const Ref &left, const Ref &right) const { - return left->_get_name() < right->_get_name(); + return left->get_name() < right->get_name(); } }; @@ -1033,14 +1033,14 @@ Error EditorExportPlatform::export_project_files(const Ref & if (export_plugins.write[i]->_begin_customize_resources(Ref(this), features_psa)) { customize_resources_plugins.push_back(export_plugins[i]); - custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->_get_name().hash64(), custom_resources_hash); + custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->get_name().hash64(), custom_resources_hash); uint64_t hash = export_plugins[i]->_get_customization_configuration_hash(); custom_resources_hash = hash_murmur3_one_64(hash, custom_resources_hash); } if (export_plugins.write[i]->_begin_customize_scenes(Ref(this), features_psa)) { customize_scenes_plugins.push_back(export_plugins[i]); - custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->_get_name().hash64(), custom_resources_hash); + custom_resources_hash = hash_murmur3_one_64(export_plugins[i]->get_name().hash64(), custom_resources_hash); uint64_t hash = export_plugins[i]->_get_customization_configuration_hash(); custom_scene_hash = hash_murmur3_one_64(hash, custom_scene_hash); } @@ -1800,6 +1800,24 @@ bool EditorExportPlatform::can_export(const Ref &p_preset, S if (!templates_error.is_empty()) { r_error += templates_error; } + + String export_plugins_warning; + Vector> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + Ref export_platform = Ref(this); + if (!export_plugins[i]->supports_platform(export_platform)) { + continue; + } + + String plugin_warning = export_plugins.write[i]->_has_valid_export_configuration(export_platform, p_preset); + if (!plugin_warning.is_empty()) { + export_plugins_warning += plugin_warning; + } + } + + if (!export_plugins_warning.is_empty()) { + r_error += export_plugins_warning; + } #endif String project_configuration_error; diff --git a/editor/export/editor_export_plugin.cpp b/editor/export/editor_export_plugin.cpp index 4e2c1a9af72..6576960b9a0 100644 --- a/editor/export/editor_export_plugin.cpp +++ b/editor/export/editor_export_plugin.cpp @@ -132,6 +132,27 @@ Variant EditorExportPlugin::get_option(const StringName &p_name) const { return export_preset->get(p_name); } +String EditorExportPlugin::_has_valid_export_configuration(const Ref &p_export_platform, const Ref &p_preset) { + String warning; + if (!supports_platform(p_export_platform)) { + warning += vformat(TTR("Plugin \"%s\" is not supported on \"%s\""), get_name(), p_export_platform->get_name()); + warning += "\n"; + return warning; + } + + set_export_preset(p_preset); + List options; + _get_export_options(p_export_platform, &options); + for (const EditorExportPlatform::ExportOption &E : options) { + String option_warning = _get_export_option_warning(p_export_platform, E.option.name); + if (!option_warning.is_empty()) { + warning += option_warning + "\n"; + } + } + + return warning; +} + void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const Vector &p_features) { GDVIRTUAL_CALL(_export_file, p_path, p_type, p_features); } @@ -184,12 +205,54 @@ void EditorExportPlugin::_end_customize_resources() { GDVIRTUAL_CALL(_end_customize_resources); } -String EditorExportPlugin::_get_name() const { +String EditorExportPlugin::get_name() const { String ret; GDVIRTUAL_REQUIRED_CALL(_get_name, ret); return ret; } +bool EditorExportPlugin::supports_platform(const Ref &p_export_platform) const { + bool ret = false; + GDVIRTUAL_CALL(_supports_platform, p_export_platform, ret); + return ret; +} + +PackedStringArray EditorExportPlugin::get_android_dependencies(const Ref &p_export_platform, bool p_debug) const { + PackedStringArray ret; + GDVIRTUAL_CALL(_get_android_dependencies, p_export_platform, p_debug, ret); + return ret; +} + +PackedStringArray EditorExportPlugin::get_android_dependencies_maven_repos(const Ref &p_export_platform, bool p_debug) const { + PackedStringArray ret; + GDVIRTUAL_CALL(_get_android_dependencies_maven_repos, p_export_platform, p_debug, ret); + return ret; +} + +PackedStringArray EditorExportPlugin::get_android_libraries(const Ref &p_export_platform, bool p_debug) const { + PackedStringArray ret; + GDVIRTUAL_CALL(_get_android_libraries, p_export_platform, p_debug, ret); + return ret; +} + +String EditorExportPlugin::get_android_manifest_activity_element_contents(const Ref &p_export_platform, bool p_debug) const { + String ret; + GDVIRTUAL_CALL(_get_android_manifest_activity_element_contents, p_export_platform, p_debug, ret); + return ret; +} + +String EditorExportPlugin::get_android_manifest_application_element_contents(const Ref &p_export_platform, bool p_debug) const { + String ret; + GDVIRTUAL_CALL(_get_android_manifest_application_element_contents, p_export_platform, p_debug, ret); + return ret; +} + +String EditorExportPlugin::get_android_manifest_element_contents(const Ref &p_export_platform, bool p_debug) const { + String ret; + GDVIRTUAL_CALL(_get_android_manifest_element_contents, p_export_platform, p_debug, ret); + return ret; +} + PackedStringArray EditorExportPlugin::_get_export_features(const Ref &p_platform, bool p_debug) const { PackedStringArray ret; GDVIRTUAL_CALL(_get_export_features, p_platform, p_debug, ret); @@ -216,6 +279,12 @@ bool EditorExportPlugin::_should_update_export_options(const Ref &p_export_platform, const String &p_option_name) const { + String ret; + GDVIRTUAL_CALL(_get_export_option_warning, p_export_platform, p_option_name, ret); + return ret; +} + void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet &p_features) { } @@ -257,9 +326,19 @@ void EditorExportPlugin::_bind_methods() { GDVIRTUAL_BIND(_get_export_options, "platform"); GDVIRTUAL_BIND(_should_update_export_options, "platform"); + GDVIRTUAL_BIND(_get_export_option_warning, "platform", "option"); GDVIRTUAL_BIND(_get_export_features, "platform", "debug"); GDVIRTUAL_BIND(_get_name); + + GDVIRTUAL_BIND(_supports_platform, "platform"); + + GDVIRTUAL_BIND(_get_android_dependencies, "platform", "debug"); + GDVIRTUAL_BIND(_get_android_dependencies_maven_repos, "platform", "debug"); + GDVIRTUAL_BIND(_get_android_libraries, "platform", "debug"); + GDVIRTUAL_BIND(_get_android_manifest_activity_element_contents, "platform", "debug"); + GDVIRTUAL_BIND(_get_android_manifest_application_element_contents, "platform", "debug"); + GDVIRTUAL_BIND(_get_android_manifest_element_contents, "platform", "debug"); } EditorExportPlugin::EditorExportPlugin() { diff --git a/editor/export/editor_export_plugin.h b/editor/export/editor_export_plugin.h index 120141b3479..7d866ce37e6 100644 --- a/editor/export/editor_export_plugin.h +++ b/editor/export/editor_export_plugin.h @@ -42,6 +42,7 @@ class EditorExportPlugin : public RefCounted { friend class EditorExport; friend class EditorExportPlatform; + friend class EditorExportPreset; Ref export_preset; @@ -85,6 +86,8 @@ class EditorExportPlugin : public RefCounted { void _export_begin_script(const Vector &p_features, bool p_debug, const String &p_path, int p_flags); void _export_end_script(); + String _has_valid_export_configuration(const Ref &p_export_platform, const Ref &p_preset); + protected: void set_export_preset(const Ref &p_preset); Ref get_export_preset() const; @@ -125,9 +128,19 @@ protected: GDVIRTUAL2RC(PackedStringArray, _get_export_features, const Ref &, bool); GDVIRTUAL1RC(TypedArray, _get_export_options, const Ref &); GDVIRTUAL1RC(bool, _should_update_export_options, const Ref &); + GDVIRTUAL2RC(String, _get_export_option_warning, const Ref &, String); GDVIRTUAL0RC(String, _get_name) + GDVIRTUAL1RC(bool, _supports_platform, const Ref &); + + GDVIRTUAL2RC(PackedStringArray, _get_android_dependencies, const Ref &, bool); + GDVIRTUAL2RC(PackedStringArray, _get_android_dependencies_maven_repos, const Ref &, bool); + GDVIRTUAL2RC(PackedStringArray, _get_android_libraries, const Ref &, bool); + GDVIRTUAL2RC(String, _get_android_manifest_activity_element_contents, const Ref &, bool); + GDVIRTUAL2RC(String, _get_android_manifest_application_element_contents, const Ref &, bool); + GDVIRTUAL2RC(String, _get_android_manifest_element_contents, const Ref &, bool); + virtual bool _begin_customize_resources(const Ref &p_platform, const Vector &p_features); // Return true if this plugin does property export customization virtual Ref _customize_resource(const Ref &p_resource, const String &p_path); // If nothing is returned, it means do not touch (nothing changed). If something is returned (either the same or a different resource) it means changes are made. @@ -142,10 +155,20 @@ protected: virtual PackedStringArray _get_export_features(const Ref &p_export_platform, bool p_debug) const; virtual void _get_export_options(const Ref &p_export_platform, List *r_options) const; virtual bool _should_update_export_options(const Ref &p_export_platform) const; - - virtual String _get_name() const; + virtual String _get_export_option_warning(const Ref &p_export_platform, const String &p_option_name) const; public: + virtual String get_name() const; + + virtual bool supports_platform(const Ref &p_export_platform) const; + + virtual PackedStringArray get_android_dependencies(const Ref &p_export_platform, bool p_debug) const; + virtual PackedStringArray get_android_dependencies_maven_repos(const Ref &p_export_platform, bool p_debug) const; + virtual PackedStringArray get_android_libraries(const Ref &p_export_platform, bool p_debug) const; + virtual String get_android_manifest_activity_element_contents(const Ref &p_export_platform, bool p_debug) const; + virtual String get_android_manifest_application_element_contents(const Ref &p_export_platform, bool p_debug) const; + virtual String get_android_manifest_element_contents(const Ref &p_export_platform, bool p_debug) const; + Vector get_ios_frameworks() const; Vector get_ios_embedded_frameworks() const; Vector get_ios_project_static_libs() const; diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp index a7dc44e3a81..dfc0c23afc4 100644 --- a/editor/export/editor_export_preset.cpp +++ b/editor/export/editor_export_preset.cpp @@ -57,7 +57,26 @@ void EditorExportPreset::_bind_methods() { } String EditorExportPreset::_get_property_warning(const StringName &p_name) const { - return platform->get_export_option_warning(this, p_name); + String warning = platform->get_export_option_warning(this, p_name); + if (!warning.is_empty()) { + warning += "\n"; + } + + // Get property warning from editor export plugins. + Vector> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + if (!export_plugins[i]->supports_platform(platform)) { + continue; + } + + export_plugins.write[i]->set_export_preset(Ref(this)); + String plugin_warning = export_plugins[i]->_get_export_option_warning(platform, p_name); + if (!plugin_warning.is_empty()) { + warning += plugin_warning + "\n"; + } + } + + return warning; } void EditorExportPreset::_get_property_list(List *p_list) const { diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp index e551b0531af..42e4b6f6f65 100644 --- a/editor/export/export_template_manager.cpp +++ b/editor/export/export_template_manager.cpp @@ -669,11 +669,8 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_ f->store_line(VERSION_FULL_CONFIG); } - // Create the android plugins directory. - Error err = da->make_dir_recursive("android/plugins"); - ERR_FAIL_COND_V(err != OK, err); - - err = da->make_dir_recursive("android/build"); + // Create the android build directory. + Error err = da->make_dir_recursive("android/build"); ERR_FAIL_COND_V(err != OK, err); { // Add an empty .gdignore file to avoid scan. diff --git a/editor/plugins/dedicated_server_export_plugin.h b/editor/plugins/dedicated_server_export_plugin.h index cb014ae52dc..8991c052b37 100644 --- a/editor/plugins/dedicated_server_export_plugin.h +++ b/editor/plugins/dedicated_server_export_plugin.h @@ -40,7 +40,7 @@ private: EditorExportPreset::FileExportMode _get_export_mode_for_path(const String &p_path); protected: - String _get_name() const override { return "DedicatedServer"; } + String get_name() const override { return "DedicatedServer"; } PackedStringArray _get_export_features(const Ref &p_platform, bool p_debug) const override; uint64_t _get_customization_configuration_hash() const override; diff --git a/editor/plugins/gdextension_export_plugin.h b/editor/plugins/gdextension_export_plugin.h index d1c47ab14e1..54e68997966 100644 --- a/editor/plugins/gdextension_export_plugin.h +++ b/editor/plugins/gdextension_export_plugin.h @@ -36,7 +36,7 @@ class GDExtensionExportPlugin : public EditorExportPlugin { protected: virtual void _export_file(const String &p_path, const String &p_type, const HashSet &p_features); - virtual String _get_name() const { return "GDExtension"; } + virtual String get_name() const { return "GDExtension"; } }; void GDExtensionExportPlugin::_export_file(const String &p_path, const String &p_type, const HashSet &p_features) { diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index e23bd50b8b4..605e82be6e8 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -98,7 +98,7 @@ public: return; } - virtual String _get_name() const override { return "GDScript"; } + virtual String get_name() const override { return "GDScript"; } }; static void _editor_init() { diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 9d13432dc39..ea76b6fc34c 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -261,30 +261,32 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) { EditorExportPlatformAndroid *ea = static_cast(ud); while (!ea->quit_request.is_set()) { - // Check for plugins updates +#ifndef DISABLE_DEPRECATED + // Check for android plugins updates { // Nothing to do if we already know the plugins have changed. - if (!ea->plugins_changed.is_set()) { + if (!ea->android_plugins_changed.is_set()) { Vector loaded_plugins = get_plugins(); - MutexLock lock(ea->plugins_lock); + MutexLock lock(ea->android_plugins_lock); - if (ea->plugins.size() != loaded_plugins.size()) { - ea->plugins_changed.set(); + if (ea->android_plugins.size() != loaded_plugins.size()) { + ea->android_plugins_changed.set(); } else { - for (int i = 0; i < ea->plugins.size(); i++) { - if (ea->plugins[i].name != loaded_plugins[i].name) { - ea->plugins_changed.set(); + for (int i = 0; i < ea->android_plugins.size(); i++) { + if (ea->android_plugins[i].name != loaded_plugins[i].name) { + ea->android_plugins_changed.set(); break; } } } - if (ea->plugins_changed.is_set()) { - ea->plugins = loaded_plugins; + if (ea->android_plugins_changed.is_set()) { + ea->android_plugins = loaded_plugins; } } } +#endif // DISABLE_DEPRECATED // Check for devices updates String adb = get_adb_path(); @@ -628,6 +630,7 @@ Vector EditorExportPlatformAndroid::get_abis() return abis; } +#ifndef DISABLE_DEPRECATED /// List the gdap files in the directory specified by the p_path parameter. Vector EditorExportPlatformAndroid::list_gdap_files(const String &p_path) { Vector dir_files; @@ -694,6 +697,7 @@ Vector EditorExportPlatformAndroid::get_enabled_plugins(con return enabled_plugins; } +#endif // DISABLE_DEPRECATED Error EditorExportPlatformAndroid::store_in_apk(APKExportData *ed, const String &p_path, const Vector &p_data, int compression_method) { zip_fileinfo zipfi = get_zip_fileinfo(); @@ -861,8 +865,24 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref\n"; + manifest_text += " \n"; + } + + Vector> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + if (export_plugins[i]->supports_platform(Ref(this))) { + const String contents = export_plugins[i]->get_android_manifest_element_contents(Ref(this), p_debug); + if (!contents.is_empty()) { + manifest_text += contents; + manifest_text += "\n"; + } + } + } + + manifest_text += _get_xr_features_tag(p_preset); + manifest_text += _get_application_tag(Ref(this), p_preset, _has_read_write_storage_permission(perms), p_debug); manifest_text += "\n"; String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release")); @@ -1721,7 +1741,7 @@ String EditorExportPlatformAndroid::get_export_option_warning(const EditorExport } } 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 = PluginConfigAndroid::get_plugins_names(get_enabled_plugins(Ref(p_preset))); + String enabled_plugins_names = _get_plugins_names(Ref(p_preset)); if (!enabled_plugins_names.is_empty() && !gradle_build_enabled) { return TTR("\"Use Gradle Build\" must be enabled to use the plugins."); } @@ -1808,12 +1828,14 @@ void EditorExportPlatformAndroid::get_export_options(List *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", VULKAN_MIN_SDK_VERSION)), "", false, true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), "", false, true)); +#ifndef DISABLE_DEPRECATED Vector plugins_configs = get_plugins(); for (int i = 0; i < plugins_configs.size(); i++) { print_verbose("Found Android plugin " + plugins_configs[i].name); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("plugins"), plugins_configs[i].name)), false)); } - plugins_changed.clear(); + android_plugins_changed.clear(); +#endif // DISABLE_DEPRECATED // Android supports multiple architectures in an app bundle, so // we expose each option as a checkbox in the export dialog. @@ -1892,12 +1914,14 @@ Ref EditorExportPlatformAndroid::get_logo() const { } bool EditorExportPlatformAndroid::should_update_export_options() { - bool export_options_changed = plugins_changed.is_set(); - if (export_options_changed) { +#ifndef DISABLE_DEPRECATED + if (android_plugins_changed.is_set()) { // don't clear unless we're reporting true, to avoid race - plugins_changed.clear(); + android_plugins_changed.clear(); + return true; } - return export_options_changed; +#endif // DISABLE_DEPRECATED + return false; } bool EditorExportPlatformAndroid::poll_export() { @@ -2697,6 +2721,64 @@ String EditorExportPlatformAndroid::join_abis(const Vector &p_preset) const { + Vector names; + +#ifndef DISABLE_DEPRECATED + PluginConfigAndroid::get_plugins_names(get_enabled_plugins(p_preset), names); +#endif // DISABLE_DEPRECATED + + Vector> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + if (export_plugins[i]->supports_platform(Ref(this))) { + names.push_back(export_plugins[i]->get_name()); + } + } + + String plugins_names = String("|").join(names); + return plugins_names; +} + +String EditorExportPlatformAndroid::_resolve_export_plugin_android_library_path(const String &p_android_library_path) const { + String absolute_path; + if (!p_android_library_path.is_empty()) { + if (p_android_library_path.is_absolute_path()) { + absolute_path = ProjectSettings::get_singleton()->globalize_path(p_android_library_path); + } else { + const String export_plugin_absolute_path = String("res://addons/").path_join(p_android_library_path); + absolute_path = ProjectSettings::get_singleton()->globalize_path(export_plugin_absolute_path); + } + } + return absolute_path; +} + +bool EditorExportPlatformAndroid::_is_clean_build_required(const Ref &p_preset) { + bool first_build = last_gradle_build_time == 0; + bool have_plugins_changed = false; + + String plugin_names = _get_plugins_names(p_preset); + + if (!first_build) { + have_plugins_changed = plugin_names != last_plugin_names; +#ifndef DISABLE_DEPRECATED + if (!have_plugins_changed) { + Vector enabled_plugins = get_enabled_plugins(p_preset); + for (int i = 0; i < enabled_plugins.size(); i++) { + if (enabled_plugins.get(i).last_updated > last_gradle_build_time) { + have_plugins_changed = true; + break; + } + } + } +#endif // DISABLE_DEPRECATED + } + + last_gradle_build_time = OS::get_singleton()->get_unix_time(); + last_plugin_names = plugin_names; + + return have_plugins_changed || first_build; +} + Error EditorExportPlatformAndroid::export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { int export_format = int(p_preset->get("gradle_build/export_format")); bool should_sign = p_preset->get("package/signed"); @@ -2854,11 +2936,40 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref android_libraries; + Vector android_dependencies; + Vector android_dependencies_maven_repos; + +#ifndef DISABLE_DEPRECATED Vector enabled_plugins = get_enabled_plugins(p_preset); - String local_plugins_binaries = PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_LOCAL, enabled_plugins); - String remote_plugins_binaries = PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_REMOTE, enabled_plugins); - String custom_maven_repos = PluginConfigAndroid::get_plugins_custom_maven_repos(enabled_plugins); - bool clean_build_required = is_clean_build_required(enabled_plugins); + PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_LOCAL, enabled_plugins, android_libraries); + PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_REMOTE, enabled_plugins, android_dependencies); + PluginConfigAndroid::get_plugins_custom_maven_repos(enabled_plugins, android_dependencies_maven_repos); +#endif // DISABLE_DEPRECATED + + Vector> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + if (export_plugins[i]->supports_platform(Ref(this))) { + PackedStringArray export_plugin_android_libraries = export_plugins[i]->get_android_libraries(Ref(this), p_debug); + for (int k = 0; k < export_plugin_android_libraries.size(); k++) { + const String resolved_android_library_path = _resolve_export_plugin_android_library_path(export_plugin_android_libraries[k]); + if (!resolved_android_library_path.is_empty()) { + android_libraries.push_back(resolved_android_library_path); + } + } + + PackedStringArray export_plugin_android_dependencies = export_plugins[i]->get_android_dependencies(Ref(this), p_debug); + android_dependencies.append_array(export_plugin_android_dependencies); + + PackedStringArray export_plugin_android_dependencies_maven_repos = export_plugins[i]->get_android_dependencies_maven_repos(Ref(this), p_debug); + android_dependencies_maven_repos.append_array(export_plugin_android_dependencies_maven_repos); + } + } + + bool clean_build_required = _is_clean_build_required(p_preset); + String combined_android_libraries = String("|").join(android_libraries); + String combined_android_dependencies = String("|").join(android_dependencies); + String combined_android_dependencies_maven_repos = String("|").join(android_dependencies_maven_repos); List cmdline; if (clean_build_required) { @@ -2882,9 +2993,9 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref plugins; +#ifndef DISABLE_DEPRECATED + mutable Vector android_plugins; + mutable SafeFlag android_plugins_changed; + Mutex android_plugins_lock; +#endif // DISABLE_DEPRECATED String last_plugin_names; uint64_t last_gradle_build_time = 0; - mutable SafeFlag plugins_changed; - Mutex plugins_lock; + Vector devices; SafeFlag devices_changed; Mutex device_lock; @@ -128,12 +133,14 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { static Vector get_abis(); +#ifndef DISABLE_DEPRECATED /// List the gdap files in the directory specified by the p_path parameter. static Vector list_gdap_files(const String &p_path); static Vector get_plugins(); static Vector get_enabled_plugins(const Ref &p_presets); +#endif // DISABLE_DEPRECATED static Error store_in_apk(APKExportData *ed, const String &p_path, const Vector &p_data, int compression_method = Z_DEFLATED); @@ -224,28 +231,11 @@ public: virtual List get_binary_extensions(const Ref &p_preset) const override; - inline bool is_clean_build_required(Vector enabled_plugins) { - String plugin_names = PluginConfigAndroid::get_plugins_names(enabled_plugins); - bool first_build = last_gradle_build_time == 0; - bool have_plugins_changed = false; + String _get_plugins_names(const Ref &p_preset) const; - if (!first_build) { - have_plugins_changed = plugin_names != last_plugin_names; - if (!have_plugins_changed) { - for (int i = 0; i < enabled_plugins.size(); i++) { - if (enabled_plugins.get(i).last_updated > last_gradle_build_time) { - have_plugins_changed = true; - break; - } - } - } - } + String _resolve_export_plugin_android_library_path(const String &p_android_library_path) const; - last_gradle_build_time = OS::get_singleton()->get_unix_time(); - last_plugin_names = plugin_names; - - return have_plugins_changed || first_build; - } + bool _is_clean_build_required(const Ref &p_preset); String get_apk_expansion_fullpath(const Ref &p_preset, const String &p_path); diff --git a/platform/android/export/godot_plugin_config.cpp b/platform/android/export/godot_plugin_config.cpp index b64cca3254a..cdec5f55b71 100644 --- a/platform/android/export/godot_plugin_config.cpp +++ b/platform/android/export/godot_plugin_config.cpp @@ -30,6 +30,8 @@ #include "godot_plugin_config.h" +#ifndef DISABLE_DEPRECATED + /* * Set of prebuilt plugins. * Currently unused, this is just for future reference: @@ -145,10 +147,8 @@ PluginConfigAndroid PluginConfigAndroid::load_plugin_config(Ref conf return plugin_config; } -String PluginConfigAndroid::get_plugins_binaries(String binary_type, Vector plugins_configs) { - String plugins_binaries; +void PluginConfigAndroid::get_plugins_binaries(String binary_type, Vector plugins_configs, Vector &r_result) { if (!plugins_configs.is_empty()) { - Vector binaries; for (int i = 0; i < plugins_configs.size(); i++) { PluginConfigAndroid config = plugins_configs[i]; if (!config.valid_config) { @@ -156,56 +156,44 @@ String PluginConfigAndroid::get_plugins_binaries(String binary_type, Vector plugins_configs) { - String custom_maven_repos; +void PluginConfigAndroid::get_plugins_custom_maven_repos(Vector plugins_configs, Vector &r_result) { if (!plugins_configs.is_empty()) { - Vector repos_urls; for (int i = 0; i < plugins_configs.size(); i++) { PluginConfigAndroid config = plugins_configs[i]; if (!config.valid_config) { continue; } - repos_urls.append_array(config.custom_maven_repos); + r_result.append_array(config.custom_maven_repos); } - - custom_maven_repos = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(repos_urls); } - return custom_maven_repos; } -String PluginConfigAndroid::get_plugins_names(Vector plugins_configs) { - String plugins_names; +void PluginConfigAndroid::get_plugins_names(Vector plugins_configs, Vector &r_result) { if (!plugins_configs.is_empty()) { - Vector names; for (int i = 0; i < plugins_configs.size(); i++) { PluginConfigAndroid config = plugins_configs[i]; if (!config.valid_config) { continue; } - names.push_back(config.name); + r_result.push_back(config.name); } - plugins_names = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(names); } - - return plugins_names; } + +#endif // DISABLE_DEPRECATED diff --git a/platform/android/export/godot_plugin_config.h b/platform/android/export/godot_plugin_config.h index bef00979a91..8c56d00187e 100644 --- a/platform/android/export/godot_plugin_config.h +++ b/platform/android/export/godot_plugin_config.h @@ -31,6 +31,8 @@ #ifndef ANDROID_GODOT_PLUGIN_CONFIG_H #define ANDROID_GODOT_PLUGIN_CONFIG_H +#ifndef DISABLE_DEPRECATED + #include "core/config/project_settings.h" #include "core/error/error_list.h" #include "core/io/config_file.h" @@ -67,8 +69,6 @@ struct PluginConfigAndroid { inline static const char *BINARY_TYPE_LOCAL = "local"; inline static const char *BINARY_TYPE_REMOTE = "remote"; - inline static const char *PLUGIN_VALUE_SEPARATOR = "|"; - // Set to true when the config file is properly loaded. bool valid_config = false; // Unix timestamp of last change to this plugin. @@ -96,11 +96,13 @@ struct PluginConfigAndroid { static PluginConfigAndroid load_plugin_config(Ref config_file, const String &path); - static String get_plugins_binaries(String binary_type, Vector plugins_configs); + static void get_plugins_binaries(String binary_type, Vector plugins_configs, Vector &r_result); - static String get_plugins_custom_maven_repos(Vector plugins_configs); + static void get_plugins_custom_maven_repos(Vector plugins_configs, Vector &r_result); - static String get_plugins_names(Vector plugins_configs); + static void get_plugins_names(Vector plugins_configs, Vector &r_result); }; +#endif // DISABLE_DEPRECATED + #endif // ANDROID_GODOT_PLUGIN_CONFIG_H diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp index 8912877faaf..78a439284d8 100644 --- a/platform/android/export/gradle_export_util.cpp +++ b/platform/android/export/gradle_export_util.cpp @@ -254,7 +254,7 @@ String _get_screen_sizes_tag(const Ref &p_preset) { return manifest_screen_sizes; } -String _get_xr_features_tag(const Ref &p_preset, bool p_uses_vulkan) { +String _get_xr_features_tag(const Ref &p_preset) { String manifest_xr_features; int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode")); bool uses_xr = xr_mode_index == XR_MODE_OPENXR; @@ -273,15 +273,10 @@ String _get_xr_features_tag(const Ref &p_preset, bool p_uses manifest_xr_features += " \n"; } } - - if (p_uses_vulkan) { - manifest_xr_features += " \n"; - manifest_xr_features += " \n"; - } return manifest_xr_features; } -String _get_activity_tag(const Ref &p_preset, bool p_uses_xr) { +String _get_activity_tag(const Ref &p_export_platform, const Ref &p_preset, bool p_debug) { String orientation = _get_android_orientation_label(DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation")))); String manifest_activity_text = vformat( " &p_preset, bool p_uses_xr " \n" " \n"; - if (p_uses_xr) { + int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode")); + bool uses_xr = xr_mode_index == XR_MODE_OPENXR; + if (uses_xr) { manifest_activity_text += "\n" " \n" @@ -323,12 +320,24 @@ String _get_activity_tag(const Ref &p_preset, bool p_uses_xr manifest_activity_text += " \n"; } - manifest_activity_text += " \n" - " \n"; + manifest_activity_text += " \n"; + + Vector> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + if (export_plugins[i]->supports_platform(p_export_platform)) { + const String contents = export_plugins[i]->get_android_manifest_activity_element_contents(p_export_platform, p_debug); + if (!contents.is_empty()) { + manifest_activity_text += contents; + manifest_activity_text += "\n"; + } + } + } + + manifest_activity_text += " \n"; return manifest_activity_text; } -String _get_application_tag(const Ref &p_preset, bool p_has_read_write_storage_permission) { +String _get_application_tag(const Ref &p_export_platform, const Ref &p_preset, bool p_has_read_write_storage_permission, bool p_debug) { int app_category_index = (int)(p_preset->get("package/app_category")); bool is_game = app_category_index == APP_CATEGORY_GAME; @@ -362,7 +371,19 @@ String _get_application_tag(const Ref &p_preset, bool p_has_ manifest_application_text += " \n"; } } - manifest_application_text += _get_activity_tag(p_preset, uses_xr); + + Vector> export_plugins = EditorExport::get_singleton()->get_export_plugins(); + for (int i = 0; i < export_plugins.size(); i++) { + if (export_plugins[i]->supports_platform(p_export_platform)) { + const String contents = export_plugins[i]->get_android_manifest_application_element_contents(p_export_platform, p_debug); + if (!contents.is_empty()) { + manifest_application_text += contents; + manifest_application_text += "\n"; + } + } + } + + manifest_application_text += _get_activity_tag(p_export_platform, p_preset, p_debug); manifest_application_text += " \n"; return manifest_application_text; } diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 8a885a0d12c..ad2ab31dad3 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -116,10 +116,10 @@ String _get_gles_tag(); String _get_screen_sizes_tag(const Ref &p_preset); -String _get_xr_features_tag(const Ref &p_preset, bool p_uses_vulkan); +String _get_xr_features_tag(const Ref &p_preset); -String _get_activity_tag(const Ref &p_preset, bool p_uses_xr); +String _get_activity_tag(const Ref &p_export_platform, const Ref &p_preset, bool p_debug); -String _get_application_tag(const Ref &p_preset, bool p_has_read_write_storage_permission); +String _get_application_tag(const Ref &p_export_platform, const Ref &p_preset, bool p_has_read_write_storage_permission, bool p_debug); #endif // ANDROID_GRADLE_EXPORT_UTIL_H