diff --git a/Source/Editor/Utilities/ScreenUtilities.cpp b/Source/Editor/Utilities/ScreenUtilities.cpp deleted file mode 100644 index b35e2817c..000000000 --- a/Source/Editor/Utilities/ScreenUtilities.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) Wojciech Figat. All rights reserved. - -#include "ScreenUtilities.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" -#include "Engine/Core/Log.h" -#include "Engine/Profiler/ProfilerCPU.h" - -Delegate ScreenUtilities::PickColorDone; - -#if PLATFORM_WINDOWS - -#include - -#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 = ScreenUtilities::GetColorAt(cursorPos); - ScreenUtilities::PickColorDone(colorPicked); - return 1; - } - return CallNextHookEx(NULL, nCode, wParam, lParam); -} - -Color32 ScreenUtilities::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 ScreenUtilities::PickColor() -{ - MouseCallbackHook = SetWindowsHookEx(WH_MOUSE_LL, OnScreenUtilsMouseCallback, NULL, NULL); - if (MouseCallbackHook == NULL) - { - LOG(Warning, "Failed to set mouse hook."); - LOG(Warning, "Error: {0}", GetLastError()); - } -} - -#elif PLATFORM_LINUX - -#include "Engine/Platform/Linux/LinuxPlatform.h" -#include "Engine/Platform/Linux/IncludeX11.h" - -Color32 ScreenUtilities::GetColorAt(const Float2& pos) -{ - X11::XColor color; - - X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); - int defaultScreen = X11::XDefaultScreen(display); - - X11::XImage* image; - image = X11::XGetImage(display, X11::XRootWindow(display, defaultScreen), (int)pos.X, (int)pos.Y, 1, 1, AllPlanes, XYPixmap); - 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; -} - -void OnScreenUtilsXEventCallback(void* eventPtr) -{ - X11::XEvent* event = (X11::XEvent*) eventPtr; - X11::Display* display = (X11::Display*)LinuxPlatform::GetXDisplay(); - if (event->type == ButtonPress) - { - const Float2 cursorPos = Platform::GetMousePosition(); - const Color32 colorPicked = ScreenUtilities::GetColorAt(cursorPos); - X11::XUngrabPointer(display, CurrentTime); - ScreenUtilities::PickColorDone(colorPicked); - LinuxPlatform::xEventRecieved.Unbind(OnScreenUtilsXEventCallback); - } -} - -void ScreenUtilities::PickColor() -{ - PROFILE_CPU(); - X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); - 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::xEventRecieved.Bind(OnScreenUtilsXEventCallback); -} - -#elif PLATFORM_MAC - -#include -#include - -Color32 ScreenUtilities::GetColorAt(const Float2& pos) -{ - // TODO: implement ScreenUtilities for macOS - return { 0, 0, 0, 255 }; -} - -void ScreenUtilities::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/Editor/Utilities/ScreenUtilities.h b/Source/Editor/Utilities/ScreenUtilities.h index 421ecf22f..be946dcae 100644 --- a/Source/Editor/Utilities/ScreenUtilities.h +++ b/Source/Editor/Utilities/ScreenUtilities.h @@ -2,32 +2,4 @@ #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" - -/// -/// Platform-dependent screen utilities. -/// -API_CLASS(Static) class FLAXENGINE_API ScreenUtilities -{ - DECLARE_SCRIPTING_TYPE_MINIMAL(ScreenUtilities); - - /// - /// Gets the pixel color at the specified coordinates. - /// - /// Screen-space coordinate to read. - /// Pixel color at the specified coordinates. - API_FUNCTION() static Color32 GetColorAt(const Float2& pos); - - /// - /// 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; -}; +#include "Engine/Platform/ScreenUtilities.h" diff --git a/Source/Engine/Platform/Base/ScreenUtilitiesBase.h b/Source/Engine/Platform/Base/ScreenUtilitiesBase.h new file mode 100644 index 000000000..635e4441e --- /dev/null +++ b/Source/Engine/Platform/Base/ScreenUtilitiesBase.h @@ -0,0 +1,42 @@ +// Copyright (c) 2012-2024 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. + 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/Linux/LinuxScreenUtilities.cpp b/Source/Engine/Platform/Linux/LinuxScreenUtilities.cpp new file mode 100644 index 000000000..288bb4b90 --- /dev/null +++ b/Source/Engine/Platform/Linux/LinuxScreenUtilities.cpp @@ -0,0 +1,94 @@ +// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. + +#if USE_EDITOR && 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/Profiler/ProfilerCPU.h" +#include "Engine/Platform/Linux/LinuxPlatform.h" +#include "Engine/Platform/Linux/IncludeX11.h" + +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... + // TODO: Fallback to Wayland implementation here? + return Color32::Black; + } + } + else + { + // TODO: Wayland + ASSERT(false); + } +} + +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); + } + else + { + // TODO: Wayland + ASSERT(false); + } +} + +#endif diff --git a/Source/Engine/Platform/Linux/LinuxScreenUtilities.h b/Source/Engine/Platform/Linux/LinuxScreenUtilities.h new file mode 100644 index 000000000..8de2141f0 --- /dev/null +++ b/Source/Engine/Platform/Linux/LinuxScreenUtilities.h @@ -0,0 +1,25 @@ +// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. + +#pragma once + +#if USE_EDITOR && PLATFORM_LINUX + +#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 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 new file mode 100644 index 000000000..a482362f0 --- /dev/null +++ b/Source/Engine/Platform/Mac/MacScreenUtilities.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2012-2024 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 new file mode 100644 index 000000000..8a9610d7e --- /dev/null +++ b/Source/Engine/Platform/Mac/MacScreenUtilities.h @@ -0,0 +1,25 @@ +// Copyright (c) 2012-2024 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 new file mode 100644 index 000000000..c989d7caf --- /dev/null +++ b/Source/Engine/Platform/ScreenUtilities.h @@ -0,0 +1,15 @@ +// Copyright (c) 2012-2024 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 50af4279c..43e8b17f7 100644 --- a/Source/Engine/Platform/Types.h +++ b/Source/Engine/Platform/Types.h @@ -4,8 +4,6 @@ #if PLATFORM_WINDOWS -class WindowsClipboard; -typedef WindowsClipboard Clipboard; class Win32CriticalSection; typedef Win32CriticalSection CriticalSection; class Win32ConditionVariable; @@ -16,21 +14,23 @@ class WindowsFileSystemWatcher; typedef WindowsFileSystemWatcher FileSystemWatcher; class Win32File; typedef Win32File File; -class WindowsPlatform; -typedef WindowsPlatform Platform; class Win32Thread; typedef Win32Thread Thread; +class WindowsClipboard; +typedef WindowsClipboard Clipboard; +class WindowsPlatform; +typedef WindowsPlatform Platform; class WindowsWindow; typedef WindowsWindow Window; class Win32Network; typedef Win32Network Network; class UserBase; typedef UserBase User; +class WindowsScreenUtilities; +typedef WindowsScreenUtilities ScreenUtilities; #elif PLATFORM_UWP -class ClipboardBase; -typedef ClipboardBase Clipboard; class Win32CriticalSection; typedef Win32CriticalSection CriticalSection; class Win32ConditionVariable; @@ -41,10 +41,12 @@ class FileSystemWatcherBase; typedef FileSystemWatcherBase FileSystemWatcher; class Win32File; typedef Win32File File; -class UWPPlatform; -typedef UWPPlatform Platform; class Win32Thread; typedef Win32Thread Thread; +class ClipboardBase; +typedef ClipboardBase Clipboard; +class UWPPlatform; +typedef UWPPlatform Platform; class UWPWindow; typedef UWPWindow Window; class Win32Network; @@ -54,8 +56,6 @@ typedef UserBase User; #elif PLATFORM_LINUX -class LinuxClipboard; -typedef LinuxClipboard Clipboard; class UnixCriticalSection; typedef UnixCriticalSection CriticalSection; class UnixConditionVariable; @@ -66,21 +66,23 @@ class LinuxFileSystemWatcher; typedef LinuxFileSystemWatcher FileSystemWatcher; class UnixFile; typedef UnixFile File; -class LinuxPlatform; -typedef LinuxPlatform Platform; class LinuxThread; typedef LinuxThread Thread; +class LinuxClipboard; +typedef LinuxClipboard Clipboard; +class LinuxPlatform; +typedef LinuxPlatform Platform; class LinuxWindow; typedef LinuxWindow Window; class UnixNetwork; typedef UnixNetwork Network; class UserBase; typedef UserBase User; +class LinuxScreenUtilities; +typedef LinuxScreenUtilities ScreenUtilities; #elif PLATFORM_PS4 -class ClipboardBase; -typedef ClipboardBase Clipboard; class UnixCriticalSection; typedef UnixCriticalSection CriticalSection; class UnixConditionVariable; @@ -91,10 +93,12 @@ class FileSystemWatcherBase; typedef FileSystemWatcherBase FileSystemWatcher; class UnixFile; typedef UnixFile File; -class PS4Platform; -typedef PS4Platform Platform; class PS4Thread; typedef PS4Thread Thread; +class ClipboardBase; +typedef ClipboardBase Clipboard; +class PS4Platform; +typedef PS4Platform Platform; class PS4Window; typedef PS4Window Window; class PS4Network; @@ -104,8 +108,6 @@ typedef PS4User User; #elif PLATFORM_PS5 -class ClipboardBase; -typedef ClipboardBase Clipboard; class UnixCriticalSection; typedef UnixCriticalSection CriticalSection; class UnixConditionVariable; @@ -116,10 +118,12 @@ class FileSystemWatcherBase; typedef FileSystemWatcherBase FileSystemWatcher; class UnixFile; typedef UnixFile File; -class PS5Platform; -typedef PS5Platform Platform; +class ClipboardBase; +typedef ClipboardBase Clipboard; class PS5Thread; typedef PS5Thread Thread; +class PS5Platform; +typedef PS5Platform Platform; class PS5Window; typedef PS5Window Window; class PS5Network; @@ -129,8 +133,6 @@ typedef PS5User User; #elif PLATFORM_XBOX_ONE -class ClipboardBase; -typedef ClipboardBase Clipboard; class Win32CriticalSection; typedef Win32CriticalSection CriticalSection; class Win32ConditionVariable; @@ -141,10 +143,12 @@ class FileSystemWatcherBase; typedef FileSystemWatcherBase FileSystemWatcher; class Win32File; typedef Win32File File; -class XboxOnePlatform; -typedef XboxOnePlatform Platform; class Win32Thread; typedef Win32Thread Thread; +class ClipboardBase; +typedef ClipboardBase Clipboard; +class XboxOnePlatform; +typedef XboxOnePlatform Platform; class GDKWindow; typedef GDKWindow Window; class Win32Network; @@ -154,8 +158,6 @@ typedef GDKUser User; #elif PLATFORM_XBOX_SCARLETT -class ClipboardBase; -typedef ClipboardBase Clipboard; class Win32CriticalSection; typedef Win32CriticalSection CriticalSection; class Win32ConditionVariable; @@ -166,10 +168,12 @@ class FileSystemWatcherBase; typedef FileSystemWatcherBase FileSystemWatcher; class Win32File; typedef Win32File File; -class XboxScarlettPlatform; -typedef XboxScarlettPlatform Platform; class Win32Thread; typedef Win32Thread Thread; +class ClipboardBase; +typedef ClipboardBase Clipboard; +class XboxScarlettPlatform; +typedef XboxScarlettPlatform Platform; class GDKWindow; typedef GDKWindow Window; class Win32Network; @@ -179,8 +183,6 @@ typedef GDKUser User; #elif PLATFORM_ANDROID -class ClipboardBase; -typedef ClipboardBase Clipboard; class UnixCriticalSection; typedef UnixCriticalSection CriticalSection; class UnixConditionVariable; @@ -191,10 +193,12 @@ class FileSystemWatcherBase; typedef FileSystemWatcherBase FileSystemWatcher; class AndroidFile; typedef AndroidFile File; -class AndroidPlatform; -typedef AndroidPlatform Platform; class AndroidThread; typedef AndroidThread Thread; +class ClipboardBase; +typedef ClipboardBase Clipboard; +class AndroidPlatform; +typedef AndroidPlatform Platform; class AndroidWindow; typedef AndroidWindow Window; class UnixNetwork; @@ -204,8 +208,6 @@ typedef UserBase User; #elif PLATFORM_SWITCH -class ClipboardBase; -typedef ClipboardBase Clipboard; class SwitchCriticalSection; typedef SwitchCriticalSection CriticalSection; class SwitchConditionVariable; @@ -216,10 +218,12 @@ class FileSystemWatcherBase; typedef FileSystemWatcherBase FileSystemWatcher; class SwitchFile; typedef SwitchFile File; -class SwitchPlatform; -typedef SwitchPlatform Platform; class SwitchThread; typedef SwitchThread Thread; +class ClipboardBase; +typedef ClipboardBase Clipboard; +class SwitchPlatform; +typedef SwitchPlatform Platform; class SwitchWindow; typedef SwitchWindow Window; class SwitchNetwork; @@ -229,8 +233,6 @@ typedef SwitchUser User; #elif PLATFORM_MAC -class MacClipboard; -typedef MacClipboard Clipboard; class UnixCriticalSection; typedef UnixCriticalSection CriticalSection; class UnixConditionVariable; @@ -241,21 +243,23 @@ class MacFileSystemWatcher; typedef MacFileSystemWatcher FileSystemWatcher; class UnixFile; typedef UnixFile File; -class MacPlatform; -typedef MacPlatform Platform; class AppleThread; typedef AppleThread Thread; +class MacClipboard; +typedef MacClipboard Clipboard; +class MacPlatform; +typedef MacPlatform Platform; class MacWindow; typedef MacWindow Window; class UnixNetwork; typedef UnixNetwork Network; class UserBase; typedef UserBase User; +class MacScreenUtilities; +typedef MacScreenUtilities ScreenUtilities; #elif PLATFORM_IOS -class ClipboardBase; -typedef ClipboardBase Clipboard; class UnixCriticalSection; typedef UnixCriticalSection CriticalSection; class UnixConditionVariable; @@ -266,10 +270,12 @@ class FileSystemWatcherBase; typedef FileSystemWatcherBase FileSystemWatcher; class iOSFile; typedef iOSFile File; -class iOSPlatform; -typedef iOSPlatform Platform; class AppleThread; typedef AppleThread Thread; +class ClipboardBase; +typedef ClipboardBase Clipboard; +class iOSPlatform; +typedef iOSPlatform Platform; class iOSWindow; typedef iOSWindow Window; class UnixNetwork; diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtilities.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtilities.cpp new file mode 100644 index 000000000..611781188 --- /dev/null +++ b/Source/Engine/Platform/Windows/WindowsScreenUtilities.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. + +#if USE_EDITOR && 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 new file mode 100644 index 000000000..d0c2da6d3 --- /dev/null +++ b/Source/Engine/Platform/Windows/WindowsScreenUtilities.h @@ -0,0 +1,25 @@ +// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. + +#pragma once + +#if USE_EDITOR && 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