XR: Fix controller flicker when switching action sets

This could happen when switching between custom action sets that both
had controller pose actions. Problem was that controller data is
cleared when changing action sets, and this clearing was done when
handling WM events, which always occurs after XR controller data is
updated from GHOST.

Now, instead of activating the action set immediately, delay activation
until just before the next XR actions sync.
This commit is contained in:
2022-05-28 17:23:27 +09:00
parent 16166f69be
commit 314e5cb889
5 changed files with 20 additions and 5 deletions

View File

@@ -1700,7 +1700,7 @@ void WM_xr_action_binding_destroy(wmXrData *xr,
/**
* 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);
bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name, bool delayed);
bool WM_xr_controller_pose_actions_set(wmXrData *xr,
const char *action_set_name,

View File

@@ -391,13 +391,20 @@ void WM_xr_action_binding_destroy(wmXrData *xr,
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)
bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name, bool delayed)
{
wmXrActionSet *action_set = action_set_find(xr, action_set_name);
if (!action_set) {
return false;
}
if (delayed) {
/* Save name to activate action set later, before next actions sync
* (see #wm_xr_session_actions_update()). */
strcpy(xr->runtime->session_state.active_action_set_next, action_set_name);
return true;
}
{
/* Clear any active modal/haptic actions. */
wmXrActionSet *active_action_set = xr->runtime->session_state.active_action_set;

View File

@@ -54,9 +54,11 @@ typedef struct wmXrSessionState {
ListBase controllers; /* #wmXrController */
/** The currently active action set that will be updated on calls to
* wm_xr_session_actions_update(). If NULL, all action sets will be treated as active and
* #wm_xr_session_actions_update(). If NULL, all action sets will be treated as active and
* updated. */
struct wmXrActionSet *active_action_set;
/* Name of the action set (if any) to activate before the next actions sync. */
char active_action_set_next[64]; /* MAX_NAME */
} wmXrSessionState;
typedef struct wmXrRuntimeData {

View File

@@ -1175,7 +1175,6 @@ void wm_xr_session_actions_update(wmWindowManager *wm)
XrSessionSettings *settings = &xr->session_settings;
GHOST_XrContextHandle xr_context = xr->runtime->context;
wmXrSessionState *state = &xr->runtime->session_state;
wmXrActionSet *active_action_set = state->active_action_set;
if (state->is_navigation_dirty) {
memcpy(&state->nav_pose_prev, &state->nav_pose, sizeof(state->nav_pose_prev));
@@ -1192,6 +1191,13 @@ void wm_xr_session_actions_update(wmWindowManager *wm)
&state->viewer_pose, settings->base_scale * state->nav_scale, state->viewer_viewmat);
}
/* Set active action set if requested previously. */
if (state->active_action_set_next[0]) {
WM_xr_active_action_set_set(xr, state->active_action_set_next, false);
state->active_action_set_next[0] = '\0';
}
wmXrActionSet *active_action_set = state->active_action_set;
const bool synced = GHOST_XrSyncActions(xr_context,
active_action_set ? active_action_set->name : NULL);
if (!synced) {