[Bf-blender-cvs] [08511b1c3de] master: XR: Add runtime window area for XR events

Peter Kim noreply at git.blender.org
Tue Oct 5 09:13:36 CEST 2021


Commit: 08511b1c3de0338314940397083adaba4e9cf492
Author: Peter Kim
Date:   Tue Oct 5 15:55:57 2021 +0900
Branches: master
https://developer.blender.org/rB08511b1c3de0338314940397083adaba4e9cf492

XR: Add runtime window area for XR events

This adds an offscreen View3D window area for the VR view in order to
execute XR events/operators in the proper context. The area is created
as runtime data before XR events are dispatched and set as the active
area during XR event handling.

Since the area is runtime-only, it will not be saved in files and since
the area is offscreen, it will not interfere with regular window areas.
The area is removed with the rest of the XR runtime data on exit, file
read, or when stopping the VR session.

Note: This also adds internal types (EVT_DATA_XR, EVT_XR_ACTION) and
structs (wmXrActionData) for XR events.

Reviewed By: Severin

Differential Revision: https://developer.blender.org/D12472

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

M	source/blender/editors/include/ED_screen.h
M	source/blender/editors/screen/area.c
M	source/blender/editors/screen/screen_edit.c
M	source/blender/editors/screen/screen_intern.h
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/WM_types.h
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/wm_event_system.h
M	source/blender/windowmanager/wm_event_types.h
M	source/blender/windowmanager/xr/intern/wm_xr.c
M	source/blender/windowmanager/xr/intern/wm_xr_intern.h
M	source/blender/windowmanager/xr/intern/wm_xr_session.c

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

diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 60ef3e740c6..0de6907e677 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -178,6 +178,12 @@ void ED_area_update_region_sizes(struct wmWindowManager *wm,
                                  struct wmWindow *win,
                                  struct ScrArea *area);
 bool ED_area_has_shared_border(struct ScrArea *a, struct ScrArea *b);
+ScrArea *ED_area_offscreen_create(struct wmWindowManager *wm,
+                                  struct wmWindow *win,
+                                  eSpace_Type space_type);
+void ED_area_offscreen_free(struct wmWindowManager *wm,
+                            struct wmWindow *win,
+                            struct ScrArea *area);
 
 ScrArea *ED_screen_areas_iter_first(const struct wmWindow *win, const bScreen *screen);
 ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 833c9accf95..d5456482d67 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -2001,6 +2001,68 @@ void ED_area_init(wmWindowManager *wm, wmWindow *win, ScrArea *area)
   }
 }
 
+static void area_offscreen_init(wmWindowManager *wm, ScrArea *area)
+{
+  area->type = BKE_spacetype_from_id(area->spacetype);
+
+  if (area->type == NULL) {
+    area->spacetype = SPACE_VIEW3D;
+    area->type = BKE_spacetype_from_id(area->spacetype);
+  }
+
+  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+    region->type = BKE_regiontype_from_id_or_first(area->type, region->regiontype);
+  }
+}
+
+ScrArea *ED_area_offscreen_create(wmWindowManager *wm, wmWindow *win, eSpace_Type space_type)
+{
+  ScrArea *area = MEM_callocN(sizeof(*area), __func__);
+  area->spacetype = space_type;
+
+  screen_area_spacelink_add(WM_window_get_active_scene(win), area, space_type);
+  area_offscreen_init(wm, area);
+
+  return area;
+}
+
+static void area_offscreen_exit(wmWindowManager *wm, wmWindow *win, ScrArea *area)
+{
+  if (area->type && area->type->exit) {
+    area->type->exit(wm, area);
+  }
+
+  LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+    if (region->type && region->type->exit) {
+      region->type->exit(wm, region);
+    }
+
+    WM_event_modal_handler_region_replace(win, region, NULL);
+    WM_draw_region_free(region, true);
+
+    MEM_SAFE_FREE(region->headerstr);
+
+    if (region->regiontimer) {
+      WM_event_remove_timer(wm, win, region->regiontimer);
+      region->regiontimer = NULL;
+    }
+
+    if (wm->message_bus) {
+      WM_msgbus_clear_by_owner(wm->message_bus, region);
+    }
+  }
+
+  WM_event_modal_handler_area_replace(win, area, NULL);
+}
+
+void ED_area_offscreen_free(wmWindowManager *wm, wmWindow *win, ScrArea *area)
+{
+  area_offscreen_exit(wm, win, area);
+
+  BKE_screen_area_free(area);
+  MEM_freeN(area);
+}
+
 static void region_update_rect(ARegion *region)
 {
   region->winx = BLI_rcti_size_x(&region->winrct) + 1;
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 1c068fdd6e4..02b1e002d86 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -574,6 +574,17 @@ bool screen_area_close(struct bContext *C, bScreen *screen, ScrArea *area)
   return screen_area_join_ex(C, screen, sa2, area, true);
 }
 
+void screen_area_spacelink_add(Scene *scene, ScrArea *area, eSpace_Type space_type)
+{
+  SpaceType *stype = BKE_spacetype_from_id(space_type);
+  SpaceLink *slink = stype->create(area, scene);
+
+  area->regionbase = slink->regionbase;
+
+  BLI_addhead(&area->spacedata, slink);
+  BLI_listbase_clear(&slink->regionbase);
+}
+
 /* ****************** EXPORTED API TO OTHER MODULES *************************** */
 
 /* screen sets cursor based on active region */
