| 
									
										
										
										
											2023-01-05 13:25:55 +01:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  xr_server.cpp                                                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining  */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the        */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including    */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,    */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to  */ | 
					
						
							|  |  |  | /* the following conditions:                                              */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be         */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.        */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | #include "xr_server.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/config/project_settings.h"
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | #include "xr/xr_interface.h"
 | 
					
						
							|  |  |  | #include "xr/xr_positional_tracker.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-24 20:43:30 +10:00
										 |  |  | XRServer::XRMode XRServer::xr_mode = XRMODE_DEFAULT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | XRServer::XRMode XRServer::get_xr_mode() { | 
					
						
							|  |  |  | 	return xr_mode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void XRServer::set_xr_mode(XRServer::XRMode p_mode) { | 
					
						
							|  |  |  | 	xr_mode = p_mode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | XRServer *XRServer::singleton = nullptr; | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | XRServer *XRServer::get_singleton() { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	return singleton; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | void XRServer::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_world_scale"), &XRServer::get_world_scale); | 
					
						
							| 
									
										
										
										
											2021-10-08 23:26:13 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_world_scale", "scale"), &XRServer::set_world_scale); | 
					
						
							| 
									
										
										
										
											2023-03-01 20:02:25 +11:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_world_origin"), &XRServer::get_world_origin); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_world_origin", "world_origin"), &XRServer::set_world_origin); | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_reference_frame"), &XRServer::get_reference_frame); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &XRServer::center_on_hmd); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_hmd_transform"), &XRServer::get_hmd_transform); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
											
										 
											2020-02-24 15:20:53 -03:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale"); | 
					
						
							| 
									
										
										
										
											2023-03-01 20:02:25 +11:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "world_origin"), "set_world_origin", "get_world_origin"); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 21:15:53 +11:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("add_interface", "interface"), &XRServer::add_interface); | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_interface_count"), &XRServer::get_interface_count); | 
					
						
							| 
									
										
										
										
											2021-03-29 21:15:53 +11:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("remove_interface", "interface"), &XRServer::remove_interface); | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_interface", "idx"), &XRServer::get_interface); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_interfaces"), &XRServer::get_interfaces); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("find_interface", "name"), &XRServer::find_interface); | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 21:15:53 +11:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("add_tracker", "tracker"), &XRServer::add_tracker); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("remove_tracker", "tracker"), &XRServer::remove_tracker); | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_trackers", "tracker_types"), &XRServer::get_trackers); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_tracker", "tracker_name"), &XRServer::get_tracker); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_primary_interface"), &XRServer::get_primary_interface); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &XRServer::set_primary_interface); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-24 00:57:58 +07:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "primary_interface"), "set_primary_interface", "get_primary_interface"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	BIND_ENUM_CONSTANT(TRACKER_HEAD); | 
					
						
							| 
									
										
										
										
											2017-08-20 17:45:01 +02:00
										 |  |  | 	BIND_ENUM_CONSTANT(TRACKER_CONTROLLER); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(TRACKER_BASESTATION); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(TRACKER_ANCHOR); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(TRACKER_ANY_KNOWN); | 
					
						
							| 
									
										
										
										
											2017-10-22 01:58:02 +07:00
										 |  |  | 	BIND_ENUM_CONSTANT(TRACKER_UNKNOWN); | 
					
						
							| 
									
										
										
										
											2017-08-20 17:45:01 +02:00
										 |  |  | 	BIND_ENUM_CONSTANT(TRACKER_ANY); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-21 23:10:44 +11:00
										 |  |  | 	BIND_ENUM_CONSTANT(RESET_FULL_ROTATION); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(RESET_BUT_KEEP_TILT); | 
					
						
							|  |  |  | 	BIND_ENUM_CONSTANT(DONT_RESET_ROTATION); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 18:58:05 -03:00
										 |  |  | 	ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING_NAME, "interface_name"))); | 
					
						
							|  |  |  | 	ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING_NAME, "interface_name"))); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"))); | 
					
						
							|  |  |  | 	ADD_SIGNAL(MethodInfo("tracker_updated", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"))); | 
					
						
							|  |  |  | 	ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"))); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-28 14:32:40 +10:00
										 |  |  | double XRServer::get_world_scale() const { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	return world_scale; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-28 14:32:40 +10:00
										 |  |  | void XRServer::set_world_scale(double p_world_scale) { | 
					
						
							| 
									
										
										
										
											2019-07-07 23:08:51 +02:00
										 |  |  | 	if (p_world_scale < 0.01) { | 
					
						
							|  |  |  | 		p_world_scale = 0.01; | 
					
						
							|  |  |  | 	} else if (p_world_scale > 1000.0) { | 
					
						
							|  |  |  | 		p_world_scale = 1000.0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	world_scale = p_world_scale; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D XRServer::get_world_origin() const { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	return world_origin; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | void XRServer::set_world_origin(const Transform3D &p_world_origin) { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	world_origin = p_world_origin; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D XRServer::get_reference_frame() const { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	return reference_frame; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | void XRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) { | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 	if (primary_interface == nullptr) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (primary_interface->get_play_area_mode() == XRInterface::XR_PLAY_AREA_STAGE) { | 
					
						
							|  |  |  | 		// center_on_hmd is not available in this mode
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | 		reference_frame = Transform3D(); | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 	// clear our current reference frame or we'll end up double adjusting it
 | 
					
						
							|  |  |  | 	reference_frame = Transform3D(); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 	// requesting our EYE_MONO transform should return our current HMD position
 | 
					
						
							|  |  |  | 	Transform3D new_reference_frame = primary_interface->get_camera_transform(); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 	// remove our tilt
 | 
					
						
							|  |  |  | 	if (p_rotation_mode == 1) { | 
					
						
							|  |  |  | 		// take the Y out of our Z
 | 
					
						
							| 
									
										
										
										
											2022-05-03 07:50:35 -05:00
										 |  |  | 		new_reference_frame.basis.set_column(2, Vector3(new_reference_frame.basis.rows[0][2], 0.0, new_reference_frame.basis.rows[2][2]).normalized()); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 		// Y is straight up
 | 
					
						
							| 
									
										
										
										
											2022-05-03 07:50:35 -05:00
										 |  |  | 		new_reference_frame.basis.set_column(1, Vector3(0.0, 1.0, 0.0)); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 		// and X is our cross reference
 | 
					
						
							| 
									
										
										
										
											2022-05-03 07:50:35 -05:00
										 |  |  | 		new_reference_frame.basis.set_column(0, new_reference_frame.basis.get_column(1).cross(new_reference_frame.basis.get_column(2)).normalized()); | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 	} else if (p_rotation_mode == 2) { | 
					
						
							|  |  |  | 		// remove our rotation, we're only interesting in centering on position
 | 
					
						
							|  |  |  | 		new_reference_frame.basis = Basis(); | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 	// don't negate our height
 | 
					
						
							|  |  |  | 	if (p_keep_height) { | 
					
						
							|  |  |  | 		new_reference_frame.origin.y = 0.0; | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2021-06-27 21:51:30 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	reference_frame = new_reference_frame.inverse(); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 01:08:21 -04:00
										 |  |  | Transform3D XRServer::get_hmd_transform() { | 
					
						
							|  |  |  | 	Transform3D hmd_transform; | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	if (primary_interface != nullptr) { | 
					
						
							| 
									
										
										
										
											2021-05-07 23:19:04 +10:00
										 |  |  | 		hmd_transform = primary_interface->get_camera_transform(); | 
					
						
							| 
									
										
										
										
											2018-03-15 22:33:55 +11:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 	return hmd_transform; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | void XRServer::add_interface(const Ref<XRInterface> &p_interface) { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	ERR_FAIL_COND(p_interface.is_null()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < interfaces.size(); i++) { | 
					
						
							|  |  |  | 		if (interfaces[i] == p_interface) { | 
					
						
							|  |  |  | 			ERR_PRINT("Interface was already added"); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	interfaces.push_back(p_interface); | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 	emit_signal(SNAME("interface_added"), p_interface->get_name()); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | void XRServer::remove_interface(const Ref<XRInterface> &p_interface) { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	ERR_FAIL_COND(p_interface.is_null()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int idx = -1; | 
					
						
							|  |  |  | 	for (int i = 0; i < interfaces.size(); i++) { | 
					
						
							|  |  |  | 		if (interfaces[i] == p_interface) { | 
					
						
							|  |  |  | 			idx = i; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-25 11:39:00 -05:00
										 |  |  | 	ERR_FAIL_COND_MSG(idx == -1, "Interface not found."); | 
					
						
							| 
									
										
										
										
											2023-10-05 22:11:05 +05:30
										 |  |  | 	print_verbose("XR: Removed interface \"" + p_interface->get_name() + "\""); | 
					
						
							| 
									
										
										
										
											2021-07-17 18:22:52 -03:00
										 |  |  | 	emit_signal(SNAME("interface_removed"), p_interface->get_name()); | 
					
						
							| 
									
										
										
										
											2021-07-03 16:17:03 -06:00
										 |  |  | 	interfaces.remove_at(idx); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | int XRServer::get_interface_count() const { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	return interfaces.size(); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | Ref<XRInterface> XRServer::get_interface(int p_index) const { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_index, interfaces.size(), nullptr); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return interfaces[p_index]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | Ref<XRInterface> XRServer::find_interface(const String &p_name) const { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	int idx = -1; | 
					
						
							|  |  |  | 	for (int i = 0; i < interfaces.size(); i++) { | 
					
						
							|  |  |  | 		if (interfaces[i]->get_name() == p_name) { | 
					
						
							|  |  |  | 			idx = i; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-25 11:39:00 -05:00
										 |  |  | 	ERR_FAIL_COND_V_MSG(idx == -1, nullptr, "Interface not found."); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return interfaces[idx]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 00:52:20 +02:00
										 |  |  | TypedArray<Dictionary> XRServer::get_interfaces() const { | 
					
						
							| 
									
										
										
										
											2017-11-04 11:50:05 +11:00
										 |  |  | 	Array ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < interfaces.size(); i++) { | 
					
						
							|  |  |  | 		Dictionary iface_info; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		iface_info["id"] = i; | 
					
						
							|  |  |  | 		iface_info["name"] = interfaces[i]->get_name(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ret.push_back(iface_info); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | Ref<XRInterface> XRServer::get_primary_interface() const { | 
					
						
							|  |  |  | 	return primary_interface; | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | void XRServer::set_primary_interface(const Ref<XRInterface> &p_primary_interface) { | 
					
						
							|  |  |  | 	if (p_primary_interface.is_null()) { | 
					
						
							|  |  |  | 		print_verbose("XR: Clearing primary interface"); | 
					
						
							|  |  |  | 		primary_interface.unref(); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		primary_interface = p_primary_interface; | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 		print_verbose("XR: Primary interface set to: " + primary_interface->get_name()); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 21:15:53 +11:00
										 |  |  | void XRServer::add_tracker(Ref<XRPositionalTracker> p_tracker) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND(p_tracker.is_null()); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	StringName tracker_name = p_tracker->get_tracker_name(); | 
					
						
							|  |  |  | 	if (trackers.has(tracker_name)) { | 
					
						
							|  |  |  | 		if (trackers[tracker_name] != p_tracker) { | 
					
						
							|  |  |  | 			// We already have a tracker with this name, we're going to replace it
 | 
					
						
							|  |  |  | 			trackers[tracker_name] = p_tracker; | 
					
						
							|  |  |  | 			emit_signal(SNAME("tracker_updated"), tracker_name, p_tracker->get_tracker_type()); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		trackers[tracker_name] = p_tracker; | 
					
						
							|  |  |  | 		emit_signal(SNAME("tracker_added"), tracker_name, p_tracker->get_tracker_type()); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 21:15:53 +11:00
										 |  |  | void XRServer::remove_tracker(Ref<XRPositionalTracker> p_tracker) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND(p_tracker.is_null()); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	StringName tracker_name = p_tracker->get_tracker_name(); | 
					
						
							|  |  |  | 	if (trackers.has(tracker_name)) { | 
					
						
							|  |  |  | 		// we send the signal right before removing it
 | 
					
						
							|  |  |  | 		emit_signal(SNAME("tracker_removed"), p_tracker->get_tracker_name(), p_tracker->get_tracker_type()); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 		// and remove it
 | 
					
						
							|  |  |  | 		trackers.erase(tracker_name); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | Dictionary XRServer::get_trackers(int p_tracker_types) { | 
					
						
							|  |  |  | 	Dictionary res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < trackers.size(); i++) { | 
					
						
							|  |  |  | 		Ref<XRPositionalTracker> tracker = trackers.get_value_at_index(i); | 
					
						
							|  |  |  | 		if (tracker.is_valid() && (tracker->get_tracker_type() & p_tracker_types) != 0) { | 
					
						
							|  |  |  | 			res[tracker->get_tracker_name()] = tracker; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | Ref<XRPositionalTracker> XRServer::get_tracker(const StringName &p_name) const { | 
					
						
							|  |  |  | 	if (trackers.has(p_name)) { | 
					
						
							|  |  |  | 		return trackers[p_name]; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// tracker hasn't been registered yet, which is fine, no need to spam the error log...
 | 
					
						
							|  |  |  | 		return Ref<XRPositionalTracker>(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | PackedStringArray XRServer::get_suggested_tracker_names() const { | 
					
						
							|  |  |  | 	PackedStringArray arr; | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	for (int i = 0; i < interfaces.size(); i++) { | 
					
						
							|  |  |  | 		Ref<XRInterface> interface = interfaces[i]; | 
					
						
							|  |  |  | 		PackedStringArray interface_arr = interface->get_suggested_tracker_names(); | 
					
						
							|  |  |  | 		for (int a = 0; a < interface_arr.size(); a++) { | 
					
						
							|  |  |  | 			if (!arr.has(interface_arr[a])) { | 
					
						
							|  |  |  | 				arr.push_back(interface_arr[a]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	if (arr.size() == 0) { | 
					
						
							|  |  |  | 		// no suggestions from our tracker? include our defaults
 | 
					
						
							|  |  |  | 		arr.push_back(String("head")); | 
					
						
							|  |  |  | 		arr.push_back(String("left_hand")); | 
					
						
							|  |  |  | 		arr.push_back(String("right_hand")); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	return arr; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | PackedStringArray XRServer::get_suggested_pose_names(const StringName &p_tracker_name) const { | 
					
						
							|  |  |  | 	PackedStringArray arr; | 
					
						
							| 
									
										
										
										
											2021-08-23 15:23:16 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	for (int i = 0; i < interfaces.size(); i++) { | 
					
						
							|  |  |  | 		Ref<XRInterface> interface = interfaces[i]; | 
					
						
							|  |  |  | 		PackedStringArray interface_arr = interface->get_suggested_pose_names(p_tracker_name); | 
					
						
							|  |  |  | 		for (int a = 0; a < interface_arr.size(); a++) { | 
					
						
							|  |  |  | 			if (!arr.has(interface_arr[a])) { | 
					
						
							|  |  |  | 				arr.push_back(interface_arr[a]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-08-23 15:23:16 +10:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (arr.size() == 0) { | 
					
						
							|  |  |  | 		// no suggestions from our tracker? include our defaults
 | 
					
						
							|  |  |  | 		arr.push_back(String("default")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ((p_tracker_name == "left_hand") || (p_tracker_name == "right_hand")) { | 
					
						
							|  |  |  | 			arr.push_back(String("aim")); | 
					
						
							|  |  |  | 			arr.push_back(String("grip")); | 
					
						
							|  |  |  | 			arr.push_back(String("skeleton")); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return arr; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | void XRServer::_process() { | 
					
						
							| 
									
										
										
										
											2021-12-14 12:44:12 +11:00
										 |  |  | 	// called from our main game loop before we handle physics and game logic
 | 
					
						
							|  |  |  | 	// note that we can have multiple interfaces active if we have interfaces that purely handle tracking
 | 
					
						
							| 
									
										
										
										
											2018-03-15 22:33:55 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-14 12:44:12 +11:00
										 |  |  | 	// process all active interfaces
 | 
					
						
							| 
									
										
										
										
											2018-03-15 22:33:55 +11:00
										 |  |  | 	for (int i = 0; i < interfaces.size(); i++) { | 
					
						
							|  |  |  | 		if (!interfaces[i].is_valid()) { | 
					
						
							|  |  |  | 			// ignore, not a valid reference
 | 
					
						
							|  |  |  | 		} else if (interfaces[i]->is_initialized()) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 			interfaces.write[i]->process(); | 
					
						
							| 
									
										
										
										
											2018-03-15 22:33:55 +11:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 12:25:20 +11:00
										 |  |  | void XRServer::pre_render() { | 
					
						
							|  |  |  | 	// called from RendererViewport.draw_viewports right before we start drawing our viewports
 | 
					
						
							|  |  |  | 	// note that we can have multiple interfaces active if we have interfaces that purely handle tracking
 | 
					
						
							| 
									
										
										
										
											2018-03-15 22:33:55 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 12:25:20 +11:00
										 |  |  | 	// process all active interfaces
 | 
					
						
							|  |  |  | 	for (int i = 0; i < interfaces.size(); i++) { | 
					
						
							|  |  |  | 		if (!interfaces[i].is_valid()) { | 
					
						
							|  |  |  | 			// ignore, not a valid reference
 | 
					
						
							|  |  |  | 		} else if (interfaces[i]->is_initialized()) { | 
					
						
							|  |  |  | 			interfaces.write[i]->pre_render(); | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void XRServer::end_frame() { | 
					
						
							|  |  |  | 	// called from RenderingServerDefault after Vulkan queues have been submitted
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// process all active interfaces
 | 
					
						
							|  |  |  | 	for (int i = 0; i < interfaces.size(); i++) { | 
					
						
							|  |  |  | 		if (!interfaces[i].is_valid()) { | 
					
						
							|  |  |  | 			// ignore, not a valid reference
 | 
					
						
							|  |  |  | 		} else if (interfaces[i]->is_initialized()) { | 
					
						
							|  |  |  | 			interfaces.write[i]->end_frame(); | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-03-15 22:33:55 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | XRServer::XRServer() { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	singleton = this; | 
					
						
							|  |  |  | 	world_scale = 1.0; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-09 00:47:36 +10:00
										 |  |  | XRServer::~XRServer() { | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	primary_interface.unref(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (interfaces.size() > 0) { | 
					
						
							| 
									
										
										
										
											2021-07-03 16:17:03 -06:00
										 |  |  | 		interfaces.remove_at(0); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 	// TODO pretty sure there is a clear function or something...
 | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	while (trackers.size() > 0) { | 
					
						
							| 
									
										
										
										
											2021-08-29 16:05:11 +10:00
										 |  |  | 		trackers.erase(trackers.get_key_at_index(0)); | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	singleton = nullptr; | 
					
						
							| 
									
										
										
										
											2017-04-23 22:10:41 +10:00
										 |  |  | }; |