[Bf-blender-cvs] [c8db91fc936] xr-actions-D9124: XR: Only allow one active modal action/subaction

Peter Kim noreply at git.blender.org
Mon Nov 23 08:17:56 CET 2020


Commit: c8db91fc936ed90cbc86622bbd6ab4e016cb7f08
Author: Peter Kim
Date:   Mon Nov 23 16:16:41 2020 +0900
Branches: xr-actions-D9124
https://developer.blender.org/rBc8db91fc936ed90cbc86622bbd6ab4e016cb7f08

XR: Only allow one active modal action/subaction

Prevents unwanted behavior when a modal operator is bound to multiple
inputs (e.g. when an action has multiple subaction paths). Can be
refactored in the future to support "bimanual" interaction for some
operators.

===================================================================

M	intern/ghost/GHOST_Types.h
M	source/blender/windowmanager/xr/intern/wm_xr_actions.c
M	source/blender/windowmanager/xr/intern/wm_xr_intern.h
M	source/blender/windowmanager/xr/intern/wm_xr_session.c

===================================================================

diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index c1ee5dbd1d1..4e7a75bb393 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -713,6 +713,9 @@ typedef struct GHOST_XrActionInfo {
   /** Input threshold for float actions (only used by wm). */
   float threshold;
 
+  /** The currently active subaction path (if any) for modal actions (only used by wm). */
+  char **active_modal_path;
+
   /** Operator to be called on XR events (only used by wm). */
   void *ot;
   void *op_properties;
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actions.c b/source/blender/windowmanager/xr/intern/wm_xr_actions.c
index 3ada9b6ca8e..70d46f3faf9 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_actions.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_actions.c
@@ -197,6 +197,9 @@ void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name, bool re
       wm_xr_session_controller_data_clear(&xr->runtime->session_state);
       action_set->controller_pose_action = NULL;
     }
+    if (action_set->active_modal_action) {
+      action_set->active_modal_action = NULL;
+    }
     session_state->active_action_set = NULL;
   }
 
@@ -261,21 +264,38 @@ void WM_xr_actions_destroy(wmXrData *xr,
 
   GHOST_XrDestroyActions(xr->runtime->context, action_set_name, count, action_names);
 
-  /* Save name of controller pose action in case the action is removed from the GHash. */
+  GHash *actions = action_set->actions;
   char controller_pose_name[64];
-  strcpy(controller_pose_name, action_set->controller_pose_action->name);
+  char active_modal_name[64];
+
+  /* Save names of controller pose and active modal actions in case they are removed from the
+   * GHash. */
+  if (action_set->controller_pose_action) {
+    strcpy(controller_pose_name, action_set->controller_pose_action->name);
+  }
+  else {
+    controller_pose_name[0] = '\0';
+  }
+  if (action_set->active_modal_action) {
+    strcpy(active_modal_name, action_set->active_modal_action->name);
+  }
+  else {
+    active_modal_name[0] = '\0';
+  }
 
-  GHash *actions = action_set->actions;
   for (unsigned int i = 0; i < count; ++i) {
     BLI_ghash_remove(actions, action_names[i], NULL, action_destroy);
   }
 
-  if (!action_find(action_set, controller_pose_name)) {
+  if ((controller_pose_name[0] != '\0') && !action_find(action_set, controller_pose_name)) {
     if (action_set == xr->runtime->session_state.active_action_set) {
       wm_xr_session_controller_data_clear(&xr->runtime->session_state);
     }
     action_set->controller_pose_action = NULL;
   }
+  if ((active_modal_name[0] != '\0') && !action_find(action_set, active_modal_name)) {
+    action_set->active_modal_action = NULL;
+  }
 }
 
 bool WM_xr_action_spaces_create(wmXrData *xr,
@@ -318,6 +338,20 @@ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name)
     return false;
   }
 
