Multi-View: Map cursor coordinates to visual coordinates
authorJulian Eisel <eiseljulian@gmail.com>
Sun, 5 Mar 2017 23:40:48 +0000 (00:40 +0100)
committerJulian Eisel <eiseljulian@gmail.com>
Mon, 6 Mar 2017 00:32:35 +0000 (01:32 +0100)
When rendering multi-view in side-by-side or top-bottom mode, we squash
the UI to half of its size and draw it twice on screen. That means the
cursor coordinates used for UI interaction don't match what's visible on
screen.
This commit is a little event system hack (tm) to fix this. It has some
small glitches with cursor grabbing, but nothing to bad.
We'll also use it for viewport HMD support.

D1350, thanks for the feedback @dfelinto!

source/blender/editors/interface/interface_handlers.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_stereo.c
source/blender/windowmanager/wm.h

index 734cd02a05683b4f0d6bd9c92d12af1b8d48dbdc..6e3c3c3674a1c432aaffcdaa00fb3843895284e3 100644 (file)
@@ -7741,7 +7741,8 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
                if (ui_but_is_cursor_warp(but)) {
 
 #ifdef USE_CONT_MOUSE_CORRECT
-                       if (data->ungrab_mval[0] != FLT_MAX) {
+                       /* stereo3d has issues with changing cursor location so rather avoid */
+                       if (data->ungrab_mval[0] != FLT_MAX && !WM_stereo3d_enabled(data->window, false)) {
                                int mouse_ungrab_xy[2];
                                ui_block_to_window_fl(data->region, but->block, &data->ungrab_mval[0], &data->ungrab_mval[1]);
                                mouse_ungrab_xy[0] = data->ungrab_mval[0];
index d2b0acd836b43bb4f6ef03f28c476771cf0c5d1a..eba132062c912d3b0e50b3cd7e2e25561e4b591a 100644 (file)
@@ -3179,6 +3179,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
                        GHOST_TEventCursorData *cd = customdata;
 
                        copy_v2_v2_int(&event.x, &cd->x);
+                       wm_stereo3d_mouse_offset_apply(win, &event.x);
+
                        event.type = MOUSEMOVE;
                        wm_event_add_mousemove(win, &event);
                        copy_v2_v2_int(&evt->x, &event.x);
index 46cee907991edea04da70e1dcffaf487a2306324..66ebf18c9e1da4340d2e05be631b698b09d0a0cf 100644 (file)
@@ -345,6 +345,32 @@ bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check)
        return true;
 }
 
+/**
+ * If needed, this adjusts \a r_mouse_xy so that drawn cursor and handled mouse position are matching visually.
+*/
+void wm_stereo3d_mouse_offset_apply(wmWindow *win, int *r_mouse_xy)
+{
+       if (!WM_stereo3d_enabled(win, false))
+               return;
+
+       if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) {
+               const int half_x = win->sizex / 2;
+               /* right half of the screen */
+               if (r_mouse_xy[0] > half_x) {
+                       r_mouse_xy[0] -= half_x;
+               }
+               r_mouse_xy[0] *= 2;
+       }
+       else if (win->stereo3d_format->display_mode == S3D_DISPLAY_TOPBOTTOM) {
+               const int half_y = win->sizey / 2;
+               /* upper half of the screen */
+               if (r_mouse_xy[1] > half_y) {
+                       r_mouse_xy[1] -= half_y;
+               }
+               r_mouse_xy[1] *= 2;
+       }
+}
+
 /************************** Stereo 3D operator **********************************/
 typedef struct Stereo3dData {
        Stereo3dFormat stereo3d_format;
index 2f06ddab1e80ad23faa86832d891ea345fa4877a..e84853594900a4da50f0f99d0bd5ac24670c7641 100644 (file)
@@ -78,6 +78,7 @@ void wm_autosave_location(char *filepath);
 
 /* wm_stereo.c */
 void wm_method_draw_stereo3d(const bContext *C, wmWindow *win);
+void wm_stereo3d_mouse_offset_apply(wmWindow *win, int *r_mouse_xy);
 int wm_stereo3d_set_exec(bContext *C, wmOperator *op);
 int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *event);
 void wm_stereo3d_set_draw(bContext *C, wmOperator *op);