Browse Source

Add support for OpenXR export configurations.

Fredia Huya-Kouadio 3 years ago
parent
commit
882ec0d611

+ 41 - 11
platform/android/export/export_plugin.cpp

@@ -751,9 +751,9 @@ void EditorExportPlatformAndroid::_get_permissions(const Ref<EditorExportPreset>
 	}
 	}
 
 
 	int xr_mode_index = p_preset->get("xr_features/xr_mode");
 	int xr_mode_index = p_preset->get("xr_features/xr_mode");
-	if (xr_mode_index == 1 /* XRMode.OVR */) {
+	if (xr_mode_index == XR_MODE_OPENXR) {
 		int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required
 		int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required
-		if (hand_tracking_index > 0) {
+		if (hand_tracking_index > XR_HAND_TRACKING_NONE) {
 			if (r_permissions.find("com.oculus.permission.HAND_TRACKING") == -1) {
 			if (r_permissions.find("com.oculus.permission.HAND_TRACKING") == -1) {
 				r_permissions.push_back("com.oculus.permission.HAND_TRACKING");
 				r_permissions.push_back("com.oculus.permission.HAND_TRACKING");
 			}
 			}
@@ -964,6 +964,20 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
 						}
 						}
 					}
 					}
 
 
+					if (tname == "meta-data" && attrname == "name" && value == "xr_mode_metadata_name") {
+						// Update the meta-data 'android:name' attribute based on the selected XR mode.
+						if (xr_mode_index == XR_MODE_OPENXR) {
+							string_table.write[attr_value] = "com.samsung.android.vr.application.mode";
+						}
+					}
+
+					if (tname == "meta-data" && attrname == "value" && value == "xr_mode_metadata_value") {
+						// Update the meta-data 'android:value' attribute based on the selected XR mode.
+						if (xr_mode_index == XR_MODE_OPENXR) {
+							string_table.write[attr_value] = "vr_only";
+						}
+					}
+
 					iofs += 20;
 					iofs += 20;
 				}
 				}
 
 
@@ -978,7 +992,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
 					Vector<bool> feature_required_list;
 					Vector<bool> feature_required_list;
 					Vector<int> feature_versions;
 					Vector<int> feature_versions;
 
 
-					if (xr_mode_index == 1 /* XRMode.OVR */) {
+					if (xr_mode_index == XR_MODE_OPENXR) {
 						// Set degrees of freedom
 						// Set degrees of freedom
 						feature_names.push_back("android.hardware.vr.headtracking");
 						feature_names.push_back("android.hardware.vr.headtracking");
 						feature_required_list.push_back(true);
 						feature_required_list.push_back(true);
@@ -986,11 +1000,19 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
 
 
 						// Check for hand tracking
 						// Check for hand tracking
 						int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required
 						int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required
-						if (hand_tracking_index > 0) {
+						if (hand_tracking_index > XR_HAND_TRACKING_NONE) {
 							feature_names.push_back("oculus.software.handtracking");
 							feature_names.push_back("oculus.software.handtracking");
-							feature_required_list.push_back(hand_tracking_index == 2);
+							feature_required_list.push_back(hand_tracking_index == XR_HAND_TRACKING_REQUIRED);
 							feature_versions.push_back(-1); // no version attribute should be added.
 							feature_versions.push_back(-1); // no version attribute should be added.
 						}
 						}
+
+						// Check for passthrough
+						int passthrough_mode = p_preset->get("xr_features/passthrough");
+						if (passthrough_mode > XR_PASSTHROUGH_NONE) {
+							feature_names.push_back("com.oculus.feature.PASSTHROUGH");
+							feature_required_list.push_back(passthrough_mode == XR_PASSTHROUGH_REQUIRED);
+							feature_versions.push_back(-1);
+						}
 					}
 					}
 
 
 					if (feature_names.size() > 0) {
 					if (feature_names.size() > 0) {
@@ -1669,8 +1691,9 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
 
 
 	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/opengl_debug"), false));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/opengl_debug"), false));
 
 
-	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,Oculus Mobile VR"), 0));
+	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,OpenXR"), 0));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/hand_tracking", PROPERTY_HINT_ENUM, "None,Optional,Required"), 0));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/hand_tracking", PROPERTY_HINT_ENUM, "None,Optional,Required"), 0));
+	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/passthrough", PROPERTY_HINT_ENUM, "None,Optional,Required"), 0));
 
 
 	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_small"), true));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_small"), true));