+  {
+    /* Unset active modal action (if any). */
+    wmXrActionSet *active_action_set = xr->runtime->session_state.active_action_set;
+    if (active_action_set) {
+      wmXrAction *active_modal_action = active_action_set->active_modal_action;
+      if (active_modal_action) {
+        if (active_modal_action->active_modal_path) {
+          active_modal_action->active_modal_path = NULL;
+        }
+        active_action_set->active_modal_action = NULL;
+      }
+    }
+  }
+
   xr->runtime->session_state.active_action_set = action_set;
 
   if (action_set->controller_pose_action) {
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
index 1ef2ac595de..cff648f1341 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -136,6 +136,9 @@ typedef struct wmXrAction {
   /** Input threshold for float actions. */
   float threshold;
 
+  /** The currently active subaction path (if any) for modal actions. */
+  char **active_modal_path;
+
   /** Operator to be called on XR events. */
   struct wmOperatorType *ot;
   IDProperty *op_properties;
@@ -145,10 +148,14 @@ typedef struct wmXrAction {
 typedef struct wmXrActionSet {
   char *name;
   struct GHash *actions; /* wmXrAction */
+
   /** Shared pointer with the GHash. The XR pose action that determines the controller
    * transforms. This is usually identified by the OpenXR path "/grip/pose" or "/aim/pose",
    * although it could differ depending on the specification and hardware. */
   wmXrAction *controller_pose_action;
+
+  /** Shared pointer with the GHash. The currently active modal action (if any). */
+  wmXrAction *active_modal_action;
 } wmXrActionSet;
 
 wmXrRuntimeData *wm_xr_runtime_data_create(void);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index 69b2cb6f8e6..024ef21b97d 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -621,12 +621,16 @@ static const GHOST_XrPose *wm_xr_session_controller_pose_find(const wmXrSessionS
 
 /* Dispatch events to XR surface / window queues. */
 static void wm_xr_session_events_dispatch(const XrSessionSettings *settings,
-                                          const char *action_set_name,
-                                          GHash *actions,
+                                          wmXrActionSet *action_set,
                                           wmXrSessionState *session_state,
                                           wmSurface *surface,
                                           wmWindow *win)
 {
+  const wmXrEyeData *eye_data = &session_state->eyes[settings->selection_eye];
+  const char *action_set_name = action_set->name;
+  GHash *actions = action_set->actions;
+  wmXrAction *active_modal_action = action_set->active_modal_action;
+
   GHashIterator *ghi = BLI_ghashIterator_new(actions);
   GHASH_ITER (*ghi, actions) {
     wmXrAction *action = BLI_ghashIterator_getValue(ghi);
@@ -634,7 +638,7 @@ static void wm_xr_session_events_dispatch(const XrSessionSettings *settings,
       bool modal = (action->ot->modal || action->ot->modal_3d) ? true : false;
 
       for (unsigned int i = 0; i < action->count_subaction_paths; ++i) {
-        short val = KM_ANY;
+        short val = KM_NOTHING;
         bool press_start;
 
         switch (action->type) {
@@ -646,6 +650,11 @@ static void wm_xr_session_events_dispatch(const XrSessionSettings *settings,
                 if (modal || action->op_flag == XR_OP_PRESS) {
                   val = KM_PRESS;
                   press_start = true;
+                  if (modal && !active_modal_action) {
+                    /* Set active modal action. */
+                    active_modal_action = action_set->active_modal_action = action;
+                    active_modal_action->active_modal_path = &action->subaction_paths[i];
+                  }
                 }
               }
               else if (modal) {
@@ -657,6 +666,12 @@ static void wm_xr_session_events_dispatch(const XrSessionSettings *settings,
               if (modal || action->op_flag == XR_OP_RELEASE) {
                 val = KM_RELEASE;
                 press_start = false;
+                if (modal && ((action == active_modal_action) &&
+                              (&action->subaction_paths[i] == action->active_modal_path))) {
+                  /* Unset active modal action. */
+                  active_modal_action->active_modal_path = NULL;
+                  active_modal_action = action_set->active_modal_action = NULL;
+                }
               }
             }
             *state_prev = *state;
@@ -670,6 +685,11 @@ static void wm_xr_session_events_dispatch(const XrSessionSettings *settings,
                 if (modal || action->op_flag == XR_OP_PRESS) {
                   val = KM_PRESS;
                   press_start = true;
+                  if (modal && !active_modal_action) {
+                    /* Set active modal action. */
+                    active_modal_action = action_set->active_modal_action = action;
+                    active_modal_action->active_modal_path = &action->subaction_paths[i];
+                  }
                 }
               }
               else if (modal) {
@@ -681,6 +701,12 @@ static void wm_xr_session_events_dispatch(const XrSessionSettings *settings,
               if (modal || action->op_flag == XR_OP_RELEASE) {
                 val = KM_RELEASE;
                 press_start = false;
+                if (modal && ((action == active_modal_action) &&
+                              (&action->subaction_paths[i] == action->active_modal_path))) {
+                  /* Unset active modal action. */
+                  active_modal_action->active_modal_path = NULL;
+                  active_modal_action = action_set->active_modal_action = NULL;
+                }
               }
             }
             *state_prev = *state;
@@ -694,6 +720,11 @@ static void wm_xr_session_events_dispatch(const XrSessionSettings *settings,
                 if (modal || action->op_flag == XR_OP_PRESS) {
                   val = KM_PRESS;
                   press_start = true;
+                  if (modal && !active_modal_action) {
+                    /* Set active modal action. */
+                    active_modal_action = action_set->active_modal_action = action;
+                    active_modal_action->active_modal_path = &action->subaction_paths[i];
+                  }
                 }
               }
               else if (modal) {
@@ -705,6 +736,12 @@ static void wm_xr_session_events_dispatch(const XrSessionSettings *settings,
               if (modal || action->op_flag == XR_OP_RELEASE) {
                 val = KM_RELEASE;
                 press_start = false;
+                if (modal && ((action == active_modal_action) &&
+                              (&action->subaction_paths[i] == action->active_modal_path))) {
+                  /* Unset active modal action. */
+                  active_modal_action->active_modal_path = NULL;
+                  active_modal_action = action_set->active_modal_action = NULL;
+  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list