Skip to content

Commit

Permalink
Refactor the Godot OpenXR loader to match the new Android plugin pack…
Browse files Browse the repository at this point in the history
…aging 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.
  • Loading branch information
m4gr3d committed Jul 3, 2023
1 parent 547d542 commit f3a42f7
Show file tree
Hide file tree
Showing 13 changed files with 556 additions and 1 deletion.
2 changes: 2 additions & 0 deletions demo/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf
5 changes: 5 additions & 0 deletions demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Godot 4+ specific ignores
.godot/
/addons/godotopenxrmeta/godotopenxrmeta-debug.aar
/android/
*.import
Empty file.
212 changes: 212 additions & 0 deletions demo/addons/godotopenxrmeta/godot_openxr_meta_export_plugin.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
@tool
extends EditorExportPlugin

const OPENXR_MODE_VALUE = 1

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 ENABLE_META_LOADER_OPTION = {
"option": {
"name": "xr_features/enable_meta_plugin",
"class_name": "",
"type": TYPE_BOOL,
"hint": PROPERTY_HINT_NONE,
"hint_string": "",
"usage": PROPERTY_USAGE_DEFAULT,
},
"default_value": false,
"update_visibility": false,
}

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_name():
return "GodotOpenXRMeta"


# For production, the Maven central dependency is used.
# This should be commented out if '_get_android_libraries' is enabled
func _get_android_dependencies(platform, debug):
if platform is EditorExportPlatformAndroid and _is_meta_loader_option_enabled():
return PackedStringArray(["org.godotengine:godot-openxr-loaders-meta:1.0.0"])


# Used only for development purpose.
# '_get_android_dependencies' should be commented out if this is enabled
#func _get_android_libraries(platform, debug):
# if platform is EditorExportPlatformAndroid and _is_meta_loader_option_enabled():
# return PackedStringArray(["godotopenxrmeta/godotopenxrmeta-debug.aar"])


func _supports_platform(platform):
if platform is EditorExportPlatformAndroid:
var test := platform as 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_meta_loader_option_enabled() -> bool:
return _get_bool_option("xr_features/enable_meta_plugin")


func _get_export_options(platform):
if not(platform is EditorExportPlatformAndroid):
return []

return [
ENABLE_META_LOADER_OPTION,
HAND_TRACKING_OPTION,
HAND_TRACKING_FREQUENCY_OPTION,
PASSTHROUGH_OPTION,
]


func _get_export_option_warning(platform, option):
if not(platform is EditorExportPlatformAndroid):
return ""

var warning = ""
var openxr_enabled = _get_int_option("xr_features/xr_mode", 0) == OPENXR_MODE_VALUE
match (option):
"xr_features/enable_meta_plugin":
if not(openxr_enabled) and _get_bool_option(option):
warning = "\"Enable Meta Plugin\" requires \"XR Mode\" to be \"OpenXR\".\n"

"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 = ""

return warning


func _get_android_manifest_element_contents(platform, debug):
if not(platform is EditorExportPlatformAndroid) or not(_is_meta_loader_option_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 += " <uses-permission android:name=\"com.oculus.permission.HAND_TRACKING\" />\n"
if hand_tracking_value == HAND_TRACKING_OPTIONAL_VALUE:
contents += " <uses-feature tools:node=\"replace\" android:name=\"oculus.software.handtracking\" android:required=\"false\" />\n"
elif hand_tracking_value == HAND_TRACKING_REQUIRED_VALUE:
contents += " <uses-feature tools:node=\"replace\" android:name=\"oculus.software.handtracking\" android:required=\"true\" />\n"

# Check for passthrough
var passthrough_mode = _get_int_option("meta_xr_features/passthrough", PASSTHROUGH_NONE_VALUE)
if passthrough_mode == PASSTHROUGH_OPTIONAL_VALUE:
contents += " <uses-feature tools:node=\"replace\" android:name=\"com.oculus.feature.PASSTHROUGH\" android:required=\"false\" />\n"
elif passthrough_mode == PASSTHROUGH_REQUIRED_VALUE:
contents += " <uses-feature tools:node=\"replace\" android:name=\"com.oculus.feature.PASSTHROUGH\" android:required=\"true\" />\n"

return contents


func _get_android_manifest_application_element_contents(platform, debug):
if not(platform is EditorExportPlatformAndroid) or not(_is_meta_loader_option_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 += " <meta-data tools:node=\"replace\" android:name=\"com.oculus.handtracking.frequency\" android:value=\"%s\" />\n" % hand_tracking_frequency_label
contents += " <meta-data tools:node=\"replace\" android:name=\"com.oculus.handtracking.version\" android:value=\"V2.0\" />\n"

return contents

func _get_android_manifest_activity_element_contents(platform, debug):
if not(platform is EditorExportPlatformAndroid) or not(_is_meta_loader_option_enabled()):
return ""

var contents = """
<intent-filter>\n
<action android:name=\"android.intent.action.MAIN\" />\n
<category android:name=\"android.intent.category.LAUNCHER\" />\n
\n
<!-- Enable access to OpenXR on Oculus mobile devices, no-op on other Android\n
platforms. -->\n
<category android:name=\"com.oculus.intent.category.VR\" />\n
\n
<!-- OpenXR category tag to indicate the activity starts in an immersive OpenXR mode. \n
See https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#android-runtime-category. -->\n
<category android:name=\"org.khronos.openxr.intent.category.IMMERSIVE_HMD\" />\n
\n
<!-- Enable VR access on HTC Vive Focus devices. -->\n
<category android:name=\"com.htc.intent.category.VRAPP\" />\n
</intent-filter>\n
"""

return contents
16 changes: 16 additions & 0 deletions demo/addons/godotopenxrmeta/godot_openxr_meta_plugin.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@tool
extends EditorPlugin

# A class member to hold the export plugin during its lifecycle.
var export_plugin : EditorExportPlugin

func _enter_tree():
# Initializing the export plugin
export_plugin = preload("godot_openxr_meta_export_plugin.gd").new()
add_export_plugin(export_plugin)


func _exit_tree():
# Cleaning up the export plugin
remove_export_plugin(export_plugin)
export_plugin = null
7 changes: 7 additions & 0 deletions demo/addons/godotopenxrmeta/plugin.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[plugin]

name="GodotOpenXRMeta"
description="Godot OpenXR loader for Meta devices"
author="See https://github.com/GodotVR/godot_openxr_loaders/blob/master/CONTRIBUTORS.md"
version="1.1.0"
script="godot_openxr_meta_plugin.gd"
Loading

0 comments on commit f3a42f7

Please sign in to comment.