From 019a9f6089518702314838e4a16726ff1cb2db17 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 11 Feb 2026 17:59:11 +0100 Subject: [PATCH] Merge `ScreenUtilities` into `Platform` for simplicity and make it Editor-only #2800 --- .../Editor/GUI/Dialogs/ColorPickerDialog.cs | 21 ++- Source/Editor/Utilities/ScreenUtilities.h | 6 - Source/Engine/Platform/Base/PlatformBase.cpp | 20 +++ Source/Engine/Platform/Base/PlatformBase.h | 20 +++ .../Platform/Base/ScreenUtilitiesBase.h | 42 ----- Source/Engine/Platform/Base/WindowBase.cpp | 5 +- .../Engine/Platform/Linux/LinuxPlatform.cpp | 156 +++++++++++++++++ Source/Engine/Platform/Linux/LinuxPlatform.h | 4 + .../Platform/Linux/LinuxScreenUtilities.cpp | 164 ------------------ .../Platform/Linux/LinuxScreenUtilities.h | 24 --- .../Platform/Mac/MacScreenUtilities.cpp | 29 ---- .../Engine/Platform/Mac/MacScreenUtilities.h | 25 --- Source/Engine/Platform/ScreenUtilities.h | 15 -- Source/Engine/Platform/Types.h | 22 --- .../Platform/Windows/WindowsPlatform.cpp | 45 +++++ .../Engine/Platform/Windows/WindowsPlatform.h | 4 + .../Windows/WindowsScreenUtilities.cpp | 54 ------ .../Platform/Windows/WindowsScreenUtilities.h | 25 --- 18 files changed, 264 insertions(+), 417 deletions(-) delete mode 100644 Source/Editor/Utilities/ScreenUtilities.h delete mode 100644 Source/Engine/Platform/Base/ScreenUtilitiesBase.h delete mode 100644 Source/Engine/Platform/Linux/LinuxScreenUtilities.cpp delete mode 100644 Source/Engine/Platform/Linux/LinuxScreenUtilities.h delete mode 100644 Source/Engine/Platform/Mac/MacScreenUtilities.cpp delete mode 100644 Source/Engine/Platform/Mac/MacScreenUtilities.h delete mode 100644 Source/Engine/Platform/ScreenUtilities.h delete mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtilities.cpp delete mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtilities.h diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index 84feeabd0..d028b7c7c 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -303,19 +303,22 @@ namespace FlaxEditor.GUI.Dialogs if (_activeEyedropper) { _activeEyedropper = false; - Color color = colorPicked; - if (_linear) - color = color.ToLinear(); - SelectedColor = color; - ScreenUtilities.PickColorDone -= OnColorPicked; + if (colorPicked != Color.Transparent) + { + Color color = colorPicked; + if (_linear) + color = color.ToLinear(); + SelectedColor = color; + } + Platform.PickScreenColorDone -= OnColorPicked; } } private void OnEyedropStart() { _activeEyedropper = true; - ScreenUtilities.PickColor(); - ScreenUtilities.PickColorDone += OnColorPicked; + Platform.PickScreenColor(); + Platform.PickScreenColorDone += OnColorPicked; } private void OnRGBAChanged() @@ -353,7 +356,7 @@ namespace FlaxEditor.GUI.Dialogs { // Try reading the color under the cursor in realtime if supported by the platform Float2 mousePosition = Platform.MousePosition; - Color color = ScreenUtilities.GetColorAt(mousePosition); + Color color = Platform.GetScreenColorAt(mousePosition); if (color != Color.Transparent) { if (_linear) @@ -441,7 +444,7 @@ namespace FlaxEditor.GUI.Dialogs { // Cancel eye dropping _activeEyedropper = false; - ScreenUtilities.PickColorDone -= OnColorPicked; + Platform.PickScreenColorDone -= OnColorPicked; return true; } diff --git a/Source/Editor/Utilities/ScreenUtilities.h b/Source/Editor/Utilities/ScreenUtilities.h deleted file mode 100644 index 4e56a09ed..000000000 --- a/Source/Editor/Utilities/ScreenUtilities.h +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#pragma once - -// [Deprecated in v1.12] -#include "Engine/Platform/ScreenUtilities.h" diff --git a/Source/Engine/Platform/Base/PlatformBase.cpp b/Source/Engine/Platform/Base/PlatformBase.cpp index 664eaa964..07d78e46c 100644 --- a/Source/Engine/Platform/Base/PlatformBase.cpp +++ b/Source/Engine/Platform/Base/PlatformBase.cpp @@ -797,6 +797,26 @@ void PlatformBase::CollectCrashData(const String& crashDataFolder, void* context { } +#if USE_EDITOR + +#include "Engine/Core/Math/Color32.h" + +Delegate PlatformBase::PickScreenColorDone; + +Color32 PlatformBase::GetScreenColorAt(const Float2& pos) +{ + // No supported + return Color32::Transparent; +} + +void PlatformBase::PickScreenColor() +{ + // Just return transparent color when not implemented/supported + PickScreenColorDone(Color32::Transparent); +} + +#endif + const Char* ToString(PlatformType type) { switch (type) diff --git a/Source/Engine/Platform/Base/PlatformBase.h b/Source/Engine/Platform/Base/PlatformBase.h index 67cfa4698..87e2217c2 100644 --- a/Source/Engine/Platform/Base/PlatformBase.h +++ b/Source/Engine/Platform/Base/PlatformBase.h @@ -888,6 +888,26 @@ public: // Crash dump data handling static void CollectCrashData(const String& crashDataFolder, void* context = nullptr); + +public: +#if USE_EDITOR + /// + /// Gets the pixel color at the specified coordinates. + /// + /// Screen-space coordinate to read. + /// Pixel color at the specified coordinates, or transparent color when color couldn't be picked up. + API_FUNCTION() static Color32 GetScreenColorAt(const Float2& pos); + + /// + /// Starts async color picking. Color will be returned through PickColorDone event when the action ends (user selected the final color with a mouse). When action is active, GetColorAt can be used to read the current value. + /// + API_FUNCTION() static void PickScreenColor(); + + /// + /// Called when PickColor action is finished. + /// + API_EVENT() static Delegate PickScreenColorDone; +#endif }; extern FLAXENGINE_API const Char* ToString(PlatformType type); diff --git a/Source/Engine/Platform/Base/ScreenUtilitiesBase.h b/Source/Engine/Platform/Base/ScreenUtilitiesBase.h deleted file mode 100644 index b6259c40d..000000000 --- a/Source/Engine/Platform/Base/ScreenUtilitiesBase.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#pragma once - -#include "Engine/Core/Types/BaseTypes.h" -#include "Engine/Core/Math/Color32.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" - -API_INJECT_CODE(cpp, "#include \"Engine/Platform/ScreenUtilities.h\""); - -/// -/// Platform-dependent screen utilities. -/// -API_CLASS(Static, Name="ScreenUtilities", Tag="NativeInvokeUseName") -class FLAXENGINE_API ScreenUtilitiesBase -{ -public: - static struct FLAXENGINE_API ScriptingTypeInitializer TypeInitializer; - - /// - /// Gets the pixel color at the specified coordinates. - /// - /// Screen-space coordinate to read. - /// Pixel color at the specified coordinates, or transparent color when color couldn't be picked up. - API_FUNCTION() static Color32 GetColorAt(const Float2& pos) - { - return Color32::Transparent; - } - - /// - /// Starts async color picking. Color will be returned through PickColorDone event when the actions ends (user selected the final color with a mouse). When action is active, GetColorAt can be used to read the current value. - /// - API_FUNCTION() static void PickColor() - { - } - - /// - /// Called when PickColor action is finished. - /// - API_EVENT() static Delegate PickColorDone; -}; diff --git a/Source/Engine/Platform/Base/WindowBase.cpp b/Source/Engine/Platform/Base/WindowBase.cpp index 86247763f..e76aa4066 100644 --- a/Source/Engine/Platform/Base/WindowBase.cpp +++ b/Source/Engine/Platform/Base/WindowBase.cpp @@ -1,13 +1,14 @@ // Copyright (c) Wojciech Figat. All rights reserved. +#include "Engine/Core/Math/Color32.h" #include "Engine/Platform/Window.h" +#include "Engine/Platform/WindowsManager.h" +#include "Engine/Platform/IGuiData.h" #include "Engine/Engine/Engine.h" #include "Engine/Graphics/RenderTask.h" -#include "Engine/Platform/WindowsManager.h" #include "Engine/Graphics/GPUSwapChain.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Input/Input.h" -#include "Engine/Platform/IGuiData.h" #include "Engine/Scripting/ScriptingType.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Profiler/ProfilerMemory.h" diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp index 98525d306..7d38e0c07 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp +++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp @@ -3164,4 +3164,160 @@ Array LinuxPlatform::GetStackFrames(int32 skipCount, return result; } +#if USE_EDITOR + +#include "Engine/Core/Math/Vector2.h" +#include "Engine/Core/Math/Vector4.h" +#include "Engine/Profiler/ProfilerCPU.h" +#include "Engine/Platform/Linux/LinuxPlatform.h" +#include "Engine/Platform/Linux/IncludeX11.h" + +#if PLATFORM_SDL +#include +#include + +namespace PortalImpl +{ + XdpPortal* Portal = nullptr; + int64 MainLoopReady = 0; + + gpointer GLibMainLoop(gpointer data); + void PickColorCallback(GObject* source, GAsyncResult* result, gpointer data); +} +#endif + +Color32 LinuxPlatform::GetScreenColorAt(const Float2& pos) +{ + X11::Display* display = (X11::Display*)Platform::GetXDisplay(); + if (display) + { + int defaultScreen = X11::XDefaultScreen(display); + X11::Window rootWindow = X11::XRootWindow(display, defaultScreen); + X11::XImage* image = X11::XGetImage(display, rootWindow, (int)pos.X, (int)pos.Y, 1, 1, AllPlanes, XYPixmap); + if (image) + { + X11::XColor color; + color.pixel = XGetPixel(image, 0, 0); + X11::XFree(image); + + X11::XQueryColor(display, X11::XDefaultColormap(display, defaultScreen), &color); + + Color32 outputColor; + outputColor.R = color.red / 256; + outputColor.G = color.green / 256; + outputColor.B = color.blue / 256; + outputColor.A = 255; + return outputColor; + } + else + { + // XWayland doesn't support XGetImage + } + } + + return Color32::Transparent; +} + +void OnScreenUtilsXEventCallback(void* eventPtr) +{ + X11::XEvent* event = (X11::XEvent*)eventPtr; + X11::Display* display = (X11::Display*)Platform::GetXDisplay(); + if (event->type == ButtonPress) + { + const Float2 cursorPos = Platform::GetMousePosition(); + const Color32 colorPicked = LinuxPlatform::GetScreenColorAt(cursorPos); + X11::XUngrabPointer(display, CurrentTime); + PlatformBase::PickScreenColorDone(colorPicked); + LinuxPlatform::xEventReceived.Unbind(OnScreenUtilsXEventCallback); + } +} + +void LinuxPlatform::PickScreenColor() +{ + PROFILE_CPU(); + X11::Display* display = (X11::Display*)Platform::GetXDisplay(); + if (display) + { + X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); + X11::Cursor cursor = XCreateFontCursor(display, 130); + int grabbedPointer = X11::XGrabPointer(display, rootWindow, 0, ButtonPressMask, GrabModeAsync, GrabModeAsync, rootWindow, cursor, CurrentTime); + if (grabbedPointer != GrabSuccess) + { + LOG(Error, "Failed to grab cursor for events."); + X11::XFreeCursor(display, cursor); + return; + } + + X11::XFreeCursor(display, cursor); + LinuxPlatform::xEventReceived.Bind(OnScreenUtilsXEventCallback); + return; + } +#if PLATFORM_SDL + if (PortalImpl::MainLoopReady == 0) + { + // Initialize portal + GError* error = nullptr; + PortalImpl::Portal = xdp_portal_initable_new(&error); + if (error != nullptr) + { + PortalImpl::MainLoopReady = 2; + LOG(Error, "Failed to initialize XDP Portal"); + return; + } + + // Run the GLib main loop in other thread in order to process asynchronous callbacks + g_thread_new(nullptr, PortalImpl::GLibMainLoop, nullptr); + while (Platform::AtomicRead(&PortalImpl::MainLoopReady) != 1) + Platform::Sleep(1); + } + + if (PortalImpl::Portal != nullptr) + { + // Enter color picking mode, the callback receives the final color + xdp_portal_pick_color(PortalImpl::Portal, nullptr, nullptr, PortalImpl::PickColorCallback, nullptr); + } +#endif +} + +#if PLATFORM_SDL + +gpointer PortalImpl::GLibMainLoop(gpointer data) +{ + GMainContext* mainContext = g_main_context_get_thread_default(); + GMainLoop* mainLoop = g_main_loop_new(mainContext, false); + + Platform::AtomicStore(&PortalImpl::MainLoopReady, 1); + + g_main_loop_run(mainLoop); + g_main_loop_unref(mainLoop); + return nullptr; +} + +void PortalImpl::PickColorCallback(GObject* source, GAsyncResult* result, gpointer data) +{ + GError* error = nullptr; + GVariant* variant = xdp_portal_pick_color_finish(PortalImpl::Portal, result, &error); + if (error) + { + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + LOG(Info, "XDP Portal pick color cancelled"); + else + LOG(Error, "XDP Portal pick color failed: {}", String(error->message)); + return; + } + + // The color is stored in a triple double variant, extract the values + Double4 colorDouble; + g_variant_get(variant, "(ddd)", &colorDouble.X, &colorDouble.Y, &colorDouble.Z); + g_variant_unref(variant); + colorDouble.W = 1.0f; + Vector4 colorVector = colorDouble; + Color32 color = Color32(colorVector); + + PlatformBase::PickScreenColorDone(color); +} +#endif + +#endif + #endif diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.h b/Source/Engine/Platform/Linux/LinuxPlatform.h index bb5f85524..422a6dbfa 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.h +++ b/Source/Engine/Platform/Linux/LinuxPlatform.h @@ -155,6 +155,10 @@ public: static void FreeLibrary(void* handle); static void* GetProcAddress(void* handle, const char* symbol); static Array GetStackFrames(int32 skipCount = 0, int32 maxDepth = 60, void* context = nullptr); +#if USE_EDITOR + static Color32 GetScreenColorAt(const Float2& pos); + static void PickScreenColor(); +#endif }; #endif diff --git a/Source/Engine/Platform/Linux/LinuxScreenUtilities.cpp b/Source/Engine/Platform/Linux/LinuxScreenUtilities.cpp deleted file mode 100644 index cd75fe8ef..000000000 --- a/Source/Engine/Platform/Linux/LinuxScreenUtilities.cpp +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#if PLATFORM_LINUX - -#include "Engine/Platform/Types.h" -#include "Engine/Platform/ScreenUtilities.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" -#include "Engine/Core/Log.h" -#include "Engine/Core/Math/Vector4.h" -#include "Engine/Profiler/ProfilerCPU.h" -#include "Engine/Platform/Linux/LinuxPlatform.h" -#include "Engine/Platform/Linux/IncludeX11.h" - -#if PLATFORM_SDL -#include -#include - -namespace PortalImpl -{ - XdpPortal* Portal = nullptr; - int64 MainLoopReady = 0; - - gpointer GLibMainLoop(gpointer data); - void PickColorCallback(GObject* source, GAsyncResult* result, gpointer data); -} -#endif - -Delegate ScreenUtilitiesBase::PickColorDone; - -Color32 LinuxScreenUtilities::GetColorAt(const Float2& pos) -{ - X11::Display* display = (X11::Display*)Platform::GetXDisplay(); - if (display) - { - int defaultScreen = X11::XDefaultScreen(display); - X11::Window rootWindow = X11::XRootWindow(display, defaultScreen); - X11::XImage* image = X11::XGetImage(display, rootWindow, (int)pos.X, (int)pos.Y, 1, 1, AllPlanes, XYPixmap); - if (image) - { - X11::XColor color; - color.pixel = XGetPixel(image, 0, 0); - X11::XFree(image); - - X11::XQueryColor(display, X11::XDefaultColormap(display, defaultScreen), &color); - - Color32 outputColor; - outputColor.R = color.red / 256; - outputColor.G = color.green / 256; - outputColor.B = color.blue / 256; - outputColor.A = 255; - return outputColor; - } - else - { - // XWayland doesn't support XGetImage - } - } - - return Color32::Transparent; -} - -void OnScreenUtilsXEventCallback(void* eventPtr) -{ - X11::XEvent* event = (X11::XEvent*) eventPtr; - X11::Display* display = (X11::Display*)Platform::GetXDisplay(); - if (event->type == ButtonPress) - { - const Float2 cursorPos = Platform::GetMousePosition(); - const Color32 colorPicked = ScreenUtilities::GetColorAt(cursorPos); - X11::XUngrabPointer(display, CurrentTime); - ScreenUtilities::PickColorDone(colorPicked); - LinuxPlatform::xEventReceived.Unbind(OnScreenUtilsXEventCallback); - } -} - -void LinuxScreenUtilities::PickColor() -{ - PROFILE_CPU(); - X11::Display* display = (X11::Display*)Platform::GetXDisplay(); - if (display) - { - X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); - - X11::Cursor cursor = XCreateFontCursor(display, 130); - int grabbedPointer = X11::XGrabPointer(display, rootWindow, 0, ButtonPressMask, GrabModeAsync, GrabModeAsync, rootWindow, cursor, CurrentTime); - if (grabbedPointer != GrabSuccess) - { - LOG(Error, "Failed to grab cursor for events."); - X11::XFreeCursor(display, cursor); - return; - } - - X11::XFreeCursor(display, cursor); - LinuxPlatform::xEventReceived.Bind(OnScreenUtilsXEventCallback); - return; - } -#if PLATFORM_SDL - if (PortalImpl::MainLoopReady == 0) - { - // Initialize portal - GError* error = nullptr; - PortalImpl::Portal = xdp_portal_initable_new(&error); - if (error != nullptr) - { - PortalImpl::MainLoopReady = 2; - LOG(Error, "Failed to initialize XDP Portal"); - return; - } - - // Run the GLib main loop in other thread in order to process asynchronous callbacks - g_thread_new(nullptr, PortalImpl::GLibMainLoop, nullptr); - while (Platform::AtomicRead(&PortalImpl::MainLoopReady) != 1) - Platform::Sleep(1); - } - - if (PortalImpl::Portal != nullptr) - { - // Enter color picking mode, the callback receives the final color - xdp_portal_pick_color(PortalImpl::Portal, nullptr, nullptr, PortalImpl::PickColorCallback, nullptr); - } -#endif -} - -#if PLATFORM_SDL - -gpointer PortalImpl::GLibMainLoop(gpointer data) -{ - GMainContext* mainContext = g_main_context_get_thread_default(); - GMainLoop* mainLoop = g_main_loop_new(mainContext, false); - - Platform::AtomicStore(&PortalImpl::MainLoopReady, 1); - - g_main_loop_run(mainLoop); - g_main_loop_unref(mainLoop); - return nullptr; -} - -void PortalImpl::PickColorCallback(GObject* source, GAsyncResult* result, gpointer data) -{ - GError* error = nullptr; - GVariant* variant = xdp_portal_pick_color_finish(PortalImpl::Portal, result, &error); - if (error) - { - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - LOG(Info, "XDP Portal pick color cancelled"); - else - LOG(Error, "XDP Portal pick color failed: {}", String(error->message)); - return; - } - - // The color is stored in a triple double variant, extract the values - Double4 colorDouble; - g_variant_get(variant, "(ddd)", &colorDouble.X, &colorDouble.Y, &colorDouble.Z); - g_variant_unref(variant); - colorDouble.W = 1.0f; - Vector4 colorVector = colorDouble; - Color32 color = Color32(colorVector); - - ScreenUtilities::PickColorDone(color); -} -#endif - -#endif diff --git a/Source/Engine/Platform/Linux/LinuxScreenUtilities.h b/Source/Engine/Platform/Linux/LinuxScreenUtilities.h deleted file mode 100644 index 27fdb9297..000000000 --- a/Source/Engine/Platform/Linux/LinuxScreenUtilities.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#pragma once - -#if PLATFORM_LINUX - -#include "Engine/Platform/Base/ScreenUtilitiesBase.h" -#include "Engine/Core/Types/BaseTypes.h" -#include "Engine/Core/Math/Color32.h" -#include "Engine/Core/Delegate.h" - -/// -/// Platform-dependent screen utilities. -/// -class FLAXENGINE_API LinuxScreenUtilities : public ScreenUtilitiesBase -{ -public: - - // [ScreenUtilitiesBase] - static Color32 GetColorAt(const Float2& pos); - static void PickColor(); -}; - -#endif diff --git a/Source/Engine/Platform/Mac/MacScreenUtilities.cpp b/Source/Engine/Platform/Mac/MacScreenUtilities.cpp deleted file mode 100644 index 62c405635..000000000 --- a/Source/Engine/Platform/Mac/MacScreenUtilities.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#if USE_EDITOR && PLATFORM_MAC - -#include "Engine/Platform/Types.h" -#include "Engine/Platform/ScreenUtilities.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" -#include "Engine/Core/Log.h" - -#include -#include - -Delegate ScreenUtilitiesBase::PickColorDone; - -Color32 MacScreenUtilities::GetColorAt(const Float2& pos) -{ - // TODO: implement ScreenUtilities for macOS - return { 0, 0, 0, 255 }; -} - -void MacScreenUtilities::PickColor() -{ - // This is what C# calls to start the color picking sequence - // This should stop mouse clicks from working for one click, and that click is on the selected color - // There is a class called NSColorSample that might implement that for you, but maybe not. -} - -#endif diff --git a/Source/Engine/Platform/Mac/MacScreenUtilities.h b/Source/Engine/Platform/Mac/MacScreenUtilities.h deleted file mode 100644 index 4f7ef0347..000000000 --- a/Source/Engine/Platform/Mac/MacScreenUtilities.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#pragma once - -#if USE_EDITOR && PLATFORM_MAC - -#include "Engine/Platform/Base/ScreenUtilitiesBase.h" -#include "Engine/Core/Types/BaseTypes.h" -#include "Engine/Core/Math/Color32.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" - -/// -/// Platform-dependent screen utilities. -/// -class FLAXENGINE_API MacScreenUtilities : public ScreenUtilitiesBase -{ -public: - - // [ScreenUtilitiesBase] - static Color32 GetColorAt(const Float2& pos); - static void PickColor(); -}; - -#endif diff --git a/Source/Engine/Platform/ScreenUtilities.h b/Source/Engine/Platform/ScreenUtilities.h deleted file mode 100644 index 05678f2da..000000000 --- a/Source/Engine/Platform/ScreenUtilities.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#pragma once - -#if PLATFORM_WINDOWS -#include "Windows/WindowsScreenUtilities.h" -#elif PLATFORM_LINUX -#include "Linux/LinuxScreenUtilities.h" -#elif PLATFORM_MAC -#include "Mac/MacScreenUtilities.h" -#else -#include "Base/ScreenUtilitiesBase.h" -#endif - -#include "Types.h" diff --git a/Source/Engine/Platform/Types.h b/Source/Engine/Platform/Types.h index e9917e16a..7a008abc8 100644 --- a/Source/Engine/Platform/Types.h +++ b/Source/Engine/Platform/Types.h @@ -30,8 +30,6 @@ class Win32Network; typedef Win32Network Network; class UserBase; typedef UserBase User; -class WindowsScreenUtilities; -typedef WindowsScreenUtilities ScreenUtilities; #elif PLATFORM_UWP @@ -59,8 +57,6 @@ class Win32Network; typedef Win32Network Network; class UserBase; typedef UserBase User; -class ScreenUtilitiesBase; -typedef ScreenUtilitiesBase ScreenUtilities; #elif PLATFORM_LINUX @@ -90,8 +86,6 @@ class UnixNetwork; typedef UnixNetwork Network; class UserBase; typedef UserBase User; -class LinuxScreenUtilities; -typedef LinuxScreenUtilities ScreenUtilities; #elif PLATFORM_PS4 @@ -119,8 +113,6 @@ class PS4Network; typedef PS4Network Network; class PS4User; typedef PS4User User; -class ScreenUtilitiesBase; -typedef ScreenUtilitiesBase ScreenUtilities; #elif PLATFORM_PS5 @@ -148,8 +140,6 @@ class PS5Network; typedef PS5Network Network; class PS5User; typedef PS5User User; -class ScreenUtilitiesBase; -typedef ScreenUtilitiesBase ScreenUtilities; #elif PLATFORM_XBOX_ONE @@ -177,8 +167,6 @@ class Win32Network; typedef Win32Network Network; class GDKUser; typedef GDKUser User; -class ScreenUtilitiesBase; -typedef ScreenUtilitiesBase ScreenUtilities; #elif PLATFORM_XBOX_SCARLETT @@ -206,8 +194,6 @@ class Win32Network; typedef Win32Network Network; class GDKUser; typedef GDKUser User; -class ScreenUtilitiesBase; -typedef ScreenUtilitiesBase ScreenUtilities; #elif PLATFORM_ANDROID @@ -235,8 +221,6 @@ class UnixNetwork; typedef UnixNetwork Network; class UserBase; typedef UserBase User; -class ScreenUtilitiesBase; -typedef ScreenUtilitiesBase ScreenUtilities; #elif PLATFORM_SWITCH @@ -264,8 +248,6 @@ class SwitchNetwork; typedef SwitchNetwork Network; class SwitchUser; typedef SwitchUser User; -class ScreenUtilitiesBase; -typedef ScreenUtilitiesBase ScreenUtilities; #elif PLATFORM_MAC @@ -295,8 +277,6 @@ class UnixNetwork; typedef UnixNetwork Network; class UserBase; typedef UserBase User; -class MacScreenUtilities; -typedef MacScreenUtilities ScreenUtilities; #elif PLATFORM_IOS @@ -324,8 +304,6 @@ class UnixNetwork; typedef UnixNetwork Network; class UserBase; typedef UserBase User; -class ScreenUtilitiesBase; -typedef ScreenUtilitiesBase ScreenUtilities; #else diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index 5fd6540ee..69c7ad50c 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -1562,4 +1562,49 @@ void WindowsPlatform::CollectCrashData(const String& crashDataFolder, void* cont #endif +#if USE_EDITOR + +#include "Engine/Core/Math/Color32.h" + +WIN_API COLORREF WIN_API_CALLCONV GetPixel(_In_ HDC hdc, _In_ int x, _In_ int y); +#define GetRValue(rgb) (LOBYTE(rgb)) +#define GetGValue(rgb) (LOBYTE(((WORD)(rgb)) >> 8)) +#define GetBValue(rgb) (LOBYTE((rgb) >> 16)) +#pragma comment(lib, "Gdi32.lib") + +static HHOOK MouseCallbackHook; + +LRESULT CALLBACK OnScreenUtilsMouseCallback(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + if (nCode >= 0 && wParam == WM_LBUTTONDOWN) + { + UnhookWindowsHookEx(MouseCallbackHook); + + // Push event with the picked color + const Float2 cursorPos = Platform::GetMousePosition(); + const Color32 colorPicked = PlatformBase::GetScreenColorAt(cursorPos); + PlatformBase::PickScreenColorDone(colorPicked); + return 1; + } + return CallNextHookEx(NULL, nCode, wParam, lParam); +} + +Color32 WindowsPlatform::GetScreenColorAt(const Float2& pos) +{ + PROFILE_CPU(); + HDC deviceContext = GetDC(NULL); + COLORREF color = GetPixel(deviceContext, (int)pos.X, (int)pos.Y); + ReleaseDC(NULL, deviceContext); + return Color32(GetRValue(color), GetGValue(color), GetBValue(color), 255); +} + +void WindowsPlatform::PickScreenColor() +{ + MouseCallbackHook = SetWindowsHookEx(WH_MOUSE_LL, OnScreenUtilsMouseCallback, NULL, NULL); + if (MouseCallbackHook == NULL) + LOG(Warning, "Failed to set mouse hook (GetLastError={})", GetLastError()); +} + +#endif + #endif diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.h b/Source/Engine/Platform/Windows/WindowsPlatform.h index f989701be..eb2d51c3f 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.h +++ b/Source/Engine/Platform/Windows/WindowsPlatform.h @@ -90,6 +90,10 @@ public: static Array GetStackFrames(int32 skipCount = 0, int32 maxDepth = 60, void* context = nullptr); static void CollectCrashData(const String& crashDataFolder, void* context = nullptr); #endif +#if USE_EDITOR + static Color32 GetScreenColorAt(const Float2& pos); + static void PickScreenColor(); +#endif }; #endif diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtilities.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtilities.cpp deleted file mode 100644 index 440963af6..000000000 --- a/Source/Engine/Platform/Windows/WindowsScreenUtilities.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#if PLATFORM_WINDOWS - -#include "Engine/Platform/Types.h" -#include "Engine/Platform/ScreenUtilities.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" -#include "Engine/Core/Log.h" -#include "Engine/Profiler/ProfilerCPU.h" - -#include - -#pragma comment(lib, "Gdi32.lib") - -Delegate ScreenUtilitiesBase::PickColorDone; - -static HHOOK MouseCallbackHook; - -LRESULT CALLBACK OnScreenUtilsMouseCallback(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam) -{ - if (nCode >= 0 && wParam == WM_LBUTTONDOWN) - { - UnhookWindowsHookEx(MouseCallbackHook); - - // Push event with the picked color - const Float2 cursorPos = Platform::GetMousePosition(); - const Color32 colorPicked = ScreenUtilities::GetColorAt(cursorPos); - ScreenUtilities::PickColorDone(colorPicked); - return 1; - } - return CallNextHookEx(NULL, nCode, wParam, lParam); -} - -Color32 WindowsScreenUtilities::GetColorAt(const Float2& pos) -{ - PROFILE_CPU(); - HDC deviceContext = GetDC(NULL); - COLORREF color = GetPixel(deviceContext, (int)pos.X, (int)pos.Y); - ReleaseDC(NULL, deviceContext); - return Color32(GetRValue(color), GetGValue(color), GetBValue(color), 255); -} - -void WindowsScreenUtilities::PickColor() -{ - MouseCallbackHook = SetWindowsHookEx(WH_MOUSE_LL, OnScreenUtilsMouseCallback, NULL, NULL); - if (MouseCallbackHook == NULL) - { - LOG(Warning, "Failed to set mouse hook."); - LOG(Warning, "Error: {0}", GetLastError()); - } -} - -#endif diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtilities.h b/Source/Engine/Platform/Windows/WindowsScreenUtilities.h deleted file mode 100644 index 91abe22fc..000000000 --- a/Source/Engine/Platform/Windows/WindowsScreenUtilities.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#pragma once - -#if PLATFORM_WINDOWS - -#include "Engine/Platform/Base/ScreenUtilitiesBase.h" -#include "Engine/Core/Types/BaseTypes.h" -#include "Engine/Core/Math/Color32.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" - -/// -/// Platform-dependent screen utilities. -/// -class FLAXENGINE_API WindowsScreenUtilities : public ScreenUtilitiesBase -{ -public: - - // [ScreenUtilitiesBase] - static Color32 GetColorAt(const Float2& pos); - static void PickColor(); -}; - -#endif