[Bf-blender-cvs] [b94ab93dfb8] master: Eyedropper: Support get samples from other windows

Germano Cavalcante noreply at git.blender.org
Wed Jun 3 20:46:07 CEST 2020


Commit: b94ab93dfb82275c5c6241f8de1556c4f4be934c
Author: Germano Cavalcante
Date:   Wed Jun 3 15:45:43 2020 -0300
Branches: master
https://developer.blender.org/rBb94ab93dfb82275c5c6241f8de1556c4f4be934c

Eyedropper: Support get samples from other windows

This fix T77226

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

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

M	source/blender/editors/interface/interface_eyedropper_color.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/intern/wm_window.c

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

diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index ace367fd513..c917ffb3f3e 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -138,11 +138,26 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
 {
   /* we could use some clever */
   Main *bmain = CTX_data_main(C);
-  bScreen *screen = CTX_wm_screen(C);
-  ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+  wmWindowManager *wm = CTX_wm_manager(C);
   const char *display_device = CTX_data_scene(C)->display_settings.display_device;
   struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
 
+  wmWindow *win = CTX_wm_window(C);
+  bScreen *screen = CTX_wm_screen(C);
+  ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+  if (area == NULL) {
+    int mval[2] = {mx, my};
+    if (WM_window_find_under_cursor(wm, NULL, win, mval, &win, mval)) {
+      mx = mval[0];
+      my = mval[1];
+      screen = WM_window_get_active_screen(win);
+      area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+    }
+    else {
+      win = NULL;
+    }
+  }
+
   if (area) {
     if (area->spacetype == SPACE_IMAGE) {
       ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
@@ -179,12 +194,15 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
     }
   }
 
-  /* fallback to simple opengl picker */
-  glReadBuffer(GL_FRONT);
-  glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
-  glReadBuffer(GL_BACK);
-
-  IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
+  if (win) {
+    /* Fallback to simple opengl picker. */
+    int mval[2] = {mx, my};
+    WM_window_pixel_sample_read(wm, win, mval, r_col);
+    IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
+  }
+  else {
+    zero_v3(r_col);
+  }
 }
 
 /* sets the sample color RGB, maintaining A */
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index ffa5bc15876..8783f2b5335 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -106,6 +106,17 @@ void WM_reinit_gizmomap_all(struct Main *bmain);
 
 void WM_script_tag_reload(void);
 
+bool WM_window_find_under_cursor(const wmWindowManager *wm,
+                                 const wmWindow *win_ignore,
+                                 const wmWindow *win,
+                                 const int mval[2],
+                                 wmWindow **r_win,
+                                 int r_mval[2]);
+void WM_window_pixel_sample_read(const wmWindowManager *wm,
+                                 const wmWindow *win,
+                                 const int pos[2],
+                                 float r_col[3]);
+
 uint *WM_window_pixels_read(struct wmWindowManager *wm, struct wmWindow *win, int r_size[2]);
 
 int WM_window_pixels_x(const struct wmWindow *win);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index e5f288b1963..53d6df915d6 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1,4 +1,4 @@
