Преглед изворни кода

OpenXR: Add access to session state and change interaction profile update.

Bastiaan Olij пре 1 месец
родитељ
комит
df06aa8392

+ 42 - 2
modules/openxr/doc_classes/OpenXRInterface.xml

@@ -85,6 +85,12 @@
 				If handtracking is enabled and motion range is supported, gets the currently configured motion range for [param hand].
 				If handtracking is enabled and motion range is supported, gets the currently configured motion range for [param hand].
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="get_session_state">
+			<return type="int" enum="OpenXRInterface.OpenXrSessionState" />
+			<description>
+				Returns the current state of our OpenXR session.
+			</description>
+		</method>
 		<method name="is_action_set_active" qualifiers="const">
 		<method name="is_action_set_active" qualifiers="const">
 			<return type="bool" />
 			<return type="bool" />
 			<param index="0" name="name" type="String" />
 			<param index="0" name="name" type="String" />
@@ -216,7 +222,7 @@
 		</signal>
 		</signal>
 		<signal name="session_focussed">
 		<signal name="session_focussed">
 			<description>
 			<description>
-				Informs our OpenXR session now has focus.
+				Informs our OpenXR session now has focus, e.g. output is sent to our HMD and we're receiving XR input.
 			</description>
 			</description>
 		</signal>
 		</signal>
 		<signal name="session_loss_pending">
 		<signal name="session_loss_pending">
@@ -229,13 +235,47 @@
 				Informs our OpenXR session is stopping.
 				Informs our OpenXR session is stopping.
 			</description>
 			</description>
 		</signal>
 		</signal>
+		<signal name="session_synchronized">
+			<description>
+				Informs our OpenXR session has been synchronized.
+			</description>
+		</signal>
 		<signal name="session_visible">
 		<signal name="session_visible">
 			<description>
 			<description>
-				Informs our OpenXR session is now visible (output is being sent to the HMD).
+				Informs our OpenXR session is now visible, e.g. output is being sent to the HMD but we don't receive XR input.
 			</description>
 			</description>
 		</signal>
 		</signal>
 	</signals>
 	</signals>
 	<constants>
 	<constants>
+		<constant name="OPENXR_SESSION_STATE_UNKNOWN" value="0" enum="OpenXrSessionState">
+			The state of the session is unknown, we haven't tried setting up OpenXR yet.
+		</constant>
+		<constant name="OPENXR_SESSION_STATE_IDLE" value="1" enum="OpenXrSessionState">
+			The initial state after the OpenXR session is created or after the session is destroyed.
+		</constant>
+		<constant name="OPENXR_SESSION_STATE_READY" value="2" enum="OpenXrSessionState">
+			OpenXR is ready to begin our session. [signal session_begun] is emitted when we change to this state.
+		</constant>
+		<constant name="OPENXR_SESSION_STATE_SYNCHRONIZED" value="3" enum="OpenXrSessionState">
+			The application has synched its frame loop with the runtime but we're not rendering anything. [signal session_synchronized] is emitted when we change to this state.
+		</constant>
+		<constant name="OPENXR_SESSION_STATE_VISIBLE" value="4" enum="OpenXrSessionState">
+			The application has synched its frame loop with the runtime and we're rendering output to the user, however we receive no user input. [signal session_visible] is emitted when we change to this state.
+			[b]Note:[/b] This is the current state just before we get the focused state, whenever the user opens a system menu, switches to another application or takes off their headset.
+		</constant>
+		<constant name="OPENXR_SESSION_STATE_FOCUSED" value="5" enum="OpenXrSessionState">
+			The application has synched its frame loop with the runtime, we're rendering output to the user and we're receiving XR input. [signal session_focussed] is emitted when we change to this state.
+			[b]Note:[/b] This is the state OpenXR will be in when the user can fully interact with your game.
+		</constant>
+		<constant name="OPENXR_SESSION_STATE_STOPPING" value="6" enum="OpenXrSessionState">
+			Our session is being stopped. [signal session_stopping] is emitted when we change to this state.
+		</constant>
+		<constant name="OPENXR_SESSION_STATE_LOSS_PENDING" value="7" enum="OpenXrSessionState">
+			The session is about to be lost. [signal session_loss_pending] is emitted when we change to this state.
+		</constant>
+		<constant name="OPENXR_SESSION_STATE_EXITING" value="8" enum="OpenXrSessionState">
+			The OpenXR instance is about to be destroyed and we're existing. [signal instance_exiting] is emitted when we change to this state.
+		</constant>
 		<constant name="HAND_LEFT" value="0" enum="Hand">
 		<constant name="HAND_LEFT" value="0" enum="Hand">
 			Left hand.
 			Left hand.
 		</constant>
 		</constant>

