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)