diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/gdscript/doc_classes/@GDScript.xml | 6 | ||||
-rw-r--r-- | modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs | 42 | ||||
-rw-r--r-- | modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs | 28 | ||||
-rw-r--r-- | modules/mono/editor/bindings_generator.cpp | 20 | ||||
-rw-r--r-- | modules/openxr/extensions/openxr_hand_tracking_extension.cpp | 72 | ||||
-rw-r--r-- | modules/openxr/extensions/openxr_hand_tracking_extension.h | 28 | ||||
-rw-r--r-- | modules/openxr/openxr_interface.cpp | 48 | ||||
-rw-r--r-- | modules/openxr/openxr_interface.h | 4 | ||||
-rw-r--r-- | modules/openxr/register_types.cpp | 12 | ||||
-rw-r--r-- | modules/openxr/scene/openxr_hand.cpp | 15 |
10 files changed, 142 insertions, 133 deletions
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 806ab1e3df..4fec745999 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -601,8 +601,8 @@ @icon("res://path/to/class/icon.svg") [/codeblock] [b]Note:[/b] Only the script can have a custom icon. Inner classes are not supported. - [b]Note:[/b] As annotations describe their subject, the [code]@icon[/code] annotation must be placed before the class definition and inheritance. - [b]Note:[/b] Unlike other annotations, the argument of the [code]@icon[/code] annotation must be a string literal (constant expressions are not supported). + [b]Note:[/b] As annotations describe their subject, the [annotation @icon] annotation must be placed before the class definition and inheritance. + [b]Note:[/b] Unlike other annotations, the argument of the [annotation @icon] annotation must be a string literal (constant expressions are not supported). </description> </annotation> <annotation name="@onready"> @@ -653,7 +653,7 @@ @tool extends Node [/codeblock] - [b]Note:[/b] As annotations describe their subject, the [code]@tool[/code] annotation must be placed before the class definition and inheritance. + [b]Note:[/b] As annotations describe their subject, the [annotation @tool] annotation must be placed before the class definition and inheritance. </description> </annotation> <annotation name="@warning_ignore" qualifiers="vararg"> diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs index 9bb4fd153b..907511d140 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildManager.cs @@ -206,17 +206,19 @@ namespace GodotTools.Build if (!File.Exists(buildInfo.Project)) return true; // No project to build. - using var pr = new EditorProgress("dotnet_build_project", "Building .NET project...", 1); - - pr.Step("Building project", 0); + bool success; + using (var pr = new EditorProgress("dotnet_build_project", "Building .NET project...", 1)) + { + pr.Step("Building project", 0); + success = Build(buildInfo); + } - if (!Build(buildInfo)) + if (!success) { ShowBuildErrorDialog("Failed to build project"); - return false; } - return true; + return success; } private static bool CleanProjectBlocking(BuildInfo buildInfo) @@ -224,32 +226,36 @@ namespace GodotTools.Build if (!File.Exists(buildInfo.Project)) return true; // No project to clean. - using var pr = new EditorProgress("dotnet_clean_project", "Cleaning .NET project...", 1); - - pr.Step("Cleaning project", 0); + bool success; + using (var pr = new EditorProgress("dotnet_clean_project", "Cleaning .NET project...", 1)) + { + pr.Step("Cleaning project", 0); + success = Build(buildInfo); + } - if (!Build(buildInfo)) + if (!success) { ShowBuildErrorDialog("Failed to clean project"); - return false; } - return true; + return success; } private static bool PublishProjectBlocking(BuildInfo buildInfo) { - using var pr = new EditorProgress("dotnet_publish_project", "Publishing .NET project...", 1); - - pr.Step("Running dotnet publish", 0); + bool success; + using (var pr = new EditorProgress("dotnet_publish_project", "Publishing .NET project...", 1)) + { + pr.Step("Running dotnet publish", 0); + success = Publish(buildInfo); + } - if (!Publish(buildInfo)) + if (!success) { ShowBuildErrorDialog("Failed to publish .NET project"); - return false; } - return true; + return success; } private static BuildInfo CreateBuildInfo( diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 48e654c286..a00c812c79 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -65,6 +65,7 @@ namespace GodotTools private bool CreateProjectSolution() { + string errorMessage = null; using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 2)) { pr.Step("Generating C# project...".TTR()); @@ -96,22 +97,23 @@ namespace GodotTools } catch (IOException e) { - ShowErrorDialog("Failed to save solution. Exception message: ".TTR() + e.Message); - return false; + errorMessage = "Failed to save solution. Exception message: ".TTR() + e.Message; } - - pr.Step("Done".TTR()); - - // Here, after all calls to progress_task_step - CallDeferred(nameof(_ShowDotnetFeatures)); } else { - ShowErrorDialog("Failed to create C# project.".TTR()); + errorMessage = "Failed to create C# project.".TTR(); } + } - return true; + if (!string.IsNullOrEmpty(errorMessage)) + { + ShowErrorDialog(errorMessage); + return false; } + + _ShowDotnetFeatures(); + return true; } private void _ShowDotnetFeatures() @@ -161,14 +163,14 @@ namespace GodotTools { _errorDialog.Title = title; _errorDialog.DialogText = message; - _errorDialog.PopupCentered(); + EditorInterface.Singleton.PopupDialogCentered(_errorDialog); } public void ShowConfirmCreateSlnDialog() { _confirmCreateSlnDialog.Title = "C# solution already exists. This will override the existing C# project file, any manual changes will be lost.".TTR(); _confirmCreateSlnDialog.DialogText = "Create C# solution".TTR(); - _confirmCreateSlnDialog.PopupCentered(); + EditorInterface.Singleton.PopupDialogCentered(_confirmCreateSlnDialog); } private static string _vsCodePath = string.Empty; @@ -483,11 +485,11 @@ namespace GodotTools _editorSettings = EditorInterface.Singleton.GetEditorSettings(); _errorDialog = new AcceptDialog(); - editorBaseControl.AddChild(_errorDialog); + _errorDialog.SetUnparentWhenInvisible(true); _confirmCreateSlnDialog = new ConfirmationDialog(); + _confirmCreateSlnDialog.SetUnparentWhenInvisible(true); _confirmCreateSlnDialog.Confirmed += () => CreateProjectSolution(); - editorBaseControl.AddChild(_confirmCreateSlnDialog); MSBuildPanel = new MSBuildPanel(); MSBuildPanel.BuildStateChanged += BuildStateChanged; diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index ccfcf2a87c..36fdda4625 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -264,7 +264,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf } else if (code_tag) { xml_output.append("["); pos = brk_pos + 1; - } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ") || tag.begins_with("param ")) { + } else if (tag.begins_with("method ") || tag.begins_with("constructor ") || tag.begins_with("operator ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ") || tag.begins_with("theme_item ") || tag.begins_with("param ")) { const int tag_end = tag.find(" "); const String link_tag = tag.substr(0, tag_end); const String link_target = tag.substr(tag_end + 1, tag.length()).lstrip(" "); @@ -298,6 +298,12 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf if (link_tag == "method") { _append_xml_method(xml_output, target_itype, target_cname, link_target, link_target_parts); + } else if (link_tag == "constructor") { + // TODO: Support constructors? + _append_xml_undeclared(xml_output, link_target); + } else if (link_tag == "operator") { + // TODO: Support operators? + _append_xml_undeclared(xml_output, link_target); } else if (link_tag == "member") { _append_xml_member(xml_output, target_itype, target_cname, link_target, link_target_parts); } else if (link_tag == "signal") { @@ -401,29 +407,29 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf pos = brk_end + 1; tag_stack.push_front(tag); - } else if (tag == "code") { + } else if (tag == "code" || tag.begins_with("code ")) { xml_output.append("<c>"); code_tag = true; pos = brk_end + 1; - tag_stack.push_front(tag); - } else if (tag == "codeblock") { + tag_stack.push_front("code"); + } else if (tag == "codeblock" || tag.begins_with("codeblock ")) { xml_output.append("<code>"); code_tag = true; pos = brk_end + 1; - tag_stack.push_front(tag); + tag_stack.push_front("codeblock"); } else if (tag == "codeblocks") { line_del = true; pos = brk_end + 1; tag_stack.push_front(tag); - } else if (tag == "csharp") { + } else if (tag == "csharp" || tag.begins_with("csharp ")) { xml_output.append("<code>"); line_del = false; code_tag = true; pos = brk_end + 1; - tag_stack.push_front(tag); + tag_stack.push_front("csharp"); } else if (tag == "kbd") { // keyboard combinations are not supported in xml comments pos = brk_end + 1; diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp index c92b2b08d0..caf97ca2e0 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.cpp +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.cpp @@ -32,6 +32,7 @@ #include "../openxr_api.h" +#include "core/config/project_settings.h" #include "core/string/print_string.h" #include "servers/xr_server.h" @@ -59,7 +60,6 @@ HashMap<String, bool *> OpenXRHandTrackingExtension::get_requested_extensions() request_extensions[XR_EXT_HAND_TRACKING_EXTENSION_NAME] = &hand_tracking_ext; request_extensions[XR_EXT_HAND_JOINTS_MOTION_RANGE_EXTENSION_NAME] = &hand_motion_range_ext; - request_extensions[XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME] = &hand_tracking_aim_state_ext; return request_extensions; } @@ -106,17 +106,11 @@ void OpenXRHandTrackingExtension::on_state_ready() { } // Setup our hands and reset data - for (int i = 0; i < MAX_OPENXR_TRACKED_HANDS; i++) { + for (int i = 0; i < OPENXR_MAX_TRACKED_HANDS; i++) { // we'll do this later hand_trackers[i].is_initialized = false; hand_trackers[i].hand_tracker = XR_NULL_HANDLE; - hand_trackers[i].aimState.aimPose = { { 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } }; - hand_trackers[i].aimState.pinchStrengthIndex = 0.0; - hand_trackers[i].aimState.pinchStrengthMiddle = 0.0; - hand_trackers[i].aimState.pinchStrengthRing = 0.0; - hand_trackers[i].aimState.pinchStrengthLittle = 0.0; - hand_trackers[i].locations.isActive = false; for (int j = 0; j < XR_HAND_JOINT_COUNT_EXT; j++) { @@ -141,7 +135,7 @@ void OpenXRHandTrackingExtension::on_process() { XrResult result; - for (int i = 0; i < MAX_OPENXR_TRACKED_HANDS; i++) { + for (int i = 0; i < OPENXR_MAX_TRACKED_HANDS; i++) { if (hand_trackers[i].hand_tracker == XR_NULL_HANDLE) { XrHandTrackerCreateInfoEXT createInfo = { XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT, // type @@ -157,18 +151,6 @@ void OpenXRHandTrackingExtension::on_process() { hand_trackers[i].is_initialized = false; } else { void *next_pointer = nullptr; - if (hand_tracking_aim_state_ext) { - hand_trackers[i].aimState.type = XR_TYPE_HAND_TRACKING_AIM_STATE_FB; - hand_trackers[i].aimState.next = next_pointer; - hand_trackers[i].aimState.status = 0; - hand_trackers[i].aimState.aimPose = { { 0.0, 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } }; - hand_trackers[i].aimState.pinchStrengthIndex = 0.0; - hand_trackers[i].aimState.pinchStrengthMiddle = 0.0; - hand_trackers[i].aimState.pinchStrengthRing = 0.0; - hand_trackers[i].aimState.pinchStrengthLittle = 0.0; - - next_pointer = &hand_trackers[i].aimState; - } hand_trackers[i].velocities.type = XR_TYPE_HAND_JOINT_VELOCITIES_EXT; hand_trackers[i].velocities.next = next_pointer; @@ -219,20 +201,6 @@ void OpenXRHandTrackingExtension::on_process() { !hand_trackers[i].locations.isActive || isnan(palm.position.x) || palm.position.x < -1000000.00 || palm.position.x > 1000000.00) { hand_trackers[i].locations.isActive = false; // workaround, make sure its inactive } - - /* TODO change this to managing the controller from openxr_interface - if (hand_tracking_aim_state_ext && hand_trackers[i].locations.isActive && check_bit(XR_HAND_TRACKING_AIM_VALID_BIT_FB, hand_trackers[i].aimState.status)) { - // Controllers are updated based on the aim state's pose and pinches' strength - if (hand_trackers[i].aim_state_godot_controller == -1) { - hand_trackers[i].aim_state_godot_controller = - arvr_api->godot_arvr_add_controller( - const_cast<char *>(hand_controller_names[i]), - i + HAND_CONTROLLER_ID_OFFSET, - true, - true); - } - } - */ } } } @@ -246,7 +214,7 @@ void OpenXRHandTrackingExtension::cleanup_hand_tracking() { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL(xr_server); - for (int i = 0; i < MAX_OPENXR_TRACKED_HANDS; i++) { + for (int i = 0; i < OPENXR_MAX_TRACKED_HANDS; i++) { if (hand_trackers[i].hand_tracker != XR_NULL_HANDLE) { xrDestroyHandTrackerEXT(hand_trackers[i].hand_tracker); @@ -260,25 +228,25 @@ bool OpenXRHandTrackingExtension::get_active() { return handTrackingSystemProperties.supportsHandTracking; } -const OpenXRHandTrackingExtension::HandTracker *OpenXRHandTrackingExtension::get_hand_tracker(uint32_t p_hand) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, nullptr); +const OpenXRHandTrackingExtension::HandTracker *OpenXRHandTrackingExtension::get_hand_tracker(HandTrackedHands p_hand) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, nullptr); return &hand_trackers[p_hand]; } -XrHandJointsMotionRangeEXT OpenXRHandTrackingExtension::get_motion_range(uint32_t p_hand) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, XR_HAND_JOINTS_MOTION_RANGE_MAX_ENUM_EXT); +XrHandJointsMotionRangeEXT OpenXRHandTrackingExtension::get_motion_range(HandTrackedHands p_hand) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, XR_HAND_JOINTS_MOTION_RANGE_MAX_ENUM_EXT); return hand_trackers[p_hand].motion_range; } -void OpenXRHandTrackingExtension::set_motion_range(uint32_t p_hand, XrHandJointsMotionRangeEXT p_motion_range) { - ERR_FAIL_UNSIGNED_INDEX(p_hand, MAX_OPENXR_TRACKED_HANDS); +void OpenXRHandTrackingExtension::set_motion_range(HandTrackedHands p_hand, XrHandJointsMotionRangeEXT p_motion_range) { + ERR_FAIL_UNSIGNED_INDEX(p_hand, OPENXR_MAX_TRACKED_HANDS); hand_trackers[p_hand].motion_range = p_motion_range; } -Quaternion OpenXRHandTrackingExtension::get_hand_joint_rotation(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, Quaternion()); +Quaternion OpenXRHandTrackingExtension::get_hand_joint_rotation(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, Quaternion()); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, Quaternion()); if (!hand_trackers[p_hand].is_initialized) { @@ -289,8 +257,8 @@ Quaternion OpenXRHandTrackingExtension::get_hand_joint_rotation(uint32_t p_hand, return Quaternion(location.pose.orientation.x, location.pose.orientation.y, location.pose.orientation.z, location.pose.orientation.w); } -Vector3 OpenXRHandTrackingExtension::get_hand_joint_position(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, Vector3()); +Vector3 OpenXRHandTrackingExtension::get_hand_joint_position(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, Vector3()); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, Vector3()); if (!hand_trackers[p_hand].is_initialized) { @@ -301,8 +269,8 @@ Vector3 OpenXRHandTrackingExtension::get_hand_joint_position(uint32_t p_hand, Xr return Vector3(location.pose.position.x, location.pose.position.y, location.pose.position.z); } -float OpenXRHandTrackingExtension::get_hand_joint_radius(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, 0.0); +float OpenXRHandTrackingExtension::get_hand_joint_radius(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, 0.0); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, 0.0); if (!hand_trackers[p_hand].is_initialized) { @@ -312,8 +280,8 @@ float OpenXRHandTrackingExtension::get_hand_joint_radius(uint32_t p_hand, XrHand return hand_trackers[p_hand].joint_locations[p_joint].radius; } -Vector3 OpenXRHandTrackingExtension::get_hand_joint_linear_velocity(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, Vector3()); +Vector3 OpenXRHandTrackingExtension::get_hand_joint_linear_velocity(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, Vector3()); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, Vector3()); if (!hand_trackers[p_hand].is_initialized) { @@ -324,8 +292,8 @@ Vector3 OpenXRHandTrackingExtension::get_hand_joint_linear_velocity(uint32_t p_h return Vector3(velocity.linearVelocity.x, velocity.linearVelocity.y, velocity.linearVelocity.z); } -Vector3 OpenXRHandTrackingExtension::get_hand_joint_angular_velocity(uint32_t p_hand, XrHandJointEXT p_joint) const { - ERR_FAIL_UNSIGNED_INDEX_V(p_hand, MAX_OPENXR_TRACKED_HANDS, Vector3()); +Vector3 OpenXRHandTrackingExtension::get_hand_joint_angular_velocity(HandTrackedHands p_hand, XrHandJointEXT p_joint) const { + ERR_FAIL_UNSIGNED_INDEX_V(p_hand, OPENXR_MAX_TRACKED_HANDS, Vector3()); ERR_FAIL_UNSIGNED_INDEX_V(p_joint, XR_HAND_JOINT_COUNT_EXT, Vector3()); if (!hand_trackers[p_hand].is_initialized) { diff --git a/modules/openxr/extensions/openxr_hand_tracking_extension.h b/modules/openxr/extensions/openxr_hand_tracking_extension.h index 99d315c525..5ca0ff60d3 100644 --- a/modules/openxr/extensions/openxr_hand_tracking_extension.h +++ b/modules/openxr/extensions/openxr_hand_tracking_extension.h @@ -35,10 +35,14 @@ #include "core/math/quaternion.h" #include "openxr_extension_wrapper.h" -#define MAX_OPENXR_TRACKED_HANDS 2 - class OpenXRHandTrackingExtension : public OpenXRExtensionWrapper { public: + enum HandTrackedHands { + OPENXR_TRACKED_LEFT_HAND, + OPENXR_TRACKED_RIGHT_HAND, + OPENXR_MAX_TRACKED_HANDS + }; + struct HandTracker { bool is_initialized = false; XrHandJointsMotionRangeEXT motion_range = XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT; @@ -47,7 +51,6 @@ public: XrHandJointLocationEXT joint_locations[XR_HAND_JOINT_COUNT_EXT]; XrHandJointVelocityEXT joint_velocities[XR_HAND_JOINT_COUNT_EXT]; - XrHandTrackingAimStateFB aimState; XrHandJointVelocitiesEXT velocities; XrHandJointLocationsEXT locations; }; @@ -69,29 +72,28 @@ public: virtual void on_state_stopping() override; bool get_active(); - const HandTracker *get_hand_tracker(uint32_t p_hand) const; + const HandTracker *get_hand_tracker(HandTrackedHands p_hand) const; - XrHandJointsMotionRangeEXT get_motion_range(uint32_t p_hand) const; - void set_motion_range(uint32_t p_hand, XrHandJointsMotionRangeEXT p_motion_range); + XrHandJointsMotionRangeEXT get_motion_range(HandTrackedHands p_hand) const; + void set_motion_range(HandTrackedHands p_hand, XrHandJointsMotionRangeEXT p_motion_range); - Quaternion get_hand_joint_rotation(uint32_t p_hand, XrHandJointEXT p_joint) const; - Vector3 get_hand_joint_position(uint32_t p_hand, XrHandJointEXT p_joint) const; - float get_hand_joint_radius(uint32_t p_hand, XrHandJointEXT p_joint) const; + Quaternion get_hand_joint_rotation(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; + Vector3 get_hand_joint_position(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; + float get_hand_joint_radius(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; - Vector3 get_hand_joint_linear_velocity(uint32_t p_hand, XrHandJointEXT p_joint) const; - Vector3 get_hand_joint_angular_velocity(uint32_t p_hand, XrHandJointEXT p_joint) const; + Vector3 get_hand_joint_linear_velocity(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; + Vector3 get_hand_joint_angular_velocity(HandTrackedHands p_hand, XrHandJointEXT p_joint) const; private: static OpenXRHandTrackingExtension *singleton; // state XrSystemHandTrackingPropertiesEXT handTrackingSystemProperties; - HandTracker hand_trackers[MAX_OPENXR_TRACKED_HANDS]; // Fixed for left and right hand + HandTracker hand_trackers[OPENXR_MAX_TRACKED_HANDS]; // Fixed for left and right hand // related extensions bool hand_tracking_ext = false; bool hand_motion_range_ext = false; - bool hand_tracking_aim_state_ext = false; // functions void cleanup_hand_tracking(); diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 67a459adb8..d0b01c5771 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -34,8 +34,6 @@ #include "core/io/resource_saver.h" #include "servers/rendering/rendering_server_globals.h" -#include "extensions/openxr_hand_tracking_extension.h" - #include "extensions/openxr_eye_gaze_interaction.h" void OpenXRInterface::_bind_methods() { @@ -909,6 +907,24 @@ RID OpenXRInterface::get_depth_texture() { } } +void OpenXRInterface::handle_hand_tracking(const String &p_path, OpenXRHandTrackingExtension::HandTrackedHands p_hand) { + OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); + if (hand_tracking_ext && hand_tracking_ext->get_active()) { + OpenXRInterface::Tracker *tracker = find_tracker(p_path); + if (tracker && tracker->positional_tracker.is_valid()) { + // TODO add in confidence! Requires PR #82715 + + Transform3D transform; + transform.basis = Basis(hand_tracking_ext->get_hand_joint_rotation(p_hand, XR_HAND_JOINT_PALM_EXT)); + transform.origin = hand_tracking_ext->get_hand_joint_position(p_hand, XR_HAND_JOINT_PALM_EXT); + Vector3 linear_velocity = hand_tracking_ext->get_hand_joint_linear_velocity(p_hand, XR_HAND_JOINT_PALM_EXT); + Vector3 angular_velocity = hand_tracking_ext->get_hand_joint_angular_velocity(p_hand, XR_HAND_JOINT_PALM_EXT); + + tracker->positional_tracker->set_pose("skeleton", transform, linear_velocity, angular_velocity, XRPose::XR_TRACKING_CONFIDENCE_HIGH); + } + } +} + void OpenXRInterface::process() { if (openxr_api) { // do our normal process @@ -916,8 +932,8 @@ void OpenXRInterface::process() { Transform3D t; Vector3 linear_velocity; Vector3 angular_velocity; - XRPose::TrackingConfidence confidence = openxr_api->get_head_center(t, linear_velocity, angular_velocity); - if (confidence != XRPose::XR_TRACKING_CONFIDENCE_NONE) { + head_confidence = openxr_api->get_head_center(t, linear_velocity, angular_velocity); + if (head_confidence != XRPose::XR_TRACKING_CONFIDENCE_NONE) { // Only update our transform if we have one to update it with // note that poses are stored without world scale and reference frame applied! head_transform = t; @@ -939,14 +955,14 @@ void OpenXRInterface::process() { handle_tracker(trackers[i]); } } + + // Handle hand tracking + handle_hand_tracking("/user/hand/left", OpenXRHandTrackingExtension::OPENXR_TRACKED_LEFT_HAND); + handle_hand_tracking("/user/hand/right", OpenXRHandTrackingExtension::OPENXR_TRACKED_RIGHT_HAND); } if (head.is_valid()) { - // TODO figure out how to get our velocities - - head->set_pose("default", head_transform, head_linear_velocity, head_angular_velocity); - - // TODO set confidence on pose once we support tracking this.. + head->set_pose("default", head_transform, head_linear_velocity, head_angular_velocity, head_confidence); } } @@ -1143,7 +1159,7 @@ void OpenXRInterface::set_motion_range(const Hand p_hand, const HandMotionRange break; } - hand_tracking_ext->set_motion_range(uint32_t(p_hand), xr_motion_range); + hand_tracking_ext->set_motion_range(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), xr_motion_range); } } @@ -1152,7 +1168,7 @@ OpenXRInterface::HandMotionRange OpenXRInterface::get_motion_range(const Hand p_ OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - XrHandJointsMotionRangeEXT xr_motion_range = hand_tracking_ext->get_motion_range(uint32_t(p_hand)); + XrHandJointsMotionRangeEXT xr_motion_range = hand_tracking_ext->get_motion_range(OpenXRHandTrackingExtension::HandTrackedHands(p_hand)); switch (xr_motion_range) { case XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT: @@ -1170,7 +1186,7 @@ OpenXRInterface::HandMotionRange OpenXRInterface::get_motion_range(const Hand p_ Quaternion OpenXRInterface::get_hand_joint_rotation(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_rotation(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_rotation(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return Quaternion(); @@ -1179,7 +1195,7 @@ Quaternion OpenXRInterface::get_hand_joint_rotation(Hand p_hand, HandJoints p_jo Vector3 OpenXRInterface::get_hand_joint_position(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_position(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_position(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return Vector3(); @@ -1188,7 +1204,7 @@ Vector3 OpenXRInterface::get_hand_joint_position(Hand p_hand, HandJoints p_joint float OpenXRInterface::get_hand_joint_radius(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_radius(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_radius(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return 0.0; @@ -1197,7 +1213,7 @@ float OpenXRInterface::get_hand_joint_radius(Hand p_hand, HandJoints p_joint) co Vector3 OpenXRInterface::get_hand_joint_linear_velocity(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_linear_velocity(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_linear_velocity(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return Vector3(); @@ -1206,7 +1222,7 @@ Vector3 OpenXRInterface::get_hand_joint_linear_velocity(Hand p_hand, HandJoints Vector3 OpenXRInterface::get_hand_joint_angular_velocity(Hand p_hand, HandJoints p_joint) const { OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton(); if (hand_tracking_ext && hand_tracking_ext->get_active()) { - return hand_tracking_ext->get_hand_joint_angular_velocity(uint32_t(p_hand), XrHandJointEXT(p_joint)); + return hand_tracking_ext->get_hand_joint_angular_velocity(OpenXRHandTrackingExtension::HandTrackedHands(p_hand), XrHandJointEXT(p_joint)); } return Vector3(); diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index a2cc2b27ff..8e24c8dce9 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -33,6 +33,7 @@ #include "action_map/openxr_action_map.h" #include "extensions/openxr_fb_passthrough_extension_wrapper.h" +#include "extensions/openxr_hand_tracking_extension.h" #include "openxr_api.h" #include "servers/xr/xr_interface.h" @@ -55,6 +56,7 @@ private: Transform3D head_transform; Vector3 head_linear_velocity; Vector3 head_angular_velocity; + XRPose::TrackingConfidence head_confidence; Transform3D transform_for_view[2]; // We currently assume 2, but could be 4 for VARJO which we do not support yet void _load_action_map(); @@ -97,6 +99,8 @@ private: void _set_default_pos(Transform3D &p_transform, double p_world_scale, uint64_t p_eye); + void handle_hand_tracking(const String &p_path, OpenXRHandTrackingExtension::HandTrackedHands p_hand); + protected: static void _bind_methods(); diff --git a/modules/openxr/register_types.cpp b/modules/openxr/register_types.cpp index 09a064b9a9..544932bdeb 100644 --- a/modules/openxr/register_types.cpp +++ b/modules/openxr/register_types.cpp @@ -105,20 +105,24 @@ void initialize_openxr_module(ModuleInitializationLevel p_level) { #endif // register our other extensions - if (GLOBAL_GET("xr/openxr/extensions/eye_gaze_interaction") && (!OS::get_singleton()->has_feature("mobile") || OS::get_singleton()->has_feature(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME))) { - OpenXRAPI::register_extension_wrapper(memnew(OpenXREyeGazeInteractionExtension)); - } OpenXRAPI::register_extension_wrapper(memnew(OpenXRPalmPoseExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRPicoControllerExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRCompositionLayerDepthExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRHTCControllerExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRHTCViveTrackerExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRHuaweiControllerExtension)); - OpenXRAPI::register_extension_wrapper(memnew(OpenXRHandTrackingExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRFbPassthroughExtensionWrapper)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRDisplayRefreshRateExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRWMRControllerExtension)); OpenXRAPI::register_extension_wrapper(memnew(OpenXRML2ControllerExtension)); + + // register gated extensions + if (GLOBAL_GET("xr/openxr/extensions/eye_gaze_interaction") && (!OS::get_singleton()->has_feature("mobile") || OS::get_singleton()->has_feature(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME))) { + OpenXRAPI::register_extension_wrapper(memnew(OpenXREyeGazeInteractionExtension)); + } + if (GLOBAL_GET("xr/openxr/extensions/hand_tracking")) { + OpenXRAPI::register_extension_wrapper(memnew(OpenXRHandTrackingExtension)); + } } if (OpenXRAPI::openxr_is_enabled()) { diff --git a/modules/openxr/scene/openxr_hand.cpp b/modules/openxr/scene/openxr_hand.cpp index bedc8874d6..c48fac8055 100644 --- a/modules/openxr/scene/openxr_hand.cpp +++ b/modules/openxr/scene/openxr_hand.cpp @@ -113,7 +113,7 @@ void OpenXRHand::_set_motion_range() { break; } - hand_tracking_ext->set_motion_range(hand, xr_motion_range); + hand_tracking_ext->set_motion_range(OpenXRHandTrackingExtension::HandTrackedHands(hand), xr_motion_range); } Skeleton3D *OpenXRHand::get_skeleton() { @@ -204,7 +204,7 @@ void OpenXRHand::_update_skeleton() { Quaternion inv_quaternions[XR_HAND_JOINT_COUNT_EXT]; Vector3 positions[XR_HAND_JOINT_COUNT_EXT]; - const OpenXRHandTrackingExtension::HandTracker *hand_tracker = hand_tracking_ext->get_hand_tracker(hand); + const OpenXRHandTrackingExtension::HandTracker *hand_tracker = hand_tracking_ext->get_hand_tracker(OpenXRHandTrackingExtension::HandTrackedHands(hand)); const float ws = XRServer::get_singleton()->get_world_scale(); if (hand_tracker->is_initialized && hand_tracker->locations.isActive) { @@ -243,26 +243,27 @@ void OpenXRHand::_update_skeleton() { // Get our target quaternion Quaternion q = quaternions[i]; + // Get our target position + Vector3 p = positions[i]; + // get local translation, parent should already be processed if (parent == -1) { // use our palm location here, that is what we are tracking q = inv_quaternions[XR_HAND_JOINT_PALM_EXT] * q; + p = inv_quaternions[XR_HAND_JOINT_PALM_EXT].xform(p - positions[XR_HAND_JOINT_PALM_EXT]); } else { int found = false; for (int b = 0; b < XR_HAND_JOINT_COUNT_EXT && !found; b++) { if (bones[b] == parent) { q = inv_quaternions[b] * q; + p = inv_quaternions[b].xform(p - positions[b]); found = true; } } } - // And get the movement from our rest position - // Transform3D rest = skeleton->get_bone_rest(bones[i]); - // q = rest.basis.get_quaternion().inverse() * q; - // and set our pose - // skeleton->set_bone_pose_position(bones[i], v); + skeleton->set_bone_pose_position(bones[i], p); skeleton->set_bone_pose_rotation(bones[i], q); } } |