diff options
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 19 | ||||
-rw-r--r-- | intern/ghost/GHOST_Types.h | 24 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 29 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_XrAction.cpp | 188 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_XrAction.h | 47 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_XrSession.cpp | 87 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_XrSession.h | 9 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_xr_types.h | 9 | ||||
-rw-r--r-- | source/blender/windowmanager/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 26 | ||||
-rw-r--r-- | source/blender/windowmanager/xr/intern/wm_xr_action.c (renamed from source/blender/windowmanager/xr/intern/wm_xr_actions.c) | 138 | ||||
-rw-r--r-- | source/blender/windowmanager/xr/intern/wm_xr_intern.h | 5 |
12 files changed, 256 insertions, 327 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 46e3888a367..fea5a545807 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -1067,22 +1067,6 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_context, const char *const *action_names); /** - * Create spaces for pose-based OpenXR actions. - */ -int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_context, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); - -/** - * Destroy previously created spaces for OpenXR actions. - */ -void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_context, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); - -/** * Create input/output path bindings for OpenXR actions. */ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context, @@ -1096,7 +1080,8 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context, void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_context, const char *action_set_name, uint32_t count, - const GHOST_XrActionProfileInfo *infos); + const char *const *action_names, + const char *const *profile_paths); /** * Attach all created action sets to the current OpenXR session. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 94a3fd86b73..fb19b9535ad 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -719,29 +719,27 @@ typedef struct GHOST_XrActionInfo { const char **subaction_paths; /** States for each subaction path. */ void *states; + /** Input thresholds/regions for each subaction path. */ + float *float_thresholds; + int16_t *axis_flags; GHOST_XrCustomdataFreeFn customdata_free_fn; void *customdata; /* wmXrAction */ } GHOST_XrActionInfo; -typedef struct GHOST_XrActionSpaceInfo { - const char *action_name; - uint32_t count_subaction_paths; - const char **subaction_paths; - /** Poses for each subaction path. */ - const GHOST_XrPose *poses; -} GHOST_XrActionSpaceInfo; - typedef struct GHOST_XrActionBindingInfo { - const char *action_name; - uint32_t count_interaction_paths; - /** Interaction path: User (sub-action) path + component path. */ - const char **interaction_paths; + const char *component_path; + float float_threshold; + int16_t axis_flag; + GHOST_XrPose pose; } GHOST_XrActionBindingInfo; typedef struct GHOST_XrActionProfileInfo { + const char *action_name; const char *profile_path; - uint32_t count_bindings; + uint32_t count_subaction_paths; + const char **subaction_paths; + /* Bindings for each subaction path. */ const GHOST_XrActionBindingInfo *bindings; } GHOST_XrActionProfileInfo; diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index cb409595e50..0bc9be26eb1 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -961,28 +961,6 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_contexthandle, GHOST_XR_CAPI_CALL(xr_session->destroyActions(action_set_name, count, action_names), xr_context); } -int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_contexthandle, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) -{ - GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; - GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL_RET(xr_session->createActionSpaces(action_set_name, count, infos), - xr_context); - return 0; -} - -void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_contexthandle, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) -{ - GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; - GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL(xr_session->destroyActionSpaces(action_set_name, count, infos), xr_context); -} - int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, uint32_t count, @@ -998,11 +976,14 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle, void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, uint32_t count, - const GHOST_XrActionProfileInfo *infos) + const char *const *action_names, + const char *const *profile_paths) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL(xr_session->destroyActionBindings(action_set_name, count, infos), xr_context); + GHOST_XR_CAPI_CALL( + xr_session->destroyActionBindings(action_set_name, count, action_names, profile_paths), + xr_context); } int GHOST_XrAttachActionSets(GHOST_XrContextHandle xr_contexthandle) diff --git a/intern/ghost/intern/GHOST_XrAction.cpp b/intern/ghost/intern/GHOST_XrAction.cpp index 9c4f7fbc7d8..676a3367ee1 100644 --- a/intern/ghost/intern/GHOST_XrAction.cpp +++ b/intern/ghost/intern/GHOST_XrAction.cpp @@ -33,24 +33,22 @@ * * \{ */ -GHOST_XrActionSpace::GHOST_XrActionSpace(XrInstance instance, - XrSession session, +GHOST_XrActionSpace::GHOST_XrActionSpace(XrSession session, XrAction action, - const GHOST_XrActionSpaceInfo &info, - uint32_t subaction_idx) + const char *action_name, + const char *profile_path, + XrPath subaction_path, + const char *subaction_path_str, + const GHOST_XrPose &pose) { - const char *subaction_path = info.subaction_paths[subaction_idx]; - CHECK_XR(xrStringToPath(instance, subaction_path, &m_subaction_path), - (std::string("Failed to get user path \"") + subaction_path + "\".").data()); - XrActionSpaceCreateInfo action_space_info{XR_TYPE_ACTION_SPACE_CREATE_INFO}; action_space_info.action = action; - action_space_info.subactionPath = m_subaction_path; - copy_ghost_pose_to_openxr_pose(info.poses[subaction_idx], action_space_info.poseInActionSpace); + action_space_info.subactionPath = subaction_path; + copy_ghost_pose_to_openxr_pose(pose, action_space_info.poseInActionSpace); CHECK_XR(xrCreateActionSpace(session, &action_space_info, &m_space), - (std::string("Failed to create space \"") + subaction_path + "\" for action \"" + - info.action_name + "\".") + (std::string("Failed to create space \"") + subaction_path_str + "\" for action \"" + + action_name + "\" and profile \"" + profile_path + "\".") .data()); } @@ -66,11 +64,6 @@ XrSpace GHOST_XrActionSpace::getSpace() const return m_space; } -const XrPath &GHOST_XrActionSpace::getSubactionPath() const -{ - return m_subaction_path; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -79,13 +72,19 @@ const XrPath &GHOST_XrActionSpace::getSubactionPath() const * \{ */ GHOST_XrActionProfile::GHOST_XrActionProfile(XrInstance instance, + XrSession session, XrAction action, - const char *profile_path, - const GHOST_XrActionBindingInfo &info) + GHOST_XrActionType type, + const GHOST_XrActionProfileInfo &info) { - CHECK_XR( - xrStringToPath(instance, profile_path, &m_profile), - (std::string("Failed to get interaction profile path \"") + profile_path + "\".").data()); + CHECK_XR(xrStringToPath(instance, info.profile_path, &m_profile), + (std::string("Failed to get interaction profile path \"") + info.profile_path + "\".") + .data()); + + const bool is_float_action = (type == GHOST_kXrActionTypeFloatInput || + type == GHOST_kXrActionTypeVector2fInput); + const bool is_button_action = (is_float_action || type == GHOST_kXrActionTypeBooleanInput); + const bool is_pose_action = (type == GHOST_kXrActionTypePoseInput); /* Create bindings. */ XrInteractionProfileSuggestedBinding bindings_info{ @@ -93,31 +92,80 @@ GHOST_XrActionProfile::GHOST_XrActionProfile(XrInstance instance, bindings_info.interactionProfile = m_profile; bindings_info.countSuggestedBindings = 1; - for (uint32_t interaction_idx = 0; interaction_idx < info.count_interaction_paths; - ++interaction_idx) { - const char *interaction_path = info.interaction_paths[interaction_idx]; + for (uint32_t subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) { + const char *subaction_path_str = info.subaction_paths[subaction_idx]; + const GHOST_XrActionBindingInfo &binding_info = info.bindings[subaction_idx]; + + const std::string interaction_path = std::string(subaction_path_str) + + binding_info.component_path; if (m_bindings.find(interaction_path) != m_bindings.end()) { continue; } XrActionSuggestedBinding sbinding; sbinding.action = action; - CHECK_XR(xrStringToPath(instance, interaction_path, &sbinding.binding), + CHECK_XR(xrStringToPath(instance, interaction_path.data(), &sbinding.binding), (std::string("Failed to get interaction path \"") + interaction_path + "\".").data()); bindings_info.suggestedBindings = &sbinding; /* Although the bindings will be re-suggested in GHOST_XrSession::attachActionSets(), it * greatly improves error checking to suggest them here first. */ CHECK_XR(xrSuggestInteractionProfileBindings(instance, &bindings_info), - (std::string("Failed to create binding for profile \"") + profile_path + - "\" and action \"" + info.action_name + - "\". Are the profile and action paths correct?") + (std::string("Failed to create binding for action \"") + info.action_name + + "\" and profile \"" + info.profile_path + + "\". Are the action and profile paths correct?") .data()); m_bindings.insert({interaction_path, sbinding.binding}); + + if (m_subaction_data.find(subaction_path_str) == m_subaction_data.end()) { + std::map<std::string, GHOST_XrSubactionData>::iterator it = + m_subaction_data + .emplace( + std::piecewise_construct, std::make_tuple(subaction_path_str), std::make_tuple()) + .first; + GHOST_XrSubactionData &subaction = it->second; + + CHECK_XR(xrStringToPath(instance, subaction_path_str, &subaction.subaction_path), + (std::string("Failed to get user path \"") + subaction_path_str + "\".").data()); + + if (is_float_action || is_button_action) { + if (is_float_action) { + subaction.float_threshold = binding_info.float_threshold; + } + if (is_button_action) { + subaction.axis_flag = binding_info.axis_flag; + } + } + else if (is_pose_action) { + /* Create action space for pose bindings. */ + subaction.space = std::make_unique<GHOST_XrActionSpace>(session, + action, + info.action_name, + info.profile_path, + subaction.subaction_path, + subaction_path_str, + binding_info.pose); + } + } } } +XrPath GHOST_XrActionProfile::getProfile() const +{ + return m_profile; +} + +const GHOST_XrSubactionData *GHOST_XrActionProfile::getSubaction(XrPath subaction_path) const +{ + for (auto &[subaction_path_str, subaction] : m_subaction_data) { + if (subaction.subaction_path == subaction_path) { + return &subaction; + } + } + return nullptr; +} + void GHOST_XrActionProfile::getBindings( XrAction action, std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings) const { @@ -152,6 +200,8 @@ GHOST_XrAction::GHOST_XrAction(XrInstance instance, const GHOST_XrActionInfo &info) : m_type(info.type), m_states(info.states), + m_float_thresholds(info.float_thresholds), + m_axis_flags(info.axis_flags), m_custom_data_( std::make_unique<GHOST_C_CustomDataWrapper>(info.customdata, info.customdata_free_fn)) { @@ -201,52 +251,25 @@ GHOST_XrAction::~GHOST_XrAction() } } -bool GHOST_XrAction::createSpace(XrInstance instance, - XrSession session, - const GHOST_XrActionSpaceInfo &info) -{ - uint32_t subaction_idx = 0; - for (; subaction_idx < info.count_subaction_paths; ++subaction_idx) { - if (m_spaces.find(info.subaction_paths[subaction_idx]) != m_spaces.end()) { - return false; - } - } - - for (subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) { - m_spaces.emplace(std::piecewise_construct, - std::make_tuple(info.subaction_paths[subaction_idx]), - std::make_tuple(instance, session, m_action, info, subaction_idx)); - } - - return true; -} - -void GHOST_XrAction::destroySpace(const char *subaction_path) -{ - if (m_spaces.find(subaction_path) != m_spaces.end()) { - m_spaces.erase(subaction_path); - } -} - bool GHOST_XrAction::createBinding(XrInstance instance, - const char *profile_path, - const GHOST_XrActionBindingInfo &info) + XrSession session, + const GHOST_XrActionProfileInfo &info) { - if (m_profiles.find(profile_path) != m_profiles.end()) { + if (m_profiles.find(info.profile_path) != m_profiles.end()) { return false; } m_profiles.emplace(std::piecewise_construct, - std::make_tuple(profile_path), - std::make_tuple(instance, m_action, profile_path, info)); + std::make_tuple(info.profile_path), + std::make_tuple(instance, session, m_action, m_type, info)); return true; } -void GHOST_XrAction::destroyBinding(const char *interaction_profile_path) +void GHOST_XrAction::destroyBinding(const char *profile_path) { - if (m_profiles.find(interaction_profile_path) != m_profiles.end()) { - m_profiles.erase(interaction_profile_path); + if (m_profiles.find(profile_path) != m_profiles.end()) { + m_profiles.erase(profile_path); } } @@ -255,6 +278,10 @@ void GHOST_XrAction::updateState(XrSession session, XrSpace reference_space, const XrTime &predicted_display_time) { + const bool is_float_action = (m_type == GHOST_kXrActionTypeFloatInput || + m_type == GHOST_kXrActionTypeVector2fInput); + const bool is_button_action = (is_float_action || m_type == GHOST_kXrActionTypeBooleanInput); + XrActionStateGetInfo state_info{XR_TYPE_ACTION_STATE_GET_INFO}; state_info.action = m_action; @@ -262,6 +289,28 @@ void GHOST_XrAction::updateState(XrSession session, for (size_t subaction_idx = 0; subaction_idx < count_subaction_paths; ++subaction_idx) { state_info.subactionPath = m_subaction_paths[subaction_idx]; + /* Set subaction data based on current interaction profile. */ + XrInteractionProfileState profile_state{XR_TYPE_INTERACTION_PROFILE_STATE}; + CHECK_XR(xrGetCurrentInteractionProfile(session, state_info.subactionPath, &profile_state), + "Failed to get current interaction profile."); + + const GHOST_XrSubactionData *subaction = nullptr; + for (auto &[profile_path, profile] : m_profiles) { + if (profile.getProfile() == profile_state.interactionProfile) { + subaction = profile.getSubaction(state_info.subactionPath); + break; + } + } + + if (subaction != nullptr) { + if (is_float_action) { + m_float_thresholds[subaction_idx] = subaction->float_threshold; + } + if (is_button_action) { + m_axis_flags[subaction_idx] = subaction->axis_flag; + } + } + switch (m_type) { case GHOST_kXrActionTypeBooleanInput: { XrActionStateBoolean state{XR_TYPE_ACTION_STATE_BOOLEAN}; @@ -299,14 +348,9 @@ void GHOST_XrAction::updateState(XrSession session, xrGetActionStatePose(session, &state_info, &state), (std::string("Failed to get state for pose action \"") + action_name + "\".").data()); if (state.isActive) { - XrSpace pose_space = XR_NULL_HANDLE; - for (auto &[path, space] : m_spaces) { - if (space.getSubactionPath() == state_info.subactionPath) { - pose_space = space.getSpace(); - break; - } - } - + XrSpace pose_space = ((subaction != nullptr) && (subaction->space != nullptr)) ? + subaction->space->getSpace() : + XR_NULL_HANDLE; if (pose_space != XR_NULL_HANDLE) { XrSpaceLocation space_location{XR_TYPE_SPACE_LOCATION}; CHECK_XR( diff --git a/intern/ghost/intern/GHOST_XrAction.h b/intern/ghost/intern/GHOST_XrAction.h index 32445c616bd..e2a89e87278 100644 --- a/intern/ghost/intern/GHOST_XrAction.h +++ b/intern/ghost/intern/GHOST_XrAction.h @@ -34,38 +34,53 @@ class GHOST_XrActionSpace { public: GHOST_XrActionSpace() = delete; /* Default constructor for map storage. */ - GHOST_XrActionSpace(XrInstance instance, - XrSession session, + GHOST_XrActionSpace(XrSession session, XrAction action, - const GHOST_XrActionSpaceInfo &info, - uint32_t subaction_idx); + const char *action_name, + const char *profile_path, + XrPath subaction_path, + const char *subaction_path_str, + const GHOST_XrPose &pose); ~GHOST_XrActionSpace(); XrSpace getSpace() const; - const XrPath &getSubactionPath() const; private: XrSpace m_space = XR_NULL_HANDLE; - XrPath m_subaction_path = XR_NULL_PATH; }; /* -------------------------------------------------------------------- */ +typedef struct GHOST_XrSubactionData { + XrPath subaction_path = XR_NULL_PATH; + float float_threshold; + int16_t axis_flag; + std::unique_ptr<GHOST_XrActionSpace> space = nullptr; +} GHOST_XrSubactionData; + +/* -------------------------------------------------------------------- */ + class GHOST_XrActionProfile { public: GHOST_XrActionProfile() = delete; /* Default constructor for map storage. */ GHOST_XrActionProfile(XrInstance instance, + XrSession session, XrAction action, - const char *profile_path, - const GHOST_XrActionBindingInfo &info); + GHOST_XrActionType type, + const GHOST_XrActionProfileInfo &info); ~GHOST_XrActionProfile() = default; + XrPath getProfile() const; + const GHOST_XrSubactionData *getSubaction(XrPath subaction_path) const; void getBindings(XrAction action, std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings) const; private: XrPath m_profile = XR_NULL_PATH; - /* Bindings identified by interaction (user (subaction) + component) path. */ + + /** Subaction data identified by user (subaction) path. */ + std::map<std::string, GHOST_XrSubactionData> m_subaction_data; + /** Bindings identified by interaction (user (subaction) + component) path. */ std::map<std::string, XrPath> m_bindings; }; @@ -77,12 +92,9 @@ class GHOST_XrAction { GHOST_XrAction(XrInstance instance, XrActionSet action_set, const GHOST_XrActionInfo &info); ~GHOST_XrAction(); - bool createSpace(XrInstance instance, XrSession session, const GHOST_XrActionSpaceInfo &info); - void destroySpace(const char *subaction_path); - bool createBinding(XrInstance instance, - const char *profile_path, - const GHOST_XrActionBindingInfo &info); + XrSession session, + const GHOST_XrActionProfileInfo &info); void destroyBinding(const char *profile_path); void updateState(XrSession session, @@ -105,12 +117,13 @@ class GHOST_XrAction { std::vector<XrPath> m_subaction_paths; /** States for each subaction path. */ void *m_states; + /** Input thresholds/regions for each subaction path. */ + float *m_float_thresholds; + int16_t *m_axis_flags; std::unique_ptr<GHOST_C_CustomDataWrapper> m_custom_data_ = nullptr; /* wmXrAction */ - /* Spaces identified by user (subaction) path. */ - std::map<std::string, GHOST_XrActionSpace> m_spaces; - /* Profiles identified by interaction profile path. */ + /** Profiles identified by interaction profile path. */ std::map<std::string, GHOST_XrActionProfile> m_profiles; }; diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp index 919d11d22a9..a29ec1cc560 100644 --- a/intern/ghost/intern/GHOST_XrSession.cpp +++ b/intern/ghost/intern/GHOST_XrSession.cpp @@ -610,9 +610,9 @@ void GHOST_XrSession::destroyActions(const char *action_set_name, } } -bool GHOST_XrSession::createActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) +bool GHOST_XrSession::createActionBindings(const char *action_set_name, + uint32_t count, + const GHOST_XrActionProfileInfo *infos) { GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); if (action_set == nullptr) { @@ -622,98 +622,37 @@ bool GHOST_XrSession::createActionSpaces(const char *action_set_name, XrInstance instance = m_context->getInstance(); XrSession session = m_oxr->session; - for (uint32_t action_idx = 0; action_idx < count; ++action_idx) { - const GHOST_XrActionSpaceInfo &info = infos[action_idx]; + for (uint32_t profile_idx = 0; profile_idx < count; ++profile_idx) { + const GHOST_XrActionProfileInfo &info = infos[profile_idx]; GHOST_XrAction *action = action_set->findAction(info.action_name); if (action == nullptr) { continue; } - if (!action->createSpace(instance, session, info)) { - return false; - } + action->createBinding(instance, session, info); } return true; } -void GHOST_XrSession::destroyActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) +void GHOST_XrSession::destroyActionBindings(const char *action_set_name, + uint32_t count, + const char *const *action_names, + const char *const *profile_paths) { GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); if (action_set == nullptr) { return; } - for (uint32_t action_idx = 0; action_idx < count; ++action_idx) { - const GHOST_XrActionSpaceInfo &info = infos[action_idx]; - - GHOST_XrAction *action = action_set->findAction(info.action_name); + for (uint32_t i = 0; i < count; ++i) { + GHOST_XrAction *action = action_set->findAction(action_names[i]); if (action == nullptr) { continue; } - for (uint32_t subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) { - action->destroySpace(info.subaction_paths[subaction_idx]); - } - } -} - -bool GHOST_XrSession::createActionBindings(const char *action_set_name, - uint32_t count, - const GHOST_XrActionProfileInfo *infos) -{ - GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); - if (action_set == nullptr) { - return false; - } - - XrInstance instance = m_context->getInstance(); - - for (uint32_t profile_idx = 0; profile_idx < count; ++profile_idx) { - const GHOST_XrActionProfileInfo &info = infos[profile_idx]; - const char *profile_path = info.profile_path; - - for (uint32_t binding_idx = 0; binding_idx < info.count_bindings; ++binding_idx) { - const GHOST_XrActionBindingInfo &binding = info.bindings[binding_idx]; - - GHOST_XrAction *action = action_set->findAction(binding.action_name); - if (action == nullptr) { - continue; - } - - action->createBinding(instance, profile_path, binding); - } - } - - return true; -} - -void GHOST_XrSession::destroyActionBindings(const char *action_set_name, - uint32_t count, - const GHOST_XrActionProfileInfo *infos) -{ - GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); - if (action_set == nullptr) { - return; - } - - for (uint32_t profile_idx = 0; profile_idx < count; ++profile_idx) { - const GHOST_XrActionProfileInfo &info = infos[profile_idx]; - const char *profile_path = info.profile_path; - - for (uint32_t binding_idx = 0; binding_idx < info.count_bindings; ++binding_idx) { - const GHOST_XrActionBindingInfo &binding = info.bindings[binding_idx]; - - GHOST_XrAction *action = action_set->findAction(binding.action_name); - if (action == nullptr) { - continue; - } - - action->destroyBinding(profile_path); - } + action->destroyBinding(profile_paths[i]); } } diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h index d448585d14c..cdeef153fb1 100644 --- a/intern/ghost/intern/GHOST_XrSession.h +++ b/intern/ghost/intern/GHOST_XrSession.h @@ -60,18 +60,13 @@ class GHOST_XrSession { void destroyActions(const char *action_set_name, uint32_t count, const char *const *action_names); - bool createActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); - void destroyActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); bool createActionBindings(const char *action_set_name, uint32_t count, const GHOST_XrActionProfileInfo *infos); void destroyActionBindings(const char *action_set_name, uint32_t count, - const GHOST_XrActionProfileInfo *infos); + const char *const *action_names, + const char *const *profile_paths); bool attachActionSets(); /** diff --git a/source/blender/makesdna/DNA_xr_types.h b/source/blender/makesdna/DNA_xr_types.h index fc00d5eb839..c0928e1519f 100644 --- a/source/blender/makesdna/DNA_xr_types.h +++ b/source/blender/makesdna/DNA_xr_types.h @@ -74,6 +74,15 @@ typedef enum eXrOpFlag { XR_OP_MODAL = 2, } eXrOpFlag; +typedef enum eXrAxisFlag { + /** For axis-based inputs (thumbstick/trackpad/etc). Determines the region for action execution + (mutually exclusive per axis). */ + XR_AXIS0_POS = (1 << 0), + XR_AXIS0_NEG = (1 << 1), + XR_AXIS1_POS = (1 << 2), + XR_AXIS1_NEG = (1 << 3), +} eXrAxisFlag; + #ifdef __cplusplus } #endif diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index e513c49c11b..8b0ceb02b5f 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -203,7 +203,7 @@ if(WITH_XR_OPENXR) list(APPEND SRC xr/intern/wm_xr.c - xr/intern/wm_xr_actions.c + xr/intern/wm_xr_action.c xr/intern/wm_xr_draw.c xr/intern/wm_xr_session.c diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 136c639caea..fb973592a57 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -978,34 +978,24 @@ bool WM_xr_action_create(wmXrData *xr, eXrActionType type, unsigned int count_subaction_paths, const char **subaction_paths, - const float *float_threshold, struct wmOperatorType *ot, struct IDProperty *op_properties, eXrOpFlag op_flag); void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char *action_name); -bool WM_xr_action_space_create(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths, - const struct wmXrPose *poses); -void WM_xr_action_space_destroy(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths); bool WM_xr_action_binding_create(wmXrData *xr, const char *action_set_name, - const char *profile_path, const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths); + const char *profile_path, + unsigned int count_subaction_paths, + const char **subaction_paths, + const char **component_paths, + const float *float_thresholds, + const eXrAxisFlag *axis_flags, + const struct wmXrPose *poses); void WM_xr_action_binding_destroy(wmXrData *xr, const char *action_set_name, - const char *profile_path, const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths); + const char *profile_path); /* If action_set_name is NULL, then all action sets will be treated as active. */ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name); diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actions.c b/source/blender/windowmanager/xr/intern/wm_xr_action.c index 7eabd29baa0..ee4cfcccaa7 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_actions.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_action.c @@ -68,7 +68,6 @@ static wmXrAction *action_create(const char *action_name, eXrActionType type, unsigned int count_subaction_paths, const char **subaction_paths, - const float *float_threshold, wmOperatorType *ot, IDProperty *op_properties, eXrOpFlag op_flag) @@ -109,10 +108,15 @@ static wmXrAction *action_create(const char *action_name, action->states = MEM_calloc_arrayN(count, size, "XrAction_States"); action->states_prev = MEM_calloc_arrayN(count, size, "XrAction_StatesPrev"); - if (float_threshold) { - BLI_assert(type == XR_FLOAT_INPUT || type == XR_VECTOR2F_INPUT); - action->float_threshold = *float_threshold; - CLAMP(action->float_threshold, 0.0f, 1.0f); + const bool is_float_action = (type == XR_FLOAT_INPUT || type == XR_VECTOR2F_INPUT); + const bool is_button_action = (is_float_action || type == XR_BOOLEAN_INPUT); + if (is_float_action) { + action->float_thresholds = MEM_calloc_arrayN( + count, sizeof(*action->float_thresholds), "XrAction_FloatThresholds"); + } + if (is_button_action) { + action->axis_flags = MEM_calloc_arrayN( + count, sizeof(*action->axis_flags), "XrAction_AxisFlags"); } action->ot = ot; @@ -140,6 +144,9 @@ static void action_destroy(void *val) MEM_SAFE_FREE(action->states); MEM_SAFE_FREE(action->states_prev); + MEM_SAFE_FREE(action->float_thresholds); + MEM_SAFE_FREE(action->axis_flags); + MEM_freeN(action); } @@ -198,7 +205,6 @@ bool WM_xr_action_create(wmXrData *xr, eXrActionType type, unsigned int count_subaction_paths, const char **subaction_paths, - const float *float_threshold, wmOperatorType *ot, IDProperty *op_properties, eXrOpFlag op_flag) @@ -211,7 +217,6 @@ bool WM_xr_action_create(wmXrData *xr, type, count_subaction_paths, subaction_paths, - float_threshold, ot, op_properties, op_flag); @@ -221,6 +226,8 @@ bool WM_xr_action_create(wmXrData *xr, .count_subaction_paths = count_subaction_paths, .subaction_paths = subaction_paths, .states = action->states, + .float_thresholds = action->float_thresholds, + .axis_flags = (int16_t *)action->axis_flags, .customdata_free_fn = action_destroy, .customdata = action, }; @@ -257,6 +264,11 @@ void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char return; } + wmXrAction *action = action_find(xr, action_set_name, action_name); + if (!action) { + return; + } + if (action_set->controller_pose_action && STREQ(action_set->controller_pose_action->name, action_name)) { if (action_set == xr->runtime->session_state.active_action_set) { @@ -269,98 +281,60 @@ void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char action_set->active_modal_action = NULL; } - wmXrAction *action = action_find(xr, action_set_name, action_name); - if (!action) { - return; - } + GHOST_XrDestroyActions(xr->runtime->context, action_set_name, 1, &action_name); } -bool WM_xr_action_space_create(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths, - const wmXrPose *poses) + +bool WM_xr_action_binding_create(wmXrData *xr, + const char *action_set_name, + const char *action_name, + const char *profile_path, + unsigned int count_subaction_paths, + const char **subaction_paths, + const char **component_paths, + const float *float_thresholds, + const eXrAxisFlag *axis_flags, + const struct wmXrPose *poses) { - GHOST_XrActionSpaceInfo info = { - .action_name = action_name, - .count_subaction_paths = count_subaction_paths, - .subaction_paths = subaction_paths, - }; + GHOST_XrActionBindingInfo *binding_infos = MEM_calloc_arrayN( + count_subaction_paths, sizeof(*binding_infos), __func__); - GHOST_XrPose *ghost_poses = MEM_malloc_arrayN( - count_subaction_paths, sizeof(*ghost_poses), __func__); for (unsigned int i = 0; i < count_subaction_paths; ++i) { - const wmXrPose *pose = &poses[i]; - GHOST_XrPose *ghost_pose = &ghost_poses[i]; - copy_v3_v3(ghost_pose->position, pose->position); - copy_qt_qt(ghost_pose->orientation_quat, pose->orientation_quat); + GHOST_XrActionBindingInfo *binding_info = &binding_infos[i]; + binding_info->component_path = component_paths[i]; + if (float_thresholds) { + binding_info->float_threshold = float_thresholds[i]; + } + if (axis_flags) { + binding_info->axis_flag = axis_flags[i]; + } + if (poses) { + copy_v3_v3(binding_info->pose.position, poses[i].position); + copy_qt_qt(binding_info->pose.orientation_quat, poses[i].orientation_quat); + } } - info.poses = ghost_poses; - bool ret = GHOST_XrCreateActionSpaces(xr->runtime->context, action_set_name, 1, &info) ? true : - false; - MEM_freeN(ghost_poses); - return ret; -} - -void WM_xr_action_space_destroy(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths) -{ - GHOST_XrActionSpaceInfo info = { + GHOST_XrActionProfileInfo profile_info = { .action_name = action_name, + .profile_path = profile_path, .count_subaction_paths = count_subaction_paths, .subaction_paths = subaction_paths, + .bindings = binding_infos, }; - GHOST_XrDestroyActionSpaces(xr->runtime->context, action_set_name, 1, &info); -} + bool ret = GHOST_XrCreateActionBindings(xr->runtime->context, action_set_name, 1, &profile_info); -bool WM_xr_action_binding_create(wmXrData *xr, - const char *action_set_name, - const char *profile_path, - const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths) -{ - GHOST_XrActionBindingInfo binding_info = { - .action_name = action_name, - .count_interaction_paths = count_interaction_paths, - .interaction_paths = interaction_paths, - }; - - GHOST_XrActionProfileInfo profile_info = { - .profile_path = profile_path, - .count_bindings = 1, - .bindings = &binding_info, - }; - - return GHOST_XrCreateActionBindings(xr->runtime->context, action_set_name, 1, &profile_info); + MEM_freeN(binding_infos); + return ret; } void WM_xr_action_binding_destroy(wmXrData *xr, const char *action_set_name, - const char *profile_path, const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths) + const char *profile_path) { - GHOST_XrActionBindingInfo binding_info = { - .action_name = action_name, - .count_interaction_paths = count_interaction_paths, - .interaction_paths = interaction_paths, - }; - - GHOST_XrActionProfileInfo profile_info = { - .profile_path = profile_path, - .count_bindings = 1, - .bindings = &binding_info, - }; - - GHOST_XrDestroyActionBindings(xr->runtime->context, action_set_name, 1, &profile_info); + GHOST_XrDestroyActionBindings( + xr->runtime->context, action_set_name, 1, &action_name, &profile_path); } bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name) @@ -427,12 +401,12 @@ bool WM_xr_action_state_get(const wmXrData *xr, return false; } - BLI_assert(action->type == (eXrActionType)r_state->type); + r_state->type = (int)action->type; /* Find the action state corresponding to the subaction path. */ for (unsigned int i = 0; i < action->count_subaction_paths; ++i) { if (STREQ(subaction_path, action->subaction_paths[i])) { - switch ((eXrActionType)r_state->type) { + switch (action->type) { case XR_BOOLEAN_INPUT: r_state->state_boolean = ((bool *)action->states)[i]; break; diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h index 6415f96e322..4530aeaa428 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h +++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h @@ -122,8 +122,9 @@ typedef struct wmXrAction { /** Previous states, stored to determine XR events. */ void *states_prev; - /** Input threshold for float/vector2f actions. */ - float float_threshold; + /** Input thresholds/regions for each subaction path. */ + float *float_thresholds; + eXrAxisFlag *axis_flags; /** The currently active subaction path (if any) for modal actions. */ char **active_modal_path; |