From 1d265cc4c53e4b2ca79f5fa023f53521c7690521 Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio Date: Sun, 2 Jul 2023 23:54:01 -0700 Subject: [PATCH] Refactor the Godot OpenXR loader to match the new Android plugin packaging format for Godot 4.2 The new format gives a lot of flexibility and allows each vendor plugin to provide its own set of parameters in the export window. Those parameters in turn influences how the Android manifest is generated. --- .github/workflows/build-addon-on-push.yml | 61 ++++++ .github/workflows/build-on-push.yml | 80 ------- CHANGES.md | 3 + GodotOpenXRKHR.gdap | 7 - GodotOpenXRLynx.gdap | 7 - GodotOpenXRMeta.gdap | 7 - GodotOpenXRPico.gdap | 7 - README.md | 43 ++-- config.gradle | 2 +- demo/.gitattributes | 2 + demo/.gitignore | 4 + demo/addons/godotopenxr/export/.gdignore | 0 .../godot_openxr_editor_export_plugin.gd | 120 ++++++++++ .../export/godot_openxr_editor_plugin.gd | 36 +++ .../godot_openxr_khr_editor_export_plugin.gd | 23 ++ .../godot_openxr_lynx_editor_export_plugin.gd | 20 ++ .../godot_openxr_meta_editor_export_plugin.gd | 147 +++++++++++++ .../godot_openxr_pico_editor_export_plugin.gd | 20 ++ demo/addons/godotopenxr/plugin.cfg | 7 + demo/export_presets.cfg | 205 ++++++++++++++++++ demo/icon.svg | 1 + demo/icon.svg.import | 37 ++++ demo/main.gd | 14 ++ demo/main.tscn | 57 +++++ demo/project.godot | 31 +++ godotopenxrkhr/build.gradle | 15 ++ godotopenxrlynx/build.gradle | 15 ++ godotopenxrmeta/.gitignore | 2 +- godotopenxrmeta/build.gradle | 15 ++ godotopenxrpico/build.gradle | 15 ++ 30 files changed, 872 insertions(+), 131 deletions(-) create mode 100644 .github/workflows/build-addon-on-push.yml delete mode 100644 .github/workflows/build-on-push.yml delete mode 100644 GodotOpenXRKHR.gdap delete mode 100644 GodotOpenXRLynx.gdap delete mode 100644 GodotOpenXRMeta.gdap delete mode 100644 GodotOpenXRPico.gdap create mode 100644 demo/.gitattributes create mode 100644 demo/.gitignore create mode 100644 demo/addons/godotopenxr/export/.gdignore create mode 100644 demo/addons/godotopenxr/export/godot_openxr_editor_export_plugin.gd create mode 100644 demo/addons/godotopenxr/export/godot_openxr_editor_plugin.gd create mode 100644 demo/addons/godotopenxr/export/khr/godot_openxr_khr_editor_export_plugin.gd create mode 100644 demo/addons/godotopenxr/export/lynx/godot_openxr_lynx_editor_export_plugin.gd create mode 100644 demo/addons/godotopenxr/export/meta/godot_openxr_meta_editor_export_plugin.gd create mode 100644 demo/addons/godotopenxr/export/pico/godot_openxr_pico_editor_export_plugin.gd create mode 100644 demo/addons/godotopenxr/plugin.cfg create mode 100644 demo/export_presets.cfg create mode 100644 demo/icon.svg create mode 100644 demo/icon.svg.import create mode 100644 demo/main.gd create mode 100644 demo/main.tscn create mode 100644 demo/project.godot diff --git a/.github/workflows/build-addon-on-push.yml b/.github/workflows/build-addon-on-push.yml new file mode 100644 index 00000000..d4f4a3ab --- /dev/null +++ b/.github/workflows/build-addon-on-push.yml @@ -0,0 +1,61 @@ +# Workflow to automatically create the godot openxr loaders addon +name: Build on push + +on: + [push, pull_request] + +jobs: + build: + name: Assembling artifacts + runs-on: ubuntu-20.04 + + # Note, to satisfy the asset library we need to make sure our zip files have a root folder + # this is why we checkout into aar and build into asset + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: aar + - name: Setup java + uses: actions/setup-java@v2 + with: + java-version: 11 + distribution: 'adopt' + - name: Validate Gradle wrapper + uses: gradle/wrapper-validation-action@v1 + - name: Create Godot OpenXR loader AARs + run: | + cd aar + ./gradlew build + cd .. + # GODOT 4.2 ADDON GENERATION SECTION + - name: Create Godot OpenXR loader Addon + run: | + mkdir asset + cp -r aar/demo/addons asset + cp aar/CHANGES.md asset/addons/godotopenxr/GodotOpenXRLoaders_CHANGES.md + - name: Adding vendor licences + run: | + cp aar/godotopenxrmeta/LICENSE.txt asset/addons/godotopenxr/export/meta/ + cp aar/godotopenxrpico/src/main/jniLibs/arm64-v8a/README.md asset/addons/godotopenxr/export/pico/LICENSE.md + cp aar/godotopenxrkhr/LICENSE asset/addons/godotopenxr/export/khr/LICENSE + - name: Create Godot OpenXR loader addon artifact + uses: actions/upload-artifact@v2 + with: + name: GodotOpenXRLoadersAddon + path: | + asset + - name: Zip addon + run: | + zip -qq -r godotopenxrloadersaddon.zip asset + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + - name: Create and upload asset + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifacts: "godotopenxrloadersaddon.zip" + omitNameDuringUpdate: true + omitBodyDuringUpdate: true + token: ${{ secrets.GITHUB_TOKEN }} + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + diff --git a/.github/workflows/build-on-push.yml b/.github/workflows/build-on-push.yml deleted file mode 100644 index 6f8af817..00000000 --- a/.github/workflows/build-on-push.yml +++ /dev/null @@ -1,80 +0,0 @@ -# Workflow to automatically create deliverables -name: Build on push - -on: - [push, pull_request] - -jobs: - build: - name: Assembling artifacts - runs-on: ubuntu-20.04 - - # Note, to satisfy the asset library we need to make sure our zip files have a root folder - # this is why we checkout into aar - # and build into asset - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - path: aar - - name: Setup java - uses: actions/setup-java@v2 - with: - java-version: 11 - distribution: 'adopt' - - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 - - name: Create Godot OpenXR loader AARs - run: | - cd aar - ./gradlew build - cd .. - - name: Create Godot OpenXR loader Asset - run: | - mkdir asset - mkdir asset/android - mkdir asset/android/plugins - cp aar/CHANGES.md asset/android/plugins/GodotOpenXRLoaders_CHANGES.md - - name: Adding Meta loader - run: | - mkdir asset/android/plugins/godotopenxrmeta - cp aar/GodotOpenXRMeta.gdap asset/android/plugins/ - cp aar/godotopenxrmeta/LICENSE.txt asset/android/plugins/godotopenxrmeta/ - cp aar/godotopenxrmeta/build/outputs/aar/godotopenxrmeta-debug.aar asset/android/plugins/godotopenxrmeta/ - cp aar/godotopenxrmeta/build/outputs/aar/godotopenxrmeta-release.aar asset/android/plugins/godotopenxrmeta/ - - name: Adding Pico loader - run: | - mkdir asset/android/plugins/godotopenxrpico - cp aar/GodotOpenXRPico.gdap asset/android/plugins/ - cp aar/godotopenxrpico/src/main/jniLibs/arm64-v8a/README.md asset/android/plugins/godotopenxrpico/LICENSE.md - cp aar/godotopenxrpico/build/outputs/aar/godotopenxrpico-release.aar asset/android/plugins/godotopenxrpico/ - - name: Adding KHR loader - run: | - mkdir asset/android/plugins/godotopenxrkhr - cp aar/GodotOpenXRKHR.gdap asset/android/plugins/ - cp aar/godotopenxrkhr/LICENSE asset/android/plugins/godotopenxrkhr/LICENSE - cp aar/godotopenxrkhr/build/outputs/aar/godotopenxrkhr-release.aar asset/android/plugins/godotopenxrkhr/ - - name: Adding Lynx loader - run: | - mkdir asset/android/plugins/godotopenxrlynx - cp aar/GodotOpenXRLynx.gdap asset/android/plugins/ - cp aar/godotopenxrlynx/build/outputs/aar/godotopenxrlynx-release.aar asset/android/plugins/godotopenxrlynx/ - - name: Create Godot OpenXR loader asset artifact - uses: actions/upload-artifact@v2 - with: - name: GodotOpenXRLoaders - path: | - asset - - name: Zip asset - run: | - zip -qq -r godotopenxrloaders.zip asset - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') - - name: Create and upload asset - uses: ncipollo/release-action@v1 - with: - allowUpdates: true - artifacts: "godotopenxrloaders.zip" - omitNameDuringUpdate: true - omitBodyDuringUpdate: true - token: ${{ secrets.GITHUB_TOKEN }} - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') diff --git a/CHANGES.md b/CHANGES.md index e711377e..ec4d319f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,8 @@ # Change history for the Godot OpenXR loaders asset +## 2.0.0 +- Update to the new Godot 4.2 Android plugin packaging format + ## 1.1.0 - Update Meta OpenXR loader to version 54 - Bump dependencies versions to match the latest Godot 4.x stable version (v4.0.3) diff --git a/GodotOpenXRKHR.gdap b/GodotOpenXRKHR.gdap deleted file mode 100644 index d15effbe..00000000 --- a/GodotOpenXRKHR.gdap +++ /dev/null @@ -1,7 +0,0 @@ -[config] - -name="GodotOpenXRKHR" -binary_type="local" -binary="godotopenxrkhr/godotopenxrkhr-release.aar" - -[dependencies] diff --git a/GodotOpenXRLynx.gdap b/GodotOpenXRLynx.gdap deleted file mode 100644 index c674fdf5..00000000 --- a/GodotOpenXRLynx.gdap +++ /dev/null @@ -1,7 +0,0 @@ -[config] - -name="GodotOpenXRLynx" -binary_type="local" -binary="godotopenxrlynx/godotopenxrlynx-release.aar" - -[dependencies] diff --git a/GodotOpenXRMeta.gdap b/GodotOpenXRMeta.gdap deleted file mode 100644 index 2549f8d3..00000000 --- a/GodotOpenXRMeta.gdap +++ /dev/null @@ -1,7 +0,0 @@ -[config] - -name="GodotOpenXRMeta" -binary_type="local" -binary="godotopenxrmeta/godotopenxrmeta-debug.aar" - -[dependencies] diff --git a/GodotOpenXRPico.gdap b/GodotOpenXRPico.gdap deleted file mode 100644 index 4fb70334..00000000 --- a/GodotOpenXRPico.gdap +++ /dev/null @@ -1,7 +0,0 @@ -[config] - -name="GodotOpenXRPico" -binary_type="local" -binary="godotopenxrpico/godotopenxrpico-release.aar" - -[dependencies] diff --git a/README.md b/README.md index d436ab8b..3dc5b968 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Godot OpenXR Loaders -This repository builds the AAR assets required for Godot 4 to export XR application to the Android devices. +This repository builds the Android plugin addon required for Godot 4 to export XR applications to +the Android devices. ## Building this asset @@ -27,34 +28,34 @@ Work in progress builds are available under [actions](https://github.com/GodotVR ### Installing android build templates -Due to the use of AARs you will need to use the gradle build option in Godot. -Open your Godot XR project in Godot and open the `Project` menu and select `Install Android Build templates`. -This should create an `android` folder in your project folder. +The use of a Godot Android plugin requires the use of the gradle build option in Godot: +- Open your Godot XR project in Godot +- Open the `Project` menu +- Select `Install Android Build templates` ### Copying the plugin into place -When downloading this asset from Godot's asset library it should place the required files into `android/plugins`. -If you've downloaded the zip file from the releases page, copy the files in `aar/android/plugins` manually to `android/plugins` in your project. You may need to create the plugins folder. +When downloading this asset from Godot's asset library it should place the required files into +the `addons`directory. +If you've downloaded the zip file from the releases page, copy the files in `asset/addons` +manually to `addons` in your project. You may need to create the `addons` folder. -If you have build the asset from source, you need to create the `android/plugins` folder and then copy the following files: -- `GodotopenXRMeta.gdap` into `android/plugins` -- `godotopenxrmeta\build\outputs\aar\godotopenxrmeta-release.aar` into `android/plugins/godotopenxrmeta` -- `godotopenxrmeta\build\outputs\aar\godotopenxrmeta-debug.aar` into `android/plugins/godotopenxrmeta` -- `GodotOpenXRPico.gdap` into `android/plugins` -- `godotopenxrpico\build\outputs\aar\godotopenxrpico-release.aar` into `android/plugins/godotopenxrpico` -- `GodotOpenXRKHR.gdap` into `android/plugins` -- `godotopenxrkhr\build\outputs\aar\godotopenxrkhr-release.aar` into `android/plugins/godotopenxrkhr` -- `GodotOpenXRLynx.gdap` into `android/plugins` -- `godotopenxrlynx\build\outputs\aar\godotopenxrlynx-release.aar` into `android/plugins/godotopenxrlynx` +If you have build the asset from source, you need to create the `addons` folder in your project +if it doesn't exist already, and then copy the content of the `demo/addons` folder to `addons` +in your project. ### Configuring your export -Back in Godot open the `Project` menu and select `Export...`. -If it doesn't already exist create an Android export configuration by pressing `Add...` and selecting `Android`. -Tick the `Use Gradle Build` tickbox. -Now enable the loader you need to use. Do *not* select multiple loaders! +Back in Godot open the `Project` menu and select `Export...`: +- If it doesn't already exist, create an Android export configuration by pressing `Add...` and +selecting `Android` +- Tick the `Use Gradle Build` tickbox +- Select `OpenXR` as the **XR Mode** under the **XR Features** section +- Enable the loader you need to use -You can create multiple export templates, one for each loader. +**Note:** +**Do not** select multiple loaders in the same export template! +You can instead create multiple export templates, one for each loader. ## License diff --git a/config.gradle b/config.gradle index 6affc228..d96e0b0d 100644 --- a/config.gradle +++ b/config.gradle @@ -4,7 +4,7 @@ ext { compileSdk : 33, minSdk : 21, targetSdk : 33, - godotLibVersion : '4.0.3.stable', + godotLibVersion : '4.1.0.stable', javaVersion : JavaVersion.VERSION_11, nexusPublishVersion : '1.3.0' ] diff --git a/demo/.gitattributes b/demo/.gitattributes new file mode 100644 index 00000000..8ad74f78 --- /dev/null +++ b/demo/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/demo/.gitignore b/demo/.gitignore new file mode 100644 index 00000000..b028fe9c --- /dev/null +++ b/demo/.gitignore @@ -0,0 +1,4 @@ +# Godot 4+ specific ignores +.godot/ +/addons/godotopenxr/export/*/*.aar +/android/ diff --git a/demo/addons/godotopenxr/export/.gdignore b/demo/addons/godotopenxr/export/.gdignore new file mode 100644 index 00000000..e69de29b diff --git a/demo/addons/godotopenxr/export/godot_openxr_editor_export_plugin.gd b/demo/addons/godotopenxr/export/godot_openxr_editor_export_plugin.gd new file mode 100644 index 00000000..80e36015 --- /dev/null +++ b/demo/addons/godotopenxr/export/godot_openxr_editor_export_plugin.gd @@ -0,0 +1,120 @@ +@tool +class_name GodotOpenXREditorExportPlugin extends EditorExportPlugin + +const OPENXR_MODE_VALUE = 1 + +var _vendor: String +var _plugin_version: String + +func _init(vendor: String, version: String): + _vendor = vendor + _plugin_version = version + + +func _get_name() -> String: + return "GodotOpenXR" + _vendor.capitalize() + + +# Path to the Android library aar file +# If this is not available, we fall back to the maven central dependency +func _get_android_aar_file_path(debug: bool) -> String: + return "res://addons/godotopenxr/export/" + _vendor + "/godotopenxr" + _vendor + "-" + ("debug.aar" if debug else "release.aar") + + +# Maven central dependency used as fall back when the Android library aar file is not available +func _get_android_maven_central_dependency() -> String: + return "org.godotengine:godot-openxr-loaders-" + _vendor + ":" + _plugin_version + + +func _get_vendor_toggle_option_name() -> String: + return "xr_features/enable_" + _vendor + "_plugin" + + +func _get_vendor_toggle_option() -> Dictionary: + var toggle_option = { + "option": { + "name": _get_vendor_toggle_option_name(), + "class_name": "", + "type": TYPE_BOOL, + "hint": PROPERTY_HINT_NONE, + "hint_string": "", + "usage": PROPERTY_USAGE_DEFAULT, + }, + "default_value": false, + "update_visibility": false, + } + return toggle_option + + +func _is_openxr_enabled() -> bool: + return _get_int_option("xr_features/xr_mode", 0) == OPENXR_MODE_VALUE + + +func _get_export_options(platform) -> Array[Dictionary]: + if not _supports_platform(platform): + return [] + + return [ + _get_vendor_toggle_option(), + ] + + +func _get_export_option_warning(platform, option) -> String: + if not _supports_platform(platform): + return "" + + if option != _get_vendor_toggle_option_name(): + return "" + + if not(_is_openxr_enabled()) and _get_bool_option(option): + return "\"Enable " + _vendor.capitalize() + " Plugin\" requires \"XR Mode\" to be \"OpenXR\".\n" + + return "" + + +func _supports_platform(platform) -> bool: + if platform is EditorExportPlatformAndroid: + return true + return false + + +func _get_bool_option(option: String) -> bool: + var option_enabled = get_option(option) + if option_enabled is bool: + return option_enabled + return false + + +func _get_int_option(option: String, default_value: int) -> int: + var option_value = get_option(option) + if option_value is int: + return option_value + return default_value + + +func _is_vendor_plugin_enabled() -> bool: + return _get_bool_option(_get_vendor_toggle_option_name()) + + +func _is_android_aar_file_available(debug: bool) -> bool: + return FileAccess.file_exists(_get_android_aar_file_path(debug)) + + +func _get_android_dependencies(platform, debug) -> PackedStringArray: + if not _supports_platform(platform): + return PackedStringArray() + + if _is_vendor_plugin_enabled() and not _is_android_aar_file_available(debug): + return PackedStringArray([_get_android_maven_central_dependency()]) + + return PackedStringArray() + + +func _get_android_libraries(platform, debug) -> PackedStringArray: + if not _supports_platform(platform): + return PackedStringArray() + + if _is_vendor_plugin_enabled() and _is_android_aar_file_available(debug): + return PackedStringArray([_get_android_aar_file_path(debug)]) + + return PackedStringArray() diff --git a/demo/addons/godotopenxr/export/godot_openxr_editor_plugin.gd b/demo/addons/godotopenxr/export/godot_openxr_editor_plugin.gd new file mode 100644 index 00000000..5d4348bb --- /dev/null +++ b/demo/addons/godotopenxr/export/godot_openxr_editor_plugin.gd @@ -0,0 +1,36 @@ +@tool +extends EditorPlugin + +# A class member to hold the export plugin during its lifecycle. +var meta_export_plugin : EditorExportPlugin +var pico_export_plugin : EditorExportPlugin +var lynx_export_plugin : EditorExportPlugin +var khr_export_plugin : EditorExportPlugin + + +func _enter_tree(): + var plugin_version = get_plugin_version() + + # Initializing the export plugins + meta_export_plugin = preload("meta/godot_openxr_meta_editor_export_plugin.gd").new("meta", plugin_version) + pico_export_plugin = preload("pico/godot_openxr_pico_editor_export_plugin.gd").new("pico", plugin_version) + lynx_export_plugin = preload("lynx/godot_openxr_lynx_editor_export_plugin.gd").new("lynx", plugin_version) + khr_export_plugin = preload("khr/godot_openxr_khr_editor_export_plugin.gd").new("khr", plugin_version) + + add_export_plugin(meta_export_plugin) + add_export_plugin(pico_export_plugin) + add_export_plugin(lynx_export_plugin) + add_export_plugin(khr_export_plugin) + + +func _exit_tree(): + # Cleaning up the export plugins + remove_export_plugin(meta_export_plugin) + remove_export_plugin(pico_export_plugin) + remove_export_plugin(lynx_export_plugin) + remove_export_plugin(khr_export_plugin) + + meta_export_plugin = null + pico_export_plugin = null + lynx_export_plugin = null + khr_export_plugin = null diff --git a/demo/addons/godotopenxr/export/khr/godot_openxr_khr_editor_export_plugin.gd b/demo/addons/godotopenxr/export/khr/godot_openxr_khr_editor_export_plugin.gd new file mode 100644 index 00000000..b799adf3 --- /dev/null +++ b/demo/addons/godotopenxr/export/khr/godot_openxr_khr_editor_export_plugin.gd @@ -0,0 +1,23 @@ +@tool +extends "../godot_openxr_editor_export_plugin.gd" + + +func _get_android_manifest_activity_element_contents(platform, debug) -> String: + if not _supports_platform(platform) or not(_is_vendor_plugin_enabled()): + return "" + + var contents = """ + \n + \n + \n + \n + \n + \n + \n + \n + \n + \n + """ + + return contents diff --git a/demo/addons/godotopenxr/export/lynx/godot_openxr_lynx_editor_export_plugin.gd b/demo/addons/godotopenxr/export/lynx/godot_openxr_lynx_editor_export_plugin.gd new file mode 100644 index 00000000..b81e7bb7 --- /dev/null +++ b/demo/addons/godotopenxr/export/lynx/godot_openxr_lynx_editor_export_plugin.gd @@ -0,0 +1,20 @@ +@tool +extends "../godot_openxr_editor_export_plugin.gd" + + +func _get_android_manifest_activity_element_contents(platform, debug) -> String: + if not _supports_platform(platform) or not(_is_vendor_plugin_enabled()): + return "" + + var contents = """ + \n + \n + \n + \n + \n + \n + \n + """ + + return contents diff --git a/demo/addons/godotopenxr/export/meta/godot_openxr_meta_editor_export_plugin.gd b/demo/addons/godotopenxr/export/meta/godot_openxr_meta_editor_export_plugin.gd new file mode 100644 index 00000000..b8dc0a97 --- /dev/null +++ b/demo/addons/godotopenxr/export/meta/godot_openxr_meta_editor_export_plugin.gd @@ -0,0 +1,147 @@ +@tool +extends "../godot_openxr_editor_export_plugin.gd" + +const PASSTHROUGH_NONE_VALUE = 0 +const PASSTHROUGH_OPTIONAL_VALUE = 1 +const PASSTHROUGH_REQUIRED_VALUE = 2 + +const HAND_TRACKING_NONE_VALUE = 0 +const HAND_TRACKING_OPTIONAL_VALUE = 1 +const HAND_TRACKING_REQUIRED_VALUE = 2 + +const HAND_TRACKING_FREQUENCY_LOW_VALUE = 0 +const HAND_TRACKING_FREQUENCY_HIGH_VALUE = 1 + +const HAND_TRACKING_OPTION = { + "option": { + "name": "meta_xr_features/hand_tracking", + "class_name": "", + "type": TYPE_INT, + "hint": PROPERTY_HINT_ENUM, + "hint_string": "None,Optional,Required", + "usage": PROPERTY_USAGE_DEFAULT, + }, + "default_value": HAND_TRACKING_NONE_VALUE, + "update_visibility": false, +} + +const HAND_TRACKING_FREQUENCY_OPTION = { + "option": { + "name": "meta_xr_features/hand_tracking_frequency", + "class_name": "", + "type": TYPE_INT, + "hint": PROPERTY_HINT_ENUM, + "hint_string": "Low,High", + "usage": PROPERTY_USAGE_DEFAULT, + }, + "default_value": HAND_TRACKING_FREQUENCY_LOW_VALUE, + "update_visibility": false, +} + +const PASSTHROUGH_OPTION = { + "option": { + "name": "meta_xr_features/passthrough", + "class_name": "", + "type": TYPE_INT, + "hint": PROPERTY_HINT_ENUM, + "hint_string": "None,Optional,Required", + "usage": PROPERTY_USAGE_DEFAULT, + }, + "default_value": PASSTHROUGH_NONE_VALUE, + "update_visibility": false, + } + + +func _get_export_options(platform) -> Array[Dictionary]: + if not _supports_platform(platform): + return [] + + return [ + _get_vendor_toggle_option(), + HAND_TRACKING_OPTION, + HAND_TRACKING_FREQUENCY_OPTION, + PASSTHROUGH_OPTION, + ] + + +func _get_export_option_warning(platform, option) -> String: + if not _supports_platform(platform): + return "" + + var warning = "" + var openxr_enabled = _is_openxr_enabled() + match (option): + "meta_xr_features/hand_tracking": + if not(openxr_enabled) and _get_int_option(option, HAND_TRACKING_NONE_VALUE) > HAND_TRACKING_NONE_VALUE: + warning = "\"Hand Tracking\" requires \"XR Mode\" to be \"OpenXR\".\n" + + "meta_xr_features/passthrough": + if not(openxr_enabled) and _get_int_option(option, PASSTHROUGH_NONE_VALUE) > PASSTHROUGH_NONE_VALUE: + warning = "\"Passthrough\" requires \"XR Mode\" to be \"OpenXR\".\n" + + _: + warning = super._get_export_option_warning(platform, option) + + return warning + + +func _get_android_manifest_element_contents(platform, debug) -> String: + if not _supports_platform(platform) or not(_is_vendor_plugin_enabled()): + return "" + + var contents = "" + + # Check for hand tracking + var hand_tracking_value = _get_int_option("meta_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" + elif hand_tracking_value == HAND_TRACKING_REQUIRED_VALUE: + contents += " \n" + + # Check for passthrough + var passthrough_mode = _get_int_option("meta_xr_features/passthrough", PASSTHROUGH_NONE_VALUE) + if passthrough_mode == PASSTHROUGH_OPTIONAL_VALUE: + contents += " \n" + elif passthrough_mode == PASSTHROUGH_REQUIRED_VALUE: + contents += " \n" + + return contents + + +func _get_android_manifest_application_element_contents(platform, debug) -> String: + if not _supports_platform(platform) or not(_is_vendor_plugin_enabled()): + return "" + + var contents = "" + + var hand_tracking_enabled = _get_int_option("meta_xr_features/hand_tracking", HAND_TRACKING_NONE_VALUE) > HAND_TRACKING_NONE_VALUE + if hand_tracking_enabled: + var hand_tracking_frequency = _get_int_option("meta_xr_features/hand_tracking_frequency", HAND_TRACKING_FREQUENCY_LOW_VALUE) + var hand_tracking_frequency_label = "LOW" if hand_tracking_frequency == HAND_TRACKING_FREQUENCY_LOW_VALUE else "HIGH" + contents += " \n" % hand_tracking_frequency_label + contents += " \n" + + return contents + +func _get_android_manifest_activity_element_contents(platform, debug) -> String: + if not _supports_platform(platform) or not(_is_vendor_plugin_enabled()): + return "" + + var contents = """ + \n + \n + \n + \n + \n + \n + \n + \n + \n + \n + """ + + return contents diff --git a/demo/addons/godotopenxr/export/pico/godot_openxr_pico_editor_export_plugin.gd b/demo/addons/godotopenxr/export/pico/godot_openxr_pico_editor_export_plugin.gd new file mode 100644 index 00000000..b81e7bb7 --- /dev/null +++ b/demo/addons/godotopenxr/export/pico/godot_openxr_pico_editor_export_plugin.gd @@ -0,0 +1,20 @@ +@tool +extends "../godot_openxr_editor_export_plugin.gd" + + +func _get_android_manifest_activity_element_contents(platform, debug) -> String: + if not _supports_platform(platform) or not(_is_vendor_plugin_enabled()): + return "" + + var contents = """ + \n + \n + \n + \n + \n + \n + \n + """ + + return contents diff --git a/demo/addons/godotopenxr/plugin.cfg b/demo/addons/godotopenxr/plugin.cfg new file mode 100644 index 00000000..c398c8ba --- /dev/null +++ b/demo/addons/godotopenxr/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="GodotOpenXR" +description="Godot OpenXR loader plugin" +author="https://github.com/GodotVR/godot_openxr_loaders/blob/master/CONTRIBUTORS.md" +version="1.1.0-stable" +script="export/godot_openxr_editor_plugin.gd" diff --git a/demo/export_presets.cfg b/demo/export_presets.cfg new file mode 100644 index 00000000..8e970a32 --- /dev/null +++ b/demo/export_presets.cfg @@ -0,0 +1,205 @@ +[preset.0] + +name="Android" +platform="Android" +runnable=true +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="android/OpenXR Demo.apk" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +gradle_build/use_gradle_build=true +gradle_build/export_format=0 +gradle_build/min_sdk="" +gradle_build/target_sdk="" +architectures/armeabi-v7a=false +architectures/arm64-v8a=true +architectures/x86=false +architectures/x86_64=false +version/code=1 +version/name="1.0" +package/unique_name="org.godotengine.openxr.demo" +package/name="" +package/signed=true +package/app_category=2 +package/retain_data_on_uninstall=false +package/exclude_from_recents=false +launcher_icons/main_192x192="" +launcher_icons/adaptive_foreground_432x432="" +launcher_icons/adaptive_background_432x432="" +graphics/opengl_debug=false +xr_features/xr_mode=1 +screen/immersive_mode=true +screen/support_small=true +screen/support_normal=true +screen/support_large=true +screen/support_xlarge=true +user_data_backup/allow=false +command_line/extra_args="" +apk_expansion/enable=false +apk_expansion/SALT="" +apk_expansion/public_key="" +permissions/custom_permissions=PackedStringArray() +permissions/access_checkin_properties=false +permissions/access_coarse_location=false +permissions/access_fine_location=false +permissions/access_location_extra_commands=false +permissions/access_mock_location=false +permissions/access_network_state=false +permissions/access_surface_flinger=false +permissions/access_wifi_state=false +permissions/account_manager=false +permissions/add_voicemail=false +permissions/authenticate_accounts=false +permissions/battery_stats=false +permissions/bind_accessibility_service=false +permissions/bind_appwidget=false +permissions/bind_device_admin=false +permissions/bind_input_method=false +permissions/bind_nfc_service=false +permissions/bind_notification_listener_service=false +permissions/bind_print_service=false +permissions/bind_remoteviews=false +permissions/bind_text_service=false +permissions/bind_vpn_service=false +permissions/bind_wallpaper=false +permissions/bluetooth=false +permissions/bluetooth_admin=false +permissions/bluetooth_privileged=false +permissions/brick=false +permissions/broadcast_package_removed=false +permissions/broadcast_sms=false +permissions/broadcast_sticky=false +permissions/broadcast_wap_push=false +permissions/call_phone=false +permissions/call_privileged=false +permissions/camera=false +permissions/capture_audio_output=false +permissions/capture_secure_video_output=false +permissions/capture_video_output=false +permissions/change_component_enabled_state=false +permissions/change_configuration=false +permissions/change_network_state=false +permissions/change_wifi_multicast_state=false +permissions/change_wifi_state=false +permissions/clear_app_cache=false +permissions/clear_app_user_data=false +permissions/control_location_updates=false +permissions/delete_cache_files=false +permissions/delete_packages=false +permissions/device_power=false +permissions/diagnostic=false +permissions/disable_keyguard=false +permissions/dump=false +permissions/expand_status_bar=false +permissions/factory_test=false +permissions/flashlight=false +permissions/force_back=false +permissions/get_accounts=false +permissions/get_package_size=false +permissions/get_tasks=false +permissions/get_top_activity_info=false +permissions/global_search=false +permissions/hardware_test=false +permissions/inject_events=false +permissions/install_location_provider=false +permissions/install_packages=false +permissions/install_shortcut=false +permissions/internal_system_window=false +permissions/internet=false +permissions/kill_background_processes=false +permissions/location_hardware=false +permissions/manage_accounts=false +permissions/manage_app_tokens=false +permissions/manage_documents=false +permissions/manage_external_storage=false +permissions/master_clear=false +permissions/media_content_control=false +permissions/modify_audio_settings=false +permissions/modify_phone_state=false +permissions/mount_format_filesystems=false +permissions/mount_unmount_filesystems=false +permissions/nfc=false +permissions/persistent_activity=false +permissions/process_outgoing_calls=false +permissions/read_calendar=false +permissions/read_call_log=false +permissions/read_contacts=false +permissions/read_external_storage=false +permissions/read_frame_buffer=false +permissions/read_history_bookmarks=false +permissions/read_input_state=false +permissions/read_logs=false +permissions/read_phone_state=false +permissions/read_profile=false +permissions/read_sms=false +permissions/read_social_stream=false +permissions/read_sync_settings=false +permissions/read_sync_stats=false +permissions/read_user_dictionary=false +permissions/reboot=false +permissions/receive_boot_completed=false +permissions/receive_mms=false +permissions/receive_sms=false +permissions/receive_wap_push=false +permissions/record_audio=false +permissions/reorder_tasks=false +permissions/restart_packages=false +permissions/send_respond_via_message=false +permissions/send_sms=false +permissions/set_activity_watcher=false +permissions/set_alarm=false +permissions/set_always_finish=false +permissions/set_animation_scale=false +permissions/set_debug_app=false +permissions/set_orientation=false +permissions/set_pointer_speed=false +permissions/set_preferred_applications=false +permissions/set_process_limit=false +permissions/set_time=false +permissions/set_time_zone=false +permissions/set_wallpaper=false +permissions/set_wallpaper_hints=false +permissions/signal_persistent_processes=false +permissions/status_bar=false +permissions/subscribed_feeds_read=false +permissions/subscribed_feeds_write=false +permissions/system_alert_window=false +permissions/transmit_ir=false +permissions/uninstall_shortcut=false +permissions/update_device_stats=false +permissions/use_credentials=false +permissions/use_sip=false +permissions/vibrate=false +permissions/wake_lock=false +permissions/write_apn_settings=false +permissions/write_calendar=false +permissions/write_call_log=false +permissions/write_contacts=false +permissions/write_external_storage=false +permissions/write_gservices=false +permissions/write_history_bookmarks=false +permissions/write_profile=false +permissions/write_secure_settings=false +permissions/write_settings=false +permissions/write_sms=false +permissions/write_social_stream=false +permissions/write_sync_settings=false +permissions/write_user_dictionary=false +xr_features/enable_meta_plugin=true +meta_xr_features/hand_tracking=1 +meta_xr_features/hand_tracking_frequency=0 +meta_xr_features/passthrough=1 +xr_features/enable_pico_plugin=false +xr_features/enable_lynx_plugin=false +xr_features/enable_khr_plugin=false diff --git a/demo/icon.svg b/demo/icon.svg new file mode 100644 index 00000000..b370ceb7 --- /dev/null +++ b/demo/icon.svg @@ -0,0 +1 @@ + diff --git a/demo/icon.svg.import b/demo/icon.svg.import new file mode 100644 index 00000000..c7092d22 --- /dev/null +++ b/demo/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cvlahew2pulnf" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/demo/main.gd b/demo/main.gd new file mode 100644 index 00000000..c64b3ae2 --- /dev/null +++ b/demo/main.gd @@ -0,0 +1,14 @@ +extends Node3D + + +# Called when the node enters the scene tree for the first time. +func _ready(): + var xr_interface : XRInterface = XRServer.find_interface("OpenXR") + if xr_interface and xr_interface.is_initialized(): + var vp: Viewport = get_viewport() + vp.use_xr = true + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/demo/main.tscn b/demo/main.tscn new file mode 100644 index 00000000..477dd650 --- /dev/null +++ b/demo/main.tscn @@ -0,0 +1,57 @@ +[gd_scene load_steps=8 format=3 uid="uid://cqsodpswgup8w"] + +[ext_resource type="Script" path="res://main.gd" id="1_fsva1"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_0x6cv"] +sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) +ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) + +[sub_resource type="Sky" id="Sky_dqyx0"] +sky_material = SubResource("ProceduralSkyMaterial_0x6cv") + +[sub_resource type="Environment" id="Environment_m0xew"] +background_mode = 2 +sky = SubResource("Sky_dqyx0") +tonemap_mode = 2 + +[sub_resource type="BoxMesh" id="BoxMesh_3kt6b"] +size = Vector3(0.1, 0.1, 0.1) + +[sub_resource type="BoxMesh" id="BoxMesh_ey3x4"] +size = Vector3(0.1, 0.1, 0.1) + +[sub_resource type="PlaneMesh" id="PlaneMesh_mjcgt"] +size = Vector2(10, 10) + +[node name="Main" type="Node3D"] +script = ExtResource("1_fsva1") + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_m0xew") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(-0.866025, -0.433013, 0.25, 0, 0.5, 0.866025, -0.5, 0.75, -0.433013, 0, 0, 0) +shadow_enabled = true + +[node name="XROrigin3D" type="XROrigin3D" parent="."] + +[node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.352791, 0) + +[node name="LeftHand" type="XRController3D" parent="XROrigin3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.460909, 0, -0.241118) +tracker = &"left_hand" +pose = &"aim" + +[node name="LeftHandMesh" type="MeshInstance3D" parent="XROrigin3D/LeftHand"] +mesh = SubResource("BoxMesh_3kt6b") + +[node name="RightHand" type="XRController3D" parent="XROrigin3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.478861, 0, -0.241097) +tracker = &"right_hand" + +[node name="MeshInstance3D" type="MeshInstance3D" parent="XROrigin3D/RightHand"] +mesh = SubResource("BoxMesh_ey3x4") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("PlaneMesh_mjcgt") diff --git a/demo/project.godot b/demo/project.godot new file mode 100644 index 00000000..e623c49a --- /dev/null +++ b/demo/project.godot @@ -0,0 +1,31 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="OpenXR Demo" +run/main_scene="res://main.tscn" +config/features=PackedStringArray("4.1", "GL Compatibility") +config/icon="res://icon.svg" + +[editor_plugins] + +enabled=PackedStringArray("res://addons/godotopenxr/plugin.cfg") + +[rendering] + +renderer/rendering_method="gl_compatibility" +renderer/rendering_method.mobile="gl_compatibility" +textures/vram_compression/import_etc2_astc=true + +[xr] + +openxr/enabled=true +shaders/enabled=true diff --git a/godotopenxrkhr/build.gradle b/godotopenxrkhr/build.gradle index b9d10870..ef19638d 100644 --- a/godotopenxrkhr/build.gradle +++ b/godotopenxrkhr/build.gradle @@ -51,3 +51,18 @@ android { dependencies { compileOnly "org.godotengine:godot:$versions.godotLibVersion" } + +task copyDebugAARToAddons(type: Copy) { + from 'build/outputs/aar' + include 'godotopenxrkhr-debug.aar' + into '../demo/addons/godotopenxr/export/khr' +} + +task copyReleaseAARToAddons(type: Copy) { + from 'build/outputs/aar' + include 'godotopenxrkhr-release.aar' + into '../demo/addons/godotopenxr/export/khr' +} + +assemble.finalizedBy(copyDebugAARToAddons) +assemble.finalizedBy(copyReleaseAARToAddons) diff --git a/godotopenxrlynx/build.gradle b/godotopenxrlynx/build.gradle index 3d4a08bf..5a65ac2d 100644 --- a/godotopenxrlynx/build.gradle +++ b/godotopenxrlynx/build.gradle @@ -50,3 +50,18 @@ android { dependencies { compileOnly "org.godotengine:godot:$versions.godotLibVersion" } + +task copyDebugAARToAddons(type: Copy) { + from 'build/outputs/aar' + include 'godotopenxrlynx-debug.aar' + into '../demo/addons/godotopenxr/export/lynx' +} + +task copyReleaseAARToAddons(type: Copy) { + from 'build/outputs/aar' + include 'godotopenxrlynx-release.aar' + into '../demo/addons/godotopenxr/export/lynx' +} + +assemble.finalizedBy(copyDebugAARToAddons) +assemble.finalizedBy(copyReleaseAARToAddons) diff --git a/godotopenxrmeta/.gitignore b/godotopenxrmeta/.gitignore index 42afabfd..796b96d1 100644 --- a/godotopenxrmeta/.gitignore +++ b/godotopenxrmeta/.gitignore @@ -1 +1 @@ -/build \ No newline at end of file +/build diff --git a/godotopenxrmeta/build.gradle b/godotopenxrmeta/build.gradle index 407f920f..a9c2c941 100644 --- a/godotopenxrmeta/build.gradle +++ b/godotopenxrmeta/build.gradle @@ -50,3 +50,18 @@ android { dependencies { compileOnly "org.godotengine:godot:$versions.godotLibVersion" } + +task copyDebugAARToAddons(type: Copy) { + from 'build/outputs/aar' + include 'godotopenxrmeta-debug.aar' + into '../demo/addons/godotopenxr/export/meta' +} + +task copyReleaseAARToAddons(type: Copy) { + from 'build/outputs/aar' + include 'godotopenxrmeta-release.aar' + into '../demo/addons/godotopenxr/export/meta' +} + +assemble.finalizedBy(copyDebugAARToAddons) +assemble.finalizedBy(copyReleaseAARToAddons) diff --git a/godotopenxrpico/build.gradle b/godotopenxrpico/build.gradle index e70ff81d..eb2f1d56 100644 --- a/godotopenxrpico/build.gradle +++ b/godotopenxrpico/build.gradle @@ -43,3 +43,18 @@ android { dependencies { compileOnly "org.godotengine:godot:$versions.godotLibVersion" } + +task copyDebugAARToAddons(type: Copy) { + from 'build/outputs/aar' + include 'godotopenxrpico-debug.aar' + into '../demo/addons/godotopenxr/export/pico' +} + +task copyReleaseAARToAddons(type: Copy) { + from 'build/outputs/aar' + include 'godotopenxrpico-release.aar' + into '../demo/addons/godotopenxr/export/pico' +} + +assemble.finalizedBy(copyDebugAARToAddons) +assemble.finalizedBy(copyReleaseAARToAddons)