From a4edce178b4209e72985b04aff17618d3df8c6a9 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Sun, 30 Jul 2023 18:09:14 -0700 Subject: [PATCH 1/2] Updated to the current state of main --- intern/ghost/GHOST_C-api.h | 7 +++ intern/ghost/GHOST_ISystem.hh | 7 +++ intern/ghost/GHOST_Types.h | 7 ++- intern/ghost/intern/GHOST_C-api.cc | 6 ++ intern/ghost/intern/GHOST_System.cc | 5 ++ intern/ghost/intern/GHOST_System.hh | 7 +++ intern/ghost/intern/GHOST_SystemCocoa.mm | 2 + intern/ghost/intern/GHOST_SystemHeadless.hh | 1 + intern/ghost/intern/GHOST_SystemSDL.cc | 2 + intern/ghost/intern/GHOST_SystemWayland.cc | 2 + intern/ghost/intern/GHOST_SystemWin32.cc | 25 ++++++++ intern/ghost/intern/GHOST_SystemWin32.hh | 7 +++ intern/ghost/intern/GHOST_SystemX11.cc | 2 + .../interface/eyedroppers/eyedropper_color.cc | 59 +++++++++---------- source/blender/windowmanager/WM_api.h | 8 +++ .../blender/windowmanager/intern/wm_draw.cc | 5 ++ .../blender/windowmanager/intern/wm_window.cc | 3 + 17 files changed, 124 insertions(+), 31 deletions(-) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index e59a9ac65ad..3f597ac1fbe 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -764,6 +764,13 @@ extern void GHOST_SetMultitouchGestures(GHOST_SystemHandle systemhandle, const b */ extern void GHOST_SetTabletAPI(GHOST_SystemHandle systemhandle, GHOST_TTabletAPI api); +/** + * Get the color of the pixel at the current mouse cursor location + * \param r_color: returned RGB float colors + * \return Success value (true == successful and supported by platform) + */ +extern GHOST_TSuccess GHOST_GetPixelAtCursor(float r_color[3]); + /** * Access to rectangle width. * \param rectanglehandle: The handle to the rectangle. diff --git a/intern/ghost/GHOST_ISystem.hh b/intern/ghost/GHOST_ISystem.hh index 7a2d0afb7f4..4bd218fc334 100644 --- a/intern/ghost/GHOST_ISystem.hh +++ b/intern/ghost/GHOST_ISystem.hh @@ -441,6 +441,13 @@ class GHOST_ISystem { */ virtual void setTabletAPI(GHOST_TTabletAPI api) = 0; + /** + * Get the color of the pixel at the current mouse cursor location + * \param r_color: returned RGB float colors + * \return Success value (true == successful and supported by platform) + */ + virtual GHOST_TSuccess getPixelAtCursor(float r_color[3]) const = 0; + #ifdef WITH_INPUT_NDOF /** * Sets 3D mouse deadzone diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 0bd7c72749a..19aebb3349f 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -107,6 +107,10 @@ typedef enum { * Set when there is support for system clipboard copy/paste. */ GHOST_kCapabilityClipboardImages = (1 << 4), + /** + * Support for sampling a color outside of the Blender windows. + */ + GHOST_kCapabilityDesktopSample = (1 << 5), } GHOST_TCapabilityFlag; /** @@ -115,7 +119,8 @@ typedef enum { */ #define GHOST_CAPABILITY_FLAG_ALL \ (GHOST_kCapabilityCursorWarp | GHOST_kCapabilityWindowPosition | \ - GHOST_kCapabilityPrimaryClipboard | GHOST_kCapabilityGPUReadFrontBuffer) + GHOST_kCapabilityPrimaryClipboard | GHOST_kCapabilityGPUReadFrontBuffer | \ + GHOST_kCapabilityClipboardImages | GHOST_kCapabilityDesktopSample) /* Xtilt and Ytilt represent how much the pen is tilted away from * vertically upright in either the X or Y direction, with X and Y the diff --git a/intern/ghost/intern/GHOST_C-api.cc b/intern/ghost/intern/GHOST_C-api.cc index efd41f3127b..180585de9c3 100644 --- a/intern/ghost/intern/GHOST_C-api.cc +++ b/intern/ghost/intern/GHOST_C-api.cc @@ -768,6 +768,12 @@ void GHOST_SetTabletAPI(GHOST_SystemHandle systemhandle, GHOST_TTabletAPI api) system->setTabletAPI(api); } +GHOST_TSuccess GHOST_GetPixelAtCursor(float r_color[3]) +{ + GHOST_ISystem *system = GHOST_ISystem::getSystem(); + return system->getPixelAtCursor(r_color); +} + int32_t GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle) { return ((GHOST_Rect *)rectanglehandle)->getWidth(); diff --git a/intern/ghost/intern/GHOST_System.cc b/intern/ghost/intern/GHOST_System.cc index 3436ca652cd..745fe377505 100644 --- a/intern/ghost/intern/GHOST_System.cc +++ b/intern/ghost/intern/GHOST_System.cc @@ -340,6 +340,11 @@ GHOST_TTabletAPI GHOST_System::getTabletAPI() return m_tabletAPI; } +GHOST_TSuccess GHOST_System::getPixelAtCursor(float[3] /* r_color */) const +{ + return GHOST_kFailure; +} + #ifdef WITH_INPUT_NDOF void GHOST_System::setNDOFDeadZone(float deadzone) { diff --git a/intern/ghost/intern/GHOST_System.hh b/intern/ghost/intern/GHOST_System.hh index bba17c44bb0..692d25850c9 100644 --- a/intern/ghost/intern/GHOST_System.hh +++ b/intern/ghost/intern/GHOST_System.hh @@ -256,6 +256,13 @@ class GHOST_System : public GHOST_ISystem { virtual void setTabletAPI(GHOST_TTabletAPI api); GHOST_TTabletAPI getTabletAPI(void); + /** + * Get the color of the pixel at the current mouse cursor location + * \param r_color: returned RGB float colors + * \return Success value (true == successful and supported by platform) + */ + GHOST_TSuccess getPixelAtCursor(float r_color[3]) const; + #ifdef WITH_INPUT_NDOF /*************************************************************************************** * Access to 3D mouse. diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index a77e1882408..52ce9413d6c 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -921,6 +921,8 @@ GHOST_TCapabilityFlag GHOST_SystemCocoa::getCapabilities() const ~( /* Cocoa has no support for a primary selection clipboard. */ GHOST_kCapabilityPrimaryClipboard | + /* Cocoa has no support for sampling colors from the desktop. */ + GHOST_kCapabilityDesktopSample | /* This Cocoa back-end has not yet implemented image copy/paste. */ GHOST_kCapabilityClipboardImages)); } diff --git a/intern/ghost/intern/GHOST_SystemHeadless.hh b/intern/ghost/intern/GHOST_SystemHeadless.hh index f75e0e8439a..a2f1b9dfd8e 100644 --- a/intern/ghost/intern/GHOST_SystemHeadless.hh +++ b/intern/ghost/intern/GHOST_SystemHeadless.hh @@ -50,6 +50,7 @@ class GHOST_SystemHeadless : public GHOST_System { /* No windowing functionality supported. */ ~(GHOST_kCapabilityWindowPosition | GHOST_kCapabilityCursorWarp | GHOST_kCapabilityPrimaryClipboard | + GHOST_kCapabilityDesktopSample | GHOST_kCapabilityClipboardImages)); } char *getClipboard(bool /*selection*/) const override diff --git a/intern/ghost/intern/GHOST_SystemSDL.cc b/intern/ghost/intern/GHOST_SystemSDL.cc index b756f6cee02..43900725863 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cc +++ b/intern/ghost/intern/GHOST_SystemSDL.cc @@ -772,6 +772,8 @@ GHOST_TCapabilityFlag GHOST_SystemSDL::getCapabilities() const ~( /* This SDL back-end has not yet implemented primary clipboard. */ GHOST_kCapabilityPrimaryClipboard | + /* This SDL back-end has not yet implemented color sampling the desktop. */ + GHOST_kCapabilityDesktopSample | /* This SDL back-end has not yet implemented image copy/paste. */ GHOST_kCapabilityClipboardImages)); } diff --git a/intern/ghost/intern/GHOST_SystemWayland.cc b/intern/ghost/intern/GHOST_SystemWayland.cc index 2f947b87510..de912afe6f7 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cc +++ b/intern/ghost/intern/GHOST_SystemWayland.cc @@ -6770,6 +6770,8 @@ GHOST_TCapabilityFlag GHOST_SystemWayland::getCapabilities() const * screen-shot and eye-dropper sampling logic, both operations where the overhead * is negligible. */ GHOST_kCapabilityGPUReadFrontBuffer | + /* This WAYLAND back-end has not yet implemented desktop color sample. */ + GHOST_kCapabilityDesktopSample | /* This WAYLAND back-end has not yet implemented image copy/paste. */ GHOST_kCapabilityClipboardImages)); } diff --git a/intern/ghost/intern/GHOST_SystemWin32.cc b/intern/ghost/intern/GHOST_SystemWin32.cc index 6eaf9cf9d03..58b4e910d54 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cc +++ b/intern/ghost/intern/GHOST_SystemWin32.cc @@ -448,6 +448,31 @@ GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(int32_t x, int32_t y) return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure; } +GHOST_TSuccess GHOST_SystemWin32::getPixelAtCursor(float r_color[3]) const +{ + POINT point; + if (!GetCursorPos(&point)) { + return GHOST_kFailure; + } + + HDC dc = GetDC(NULL); + if (dc == NULL) { + return GHOST_kFailure; + } + + COLORREF color = GetPixel(dc, point.x, point.y); + ReleaseDC(NULL, dc); + + if (color == CLR_INVALID) { + return GHOST_kFailure; + } + + r_color[0] = GetRValue(color) / 255.0f; + r_color[1] = GetGValue(color) / 255.0f; + r_color[2] = GetBValue(color) / 255.0f; + return GHOST_kSuccess; +} + GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys &keys) const { /* `GetAsyncKeyState` returns the current interrupt-level state of the hardware, which is needed diff --git a/intern/ghost/intern/GHOST_SystemWin32.hh b/intern/ghost/intern/GHOST_SystemWin32.hh index 5437e3667b7..c11d41c3c99 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.hh +++ b/intern/ghost/intern/GHOST_SystemWin32.hh @@ -182,6 +182,13 @@ class GHOST_SystemWin32 : public GHOST_System { */ GHOST_TSuccess setCursorPosition(int32_t x, int32_t y); + /** + * Get the color of the pixel at the current mouse cursor location + * \param r_color: returned RGB float colors + * \return Success value (true == successful and supported by platform) + */ + GHOST_TSuccess getPixelAtCursor(float r_color[3]) const; + /*************************************************************************************** ** Access to mouse button and keyboard states. ***************************************************************************************/ diff --git a/intern/ghost/intern/GHOST_SystemX11.cc b/intern/ghost/intern/GHOST_SystemX11.cc index b5f01e812b2..d1c50adf856 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cc +++ b/intern/ghost/intern/GHOST_SystemX11.cc @@ -1690,6 +1690,8 @@ GHOST_TCapabilityFlag GHOST_SystemX11::getCapabilities() const { return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL & ~( + /* No support yet for desktop sampling. */ + GHOST_kCapabilityDesktopSample | /* No support yet for image copy/paste. */ GHOST_kCapabilityClipboardImages)); } diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_color.cc b/source/blender/editors/interface/eyedroppers/eyedropper_color.cc index 5709fd098f5..f26c0e3dbf0 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_color.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_color.cc @@ -315,45 +315,35 @@ static bool eyedropper_cryptomatte_sample_fl(bContext *C, void eyedropper_color_sample_fl(bContext *C, const int m_xy[2], float r_col[3]) { - /* we could use some clever */ - Main *bmain = CTX_data_main(C); - const char *display_device = CTX_data_scene(C)->display_settings.display_device; - ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); + wmWindowManager *wm = CTX_wm_manager(C); + ScrArea *area = nullptr; int mval[2]; - wmWindow *win; - ScrArea *area; - datadropper_win_area_find(C, m_xy, mval, &win, &area); + wmWindow *win = WM_window_find_under_cursor(CTX_wm_window(C), m_xy, mval); + if (win) { + bScreen *screen = WM_window_get_active_screen(win); + area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mval); + } if (area) { - if (area->spacetype == SPACE_IMAGE) { - ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mval); - if (region) { + ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mval); + if (region) { + const int region_mval[2] = {mval[0] - region->winrct.xmin, mval[1] - region->winrct.ymin}; + if (area->spacetype == SPACE_IMAGE) { SpaceImage *sima = static_cast(area->spacedata.first); - const int region_mval[2] = {mval[0] - region->winrct.xmin, mval[1] - region->winrct.ymin}; - if (ED_space_image_color_sample(sima, region, region_mval, r_col, nullptr)) { return; } } - } - else if (area->spacetype == SPACE_NODE) { - ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mval); - if (region) { + else if (area->spacetype == SPACE_NODE) { SpaceNode *snode = static_cast(area->spacedata.first); - const int region_mval[2] = {mval[0] - region->winrct.xmin, mval[1] - region->winrct.ymin}; - + Main *bmain = CTX_data_main(C); if (ED_space_node_color_sample(bmain, snode, region, region_mval, r_col)) { return; } } - } - else if (area->spacetype == SPACE_CLIP) { - ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mval); - if (region) { + else if (area->spacetype == SPACE_CLIP) { SpaceClip *sc = static_cast(area->spacedata.first); - const int region_mval[2] = {mval[0] - region->winrct.xmin, mval[1] - region->winrct.ymin}; - if (ED_space_clip_color_sample(sc, region, region_mval, r_col)) { return; } @@ -361,13 +351,22 @@ void eyedropper_color_sample_fl(bContext *C, const int m_xy[2], float r_col[3]) } } - if (win) { - WM_window_pixels_read_sample(C, win, mval, r_col); - IMB_colormanagement_display_to_scene_linear_v3(r_col, display); - } - else { - zero_v3(r_col); + if (!(WM_capabilities_flag() & WM_CAPABILITY_DESKTOP_SAMPLE && + WM_desktop_cursor_sample_read(r_col))) + { + if (win) { + if (!WM_window_pixels_read_sample(C, win, mval, r_col)) { + WM_window_pixels_read_sample_from_offscreen(C, win, mval, r_col); + } + } + else { + zero_v3(r_col); + } } + + const char *display_device = CTX_data_scene(C)->display_settings.display_device; + ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); + IMB_colormanagement_display_to_scene_linear_v3(r_col, display); } /* sets the sample color RGB, maintaining A */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 1e3166f22ea..cf259bfb200 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -173,6 +173,8 @@ typedef enum eWM_CapabilitiesFlag { WM_CAPABILITY_GPU_FRONT_BUFFER_READ = (1 << 3), /** Ability to copy/paste system clipboard images. */ WM_CAPABILITY_CLIPBOARD_IMAGES = (1 << 4), + /** Ability to sample a color outside of Blender windows. */ + WM_CAPABILITY_DESKTOP_SAMPLE = (1 << 5), /** The initial value, indicates the value needs to be set by inspecting GHOST. */ WM_CAPABILITY_INITIALIZED = (1 << 31), } eWM_CapabilitiesFlag; @@ -197,6 +199,12 @@ wmWindow *WM_window_find_under_cursor(wmWindow *win, const int mval[2], int r_mv */ wmWindow *WM_window_find_by_area(wmWindowManager *wm, const struct ScrArea *area); +/** + * Return the color of the pixel at the current mouse cursor position on the desktop, whether in a + * Blender window or not. Returns false on failure or if not supported by the platform. + */ +bool WM_desktop_cursor_sample_read(float r_col[3]); + /** * Read pixels from the front-buffer (fast). * diff --git a/source/blender/windowmanager/intern/wm_draw.cc b/source/blender/windowmanager/intern/wm_draw.cc index ccf7601563d..62e289cad09 100644 --- a/source/blender/windowmanager/intern/wm_draw.cc +++ b/source/blender/windowmanager/intern/wm_draw.cc @@ -1378,6 +1378,11 @@ bool WM_window_pixels_read_sample(bContext *C, wmWindow *win, const int pos[2], return WM_window_pixels_read_sample_from_offscreen(C, win, pos, r_col); } +bool WM_desktop_cursor_sample_read(float r_col[3]) +{ + return GHOST_GetPixelAtCursor(r_col); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_window.cc b/source/blender/windowmanager/intern/wm_window.cc index 02d31f67fbe..108041c1929 100644 --- a/source/blender/windowmanager/intern/wm_window.cc +++ b/source/blender/windowmanager/intern/wm_window.cc @@ -1888,6 +1888,9 @@ eWM_CapabilitiesFlag WM_capabilities_flag() if (ghost_flag & GHOST_kCapabilityClipboardImages) { flag |= WM_CAPABILITY_CLIPBOARD_IMAGES; } + if (ghost_flag & GHOST_kCapabilityDesktopSample) { + flag |= WM_CAPABILITY_DESKTOP_SAMPLE; + } return flag; } -- 2.30.2 From d6307ed2224b46f7356dfedfd6271ae98ed11b04 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Tue, 15 Aug 2023 14:28:33 -0700 Subject: [PATCH 2/2] "RBG" -> "sRGB". Color Management Change. --- intern/ghost/GHOST_C-api.h | 2 +- intern/ghost/GHOST_ISystem.hh | 2 +- intern/ghost/intern/GHOST_System.hh | 2 +- intern/ghost/intern/GHOST_SystemWin32.hh | 2 +- .../interface/eyedroppers/eyedropper_color.cc | 30 ++++++++++--------- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index d246dd1f980..028fa2cc263 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -766,7 +766,7 @@ extern void GHOST_SetTabletAPI(GHOST_SystemHandle systemhandle, GHOST_TTabletAPI /** * Get the color of the pixel at the current mouse cursor location - * \param r_color: returned RGB float colors + * \param r_color: returned sRGB float colors * \return Success value (true == successful and supported by platform) */ extern GHOST_TSuccess GHOST_GetPixelAtCursor(float r_color[3]); diff --git a/intern/ghost/GHOST_ISystem.hh b/intern/ghost/GHOST_ISystem.hh index 582a2e9932e..0e145c9eac6 100644 --- a/intern/ghost/GHOST_ISystem.hh +++ b/intern/ghost/GHOST_ISystem.hh @@ -443,7 +443,7 @@ class GHOST_ISystem { /** * Get the color of the pixel at the current mouse cursor location - * \param r_color: returned RGB float colors + * \param r_color: returned sRGB float colors * \return Success value (true == successful and supported by platform) */ virtual GHOST_TSuccess getPixelAtCursor(float r_color[3]) const = 0; diff --git a/intern/ghost/intern/GHOST_System.hh b/intern/ghost/intern/GHOST_System.hh index 692d25850c9..bb4688f865f 100644 --- a/intern/ghost/intern/GHOST_System.hh +++ b/intern/ghost/intern/GHOST_System.hh @@ -258,7 +258,7 @@ class GHOST_System : public GHOST_ISystem { /** * Get the color of the pixel at the current mouse cursor location - * \param r_color: returned RGB float colors + * \param r_color: returned sRGB float colors * \return Success value (true == successful and supported by platform) */ GHOST_TSuccess getPixelAtCursor(float r_color[3]) const; diff --git a/intern/ghost/intern/GHOST_SystemWin32.hh b/intern/ghost/intern/GHOST_SystemWin32.hh index c11d41c3c99..8fa578f7cd3 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.hh +++ b/intern/ghost/intern/GHOST_SystemWin32.hh @@ -184,7 +184,7 @@ class GHOST_SystemWin32 : public GHOST_System { /** * Get the color of the pixel at the current mouse cursor location - * \param r_color: returned RGB float colors + * \param r_color: returned sRGB float colors * \return Success value (true == successful and supported by platform) */ GHOST_TSuccess getPixelAtCursor(float r_color[3]) const; diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_color.cc b/source/blender/editors/interface/eyedroppers/eyedropper_color.cc index 69ab96727de..ddd66202f9b 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_color.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_color.cc @@ -351,22 +351,24 @@ void eyedropper_color_sample_fl(bContext *C, const int m_xy[2], float r_col[3]) } } - if (!(WM_capabilities_flag() & WM_CAPABILITY_DESKTOP_SAMPLE && - WM_desktop_cursor_sample_read(r_col))) - { - if (win) { - if (!WM_window_pixels_read_sample(C, win, mval, r_col)) { - WM_window_pixels_read_sample_from_offscreen(C, win, mval, r_col); - } - } - else { - zero_v3(r_col); + if (win) { + /* Other areas within a Blender window. */ + if (!WM_window_pixels_read_sample(C, win, mval, r_col)) { + WM_window_pixels_read_sample_from_offscreen(C, win, mval, r_col); } + const char *display_device = CTX_data_scene(C)->display_settings.display_device; + ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); + IMB_colormanagement_display_to_scene_linear_v3(r_col, display); + } + else if ((WM_capabilities_flag() & WM_CAPABILITY_DESKTOP_SAMPLE) && + WM_desktop_cursor_sample_read(r_col)) + { + /* Outside of the Blender window if we support it. */ + IMB_colormanagement_srgb_to_scene_linear_v3(r_col, r_col); + } + else { + zero_v3(r_col); } - - const char *display_device = CTX_data_scene(C)->display_settings.display_device; - ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); - IMB_colormanagement_display_to_scene_linear_v3(r_col, display); } /* sets the sample color RGB, maintaining A */ -- 2.30.2