@@ -1023,13 +1034,7 @@ static void screen_global_area_refresh(wmWindow *win,
   }
   else {
     area = screen_area_create_with_geometry(&win->global_areas, rect, space_type);
-    SpaceType *stype = BKE_spacetype_from_id(space_type);
-    SpaceLink *slink = stype->create(area, WM_window_get_active_scene(win));
-
-    area->regionbase = slink->regionbase;
-
-    BLI_addhead(&area->spacedata, slink);
-    BLI_listbase_clear(&slink->regionbase);
+    screen_area_spacelink_add(WM_window_get_active_scene(win), area, space_type);
 
     /* Data specific to global areas. */
     area->global = MEM_callocN(sizeof(*area->global), __func__);
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index 04ee62b1631..47229e5e2b5 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -94,6 +94,7 @@ eScreenDir area_getorientation(ScrArea *sa_a, ScrArea *sa_b);
 void area_getoffsets(
     ScrArea *sa_a, ScrArea *sa_b, const eScreenDir dir, int *r_offset1, int *r_offset2);
 bool screen_area_close(struct bContext *C, bScreen *screen, ScrArea *area);
+void screen_area_spacelink_add(struct Scene *scene, ScrArea *area, eSpace_Type space_type);
 struct AZone *ED_area_actionzone_find_xy(ScrArea *area, const int xy[2]);
 
 /* screen_geometry.c */
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index ebb0f803acf..b79f5762955 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -989,6 +989,7 @@ bool WM_region_use_viewport(struct ScrArea *area, struct ARegion *region);
 bool WM_xr_session_exists(const wmXrData *xr);
 bool WM_xr_session_is_ready(const wmXrData *xr);
 struct wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr);
+struct ScrArea *WM_xr_session_area_get(const wmXrData *xr);
 void WM_xr_session_base_pose_reset(wmXrData *xr);
 bool WM_xr_session_state_viewer_pose_location_get(const wmXrData *xr, float r_location[3]);
 bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_rotation[4]);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 7f52bef3203..14a69d9c435 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -120,6 +120,7 @@ struct wmWindowManager;
 #include "BLI_compiler_attrs.h"
 #include "DNA_listBase.h"
 #include "DNA_vec_types.h"
+#include "DNA_xr_types.h"
 #include "RNA_types.h"
 
 /* exported types for WM */
@@ -721,6 +722,36 @@ typedef struct wmXrActionState {
   };
   int type; /* eXrActionType */
 } wmXrActionState;
+
+typedef struct wmXrActionData {
+  /** Action set name. */
+  char action_set[64];
+  /** Action name. */
+  char action[64];
+  /** Type. */
+  eXrActionType type;
+  /** State. Set appropriately based on type. */
+  float state[2];
+  /** State of the other subaction path for bimanual actions. */
+  float state_other[2];
+
+  /** Input threshold for float/vector2f actions. */
+  float float_threshold;
+
+  /** Controller aim pose corresponding to the action's subaction path. */
+  float controller_loc[3];
+  float controller_rot[4];
+  /** Controller aim pose of the other subaction path for bimanual actions. */
+  float controller_loc_other[3];
+  float controller_rot_other[4];
+
+  /** Operator. */
+  struct wmOperatorType *ot;
+  struct IDProperty *op_properties;
+
+  /** Whether bimanual interaction is occuring. */
+  bool bimanual;
+} wmXrActionData;
 #endif
 
 /** Timer flags. */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index cc0a13e96af..c92208c4818 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -3461,6 +3461,70 @@ static void wm_event_free_and_remove_from_queue_if_valid(wmEvent *event)
  * Handle events for all windows, run from the #WM_main event loop.
  * \{ */
 
+#ifdef WITH_XR_OPENXR
+/**
+ * Special handling for XR events.
+ *
+ * Although XR events are added to regular window queues, they are handled in an "offscreen area"
+ * context that is owned entirely by XR runtime data and not tied to a window.
+ */
+static void wm_event_handle_xrevent(bContext *C,
+                                    wmWindowManager *wm,
+                                    wmWindow *win,
+                                    wmEvent *event)
+{
+  ScrArea *area = WM_xr_session_area_get(&wm->xr);
+  if (!area) {
+    return;
+  }
+  BLI_assert(area->spacetype == SPACE_VIEW3D && area->spacedata.first);
+
+  /* Find a valid region for XR operator execution and modal handling. */
+  ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
+  if (!region) {
+    return;
+  }
+  BLI_assert(WM_region_use_viewport(area, region)); /* For operators using GPU-based selection. */
+
+  CTX_wm_area_set(C, area);
+  CTX_wm_region_set(C, region);
+
+  int action = wm_handlers_do(C, event, &win->modalhandlers);
+
+  if ((action & WM_HANDLER_BREAK) == 0) {
+    wmXrActionData *actiondata = event->customdata;
+    if (actiondata->ot->modal && event->val == KM_RELEASE) {
+      /* Don't execute modal operators on release. */
+    }
+    else {
+      PointerRNA properties = {.type = actiondata->ot->srna, .data = actiondata->op_properties};
+      if (actiondata->ot->invoke) {
+        /* Invoke operator, either executing operator or transferring responsibility to window
+         * modal handlers. */
+        wm_operator_invoke(C,
+                           actiondata->ot,
+                           event,
+                           actiondata->op_properties ? &properties : NULL,
+                           NULL,
+                           false,
+                           false);
+      }
+      else {
+        /* Execute operator. */
+        wmOperator *op = wm_operator_create(
+            wm, actiondata->ot, actiondata->op_properties ? &properties : NULL, NULL);
+        if ((WM_operator_call(C, op) & OPERATOR_HANDLED) == 0) {
+          WM_operator_free(op);
+        }
+      }
+    }
+  }
+
+  CTX_wm_region_set(C, NULL);
+  CTX_wm

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list