diff --git a/doc/classes/ARVRController.xml b/doc/classes/ARVRController.xml index 47a9341643e..2adc073ebe6 100644 --- a/doc/classes/ARVRController.xml +++ b/doc/classes/ARVRController.xml @@ -62,7 +62,10 @@ - The controller's id. The first controller that the [ARVRServer] detects will have id 1, the second id 2, the third id 3, etc. When a controller is turned off, it's slot is freed. This ensures controllers will keep the same id even when controllers with lower ids are turned off. + The controller's id. + A controller id of 0 is unbound and will always result in an inactive node. Controller id 1 is reserved for the first controller that identifies itself as the left hand controller and id 2 is reserved for the first controller that identifies itself as the right hand controller. + For any other controller that the [ARVRServer] detects we continue with controller id 3. + When a controller is turned off, its slot is freed. This ensures controllers will keep the same id even when controllers with lower ids are turned off. The degree to which the tracker rumbles. Ranges from [code]0.0[/code] to [code]1.0[/code] with precision [code].01[/code]. If changed, updates [member ARVRPositionalTracker.rumble] accordingly. diff --git a/doc/classes/ARVRServer.xml b/doc/classes/ARVRServer.xml index 17202c8c2c2..ffe6c35240a 100644 --- a/doc/classes/ARVRServer.xml +++ b/doc/classes/ARVRServer.xml @@ -14,7 +14,7 @@ - + @@ -154,5 +154,14 @@ Used internally to select all trackers. + + Fully reset the orientation of the HMD. Regardless of what direction the user is looking to in the real world. The user will look dead ahead in the virtual world. + + + Resets the orientation but keeps the tilt of the device. So if we're looking down, we keep looking down but heading will be reset. + + + Does not reset the orientation of the HMD, only the position of the player gets centered. + diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp index e1e0b9b1ce9..2bb41bf49e8 100644 --- a/scene/3d/arvr_nodes.cpp +++ b/scene/3d/arvr_nodes.cpp @@ -231,7 +231,7 @@ void ARVRController::_notification(int p_what) { void ARVRController::_bind_methods() { ClassDB::bind_method(D_METHOD("set_controller_id", "controller_id"), &ARVRController::set_controller_id); ClassDB::bind_method(D_METHOD("get_controller_id"), &ARVRController::get_controller_id); - ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id", PROPERTY_HINT_RANGE, "1,32,1"), "set_controller_id", "get_controller_id"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id", PROPERTY_HINT_RANGE, "0,32,1"), "set_controller_id", "get_controller_id"); ClassDB::bind_method(D_METHOD("get_controller_name"), &ARVRController::get_controller_name); // passthroughs to information about our related joystick @@ -251,7 +251,8 @@ void ARVRController::_bind_methods() { }; void ARVRController::set_controller_id(int p_controller_id) { - // we don't check any bounds here, this controller may not yet be active and just be a place holder until it is. + // We don't check any bounds here, this controller may not yet be active and just be a place holder until it is. + // Note that setting this to 0 means this node is not bound to a controller yet. controller_id = p_controller_id; }; @@ -420,7 +421,7 @@ void ARVRAnchor::_bind_methods() { ClassDB::bind_method(D_METHOD("set_anchor_id", "anchor_id"), &ARVRAnchor::set_anchor_id); ClassDB::bind_method(D_METHOD("get_anchor_id"), &ARVRAnchor::get_anchor_id); - ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_id"), "set_anchor_id", "get_anchor_id"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_id", PROPERTY_HINT_RANGE, "0,32,1"), "set_anchor_id", "get_anchor_id"); ClassDB::bind_method(D_METHOD("get_anchor_name"), &ARVRAnchor::get_anchor_name); ClassDB::bind_method(D_METHOD("get_is_active"), &ARVRAnchor::get_is_active); @@ -430,7 +431,8 @@ void ARVRAnchor::_bind_methods() { }; void ARVRAnchor::set_anchor_id(int p_anchor_id) { - // we don't check any bounds here, this anchor may not yet be active and just be a place holder until it is. + // We don't check any bounds here, this anchor may not yet be active and just be a place holder until it is. + // Note that setting this to 0 means this node is not bound to an anchor yet. anchor_id = p_anchor_id; }; diff --git a/servers/arvr/arvr_positional_tracker.cpp b/servers/arvr/arvr_positional_tracker.cpp index fc0270615cc..fb97d5b86b1 100644 --- a/servers/arvr/arvr_positional_tracker.cpp +++ b/servers/arvr/arvr_positional_tracker.cpp @@ -62,13 +62,15 @@ void ARVRPositionalTracker::_bind_methods() { void ARVRPositionalTracker::set_type(ARVRServer::TrackerType p_type) { if (type != p_type) { type = p_type; + hand = ARVRPositionalTracker::TRACKER_HAND_UNKNOWN; ARVRServer *arvr_server = ARVRServer::get_singleton(); ERR_FAIL_NULL(arvr_server); // get a tracker id for our type + // note if this is a controller this will be 3 or higher but we may change it later. tracker_id = arvr_server->get_free_tracker_id_for_type(p_type); - } + }; }; ARVRServer::TrackerType ARVRPositionalTracker::get_type() const { @@ -156,7 +158,24 @@ ARVRPositionalTracker::TrackerHand ARVRPositionalTracker::get_hand() const { }; void ARVRPositionalTracker::set_hand(const ARVRPositionalTracker::TrackerHand p_hand) { - hand = p_hand; + ARVRServer *arvr_server = ARVRServer::get_singleton(); + ERR_FAIL_NULL(arvr_server); + + if (hand != p_hand) { + // we can only set this if we've previously set this to be a controller!! + ERR_FAIL_COND((type != ARVRServer::TRACKER_CONTROLLER) && (p_hand != ARVRPositionalTracker::TRACKER_HAND_UNKNOWN)); + + hand = p_hand; + if (hand == ARVRPositionalTracker::TRACKER_LEFT_HAND) { + if (!arvr_server->is_tracker_id_in_use_for_type(type, 1)) { + tracker_id = 1; + }; + } else if (hand == ARVRPositionalTracker::TRACKER_RIGHT_HAND) { + if (!arvr_server->is_tracker_id_in_use_for_type(type, 2)) { + tracker_id = 2; + }; + }; + }; }; Transform ARVRPositionalTracker::get_transform(bool p_adjust_by_reference_frame) const { diff --git a/servers/arvr_server.cpp b/servers/arvr_server.cpp index 1e73d6753c0..df73040e1ef 100644 --- a/servers/arvr_server.cpp +++ b/servers/arvr_server.cpp @@ -43,7 +43,7 @@ void ARVRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_world_scale"), &ARVRServer::get_world_scale); ClassDB::bind_method(D_METHOD("set_world_scale"), &ARVRServer::set_world_scale); ClassDB::bind_method(D_METHOD("get_reference_frame"), &ARVRServer::get_reference_frame); - ClassDB::bind_method(D_METHOD("center_on_hmd", "ignore_tilt", "keep_height"), &ARVRServer::center_on_hmd); + ClassDB::bind_method(D_METHOD("center_on_hmd", "rotation_mode", "keep_height"), &ARVRServer::center_on_hmd); ADD_PROPERTY(PropertyInfo(Variant::REAL, "world_scale"), "set_world_scale", "get_world_scale"); @@ -63,6 +63,10 @@ void ARVRServer::_bind_methods() { BIND_ENUM_CONSTANT(TRACKER_UNKNOWN); BIND_ENUM_CONSTANT(TRACKER_ANY); + BIND_ENUM_CONSTANT(RESET_FULL_ROTATION); + BIND_ENUM_CONSTANT(RESET_BUT_KEEP_TILT); + BIND_ENUM_CONSTANT(DONT_RESET_ROTATION); + ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING, "name"))); ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING, "name"))); @@ -96,7 +100,7 @@ Transform ARVRServer::get_reference_frame() const { return reference_frame; }; -void ARVRServer::center_on_hmd(bool p_ignore_tilt, bool p_keep_height) { +void ARVRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) { if (primary_interface != NULL) { // clear our current reference frame or we'll end up double adjusting it reference_frame = Transform(); @@ -105,7 +109,7 @@ void ARVRServer::center_on_hmd(bool p_ignore_tilt, bool p_keep_height) { Transform new_reference_frame = primary_interface->get_transform_for_eye(ARVRInterface::EYE_MONO, Transform()); // remove our tilt - if (p_ignore_tilt) { + if (p_rotation_mode == 1) { // take the Y out of our Z new_reference_frame.basis.set_axis(2, Vector3(new_reference_frame.basis.elements[0][2], 0.0, new_reference_frame.basis.elements[2][2]).normalized()); @@ -114,6 +118,9 @@ void ARVRServer::center_on_hmd(bool p_ignore_tilt, bool p_keep_height) { // and X is our cross reference new_reference_frame.basis.set_axis(0, new_reference_frame.basis.get_axis(1).cross(new_reference_frame.basis.get_axis(2)).normalized()); + } else if (p_rotation_mode == 2) { + // remove our rotation, we're only interesting in centering on position + new_reference_frame.basis = Basis(); }; // don't negate our height @@ -229,8 +236,12 @@ bool ARVRServer::is_tracker_id_in_use_for_type(TrackerType p_tracker_type, int p }; int ARVRServer::get_free_tracker_id_for_type(TrackerType p_tracker_type) { - // we start checking at 1, 0 means that it's not a controller.. - int tracker_id = 1; + // We start checking at 1, 0 means that it's not a controller.. + // Note that for controller we reserve: + // - 1 for the left hand controller and + // - 2 for the right hand controller + // so we start at 3 :) + int tracker_id = p_tracker_type == ARVRServer::TRACKER_CONTROLLER ? 3 : 1; while (is_tracker_id_in_use_for_type(p_tracker_type, tracker_id)) { // try the next one diff --git a/servers/arvr_server.h b/servers/arvr_server.h index 9b84ee2e99c..0381e6e533f 100644 --- a/servers/arvr_server.h +++ b/servers/arvr_server.h @@ -68,6 +68,12 @@ public: TRACKER_ANY = 0xff /* used by get_connected_trackers to return all types */ }; + enum RotationMode { + RESET_FULL_ROTATION = 0, /* we reset the full rotation, regardless of how the HMD is oriented, we're looking dead ahead */ + RESET_BUT_KEEP_TILT = 1, /* reset rotation but keep tilt. */ + DONT_RESET_ROTATION = 2, /* don't reset the rotation, we will only center on position */ + }; + private: Vector > interfaces; Vector trackers; @@ -78,8 +84,6 @@ private: Transform world_origin; /* our world origin point, maps a location in our virtual world to the origin point in our real world tracking volume */ Transform reference_frame; /* our reference frame */ - bool is_tracker_id_in_use_for_type(TrackerType p_tracker_type, int p_tracker_id) const; - protected: static ARVRServer *singleton; @@ -127,7 +131,7 @@ public: and in the virtual world out of sync */ Transform get_reference_frame() const; - void center_on_hmd(bool p_ignore_tilt, bool p_keep_height); + void center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height); /* Interfaces are objects that 'glue' Godot to an AR or VR SDK such as the Oculus SDK, OpenVR, OpenHMD, etc. @@ -150,9 +154,8 @@ public: /* Our trackers are objects that expose the orientation and position of physical devices such as controller, anchor points, etc. They are created and managed by our active AR/VR interfaces. - - Note that for trackers that */ + bool is_tracker_id_in_use_for_type(TrackerType p_tracker_type, int p_tracker_id) const; int get_free_tracker_id_for_type(TrackerType p_tracker_type); void add_tracker(ARVRPositionalTracker *p_tracker); void remove_tracker(ARVRPositionalTracker *p_tracker); @@ -167,5 +170,6 @@ public: #define ARVR ARVRServer VARIANT_ENUM_CAST(ARVRServer::TrackerType); +VARIANT_ENUM_CAST(ARVRServer::RotationMode); #endif