Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/ghost/GHOST_C-api.h19
-rw-r--r--intern/ghost/GHOST_Types.h24
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp29
-rw-r--r--intern/ghost/intern/GHOST_XrAction.cpp188
-rw-r--r--intern/ghost/intern/GHOST_XrAction.h47
-rw-r--r--intern/ghost/intern/GHOST_XrSession.cpp87
-rw-r--r--intern/ghost/intern/GHOST_XrSession.h9
-rw-r--r--source/blender/makesdna/DNA_xr_types.h9
-rw-r--r--source/blender/windowmanager/CMakeLists.txt2
-rw-r--r--source/blender/windowmanager/WM_api.h26
-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.h5
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;