diff --git a/docs/make_rst.py b/docs/make_rst.py index dc2b0309..b345aba2 100755 --- a/docs/make_rst.py +++ b/docs/make_rst.py @@ -66,6 +66,8 @@ STYLES: Dict[str, str] = {} SKIP_CLASSES: List[str] = [ + "AndroidEditorExportPlugin", + "AndroidEditorPlugin", "KhronosEditorExportPlugin", "KhronosEditorPlugin", "LynxEditorPlugin", diff --git a/plugin/build.gradle b/plugin/build.gradle index e4ebf618..3aad954e 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -36,6 +36,18 @@ android { flavorDimensions = ["vendor"] productFlavors { + android { + dimension "vendor" + ndk { + //noinspection ChromeOsAbiSupport + abiFilters 'arm64-v8a', 'x86_64' + } + externalNativeBuild { + cmake { + arguments "-DFLAVOR=android" + } + } + } khronos { dimension "vendor" ndk { @@ -100,6 +112,11 @@ android { } publishing { + singleVariant("androidRelease") { + withSourcesJar() + withJavadocJar() + } + singleVariant("khronosRelease") { withSourcesJar() withJavadocJar() @@ -141,6 +158,9 @@ android { dependencies { compileOnly libraries.godotAndroidLib + // AndroidXR dependencies + androidImplementation "org.khronos.openxr:openxr_loader_for_android:$versions.openxrVersion" + // Khronos dependencies khronosImplementation "org.khronos.openxr:openxr_loader_for_android:$versions.openxrVersion" diff --git a/plugin/src/android/AndroidManifest.xml b/plugin/src/android/AndroidManifest.xml new file mode 100644 index 00000000..ea9076de --- /dev/null +++ b/plugin/src/android/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/plugin/src/android/android.cmake b/plugin/src/android/android.cmake new file mode 100644 index 00000000..3795bbe9 --- /dev/null +++ b/plugin/src/android/android.cmake @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.22.1) + +## Android OpenXR loader library +find_package(OpenXR REQUIRED CONFIG) + +set(VENDOR_HEADERS_DIR "") +set(OPENXR_LOADER "OpenXR::openxr_loader") + +## Setup the project sources +file(GLOB_RECURSE ANDROID_SOURCES ${CMAKE_CURRENT_LIST_DIR}/cpp/*.c**) +file(GLOB_RECURSE ANDROID_HEADERS ${CMAKE_CURRENT_LIST_DIR}/cpp/*.h**) + +add_definitions(-DANDROID_VENDOR_ENABLED) diff --git a/plugin/src/android/java/org/godotengine/openxr/vendors/android/GodotOpenXRAndroid.kt b/plugin/src/android/java/org/godotengine/openxr/vendors/android/GodotOpenXRAndroid.kt new file mode 100644 index 00000000..fa8b6b3a --- /dev/null +++ b/plugin/src/android/java/org/godotengine/openxr/vendors/android/GodotOpenXRAndroid.kt @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* GodotOpenXRAndroid.kt */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT XR */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +package org.godotengine.openxr.vendors.android + +import org.godotengine.godot.Godot +import org.godotengine.godot.utils.PermissionsUtil +import org.godotengine.openxr.vendors.GodotOpenXR + +/** + * Godot OpenXR plugin for the Android XR platform. + */ +class GodotOpenXRAndroid(godot: Godot?) : GodotOpenXR(godot) { + companion object { + /** + * Representing the user's eye pose and orientation, for the purposes of avatars + */ + private const val EYE_TRACKING_PERMISSION = "android.permission.EYE_TRACKING" + + /** + * Eye gaze input and interactions + */ + private const val EYE_TRACKING_FINE_PERMISSION = "android.permission.EYE_TRACKING_FINE" + + /** + * Tracking and rendering facial expressions + */ + private const val FACE_TRACKING_PERMISSION = "android.permission.FACE_TRACKING" + + /** + * Tracking hand joint poses and angular and linear velocities; Using a mesh representation of the user's hands + */ + private const val HAND_TRACKING_PERMISSION = "android.permission.HAND_TRACKING" + + /** + * - Light estimation + * - projecting passthrough onto mesh surfaces + * - performing raycasts against trackables in the environment + * - plane tracking + * - object tracking + * - working with depth for occlusion and hit testing + * - persistent anchors + */ + private const val SCENE_UNDERSTANDING_PERMISSION = "android.permission.SCENE_UNDERSTANDING" + + private val ANDROID_XR_PERMISSIONS_LIST = listOf( + EYE_TRACKING_PERMISSION, + EYE_TRACKING_FINE_PERMISSION, + FACE_TRACKING_PERMISSION, + HAND_TRACKING_PERMISSION, + SCENE_UNDERSTANDING_PERMISSION, + ) + } + override fun getPluginName() = "GodotOpenXRAndroid" + + override fun getPluginPermissionsToEnable(): MutableList { + val permissionsToEnable = super.getPluginPermissionsToEnable() + + // Go through the list of permissions, and request the ones that are included in the + // manifest. + for (permission in ANDROID_XR_PERMISSIONS_LIST) { + if (PermissionsUtil.hasManifestPermission(activity, permission)) { + permissionsToEnable.add(permission) + } + } + return permissionsToEnable + } + + override fun supportsFeature(featureTag: String): Boolean { + if ("PERMISSION_XR_EXT_eye_gaze_interaction" == featureTag) { + val grantedPermissions = godot?.getGrantedPermissions() + if (grantedPermissions != null) { + for (permission in grantedPermissions) { + if (EYE_TRACKING_FINE_PERMISSION == permission) { + return true + } + } + } + } + return false + } +} diff --git a/plugin/src/main/cpp/export/android_export_plugin.cpp b/plugin/src/main/cpp/export/android_export_plugin.cpp new file mode 100644 index 00000000..891ad70f --- /dev/null +++ b/plugin/src/main/cpp/export/android_export_plugin.cpp @@ -0,0 +1,204 @@ +/**************************************************************************/ +/* android_export_plugin.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT XR */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "export/android_export_plugin.h" + +#include + +using namespace godot; + +void AndroidEditorPlugin::_bind_methods() {} + +void AndroidEditorPlugin::_enter_tree() { + // Initialize the editor export plugin + android_export_plugin.instantiate(); + add_export_plugin(android_export_plugin); +} + +void AndroidEditorPlugin::_exit_tree() { + // Clean up the editor export plugin + remove_export_plugin(android_export_plugin); + android_export_plugin.unref(); +} + +AndroidEditorExportPlugin::AndroidEditorExportPlugin() { + set_vendor_name(ANDROID_VENDOR_NAME); + + _eye_tracking_option = _generate_export_option( + "android_xr_features/eye_tracking", + "", + Variant::Type::INT, + PROPERTY_HINT_ENUM, + "None,Optional,Required", + PROPERTY_USAGE_DEFAULT, + EYE_TRACKING_NONE_VALUE, + false); + _hand_tracking_option = _generate_export_option( + "android_xr_features/hand_tracking", + "", + Variant::Type::INT, + PROPERTY_HINT_ENUM, + "None,Optional,Required", + PROPERTY_USAGE_DEFAULT, + HAND_TRACKING_NONE_VALUE, + false); +} + +void AndroidEditorExportPlugin::_bind_methods() {} + +TypedArray AndroidEditorExportPlugin::_get_export_options(const Ref &platform) const { + TypedArray export_options; + if (!_supports_platform(platform)) { + return export_options; + } + + export_options.append(_get_vendor_toggle_option()); + export_options.append(_eye_tracking_option); + export_options.append(_hand_tracking_option); + + return export_options; +} + +Dictionary AndroidEditorExportPlugin::_get_export_options_overrides(const Ref &p_platform) const { + Dictionary overrides; + if (!_supports_platform(p_platform)) { + return overrides; + } + + if (!_is_vendor_plugin_enabled()) { + overrides["android_xr_features/eye_tracking"] = EYE_TRACKING_NONE_VALUE; + overrides["android_xr_features/hand_tracking"] = HAND_TRACKING_NONE_VALUE; + } + + return overrides; +} + +bool AndroidEditorExportPlugin::_is_eye_tracking_enabled() const { + bool eye_tracking_project_setting_enabled = ProjectSettings::get_singleton()->get_setting_with_override("xr/openxr/extensions/eye_gaze_interaction"); + if (!eye_tracking_project_setting_enabled) { + return false; + } + + int eye_tracking_option_value = _get_int_option("android_xr_features/eye_tracking", EYE_TRACKING_NONE_VALUE); + return eye_tracking_option_value > EYE_TRACKING_NONE_VALUE; +} + +PackedStringArray AndroidEditorExportPlugin::_get_export_features(const Ref &platform, bool debug) const { + PackedStringArray features; + if (!_supports_platform(platform) || !_is_vendor_plugin_enabled()) { + return features; + } + + // Add the eye tracking feature if necessary + if (_is_eye_tracking_enabled()) { + features.append(EYE_GAZE_INTERACTION_FEATURE); + } + + return features; +} + +String AndroidEditorExportPlugin::_get_export_option_warning(const Ref &platform, const String &option) const { + if (!_supports_platform(platform) || !_is_vendor_plugin_enabled()) { + return ""; + } + + bool openxr_enabled = _is_openxr_enabled(); + if (option == "android_xr_features/eye_tracking") { + bool eye_tracking_project_setting_enabled = ProjectSettings::get_singleton()->get_setting_with_override("xr/openxr/extensions/eye_gaze_interaction"); + int eye_tracking_option_value = _get_int_option("android_xr_features/eye_tracking", EYE_TRACKING_NONE_VALUE); + if (eye_tracking_option_value > EYE_TRACKING_NONE_VALUE && !eye_tracking_project_setting_enabled) { + return "\"Eye Tracking\" project setting must be enabled!\n"; + } + } else if (option == "android_xr_features/hand_tracking") { + if (!openxr_enabled && _get_int_option(option, HAND_TRACKING_NONE_VALUE) > HAND_TRACKING_NONE_VALUE) { + return "\"Hand Tracking\" requires \"XR Mode\" to be \"OpenXR\".\n"; + } + } + + return OpenXREditorExportPlugin::_get_export_option_warning(platform, option); +} + +String AndroidEditorExportPlugin::_get_android_manifest_activity_element_contents(const Ref &platform, bool debug) const { + if (!_supports_platform(platform) || !_is_vendor_plugin_enabled()) { + return ""; + } + + return R"( + + + + + + + + +)"; +} + +String AndroidEditorExportPlugin::_get_android_manifest_element_contents(const Ref &platform, bool debug) const { + String contents; + if (!_supports_platform(platform) || !_is_vendor_plugin_enabled()) { + return contents; + } + + // Android XR required + contents += " \n"; + + // 6DoF motion controllers required + contents += " \n"; + + // Check for eye tracking + if (_is_eye_tracking_enabled()) { + contents += " \n"; + + int eye_tracking_value = _get_int_option("android_xr_features/eye_tracking", EYE_TRACKING_NONE_VALUE); + if (eye_tracking_value == EYE_TRACKING_OPTIONAL_VALUE) { + contents += " \n"; + } else if (eye_tracking_value == EYE_TRACKING_REQUIRED_VALUE) { + contents += " \n"; + } + } + + // Check for hand tracking + int hand_tracking_value = _get_int_option("android_xr_features/hand_tracking", HAND_TRACKING_NONE_VALUE); + if (hand_tracking_value > HAND_TRACKING_NONE_VALUE) { + contents += " \n"; + + if (hand_tracking_value == HAND_TRACKING_OPTIONAL_VALUE) { + contents += " \n"; + } else if (hand_tracking_value == HAND_TRACKING_REQUIRED_VALUE) { + contents += " \n"; + } + } + + return contents; +} diff --git a/plugin/src/main/cpp/export/export_plugin.cpp b/plugin/src/main/cpp/export/export_plugin.cpp index 6fa620be..81dffe82 100644 --- a/plugin/src/main/cpp/export/export_plugin.cpp +++ b/plugin/src/main/cpp/export/export_plugin.cpp @@ -87,7 +87,7 @@ Dictionary OpenXREditorExportPlugin::_get_vendor_toggle_option(const String &ven "", PROPERTY_USAGE_DEFAULT, false, - false); + true); } bool OpenXREditorExportPlugin::_is_openxr_enabled() const { diff --git a/plugin/src/main/cpp/export/pico_export_plugin.cpp b/plugin/src/main/cpp/export/pico_export_plugin.cpp index f8efc53b..2f741c11 100644 --- a/plugin/src/main/cpp/export/pico_export_plugin.cpp +++ b/plugin/src/main/cpp/export/pico_export_plugin.cpp @@ -58,7 +58,7 @@ PicoEditorExportPlugin::PicoEditorExportPlugin() { PROPERTY_HINT_ENUM, "No,Yes", PROPERTY_USAGE_DEFAULT, - pico::MANIFEST_FALSE_VALUE, + MANIFEST_FALSE_VALUE, false); _face_tracking_option = _generate_export_option( @@ -68,7 +68,7 @@ PicoEditorExportPlugin::PicoEditorExportPlugin() { PROPERTY_HINT_ENUM, "No,Face only,Lipsync only,Hybrid", PROPERTY_USAGE_DEFAULT, - pico::FACE_TRACKING_NONE_VALUE, + FACE_TRACKING_NONE_VALUE, false); _hand_tracking_option = _generate_export_option( @@ -78,7 +78,7 @@ PicoEditorExportPlugin::PicoEditorExportPlugin() { PROPERTY_HINT_ENUM, "No,Low frequency,High frequency (60Hz)", PROPERTY_USAGE_DEFAULT, - pico::HAND_TRACKING_NONE_VALUE, + HAND_TRACKING_NONE_VALUE, false); } @@ -104,8 +104,8 @@ bool PicoEditorExportPlugin::_is_eye_tracking_enabled() const { return false; } - int eye_tracking_option_value = _get_int_option("pico_xr_features/eye_tracking", pico::MANIFEST_FALSE_VALUE); - return eye_tracking_option_value == pico::MANIFEST_TRUE_VALUE; + int eye_tracking_option_value = _get_int_option("pico_xr_features/eye_tracking", MANIFEST_FALSE_VALUE); + return eye_tracking_option_value == MANIFEST_TRUE_VALUE; } PackedStringArray PicoEditorExportPlugin::_get_export_features(const Ref &platform, bool debug) const { @@ -129,24 +129,24 @@ String PicoEditorExportPlugin::_get_export_option_warning(const Ref pico::FACE_TRACKING_NONE_VALUE) { + int face_tracking = _get_int_option(option, FACE_TRACKING_NONE_VALUE); + if (!openxr_enabled && face_tracking > FACE_TRACKING_NONE_VALUE) { return "\"Face tracking\" requires \"XR Mode\" to be \"OpenXR\".\n"; } bool record_audio = _get_bool_option("permissions/record_audio"); - if (!record_audio && face_tracking == pico::FACE_TRACKING_LIPSYNCONLY_VALUE) { + if (!record_audio && face_tracking == FACE_TRACKING_LIPSYNCONLY_VALUE) { return "\"Lipsync face tracking\" requires \"Record Audio\" to be checked.\n"; } - if (!record_audio && face_tracking == pico::FACE_TRACKING_HYBRID_VALUE) { + if (!record_audio && face_tracking == FACE_TRACKING_HYBRID_VALUE) { return "\"Hybrid face tracking\" requires \"Record Audio\" to be checked.\n"; } } else if (option == "pico_xr_features/hand_tracking") { - int hand_tracking = _get_int_option(option, pico::HAND_TRACKING_NONE_VALUE); - if (!openxr_enabled && hand_tracking > pico::HAND_TRACKING_NONE_VALUE) { + int hand_tracking = _get_int_option(option, HAND_TRACKING_NONE_VALUE); + if (!openxr_enabled && hand_tracking > HAND_TRACKING_NONE_VALUE) { return "\"Hand tracking\" requires \"XR Mode\" to be \"OpenXR\".\n"; } } @@ -166,8 +166,8 @@ String PicoEditorExportPlugin::_get_android_manifest_element_contents(const Ref< } // Face tracking - int face_tracking = _get_int_option("pico_xr_features/face_tracking", pico::FACE_TRACKING_NONE_VALUE); - if (face_tracking == pico::FACE_TRACKING_FACEONLY_VALUE || face_tracking == pico::FACE_TRACKING_HYBRID_VALUE) { + int face_tracking = _get_int_option("pico_xr_features/face_tracking", FACE_TRACKING_NONE_VALUE); + if (face_tracking == FACE_TRACKING_FACEONLY_VALUE || face_tracking == FACE_TRACKING_HYBRID_VALUE) { contents += " \n"; } @@ -186,17 +186,17 @@ String PicoEditorExportPlugin::_get_android_manifest_application_element_content } // Face tracking - int face_tracking = _get_int_option("pico_xr_features/face_tracking", pico::FACE_TRACKING_NONE_VALUE); - if (face_tracking > pico::FACE_TRACKING_NONE_VALUE) { + int face_tracking = _get_int_option("pico_xr_features/face_tracking", FACE_TRACKING_NONE_VALUE); + if (face_tracking > FACE_TRACKING_NONE_VALUE) { contents += " \n"; } //Hand tracking - int hand_tracking = _get_int_option("pico_xr_features/hand_tracking", pico::HAND_TRACKING_NONE_VALUE); - if (hand_tracking > pico::HAND_TRACKING_NONE_VALUE) { + int hand_tracking = _get_int_option("pico_xr_features/hand_tracking", HAND_TRACKING_NONE_VALUE); + if (hand_tracking > HAND_TRACKING_NONE_VALUE) { contents += " \n"; } - if (hand_tracking > pico::HAND_TRACKING_LOWFREQUENCY_VALUE) { + if (hand_tracking > HAND_TRACKING_LOWFREQUENCY_VALUE) { contents += " \n"; } diff --git a/plugin/src/main/cpp/include/export/android_export_plugin.h b/plugin/src/main/cpp/include/export/android_export_plugin.h new file mode 100644 index 00000000..7816c1d8 --- /dev/null +++ b/plugin/src/main/cpp/include/export/android_export_plugin.h @@ -0,0 +1,85 @@ +/**************************************************************************/ +/* android_export_plugin.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT XR */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2022-present Godot XR contributors (see CONTRIBUTORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#pragma once + +#include + +#include "export_plugin.h" + +using namespace godot; + +class AndroidEditorExportPlugin : public OpenXREditorExportPlugin { + GDCLASS(AndroidEditorExportPlugin, OpenXREditorExportPlugin) + + static const int EYE_TRACKING_NONE_VALUE = 0; + static const int EYE_TRACKING_OPTIONAL_VALUE = 1; + static const int EYE_TRACKING_REQUIRED_VALUE = 2; + + static const int HAND_TRACKING_NONE_VALUE = 0; + static const int HAND_TRACKING_OPTIONAL_VALUE = 1; + static const int HAND_TRACKING_REQUIRED_VALUE = 2; + +public: + AndroidEditorExportPlugin(); + + TypedArray _get_export_options(const Ref &platform) const override; + + Dictionary _get_export_options_overrides(const Ref &p_platform) const override; + + PackedStringArray _get_export_features(const Ref &platform, bool debug) const override; + + String _get_export_option_warning(const Ref &platform, const String &option) const override; + + String _get_android_manifest_activity_element_contents(const Ref &platform, bool debug) const override; + String _get_android_manifest_element_contents(const Ref &platform, bool debug) const override; + +protected: + static void _bind_methods(); + + Dictionary _eye_tracking_option; + Dictionary _hand_tracking_option; + +private: + bool _is_eye_tracking_enabled() const; +}; + +class AndroidEditorPlugin : public EditorPlugin { + GDCLASS(AndroidEditorPlugin, EditorPlugin) + +public: + void _enter_tree() override; + void _exit_tree() override; + +protected: + static void _bind_methods(); + +private: + Ref android_export_plugin; +}; diff --git a/plugin/src/main/cpp/include/export/export_plugin.h b/plugin/src/main/cpp/include/export/export_plugin.h index 5458fb4b..7e13ad2d 100644 --- a/plugin/src/main/cpp/include/export/export_plugin.h +++ b/plugin/src/main/cpp/include/export/export_plugin.h @@ -45,6 +45,7 @@ static const char *PICO_VENDOR_NAME = "pico"; static const char *LYNX_VENDOR_NAME = "lynx"; static const char *KHRONOS_VENDOR_NAME = "khronos"; static const char *MAGICLEAP_VENDOR_NAME = "magicleap"; +static const char *ANDROID_VENDOR_NAME = "android"; static const char *VENDORS_LIST[] = { META_VENDOR_NAME, @@ -52,6 +53,7 @@ static const char *VENDORS_LIST[] = { LYNX_VENDOR_NAME, KHRONOS_VENDOR_NAME, MAGICLEAP_VENDOR_NAME, + ANDROID_VENDOR_NAME, }; // Set of custom feature tags supported by the plugin diff --git a/plugin/src/main/cpp/include/export/meta_export_plugin.h b/plugin/src/main/cpp/include/export/meta_export_plugin.h index df971802..1a8d814e 100644 --- a/plugin/src/main/cpp/include/export/meta_export_plugin.h +++ b/plugin/src/main/cpp/include/export/meta_export_plugin.h @@ -35,40 +35,38 @@ using namespace godot; -namespace { -static const int EYE_TRACKING_NONE_VALUE = 0; -static const int EYE_TRACKING_OPTIONAL_VALUE = 1; -static const int EYE_TRACKING_REQUIRED_VALUE = 2; +class MetaEditorExportPlugin : public OpenXREditorExportPlugin { + GDCLASS(MetaEditorExportPlugin, OpenXREditorExportPlugin) -static const int FACE_TRACKING_NONE_VALUE = 0; -static const int FACE_TRACKING_OPTIONAL_VALUE = 1; -static const int FACE_TRACKING_REQUIRED_VALUE = 2; + static const int EYE_TRACKING_NONE_VALUE = 0; + static const int EYE_TRACKING_OPTIONAL_VALUE = 1; + static const int EYE_TRACKING_REQUIRED_VALUE = 2; -static const int BODY_TRACKING_NONE_VALUE = 0; -static const int BODY_TRACKING_OPTIONAL_VALUE = 1; -static const int BODY_TRACKING_REQUIRED_VALUE = 2; + static const int FACE_TRACKING_NONE_VALUE = 0; + static const int FACE_TRACKING_OPTIONAL_VALUE = 1; + static const int FACE_TRACKING_REQUIRED_VALUE = 2; -static const int PASSTHROUGH_NONE_VALUE = 0; -static const int PASSTHROUGH_OPTIONAL_VALUE = 1; -static const int PASSTHROUGH_REQUIRED_VALUE = 2; + static const int BODY_TRACKING_NONE_VALUE = 0; + static const int BODY_TRACKING_OPTIONAL_VALUE = 1; + static const int BODY_TRACKING_REQUIRED_VALUE = 2; -static const int RENDER_MODEL_NONE_VALUE = 0; -static const int RENDER_MODEL_OPTIONAL_VALUE = 1; -static const int RENDER_MODEL_REQUIRED_VALUE = 2; + static const int PASSTHROUGH_NONE_VALUE = 0; + static const int PASSTHROUGH_OPTIONAL_VALUE = 1; + static const int PASSTHROUGH_REQUIRED_VALUE = 2; -static const int HAND_TRACKING_NONE_VALUE = 0; -static const int HAND_TRACKING_OPTIONAL_VALUE = 1; -static const int HAND_TRACKING_REQUIRED_VALUE = 2; + static const int RENDER_MODEL_NONE_VALUE = 0; + static const int RENDER_MODEL_OPTIONAL_VALUE = 1; + static const int RENDER_MODEL_REQUIRED_VALUE = 2; -static const int HAND_TRACKING_FREQUENCY_LOW_VALUE = 0; -static const int HAND_TRACKING_FREQUENCY_HIGH_VALUE = 1; + static const int HAND_TRACKING_NONE_VALUE = 0; + static const int HAND_TRACKING_OPTIONAL_VALUE = 1; + static const int HAND_TRACKING_REQUIRED_VALUE = 2; -static const int BOUNDARY_ENABLED_VALUE = 0; -static const int BOUNDARY_DISABLED_VALUE = 1; -} // namespace + static const int HAND_TRACKING_FREQUENCY_LOW_VALUE = 0; + static const int HAND_TRACKING_FREQUENCY_HIGH_VALUE = 1; -class MetaEditorExportPlugin : public OpenXREditorExportPlugin { - GDCLASS(MetaEditorExportPlugin, OpenXREditorExportPlugin) + static const int BOUNDARY_ENABLED_VALUE = 0; + static const int BOUNDARY_DISABLED_VALUE = 1; public: MetaEditorExportPlugin(); diff --git a/plugin/src/main/cpp/include/export/pico_export_plugin.h b/plugin/src/main/cpp/include/export/pico_export_plugin.h index 6bd332f6..55bfb060 100644 --- a/plugin/src/main/cpp/include/export/pico_export_plugin.h +++ b/plugin/src/main/cpp/include/export/pico_export_plugin.h @@ -35,22 +35,20 @@ using namespace godot; -namespace pico { -static const int MANIFEST_FALSE_VALUE = 0; -static const int MANIFEST_TRUE_VALUE = 1; +class PicoEditorExportPlugin : public OpenXREditorExportPlugin { + GDCLASS(PicoEditorExportPlugin, OpenXREditorExportPlugin) -static const int FACE_TRACKING_NONE_VALUE = 0; -static const int FACE_TRACKING_FACEONLY_VALUE = 1; -static const int FACE_TRACKING_LIPSYNCONLY_VALUE = 2; -static const int FACE_TRACKING_HYBRID_VALUE = 3; + static const int MANIFEST_FALSE_VALUE = 0; + static const int MANIFEST_TRUE_VALUE = 1; -static const int HAND_TRACKING_NONE_VALUE = 0; -static const int HAND_TRACKING_LOWFREQUENCY_VALUE = 1; -static const int HAND_TRACKING_HIGHFREQUENCY_VALUE = 2; -} //namespace pico + static const int FACE_TRACKING_NONE_VALUE = 0; + static const int FACE_TRACKING_FACEONLY_VALUE = 1; + static const int FACE_TRACKING_LIPSYNCONLY_VALUE = 2; + static const int FACE_TRACKING_HYBRID_VALUE = 3; -class PicoEditorExportPlugin : public OpenXREditorExportPlugin { - GDCLASS(PicoEditorExportPlugin, OpenXREditorExportPlugin) + static const int HAND_TRACKING_NONE_VALUE = 0; + static const int HAND_TRACKING_LOWFREQUENCY_VALUE = 1; + static const int HAND_TRACKING_HIGHFREQUENCY_VALUE = 2; public: PicoEditorExportPlugin(); diff --git a/plugin/src/main/cpp/register_types.cpp b/plugin/src/main/cpp/register_types.cpp index 6c7075e3..90cbf11d 100644 --- a/plugin/src/main/cpp/register_types.cpp +++ b/plugin/src/main/cpp/register_types.cpp @@ -38,6 +38,7 @@ #include #include +#include "export/android_export_plugin.h" #include "export/export_plugin.h" #include "export/khronos_export_plugin.h" #include "export/lynx_export_plugin.h" @@ -189,6 +190,10 @@ void initialize_plugin_module(ModuleInitializationLevel p_level) { case MODULE_INITIALIZATION_LEVEL_EDITOR: { ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + EditorPlugins::add_by_type(); + ClassDB::register_class(); ClassDB::register_class(); EditorPlugins::add_by_type();