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:
authorPeter Kim <pk15950@gmail.com>2021-10-05 09:55:57 +0300
committerPeter Kim <pk15950@gmail.com>2021-10-05 10:05:12 +0300
commit08511b1c3de0338314940397083adaba4e9cf492 (patch)
tree879ddffecd08dd9315847fdcffb0b2d76cee8637 /source/blender/windowmanager
parent300403a38b8ed7f0f84125ca9a82264757ae704a (diff)
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
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/WM_api.h1
-rw-r--r--source/blender/windowmanager/WM_types.h31
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c92
-rw-r--r--source/blender/windowmanager/wm_event_system.h7
-rw-r--r--source/blender/windowmanager/wm_event_types.h4
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr.c17
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_intern.h12
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_session.c35
8 files changed, 187 insertions, 12 deletions
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_area_set(C, NULL);
+}
+#endif /* WITH_XR_OPENXR */
+
/* Called in main loop. */
/* Goes over entire hierarchy: events -> window -> screen -> area -> region. */
void wm_event_do_handlers(bContext *C)
@@ -3558,6 +3622,16 @@ void wm_event_do_handlers(bContext *C)
CTX_wm_window_set(C, win);
+#ifdef WITH_XR_OPENXR
+ if (event->type == EVT_XR_ACTION) {
+ wm_event_handle_xrevent(C, wm, win, event);
+ BLI_remlink(&win->event_queue, event);
+ wm_event_free(event);
+ /* Skip mouse event handling below, which is unnecessary for XR events. */
+ continue;
+ }
+#endif
+
/* Clear tool-tip on mouse move. */
if (screen->tool_tip && screen->tool_tip->exit_on_event) {
if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
@@ -5110,6 +5184,24 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
#endif
}
+#ifdef WITH_XR_OPENXR
+void wm_event_add_xrevent(wmWindow *win, wmXrActionData *actiondata, short val)
+{
+ BLI_assert(val == KM_PRESS || val == KM_RELEASE);
+
+ wmEvent event = {
+ .type = EVT_XR_ACTION,
+ .val = val,
+ .is_repeat = false,
+ .custom = EVT_DATA_XR,
+ .customdata = actiondata,
+ .customdatafree = 1,
+ };
+
+ wm_event_add(win, &event);
+}
+#endif /* WITH_XR_OPENXR */
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 787c840de8a..d1eb10787e2 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -33,6 +33,10 @@ struct ARegion;
struct GHOST_TabletData;
struct ScrArea;
+#ifdef WITH_XR_OPENXR
+struct wmXrActionData;
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -147,6 +151,9 @@ void wm_event_free_handler(wmEventHandler *handler);
void wm_event_do_handlers(bContext *C);
void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void *customdata);
+#ifdef WITH_XR_OPENXR
+void wm_event_add_xrevent(wmWindow *win, struct wmXrActionData *actiondata, short val);
+#endif
void wm_event_do_depsgraph(bContext *C, bool is_after_open_file);
void wm_event_do_refresh_wm_and_depsgraph(bContext *C);
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 905c57d901a..c175c211db6 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -34,6 +34,7 @@ enum {
EVT_DATA_TIMER = 2,
EVT_DATA_DRAGDROP = 3,
EVT_DATA_NDOF_MOTION = 4,
+ EVT_DATA_XR = 5,
};
/* tablet active, matches GHOST_TTabletMode */
@@ -341,6 +342,9 @@ enum {
/* could become gizmo callback */
EVT_GIZMO_UPDATE = 0x5025, /* 20517 */
+
+ /* XR events: 0x503x */
+ EVT_XR_ACTION = 0x5030, /* 20528 */
/* ********** End of Blender internal events. ********** */
};
diff --git a/source/blender/windowmanager/xr/intern/wm_xr.c b/source/blender/windowmanager/xr/intern/wm_xr.c
index 8891840cb75..36bd03ed3ea 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr.c
@@ -24,19 +24,22 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
+#include "BKE_main.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
-#include "DEG_depsgraph.h"
-
-#include "MEM_guardedalloc.h"
+#include "ED_screen.h"
#include "GHOST_C-api.h"
#include "GPU_platform.h"
+#include "MEM_guardedalloc.h"
+
#include "WM_api.h"
#include "wm_surface.h"
@@ -137,7 +140,7 @@ bool wm_xr_events_handle(wmWindowManager *wm)
/* Process OpenXR action events. */
if (WM_xr_session_is_ready(&wm->xr)) {
- wm_xr_session_actions_update(&wm->xr);
+ wm_xr_session_actions_update(wm);
}
/* wm_window_process_events() uses the return value to determine if it can put the main thread
@@ -172,6 +175,12 @@ void wm_xr_runtime_data_free(wmXrRuntimeData **runtime)
* first call, see comment above. */
(*runtime)->context = NULL;
+ if ((*runtime)->area) {
+ wmWindowManager *wm = G_MAIN->wm.first;
+ wmWindow *win = wm_xr_session_root_window_or_fallback_get(wm, (*runtime));
+ ED_area_offscreen_free(wm, win, (*runtime)->area);
+ (*runtime)->area = NULL;
+ }
wm_xr_session_data_free(&(*runtime)->session_state);
WM_xr_actionmaps_clear(*runtime);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
index fc54e261f79..ee495755ac6 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -67,6 +67,9 @@ typedef struct wmXrRuntimeData {
* be an invalid reference, i.e. the window may have been closed. */
wmWindow *session_root_win;
+ /** Offscreen area used for XR events. */
+ struct ScrArea *area;
+
/** Although this struct is internal, RNA gets a handle to this for state information queries. */
wmXrSessionState session_state;
wmXrSessionExitFn exit_fn;
@@ -172,10 +175,14 @@ typedef struct wmXrActionSet {
ListBase active_haptic_actions;
} wmXrActionSet;
+/* wm_xr.c */
wmXrRuntimeData *wm_xr_runtime_data_create(void);
void wm_xr_runtime_data_free(wmXrRuntimeData **runtime);
-void wm_xr_session_data_free(wmXrSessionState *state);
+/* wm_xr_session.c */
+void wm_xr_session_data_free(wmXrSessionState *state);
+wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm,
+ const wmXrRuntimeData *runtime_data);
void wm_xr_session_draw_data_update(const wmXrSessionState *state,
const XrSessionSettings *settings,
const GHOST_XrDrawViewInfo *draw_view,
@@ -190,12 +197,13 @@ void *wm_xr_session_gpu_binding_context_create(void);
void wm_xr_session_gpu_binding_context_destroy(GHOST_ContextHandle context);
void wm_xr_session_actions_init(wmXrData *xr);
-void wm_xr_session_actions_update(wmXrData *xr);
+void wm_xr_session_actions_update(wmWindowManager *wm);
void wm_xr_session_controller_data_populate(const wmXrAction *grip_action,
const wmXrAction *aim_action,
wmXrData *xr);
void wm_xr_session_controller_data_clear(wmXrSessionState *state);
+/* wm_xr_draw.c */
void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]);
void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4]);
void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index 88bf3ff453c..1e8cda30121 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -30,9 +30,12 @@
#include "DEG_depsgraph.h"
#include "DNA_camera_types.h"
+#include "DNA_space_types.h"
#include "DRW_engine.h"
+#include "ED_screen.h"
+
#include "GHOST_C-api.h"
#include "GPU_viewport.h"
@@ -111,6 +114,7 @@ void wm_xr_session_toggle(wmWindowManager *wm,
if (WM_xr_session_exists(xr_data)) {
GHOST_XrSessionEnd(xr_data->runtime->context);
+ xr_data->runtime->session_state.is_started = false;
}
else {
GHOST_XrSessionBeginInfo begin_info;
@@ -197,8 +201,8 @@ static void wm_xr_session_draw_data_populate(wmXrData *xr_data,
wm_xr_session_base_pose_calc(r_draw_data->scene, settings, &r_draw_data->base_pose);
}
-static wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm,
- const wmXrRuntimeData *runtime_data)
+wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm,
+ const wmXrRuntimeData *runtime_data)
{
if (runtime_data->session_root_win &&
BLI_findindex(&wm->windows, runtime_data->session_root_win) != -1) {
@@ -373,6 +377,11 @@ wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr)
return xr->runtime ? &xr->runtime->session_state : NULL;
}
+ScrArea *WM_xr_session_area_get(const wmXrData *xr)
+{
+ return xr->runtime ? xr->runtime->area : NULL;
+}
+
bool WM_xr_session_state_viewer_pose_location_get(const wmXrData *xr, float r_location[3])
{
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
@@ -550,8 +559,9 @@ static void wm_xr_session_controller_data_update(const XrSessionSettings *settin
}
}
-void wm_xr_session_actions_update(wmXrData *xr)
+void wm_xr_session_actions_update(wmWindowManager *wm)
{
+ wmXrData *xr = &wm->xr;
if (!xr->runtime) {
return;
}
@@ -565,14 +575,27 @@ void wm_xr_session_actions_update(wmXrData *xr)
return;
}
- /* Only update controller data for active action set. */
+ /* Only update controller data and dispatch events for active action set. */
if (active_action_set) {
+ const XrSessionSettings *settings = &xr->session_settings;
+ wmWindow *win = wm_xr_session_root_window_or_fallback_get(wm, xr->runtime);
+
if (active_action_set->controller_grip_action && active_action_set->controller_aim_action) {
- wm_xr_session_controller_data_update(&xr->session_settings,
+ wm_xr_session_controller_data_update(settings,
active_action_set->controller_grip_action,
active_action_set->controller_aim_action,
state);
}
+
+ if (win) {
+ /* Ensure an XR area exists for events. */
+ if (!xr->runtime->area) {
+ xr->runtime->area = ED_area_offscreen_create(wm, win, SPACE_VIEW3D);
+ }
+
+ /* Implemented in D10944. */
+ // wm_xr_session_events_dispatch(xr, settings, xr_context, active_action_set, state, win);
+ }
}
}
@@ -628,7 +651,7 @@ static void wm_xr_session_surface_draw(bContext *C)
Main *bmain = CTX_data_main(C);
wmXrDrawData draw_data;
- if (!GHOST_XrSessionIsRunning(wm->xr.runtime->context)) {
+ if (!WM_xr_session_is_ready(&wm->xr)) {
return;
}