Skip to content

Commit

Permalink
Re-architect how Android plugins are packaged and handled at export time
Browse files Browse the repository at this point in the history
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 `<activity>` element in the generated Android manifest
- `_get_android_manifest_application_element_contents`: update the contents of the `<application>` element in the generated Android manifest
- `_get_android_manifest_element_contents`: update the contents of the `<manifest>` element in the generated Android manifest
  • Loading branch information
m4gr3d authored and YuriSizov committed Jul 18, 2023
1 parent 2797325 commit d17811c
Show file tree
Hide file tree
Showing 19 changed files with 457 additions and 108 deletions.
75 changes: 75 additions & 0 deletions doc/classes/EditorExportPlugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
To use [EditorExportPlugin], register it using the [method EditorPlugin.add_export_plugin] method first.
</description>
<tutorials>
<link title="Export Android plugins">$DOCS_URL/tutorials/platform/android/android_plugin.html</link>
</tutorials>
<methods>
<method name="_begin_customize_resources" qualifiers="virtual const">
Expand Down Expand Up @@ -84,6 +85,64 @@
Calling [method skip] inside this callback will make the file not included in the export.
</description>
</method>
<method name="_get_android_dependencies" qualifiers="virtual const">
<return type="PackedStringArray" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
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.
</description>
</method>
<method name="_get_android_dependencies_maven_repos" qualifiers="virtual const">
<return type="PackedStringArray" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
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.
</description>
</method>
<method name="_get_android_libraries" qualifiers="virtual const">
<return type="PackedStringArray" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
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.
</description>
</method>
<method name="_get_android_manifest_activity_element_contents" qualifiers="virtual const">
<return type="String" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
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.
</description>
</method>
<method name="_get_android_manifest_application_element_contents" qualifiers="virtual const">
<return type="String" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
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.
</description>
</method>
<method name="_get_android_manifest_element_contents" qualifiers="virtual const">
<return type="String" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="debug" type="bool" />
<description>
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.
</description>
</method>
<method name="_get_customization_configuration_hash" qualifiers="virtual const">
<return type="int" />
<description>
Expand All @@ -99,6 +158,15 @@
Return a [PackedStringArray] of additional features this preset, for the given [param platform], should have.
</description>
</method>
<method name="_get_export_option_warning" qualifiers="virtual const">
<return type="String" />
<param index="0" name="platform" type="EditorExportPlatform" />
<param index="1" name="option" type="String" />
<description>
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.
</description>
</method>
<method name="_get_export_options" qualifiers="virtual const">
<return type="Dictionary[]" />
<param index="0" name="platform" type="EditorExportPlatform" />
Expand All @@ -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.
</description>
</method>
<method name="_supports_platform" qualifiers="virtual const">
<return type="bool" />
<param index="0" name="platform" type="EditorExportPlatform" />
<description>
Return [code]true[/code] if the plugin supports the given [param platform].
</description>
</method>
<method name="add_file">
<return type="void" />
<param index="0" name="path" type="String" />
Expand Down
6 changes: 6 additions & 0 deletions doc/classes/EditorPlugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,12 @@
Returns the [PopupMenu] under [b]Scene &gt; Export As...[/b].
</description>
</method>
<method name="get_plugin_version" qualifiers="const">
<return type="String" />
<description>
Provide the version of the plugin declared in the [code]plugin.cfg[/code] config file.
</description>
</method>
<method name="get_script_create_dialog">
<return type="ScriptCreateDialog" />
<description>
Expand Down
6 changes: 6 additions & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
9 changes: 9 additions & 0 deletions editor/editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,14 @@ const Ref<Texture2D> 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);
Expand Down Expand Up @@ -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");
Expand Down
3 changes: 3 additions & 0 deletions editor/editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -168,6 +169,8 @@ class EditorPlugin : public Node {

virtual String get_name() const;
virtual const Ref<Texture2D> 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
Expand Down
24 changes: 21 additions & 3 deletions editor/export/editor_export_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &

struct SortByName {
bool operator()(const Ref<EditorExportPlugin> &left, const Ref<EditorExportPlugin> &right) const {
return left->_get_name() < right->_get_name();
return left->get_name() < right->get_name();
}
};

Expand Down Expand Up @@ -1033,14 +1033,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
if (export_plugins.write[i]->_begin_customize_resources(Ref<EditorExportPlatform>(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<EditorExportPlatform>(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);
}
Expand Down Expand Up @@ -1800,6 +1800,24 @@ bool EditorExportPlatform::can_export(const Ref<EditorExportPreset> &p_preset, S
if (!templates_error.is_empty()) {
r_error += templates_error;
}

String export_plugins_warning;
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
for (int i = 0; i < export_plugins.size(); i++) {
Ref<EditorExportPlatform> export_platform = Ref<EditorExportPlatform>(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;
Expand Down
81 changes: 80 additions & 1 deletion editor/export/editor_export_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<EditorExportPlatform> &p_export_platform, const Ref<EditorExportPreset> &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<EditorExportPlatform::ExportOption> 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<String> &p_features) {
GDVIRTUAL_CALL(_export_file, p_path, p_type, p_features);
}
Expand Down Expand Up @@ -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<EditorExportPlatform> &p_export_platform) const {
bool ret = false;
GDVIRTUAL_CALL(_supports_platform, p_export_platform, ret);
return ret;
}

PackedStringArray EditorExportPlugin::get_android_dependencies(const Ref<EditorExportPlatform> &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<EditorExportPlatform> &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<EditorExportPlatform> &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<EditorExportPlatform> &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<EditorExportPlatform> &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<EditorExportPlatform> &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<EditorExportPlatform> &p_platform, bool p_debug) const {
PackedStringArray ret;
GDVIRTUAL_CALL(_get_export_features, p_platform, p_debug, ret);
Expand All @@ -216,6 +279,12 @@ bool EditorExportPlugin::_should_update_export_options(const Ref<EditorExportPla
return ret;
}

String EditorExportPlugin::_get_export_option_warning(const Ref<EditorExportPlatform> &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<String> &p_features) {
}

Expand Down Expand Up @@ -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() {
Expand Down
Loading

0 comments on commit d17811c

Please sign in to comment.