-/*
+/*
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
@@ -4254,7 +4254,7 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g
 /* imperfect but probably usable... draw/enable drags to other windows */
 static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event)
 {
-  int mx = event->x, my = event->y;
+  int mval[2] = {event->x, event->y};
 
   if (wm->windows.first == wm->windows.last) {
     return NULL;
@@ -4263,7 +4263,8 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
   /* in order to use window size and mouse position (pixels), we have to use a WM function */
 
   /* check if outside, include top window bar... */
-  if (mx < 0 || my < 0 || mx > WM_window_pixels_x(win) || my > WM_window_pixels_y(win) + 30) {
+  if (mval[0] < 0 || mval[1] < 0 || mval[0] > WM_window_pixels_x(win) ||
+      mval[1] > WM_window_pixels_y(win) + 30) {
     wmWindow *owin;
     wmEventHandler *handler;
 
@@ -4276,25 +4277,10 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
       }
     }
 
-    /* to desktop space */
-    mx += (int)(U.pixelsize * win->posx);
-    my += (int)(U.pixelsize * win->posy);
-
-    /* check other windows to see if it has mouse inside */
-    for (owin = wm->windows.first; owin; owin = owin->next) {
-
-      if (owin != win) {
-        int posx = (int)(U.pixelsize * owin->posx);
-        int posy = (int)(U.pixelsize * owin->posy);
-
-        if (mx - posx >= 0 && owin->posy >= 0 && mx - posx <= WM_window_pixels_x(owin) &&
-            my - posy <= WM_window_pixels_y(owin)) {
-          event->x = mx - (int)(U.pixelsize * owin->posx);
-          event->y = my - (int)(U.pixelsize * owin->posy);
-
-          return owin;
-        }
-      }
+    if (WM_window_find_under_cursor(wm, win, win, mval, &owin, mval)) {
+      event->x = mval[0];
+      event->y = mval[1];
+      return owin;
     }
   }
   return NULL;
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 02b50af0ac3..1ba22652157 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1983,6 +1983,90 @@ bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut)
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name Find Window Utility
+ *
+ * \{ */
+static void wm_window_desktop_pos_get(const wmWindow *win,
+                                      const int screen_pos[2],
+                                      int r_desk_pos[2])
+{
+  /* To desktop space. */
+  r_desk_pos[0] = screen_pos[0] + (int)(U.pixelsize * win->posx);
+  r_desk_pos[1] = screen_pos[1] + (int)(U.pixelsize * win->posy);
+}
+
+static void wm_window_screen_pos_get(const wmWindow *win,
+                                     const int desktop_pos[2],
+                                     int r_scr_pos[2])
+{
+  /* To window space. */
+  r_scr_pos[0] = desktop_pos[0] - (int)(U.pixelsize * win->posx);
+  r_scr_pos[1] = desktop_pos[1] - (int)(U.pixelsize * win->posy);
+}
+
+bool WM_window_find_under_cursor(const wmWindowManager *wm,
+                                 const wmWindow *win_ignore,
+                                 const wmWindow *win,
+                                 const int mval[2],
+                                 wmWindow **r_win,
+                                 int r_mval[2])
+{
+  int desk_pos[2];
+  wm_window_desktop_pos_get(win, mval, desk_pos);
+
+  /* TODO: This should follow the order of the activated windows.
+   * The current solution is imperfect but usable in most cases. */
+  LISTBASE_FOREACH (wmWindow *, win_iter, &wm->windows) {
+    if (win_iter == win_ignore) {
+      continue;
+    }
+
+    if (win_iter->windowstate == GHOST_kWindowStateMinimized) {
+      continue;
+    }
+
+    int scr_pos[2];
+    wm_window_screen_pos_get(win_iter, desk_pos, scr_pos);
+
+    if (scr_pos[0] >= 0 && win_iter->posy >= 0 && scr_pos[0] <= WM_window_pixels_x(win_iter) &&
+        scr_pos[1] <= WM_window_pixels_y(win_iter)) {
+
+      *r_win = win_iter;
+      copy_v2_v2_int(r_mval, scr_pos);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void WM_window_pixel_sample_read(const wmWindowManager *wm,
+                                 const wmWindow *win,
+                                 const int pos[2],
+                                 float r_col[3])
+{
+  bool setup_context = wm->windrawable != win;
+
+  if (setup_context) {
+    GHOST_ActivateWindowDrawingContext(win->ghostwin);
+    GPU_context_active_set(win->gpuctx);
+  }
+
+  glReadBuffer(GL_FRONT);
+  glReadPixels(pos[0], pos[1], 1, 1, GL_RGB, GL_FLOAT, r_col);
+  glReadBuffer(GL_BACK);
+
+  if (setup_context) {
+    if (wm->windrawable) {
+      GHOST_ActivateWindowDrawingContext(wm->windrawable->ghostwin);
+      GPU_context_active_set(wm->windrawable->gpuctx);
+    }
+  }
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name Window Screen Shot Utility
  *



More information about the Bf-blender-cvs mailing list