diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/include/ED_screen.h | 6 | ||||
-rw-r--r-- | source/blender/editors/screen/area.c | 62 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_edit.c | 19 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_intern.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_types.h | 31 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 92 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_system.h | 7 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_types.h | 4 | ||||
-rw-r--r-- | source/blender/windowmanager/xr/intern/wm_xr.c | 17 | ||||
-rw-r--r-- | source/blender/windowmanager/xr/intern/wm_xr_intern.h | 12 | ||||
-rw-r--r-- | source/blender/windowmanager/xr/intern/wm_xr_session.c | 35 |
12 files changed, 268 insertions, 19 deletions
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(®ion->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_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; } |