+ 17 - 11
modules/openxr/openxr_api.cpp

@@ -1418,15 +1418,14 @@ bool OpenXRAPI::on_state_ready() {
 bool OpenXRAPI::on_state_synchronized() {
 bool OpenXRAPI::on_state_synchronized() {
 	print_verbose("On state synchronized");
 	print_verbose("On state synchronized");
 
 
-	// Just in case, see if we already have active trackers...
-	for (const RID &tracker : tracker_owner.get_owned_list()) {
-		tracker_check_profile(tracker);
-	}
-
 	for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
 	for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
 		wrapper->on_state_synchronized();
 		wrapper->on_state_synchronized();
 	}
 	}
 
 
+	if (xr_interface) {
+		xr_interface->on_state_synchronized();
+	}
+
 	return true;
 	return true;
 }
 }
 
 
@@ -2075,11 +2074,10 @@ bool OpenXRAPI::poll_events() {
 				print_verbose("OpenXR EVENT: interaction profile changed!");
 				print_verbose("OpenXR EVENT: interaction profile changed!");
 
 
 				XrEventDataInteractionProfileChanged *event = (XrEventDataInteractionProfileChanged *)&runtimeEvent;
 				XrEventDataInteractionProfileChanged *event = (XrEventDataInteractionProfileChanged *)&runtimeEvent;
-
-				for (const RID &tracker : tracker_owner.get_owned_list()) {
-					tracker_check_profile(tracker, event->session);
+				if (event->session == session) {
+					// Make sure we get our interaction profile change
+					interaction_profile_changed = true;
 				}
 				}
-
 			} break;
 			} break;
 			default:
 			default:
 				if (!handled) {
 				if (!handled) {
@@ -3454,8 +3452,16 @@ bool OpenXRAPI::sync_action_sets(const Vector<RID> p_active_sets) {
 
 
 	XrResult result = xrSyncActions(session, &sync_info);
 	XrResult result = xrSyncActions(session, &sync_info);
 	if (XR_FAILED(result)) {
 	if (XR_FAILED(result)) {
-		print_line("OpenXR: failed to sync active action sets! [", get_error_string(result), "]");
-		return false;
+		ERR_FAIL_V_MSG(false, "OpenXR: failed to sync active action sets! [" + get_error_string(result) + "]");
+	}
+
+	if (interaction_profile_changed) {
+		// Just in case, see if we already have active trackers...
+		for (const RID &tracker : tracker_owner.get_owned_list()) {
+			tracker_check_profile(tracker);
+		}
+
+		interaction_profile_changed = false;
 	}
 	}
 
 
 	return true;
 	return true;

+ 2 - 0
modules/openxr/openxr_api.h

@@ -272,6 +272,7 @@ private:
 	};
 	};
 	RID_Owner<Tracker, true> tracker_owner;
 	RID_Owner<Tracker, true> tracker_owner;
 	RID get_tracker_rid(XrPath p_path);
 	RID get_tracker_rid(XrPath p_path);
+	bool interaction_profile_changed = true; // If true we need to check for updates to our active_profile_rid.
 
 
 	struct ActionSet { // Action sets define a set of actions that can be enabled together
 	struct ActionSet { // Action sets define a set of actions that can be enabled together
 		String name; // Name for this action set (i.e. "godot_action_set")
 		String name; // Name for this action set (i.e. "godot_action_set")
@@ -420,6 +421,7 @@ public:
 	XrInstance get_instance() const { return instance; }
 	XrInstance get_instance() const { return instance; }
 	XrSystemId get_system_id() const { return system_id; }
 	XrSystemId get_system_id() const { return system_id; }
 	XrSession get_session() const { return session; }
 	XrSession get_session() const { return session; }
+	XrSessionState get_session_state() const { return session_state; }
 	OpenXRGraphicsExtensionWrapper *get_graphics_extension() const { return graphics_extension; }
 	OpenXRGraphicsExtensionWrapper *get_graphics_extension() const { return graphics_extension; }
 	String get_runtime_name() const { return runtime_name; }
 	String get_runtime_name() const { return runtime_name; }
 	String get_runtime_version() const { return runtime_version; }
 	String get_runtime_version() const { return runtime_version; }

+ 26 - 0
modules/openxr/openxr_interface.cpp

@@ -44,6 +44,7 @@ void OpenXRInterface::_bind_methods() {
 	// lifecycle signals
 	// lifecycle signals
 	ADD_SIGNAL(MethodInfo("session_begun"));
 	ADD_SIGNAL(MethodInfo("session_begun"));
 	ADD_SIGNAL(MethodInfo("session_stopping"));
 	ADD_SIGNAL(MethodInfo("session_stopping"));
+	ADD_SIGNAL(MethodInfo("session_synchronized"));
 	ADD_SIGNAL(MethodInfo("session_focussed"));
 	ADD_SIGNAL(MethodInfo("session_focussed"));
 	ADD_SIGNAL(MethodInfo("session_visible"));
 	ADD_SIGNAL(MethodInfo("session_visible"));
 	ADD_SIGNAL(MethodInfo("session_loss_pending"));
 	ADD_SIGNAL(MethodInfo("session_loss_pending"));
@@ -54,6 +55,9 @@ void OpenXRInterface::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("cpu_level_changed", PropertyInfo(Variant::INT, "sub_domain"), PropertyInfo(Variant::INT, "from_level"), PropertyInfo(Variant::INT, "to_level")));
 	ADD_SIGNAL(MethodInfo("cpu_level_changed", PropertyInfo(Variant::INT, "sub_domain"), PropertyInfo(Variant::INT, "from_level"), PropertyInfo(Variant::INT, "to_level")));
 	ADD_SIGNAL(MethodInfo("gpu_level_changed", PropertyInfo(Variant::INT, "sub_domain"), PropertyInfo(Variant::INT, "from_level"), PropertyInfo(Variant::INT, "to_level")));
 	ADD_SIGNAL(MethodInfo("gpu_level_changed", PropertyInfo(Variant::INT, "sub_domain"), PropertyInfo(Variant::INT, "from_level"), PropertyInfo(Variant::INT, "to_level")));
 
 
+	// State
+	ClassDB::bind_method(D_METHOD("get_session_state"), &OpenXRInterface::get_session_state);
+
 	// Display refresh rate
 	// Display refresh rate
 	ClassDB::bind_method(D_METHOD("get_display_refresh_rate"), &OpenXRInterface::get_display_refresh_rate);
 	ClassDB::bind_method(D_METHOD("get_display_refresh_rate"), &OpenXRInterface::get_display_refresh_rate);
 	ClassDB::bind_method(D_METHOD("set_display_refresh_rate", "refresh_rate"), &OpenXRInterface::set_display_refresh_rate);
 	ClassDB::bind_method(D_METHOD("set_display_refresh_rate", "refresh_rate"), &OpenXRInterface::set_display_refresh_rate);
@@ -116,6 +120,16 @@ void OpenXRInterface::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength");
 
 
+	BIND_ENUM_CONSTANT(OPENXR_SESSION_STATE_UNKNOWN);
+	BIND_ENUM_CONSTANT(OPENXR_SESSION_STATE_IDLE);
+	BIND_ENUM_CONSTANT(OPENXR_SESSION_STATE_READY);
+	BIND_ENUM_CONSTANT(OPENXR_SESSION_STATE_SYNCHRONIZED);
+	BIND_ENUM_CONSTANT(OPENXR_SESSION_STATE_VISIBLE);
+	BIND_ENUM_CONSTANT(OPENXR_SESSION_STATE_FOCUSED);
+	BIND_ENUM_CONSTANT(OPENXR_SESSION_STATE_STOPPING);
+	BIND_ENUM_CONSTANT(OPENXR_SESSION_STATE_LOSS_PENDING);
+	BIND_ENUM_CONSTANT(OPENXR_SESSION_STATE_EXITING);
+
 	BIND_ENUM_CONSTANT(HAND_LEFT);
 	BIND_ENUM_CONSTANT(HAND_LEFT);
 	BIND_ENUM_CONSTANT(HAND_RIGHT);
 	BIND_ENUM_CONSTANT(HAND_RIGHT);
 	BIND_ENUM_CONSTANT(HAND_MAX);
 	BIND_ENUM_CONSTANT(HAND_MAX);
@@ -1375,6 +1389,10 @@ void OpenXRInterface::on_state_visible() {
 	emit_signal(SNAME("session_visible"));
 	emit_signal(SNAME("session_visible"));
 }
 }
 
 
+void OpenXRInterface::on_state_synchronized() {
+	emit_signal(SNAME("session_synchronized"));
+}
+
 void OpenXRInterface::on_state_focused() {
 void OpenXRInterface::on_state_focused() {
 	emit_signal(SNAME("session_focussed"));
 	emit_signal(SNAME("session_focussed"));
 }
 }
@@ -1399,6 +1417,14 @@ void OpenXRInterface::on_refresh_rate_changes(float p_new_rate) {
 	emit_signal(SNAME("refresh_rate_changed"), p_new_rate);
 	emit_signal(SNAME("refresh_rate_changed"), p_new_rate);
 }
 }
 
 
+OpenXRInterface::OpenXrSessionState OpenXRInterface::get_session_state() {
+	if (openxr_api) {
+		return (OpenXrSessionState)openxr_api->get_session_state();
+	}
+
+	return OPENXR_SESSION_STATE_UNKNOWN;
+}
+
 /** Hand tracking. */
 /** Hand tracking. */
 void OpenXRInterface::set_motion_range(const Hand p_hand, const HandMotionRange p_motion_range) {
 void OpenXRInterface::set_motion_range(const Hand p_hand, const HandMotionRange p_motion_range) {
 	ERR_FAIL_INDEX(p_hand, HAND_MAX);
 	ERR_FAIL_INDEX(p_hand, HAND_MAX);

+ 17 - 0
modules/openxr/openxr_interface.h

@@ -209,6 +209,7 @@ public:
 	void on_state_ready();
 	void on_state_ready();
 	void on_state_visible();
 	void on_state_visible();
 	void on_state_focused();
 	void on_state_focused();
+	void on_state_synchronized();
 	void on_state_stopping();
 	void on_state_stopping();
 	void on_state_loss_pending();
 	void on_state_loss_pending();
 	void on_state_exiting();
 	void on_state_exiting();
@@ -216,6 +217,21 @@ public:
 	void on_refresh_rate_changes(float p_new_rate);
 	void on_refresh_rate_changes(float p_new_rate);
 	void tracker_profile_changed(RID p_tracker, RID p_interaction_profile);
 	void tracker_profile_changed(RID p_tracker, RID p_interaction_profile);
 
 
+	/** Session */
+	enum OpenXrSessionState { // Should mirror XrSessionState
+		OPENXR_SESSION_STATE_UNKNOWN = 0,
+		OPENXR_SESSION_STATE_IDLE = 1,
+		OPENXR_SESSION_STATE_READY = 2,
+		OPENXR_SESSION_STATE_SYNCHRONIZED = 3,
+		OPENXR_SESSION_STATE_VISIBLE = 4,
+		OPENXR_SESSION_STATE_FOCUSED = 5,
+		OPENXR_SESSION_STATE_STOPPING = 6,
+		OPENXR_SESSION_STATE_LOSS_PENDING = 7,
+		OPENXR_SESSION_STATE_EXITING = 8,
+	};
+
+	OpenXrSessionState get_session_state();
+
 	/** Hand tracking. */
 	/** Hand tracking. */
 	enum Hand {
 	enum Hand {
 		HAND_LEFT,
 		HAND_LEFT,
@@ -321,6 +337,7 @@ public:
 	~OpenXRInterface();
 	~OpenXRInterface();
 };
 };
 
 
+VARIANT_ENUM_CAST(OpenXRInterface::OpenXrSessionState)
 VARIANT_ENUM_CAST(OpenXRInterface::Hand)
 VARIANT_ENUM_CAST(OpenXRInterface::Hand)
 VARIANT_ENUM_CAST(OpenXRInterface::HandMotionRange)
 VARIANT_ENUM_CAST(OpenXRInterface::HandMotionRange)
 VARIANT_ENUM_CAST(OpenXRInterface::HandTrackedSource)
 VARIANT_ENUM_CAST(OpenXRInterface::HandTrackedSource)