@@ -2137,10 +2160,17 @@ bool EditorExportPlatformAndroid::can_export(const Ref<EditorExportPreset> &p_pr
 	// Validate the Xr features are properly populated
 	// Validate the Xr features are properly populated
 	int xr_mode_index = p_preset->get("xr_features/xr_mode");
 	int xr_mode_index = p_preset->get("xr_features/xr_mode");
 	int hand_tracking = p_preset->get("xr_features/hand_tracking");
 	int hand_tracking = p_preset->get("xr_features/hand_tracking");
-	if (xr_mode_index != /* XRMode.OVR*/ 1) {
-		if (hand_tracking > 0) {
+	int passthrough_mode = p_preset->get("xr_features/passthrough");
+	if (xr_mode_index != XR_MODE_OPENXR) {
+		if (hand_tracking > XR_HAND_TRACKING_NONE) {
+			valid = false;
+			err += TTR("\"Hand Tracking\" is only valid when \"Xr Mode\" is \"OpenXR\".");
+			err += "\n";
+		}
+
+		if (passthrough_mode > XR_PASSTHROUGH_NONE) {
 			valid = false;
 			valid = false;
-			err += TTR("\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\".");
+			err += TTR("\"Passthrough\" is only valid when \"Xr Mode\" is \"OpenXR\".");
 			err += "\n";
 			err += "\n";
 		}
 		}
 	}
 	}
@@ -2202,8 +2232,8 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
 	}
 	}
 
 
 	int xr_mode_index = p_preset->get("xr_features/xr_mode");
 	int xr_mode_index = p_preset->get("xr_features/xr_mode");
-	if (xr_mode_index == 1) {
-		command_line_strings.push_back("--xr_mode_ovr");
+	if (xr_mode_index == XR_MODE_OPENXR) {
+		command_line_strings.push_back("--xr_mode_openxr");
 	} else { // XRMode.REGULAR is the default.
 	} else { // XRMode.REGULAR is the default.
 		command_line_strings.push_back("--xr_mode_regular");
 		command_line_strings.push_back("--xr_mode_regular");
 	}
 	}

+ 18 - 4
platform/android/export/gradle_export_util.cpp

@@ -211,16 +211,24 @@ String _get_screen_sizes_tag(const Ref<EditorExportPreset> &p_preset) {
 
 
 String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset) {
 String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset) {
 	String manifest_xr_features;
 	String manifest_xr_features;
-	bool uses_xr = (int)(p_preset->get("xr_features/xr_mode")) == 1;
+	int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode"));
+	bool uses_xr = xr_mode_index == XR_MODE_OPENXR;
 	if (uses_xr) {
 	if (uses_xr) {
 		manifest_xr_features += "    <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vr.headtracking\" android:required=\"true\" android:version=\"1\" />\n";
 		manifest_xr_features += "    <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vr.headtracking\" android:required=\"true\" android:version=\"1\" />\n";
 
 
 		int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required
 		int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required
-		if (hand_tracking_index == 1) {
+		if (hand_tracking_index == XR_HAND_TRACKING_OPTIONAL) {
 			manifest_xr_features += "    <uses-feature tools:node=\"replace\" android:name=\"oculus.software.handtracking\" android:required=\"false\" />\n";
 			manifest_xr_features += "    <uses-feature tools:node=\"replace\" android:name=\"oculus.software.handtracking\" android:required=\"false\" />\n";
-		} else if (hand_tracking_index == 2) {
+		} else if (hand_tracking_index == XR_HAND_TRACKING_REQUIRED) {
 			manifest_xr_features += "    <uses-feature tools:node=\"replace\" android:name=\"oculus.software.handtracking\" android:required=\"true\" />\n";
 			manifest_xr_features += "    <uses-feature tools:node=\"replace\" android:name=\"oculus.software.handtracking\" android:required=\"true\" />\n";
 		}
 		}
+
+		int passthrough_mode = p_preset->get("xr_features/passthrough");
+		if (passthrough_mode == XR_PASSTHROUGH_OPTIONAL) {
+			manifest_xr_features += "    <uses-feature tools:node=\"replace\" android:name=\"com.oculus.feature.PASSTHROUGH\" android:required=\"false\" />\n";
+		} else if (passthrough_mode == XR_PASSTHROUGH_REQUIRED) {
+			manifest_xr_features += "    <uses-feature tools:node=\"replace\" android:name=\"com.oculus.feature.PASSTHROUGH\" android:required=\"true\" />\n";
+		}
 	}
 	}
 	return manifest_xr_features;
 	return manifest_xr_features;
 }
 }
@@ -239,7 +247,8 @@ String _get_instrumentation_tag(const Ref<EditorExportPreset> &p_preset) {
 }
 }
 
 
 String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
 String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
