Răsfoiți Sursa

Merge pull request #93646 from dsnopek/webxr-environment-blend-mode

Fix support for environment blend modes on `WebXRInterface`
Rémi Verschelde 1 an în urmă
părinte
comite
7a4cdd904a

+ 1 - 1
modules/webxr/godot_webxr.h

@@ -45,7 +45,7 @@ enum WebXRInputEvent {
 };
 
 typedef void (*GodotWebXRSupportedCallback)(char *p_session_mode, int p_supported);
-typedef void (*GodotWebXRStartedCallback)(char *p_reference_space_type, char *p_enabled_features);
+typedef void (*GodotWebXRStartedCallback)(char *p_reference_space_type, char *p_enabled_features, char *p_environment_blend_mode);
 typedef void (*GodotWebXREndedCallback)();
 typedef void (*GodotWebXRFailedCallback)(char *p_message);
 typedef void (*GodotWebXRInputEventCallback)(int p_event_type, int p_input_source_id);

+ 4 - 1
modules/webxr/native/library_godot_webxr.js

@@ -322,9 +322,12 @@ const GodotWebXR = {
 						const reference_space_c_str = GodotRuntime.allocString(reference_space_type);
 						const enabled_features = 'enabledFeatures' in session ? Array.from(session.enabledFeatures) : [];
 						const enabled_features_c_str = GodotRuntime.allocString(enabled_features.join(','));
-						onstarted(reference_space_c_str, enabled_features_c_str);
+						const environment_blend_mode = 'environmentBlendMode' in session ? session.environmentBlendMode : '';
+						const environment_blend_mode_c_str = GodotRuntime.allocString(environment_blend_mode);
+						onstarted(reference_space_c_str, enabled_features_c_str, environment_blend_mode_c_str);
 						GodotRuntime.free(reference_space_c_str);
 						GodotRuntime.free(enabled_features_c_str);
+						GodotRuntime.free(environment_blend_mode_c_str);
 					}, 0);
 				}
 

+ 5 - 0
modules/webxr/native/webxr.externs.js

@@ -82,6 +82,11 @@ XRSession.prototype.supportedFrameRates;
  */
 XRSession.prototype.enabledFeatures;
 
+/**
+ * @type {string}
+ */
+XRSession.prototype.environmentBlendMode;
+
 /**
  * @type {?function (Event)}
  */

+ 41 - 1
modules/webxr/webxr_interface_js.cpp

@@ -58,7 +58,7 @@ void _emwebxr_on_session_supported(char *p_session_mode, int p_supported) {
 	interface->emit_signal(SNAME("session_supported"), session_mode, p_supported ? true : false);
 }
 
-void _emwebxr_on_session_started(char *p_reference_space_type, char *p_enabled_features) {
+void _emwebxr_on_session_started(char *p_reference_space_type, char *p_enabled_features, char *p_environment_blend_mode) {
 	XRServer *xr_server = XRServer::get_singleton();
 	ERR_FAIL_NULL(xr_server);
 
@@ -68,6 +68,7 @@ void _emwebxr_on_session_started(char *p_reference_space_type, char *p_enabled_f
 	String reference_space_type = String(p_reference_space_type);
 	interface->_set_reference_space_type(reference_space_type);
 	interface->_set_enabled_features(p_enabled_features);
+	interface->_set_environment_blend_mode(p_environment_blend_mode);
 	interface->emit_signal(SNAME("session_started"));
 }
 
@@ -230,6 +231,44 @@ Array WebXRInterfaceJS::get_available_display_refresh_rates() const {
 	return ret;
 }
 
+Array WebXRInterfaceJS::get_supported_environment_blend_modes() {
+	Array blend_modes;
+	// The blend mode can't be changed, so return the current blend mode as the only supported one.
+	blend_modes.push_back(environment_blend_mode);
+	return blend_modes;
+}
+
+XRInterface::EnvironmentBlendMode WebXRInterfaceJS::get_environment_blend_mode() const {
+	return environment_blend_mode;
+}
+
+bool WebXRInterfaceJS::set_environment_blend_mode(EnvironmentBlendMode p_new_environment_blend_mode) {
+	if (environment_blend_mode == p_new_environment_blend_mode) {
+		// Environment blend mode can't be changed, but we'll consider it a success to set it
+		// to what it already is.
+		return true;
+	}
+	return false;
+}
+
+void WebXRInterfaceJS::_set_environment_blend_mode(String p_blend_mode_string) {
+	if (p_blend_mode_string == "opaque") {
+		environment_blend_mode = XRInterface::XR_ENV_BLEND_MODE_OPAQUE;
+	} else if (p_blend_mode_string == "additive") {
+		environment_blend_mode = XRInterface::XR_ENV_BLEND_MODE_ADDITIVE;
+	} else if (p_blend_mode_string == "alpha-blend") {
+		environment_blend_mode = XRInterface::XR_ENV_BLEND_MODE_ALPHA_BLEND;
+	} else {
+		// Not all browsers can give us this information, so as a fallback,
+		// we'll make some guesses about the blend mode.
+		if (session_mode == "immersive-ar") {
+			environment_blend_mode = XRInterface::XR_ENV_BLEND_MODE_ALPHA_BLEND;
+		} else {
+			environment_blend_mode = XRInterface::XR_ENV_BLEND_MODE_OPAQUE;
+		}
+	}
+}
+
 StringName WebXRInterfaceJS::get_name() const {
 	return "WebXR";
 };
@@ -336,6 +375,7 @@ void WebXRInterfaceJS::uninitialize() {
 		texture_cache.clear();
 		reference_space_type.clear();
 		enabled_features.clear();
+		environment_blend_mode = XRInterface::XR_ENV_BLEND_MODE_OPAQUE;
 		initialized = false;
 	};
 };

+ 8 - 0
modules/webxr/webxr_interface_js.h

@@ -60,6 +60,8 @@ private:
 	String reference_space_type;
 	String enabled_features;
 
+	XRInterface::EnvironmentBlendMode environment_blend_mode = XRInterface::XR_ENV_BLEND_MODE_OPAQUE;
+
 	Size2 render_targetsize;
 	RBMap<unsigned int, RID> texture_cache;
 	struct Touch {
@@ -113,6 +115,10 @@ public:
 	virtual void set_display_refresh_rate(float p_refresh_rate) override;
 	virtual Array get_available_display_refresh_rates() const override;
 
+	virtual Array get_supported_environment_blend_modes() override;
+	virtual XRInterface::EnvironmentBlendMode get_environment_blend_mode() const override;
+	virtual bool set_environment_blend_mode(EnvironmentBlendMode p_new_environment_blend_mode) override;
+
 	virtual StringName get_name() const override;
 	virtual uint32_t get_capabilities() const override;
 
@@ -136,8 +142,10 @@ public:
 
 	void _on_input_event(int p_event_type, int p_input_source_id);
 
+	// Internal setters used by callbacks from Emscripten.
 	inline void _set_reference_space_type(String p_reference_space_type) { reference_space_type = p_reference_space_type; }
 	inline void _set_enabled_features(String p_enabled_features) { enabled_features = p_enabled_features; }
+	void _set_environment_blend_mode(String p_blend_mode_string);
 
 	WebXRInterfaceJS();
 	~WebXRInterfaceJS();