-	bool uses_xr = (int)(p_preset->get("xr_features/xr_mode")) == 1;
+	int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode"));
+	bool uses_xr = xr_mode_index == XR_MODE_OPENXR;
 	String orientation = _get_android_orientation_label(DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation"))));
 	String orientation = _get_android_orientation_label(DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation"))));
 	String manifest_activity_text = vformat(
 	String manifest_activity_text = vformat(
 			"        <activity android:name=\"com.godot.game.GodotApp\" "
 			"        <activity android:name=\"com.godot.game.GodotApp\" "
@@ -256,6 +265,8 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
 }
 }
 
 
 String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_storage_permission) {
 String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_storage_permission) {
+	int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode"));
+	bool uses_xr = xr_mode_index == XR_MODE_OPENXR;
 	String manifest_application_text = vformat(
 	String manifest_application_text = vformat(
 			"    <application android:label=\"@string/godot_project_name_string\"\n"
 			"    <application android:label=\"@string/godot_project_name_string\"\n"
 			"        android:allowBackup=\"%s\"\n"
 			"        android:allowBackup=\"%s\"\n"
@@ -270,6 +281,9 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_
 			bool_to_string(p_preset->get("package/retain_data_on_uninstall")),
 			bool_to_string(p_preset->get("package/retain_data_on_uninstall")),
 			bool_to_string(p_has_storage_permission));
 			bool_to_string(p_has_storage_permission));
 
 
+	if (uses_xr) {
+		manifest_application_text += "        <meta-data tools:node=\"replace\" android:name=\"com.samsung.android.vr.application.mode\" android:value=\"vr_only\" />\n";
+	}
 	manifest_application_text += _get_activity_tag(p_preset);
 	manifest_application_text += _get_activity_tag(p_preset);
 	manifest_application_text += "    </application>\n";
 	manifest_application_text += "    </application>\n";
 	return manifest_application_text;
 	return manifest_application_text;

+ 15 - 0
platform/android/export/gradle_export_util.h

@@ -44,6 +44,21 @@ const String godot_project_name_xml_string = R"(<?xml version="1.0" encoding="ut
 </resources>
 </resources>
 )";
 )";
 
 
+// Supported XR modes.
+// This should match the entries in 'platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java'
+static const int XR_MODE_REGULAR = 0;
+static const int XR_MODE_OPENXR = 1;
+
+// Supported XR hand tracking modes.
+static const int XR_HAND_TRACKING_NONE = 0;
+static const int XR_HAND_TRACKING_OPTIONAL = 1;
+static const int XR_HAND_TRACKING_REQUIRED = 2;
+
+// Supported XR passthrough modes.
+static const int XR_PASSTHROUGH_NONE = 0;
+static const int XR_PASSTHROUGH_OPTIONAL = 1;
+static const int XR_PASSTHROUGH_REQUIRED = 2;
+
 struct CustomExportData {
 struct CustomExportData {
 	String assets_directory;
 	String assets_directory;
 	bool debug;
 	bool debug;

+ 5 - 0
platform/android/java/app/AndroidManifest.xml

@@ -33,6 +33,11 @@
         <!-- The following metadata values are replaced when Godot exports, modifying them here has no effect. -->
         <!-- The following metadata values are replaced when Godot exports, modifying them here has no effect. -->
         <!-- Do these changes in the export preset. Adding new ones is fine. -->
         <!-- Do these changes in the export preset. Adding new ones is fine. -->
 
 
+        <!-- XR mode metadata. This is modified by the exporter based on the selected xr mode. DO NOT CHANGE the values here. -->
+        <meta-data
+            android:name="xr_mode_metadata_name"
+            android:value="xr_mode_metadata_value" />
+
         <activity
         <activity
             android:name=".GodotApp"
             android:name=".GodotApp"
             android:label="@string/godot_project_name_string"
             android:label="@string/godot_project_name_string"

+ 2 - 2
platform/android/java/lib/src/org/godotengine/godot/Godot.java

@@ -502,8 +502,8 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
 			boolean has_extra = i < command_line.length - 1;
 			boolean has_extra = i < command_line.length - 1;
 			if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) {
 			if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) {
 				xrMode = XRMode.REGULAR;
 				xrMode = XRMode.REGULAR;
-			} else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) {
-				xrMode = XRMode.OVR;
+			} else if (command_line[i].equals(XRMode.OPENXR.cmdLineArg)) {
+				xrMode = XRMode.OPENXR;
 			} else if (command_line[i].equals("--debug_opengl")) {
 			} else if (command_line[i].equals("--debug_opengl")) {
 				use_debug_opengl = true;
 				use_debug_opengl = true;
 			} else if (command_line[i].equals("--use_immersive")) {
 			} else if (command_line[i].equals("--use_immersive")) {

+ 1 - 1
platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java

@@ -174,7 +174,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
 		setPreserveEGLContextOnPause(true);
 		setPreserveEGLContextOnPause(true);
 		setFocusableInTouchMode(true);
 		setFocusableInTouchMode(true);
 		switch (xrMode) {
 		switch (xrMode) {
-			case OVR:
+			case OPENXR:
 				// Replace the default egl config chooser.
 				// Replace the default egl config chooser.
 				setEGLConfigChooser(new OvrConfigChooser());
 				setEGLConfigChooser(new OvrConfigChooser());
 
 

+ 1 - 1
platform/android/java/lib/src/org/godotengine/godot/xr/XRMode.java

@@ -35,7 +35,7 @@ package org.godotengine.godot.xr;
  */
  */
 public enum XRMode {
 public enum XRMode {
 	REGULAR(0, "Regular", "--xr_mode_regular", "Default Android Gamepad"), // Regular/flatscreen
 	REGULAR(0, "Regular", "--xr_mode_regular", "Default Android Gamepad"), // Regular/flatscreen
-	OVR(1, "Oculus Mobile VR", "--xr_mode_ovr", "");
+	OPENXR(1, "OpenXR", "--xr_mode_openxr", "");
 
 
 	final int index;
 	final int index;
 	final String label;
 	final String label;