Add support for loading custom mouse cursor images
This commit is contained in:
@@ -20,6 +20,7 @@ namespace
|
||||
Nullable<bool> Fullscreen;
|
||||
Nullable<Float2> Size;
|
||||
bool CursorVisible = true;
|
||||
CursorType CachedCursorType = CursorType::Default;
|
||||
CursorLockMode CursorLock = CursorLockMode::None;
|
||||
CursorLockMode PendingCursorLock = CursorLockMode::None;
|
||||
bool LastGameViewportFocus = false;
|
||||
@@ -107,10 +108,17 @@ void Screen::SetCursorVisible(const bool value)
|
||||
#else
|
||||
const auto win = Engine::MainWindow;
|
||||
#endif
|
||||
if (!value && win)
|
||||
{
|
||||
// Cache cursor used before hiding it to restore it later (eg. if game uses image cursor and hides it for a while)
|
||||
CachedCursorType = win->GetCursor();
|
||||
if (CachedCursorType == CursorType::Hidden)
|
||||
CachedCursorType = CursorType::Default;
|
||||
}
|
||||
if (win && Engine::HasGameViewportFocus())
|
||||
win->SetCursor(value ? CursorType::Default : CursorType::Hidden);
|
||||
win->SetCursor(value ? CachedCursorType : CursorType::Hidden);
|
||||
else if (win)
|
||||
win->SetCursor(CursorType::Default);
|
||||
win->SetCursor(CachedCursorType);
|
||||
CursorVisible = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ API_ENUM() enum class ClosingReason
|
||||
API_ENUM() enum class CursorType
|
||||
{
|
||||
/// <summary>
|
||||
/// The default.
|
||||
/// The default cursor, usually an arrow.
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
|
||||
@@ -56,7 +56,7 @@ API_ENUM() enum class CursorType
|
||||
Help,
|
||||
|
||||
/// <summary>
|
||||
/// The I beam.
|
||||
/// The I-beam for text selection.
|
||||
/// </summary>
|
||||
IBeam,
|
||||
|
||||
@@ -100,6 +100,11 @@ API_ENUM() enum class CursorType
|
||||
/// </summary>
|
||||
Hidden,
|
||||
|
||||
/// <summary>
|
||||
/// The custom cursor image. Loaded manually via Window::LoadCursorImage.
|
||||
/// </summary>
|
||||
Image,
|
||||
|
||||
MAX
|
||||
};
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ API_INJECT_CODE(cpp, "#include \"Engine/Platform/Window.h\"");
|
||||
/// <summary>
|
||||
/// Native platform window object.
|
||||
/// </summary>
|
||||
API_CLASS(NoSpawn, NoConstructor, Sealed, Name="Window")
|
||||
API_CLASS(NoSpawn, NoConstructor, Sealed, Name="Window", Tag="NativeInvokeUseName")
|
||||
class FLAXENGINE_API WindowBase : public ScriptingObject
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(WindowBase);
|
||||
@@ -31,16 +31,17 @@ class FLAXENGINE_API WindowBase : public ScriptingObject
|
||||
protected:
|
||||
bool _visible, _minimized, _maximized, _isClosing, _showAfterFirstPaint, _focused;
|
||||
GPUSwapChain* _swapChain;
|
||||
void* _cursorImage = nullptr;
|
||||
CreateWindowSettings _settings;
|
||||
String _title;
|
||||
CursorType _cursor;
|
||||
Float2 _clientSize;
|
||||
int _dpi;
|
||||
int32 _dpi;
|
||||
float _dpiScale;
|
||||
|
||||
Float2 _trackingMouseOffset;
|
||||
bool _isUsingMouseOffset = false;
|
||||
Rectangle _mouseOffsetScreenSize;
|
||||
bool _isUsingMouseOffset = false;
|
||||
bool _isTrackingMouse = false;
|
||||
bool _isHorizontalFlippingMouse = false;
|
||||
bool _isVerticalFlippingMouse = false;
|
||||
@@ -546,6 +547,52 @@ public:
|
||||
_cursor = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mouse cursor image handle.
|
||||
/// </summary>
|
||||
API_PROPERTY() FORCE_INLINE void* GetCursorImage() const
|
||||
{
|
||||
return _cursorImage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mouse cursor image handle.
|
||||
/// </summary>
|
||||
/// <param name="image">The cursor image.</param>
|
||||
API_PROPERTY() virtual void SetCursorImage(void* image)
|
||||
{
|
||||
_cursorImage = image;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a cursor file as a cursor image. Returns a native cursor handle that can be used with `SetCursorImage`. Support depends on platform (eg. Windows uses .cur/.ani files).
|
||||
/// </summary>
|
||||
/// <param name="path">Path to the cursor file (absolute or relative).</param>
|
||||
/// <returns>Loaded cursor image handle, or null if failed.</returns>
|
||||
API_FUNCTION() static void* LoadCursorImage(const StringView& path)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads a texture as a cursor image. Returns a native cursor handle that can be used with `SetCursorImage`. Support depends on platform.
|
||||
/// </summary>
|
||||
/// <param name="image">Texture data with a cursor image.</param>
|
||||
/// <param name="hotSpot">The texture coordinate of a cursor's hot spot that defines the exact 'clickable' point.</param>
|
||||
/// <returns>Loaded cursor image handle, or null if failed.</returns>
|
||||
API_FUNCTION() static void* LoadCursorImage(const TextureData& image, const Int2& hotSpot = Int2::Zero)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a cursor image loaded with `LoadCursorImage`. Should be called to release native resources after the cursor image is not needed anymore.
|
||||
/// </summary>
|
||||
/// <param name="image">The cursor image.</param>
|
||||
API_FUNCTION() static void DestroyCursorImage(void* image)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the window icon.
|
||||
/// </summary>
|
||||
|
||||
@@ -230,64 +230,32 @@ void GDKWindow::UpdateCursor() const
|
||||
return;
|
||||
}
|
||||
|
||||
int32 index = 0;
|
||||
switch (_cursor)
|
||||
const LPCWSTR cursors[] =
|
||||
{
|
||||
case CursorType::Default:
|
||||
break;
|
||||
case CursorType::Cross:
|
||||
index = 1;
|
||||
break;
|
||||
case CursorType::Hand:
|
||||
index = 2;
|
||||
break;
|
||||
case CursorType::Help:
|
||||
index = 3;
|
||||
break;
|
||||
case CursorType::IBeam:
|
||||
index = 4;
|
||||
break;
|
||||
case CursorType::No:
|
||||
index = 5;
|
||||
break;
|
||||
case CursorType::Wait:
|
||||
index = 11;
|
||||
break;
|
||||
case CursorType::SizeAll:
|
||||
index = 6;
|
||||
break;
|
||||
case CursorType::SizeNESW:
|
||||
index = 7;
|
||||
break;
|
||||
case CursorType::SizeNS:
|
||||
index = 8;
|
||||
break;
|
||||
case CursorType::SizeNWSE:
|
||||
index = 9;
|
||||
break;
|
||||
case CursorType::SizeWE:
|
||||
index = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
static const LPCWSTR cursors[] =
|
||||
{
|
||||
IDC_ARROW,
|
||||
IDC_CROSS,
|
||||
IDC_HAND,
|
||||
IDC_HELP,
|
||||
IDC_IBEAM,
|
||||
IDC_NO,
|
||||
IDC_SIZEALL,
|
||||
IDC_SIZENESW,
|
||||
IDC_SIZENS,
|
||||
IDC_SIZENWSE,
|
||||
IDC_SIZEWE,
|
||||
IDC_WAIT,
|
||||
IDC_ARROW, // Default
|
||||
IDC_CROSS, // Cross
|
||||
IDC_HAND, // Hand
|
||||
IDC_HELP, // Help
|
||||
IDC_IBEAM, // IBeam
|
||||
IDC_NO, // No
|
||||
IDC_WAIT, // Wait
|
||||
IDC_SIZEALL, // SizeAll
|
||||
IDC_SIZENESW, // SizeNESW
|
||||
IDC_SIZENS, // SizeNS
|
||||
IDC_SIZENWSE, // SizeNWSE
|
||||
IDC_SIZEWE, // SizeWE
|
||||
};
|
||||
static_assert(ARRAY_COUNT(cursors) + 2 == (int32)CursorType::MAX, "Invalid cursors count.");
|
||||
|
||||
HCURSOR cursor;
|
||||
if (_cursor == CursorType::Image)
|
||||
{
|
||||
LOG(Error, "GDK doesn't support hardware image cursors");
|
||||
cursor = NULL;
|
||||
}
|
||||
else
|
||||
cursor = LoadCursorW(nullptr, cursors[(int32)_cursor]);
|
||||
|
||||
ASSERT(index >= 0 && index < ARRAY_COUNT(cursors));
|
||||
const HCURSOR cursor = LoadCursorW(nullptr, cursors[index]);
|
||||
::SetCursor(cursor);
|
||||
}
|
||||
|
||||
|
||||
@@ -846,7 +846,7 @@ void LinuxWindow::SetCursor(CursorType type)
|
||||
WindowBase::SetCursor(type);
|
||||
|
||||
LINUX_WINDOW_PROLOG;
|
||||
if (!display)
|
||||
if (!display || type == CursorType::Image)
|
||||
return;
|
||||
X11::XDefineCursor(display, window, Cursors[(int32)type]);
|
||||
}
|
||||
|
||||
@@ -1197,6 +1197,8 @@ void MacWindow::SetCursor(CursorType type)
|
||||
case CursorType::Hidden:
|
||||
[NSCursor hide];
|
||||
return;
|
||||
case CursorType::Image:
|
||||
// TODO: custom cursor support
|
||||
default:
|
||||
cursor = [NSCursor arrowCursor];
|
||||
break;
|
||||
|
||||
@@ -995,50 +995,42 @@ void SDLWindow::UpdateCursor()
|
||||
//if (_isTrackingMouse)
|
||||
// Input::Mouse->SetRelativeMode(false, this);
|
||||
|
||||
int32 index = SDL_SYSTEM_CURSOR_DEFAULT;
|
||||
switch (_cursor)
|
||||
const SDL_SystemCursor cursors[] =
|
||||
{
|
||||
case CursorType::Cross:
|
||||
index = SDL_SYSTEM_CURSOR_CROSSHAIR;
|
||||
break;
|
||||
case CursorType::Hand:
|
||||
index = SDL_SYSTEM_CURSOR_POINTER;
|
||||
break;
|
||||
case CursorType::Help:
|
||||
//index = SDL_SYSTEM_CURSOR_DEFAULT;
|
||||
break;
|
||||
case CursorType::IBeam:
|
||||
index = SDL_SYSTEM_CURSOR_TEXT;
|
||||
break;
|
||||
case CursorType::No:
|
||||
index = SDL_SYSTEM_CURSOR_NOT_ALLOWED;
|
||||
break;
|
||||
case CursorType::Wait:
|
||||
index = SDL_SYSTEM_CURSOR_WAIT;
|
||||
break;
|
||||
case CursorType::SizeAll:
|
||||
index = SDL_SYSTEM_CURSOR_MOVE;
|
||||
break;
|
||||
case CursorType::SizeNESW:
|
||||
index = SDL_SYSTEM_CURSOR_NESW_RESIZE;
|
||||
break;
|
||||
case CursorType::SizeNS:
|
||||
index = SDL_SYSTEM_CURSOR_NS_RESIZE;
|
||||
break;
|
||||
case CursorType::SizeNWSE:
|
||||
index = SDL_SYSTEM_CURSOR_NWSE_RESIZE;
|
||||
break;
|
||||
case CursorType::SizeWE:
|
||||
index = SDL_SYSTEM_CURSOR_EW_RESIZE;
|
||||
break;
|
||||
case CursorType::Default:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SDL_SYSTEM_CURSOR_DEFAULT, // Default
|
||||
SDL_SYSTEM_CURSOR_CROSSHAIR, // Cross
|
||||
SDL_SYSTEM_CURSOR_POINTER, // Hand
|
||||
SDL_SYSTEM_CURSOR_DEFAULT, // Help
|
||||
SDL_SYSTEM_CURSOR_TEXT, // IBeam
|
||||
SDL_SYSTEM_CURSOR_NOT_ALLOWED, // No
|
||||
SDL_SYSTEM_CURSOR_WAIT, // Wait
|
||||
SDL_SYSTEM_CURSOR_MOVE, // SizeAll
|
||||
SDL_SYSTEM_CURSOR_NESW_RESIZE, // SizeNESW
|
||||
SDL_SYSTEM_CURSOR_NS_RESIZE, // SizeNS
|
||||
SDL_SYSTEM_CURSOR_NWSE_RESIZE, // SizeNWSE
|
||||
SDL_SYSTEM_CURSOR_EW_RESIZE, // SizeWE
|
||||
};
|
||||
static_assert(ARRAY_COUNT(cursors) + 2 == (int32)CursorType::MAX, "Invalid cursors count.");
|
||||
|
||||
if (SDLImpl::Cursors[index] == nullptr)
|
||||
SDLImpl::Cursors[index] = SDL_CreateSystemCursor(static_cast<SDL_SystemCursor>(index));
|
||||
SDL_SetCursor(SDLImpl::Cursors[index]);
|
||||
SDL_Cursor* cursor;
|
||||
if (_cursor == CursorType::Image)
|
||||
{
|
||||
static bool Once = true;
|
||||
if (!_cursorImage && Once)
|
||||
{
|
||||
Once = false;
|
||||
LOG(Error, "Missing cursor image to set.");
|
||||
}
|
||||
cursor = (SDL_Cursor*)_cursorImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 index = cursors[(int32)_cursor];
|
||||
if (SDLImpl::Cursors[index] == nullptr)
|
||||
SDLImpl::Cursors[index] = SDL_CreateSystemCursor(static_cast<SDL_SystemCursor>(index));
|
||||
cursor = SDLImpl::Cursors[index];
|
||||
}
|
||||
SDL_SetCursor(cursor);
|
||||
}
|
||||
|
||||
void SDLWindow::SetIcon(TextureData& icon)
|
||||
@@ -1046,10 +1038,42 @@ void SDLWindow::SetIcon(TextureData& icon)
|
||||
Array<Color32> colorData;
|
||||
icon.GetPixels(colorData);
|
||||
SDL_Surface* surface = SDL_CreateSurfaceFrom(icon.Width, icon.Height, SDL_PIXELFORMAT_ABGR8888, colorData.Get(), sizeof(Color32) * icon.Width);
|
||||
|
||||
SDL_SetWindowIcon(_window, surface);
|
||||
SDL_free(surface);
|
||||
}
|
||||
|
||||
void SDLWindow::SetCursorImage(void* image)
|
||||
{
|
||||
WindowBase::SetCursorImage(image);
|
||||
|
||||
if (_cursor == CursorType::Image)
|
||||
UpdateCursor();
|
||||
}
|
||||
|
||||
void* SDLWindow::LoadCursorImage(const StringView& path)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* SDLWindow::LoadCursorImage(const TextureData& image, const Int2& hotSpot)
|
||||
{
|
||||
Array<Color32> pixels;
|
||||
if (image.GetPixels(pixels))
|
||||
{
|
||||
LOG(Error, "Invalid cursor texture");
|
||||
return nullptr;
|
||||
}
|
||||
SDL_Surface* surface = SDL_CreateSurfaceFrom(image.Width, image.Height, SDL_PIXELFORMAT_ABGR8888, pixels.Get(), sizeof(Color32) * image.Width);
|
||||
SDL_Cursor* result = SDL_CreateColorCursor(surface, hotSpot.X, hotSpot.Y);
|
||||
SDL_free(surface);
|
||||
return result;
|
||||
}
|
||||
|
||||
void SDLWindow::DestroyCursorImage(void* image)
|
||||
{
|
||||
if (image)
|
||||
SDL_DestroyCursor((SDL_Cursor*)image);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -108,6 +108,10 @@ public:
|
||||
void SetMousePosition(const Float2& position) const override;
|
||||
void SetCursor(CursorType type) override;
|
||||
void SetIcon(TextureData& icon) override;
|
||||
void SetCursorImage(void* image) override;
|
||||
static void* LoadCursorImage(const StringView& path);
|
||||
static void* LoadCursorImage(const TextureData& image, const Int2& hotSpot = Int2::Zero);
|
||||
static void DestroyCursorImage(void* image);
|
||||
|
||||
#if USE_EDITOR && PLATFORM_WINDOWS
|
||||
// [IUnknown]
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
#include "WindowsInput.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Math/Math.h"
|
||||
#include "Engine/Core/Math/Color32.h"
|
||||
#include "Engine/Graphics/GPUSwapChain.h"
|
||||
#include "Engine/Graphics/RenderTask.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Graphics/Textures/TextureData.h"
|
||||
#include "../Win32/IncludeWindowsHeaders.h"
|
||||
#include <propidl.h>
|
||||
#if USE_EDITOR
|
||||
@@ -696,6 +698,71 @@ void WindowsWindow::SetCursor(CursorType type)
|
||||
UpdateCursor();
|
||||
}
|
||||
|
||||
void WindowsWindow::SetCursorImage(void* image)
|
||||
{
|
||||
// Base
|
||||
WindowBase::SetCursorImage(image);
|
||||
|
||||
if (_cursor == CursorType::Image)
|
||||
UpdateCursor();
|
||||
}
|
||||
|
||||
void* WindowsWindow::LoadCursorImage(const StringView& path)
|
||||
{
|
||||
return ::LoadCursorFromFileW(path.GetText());
|
||||
}
|
||||
|
||||
// From wingdi.h
|
||||
WIN_API HBITMAP WIN_API_CALLCONV CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID* lpBits);
|
||||
WIN_API BOOL WIN_API_CALLCONV DeleteObject(HGDIOBJ ho);
|
||||
#pragma comment(lib, "Gdi32.lib")
|
||||
|
||||
void* WindowsWindow::LoadCursorImage(const TextureData& image, const Int2& hotSpot)
|
||||
{
|
||||
// Get image pixels
|
||||
Array<Color32> pixels;
|
||||
if (image.GetPixels(pixels))
|
||||
{
|
||||
LOG(Error, "Invalid cursor texture");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// RGBA -> BGRA
|
||||
for (int32 y = 0; y < image.Height; y++)
|
||||
{
|
||||
for (int32 x = 0; x < image.Width; x++)
|
||||
{
|
||||
auto& color = *(pixels.Get() + y * image.Width + x);
|
||||
color = Color32(color.B, color.G, color.R, color.A);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize a dummy mask
|
||||
Array<uint8> pixelsMask;
|
||||
pixelsMask.AddUninitialized(pixels.Count());
|
||||
Platform::MemorySet(pixelsMask.Get(), pixelsMask.Count(), 255);
|
||||
|
||||
// Create cursor from the image
|
||||
HBITMAP colorBitmap = ::CreateBitmap(image.Width, image.Height, 1, 32, pixels.Get());
|
||||
HBITMAP maskBitmap = ::CreateBitmap(image.Width, image.Height, 1, 8, pixelsMask.Get());
|
||||
ICONINFO iconInfo = {};
|
||||
iconInfo.xHotspot = hotSpot.X;
|
||||
iconInfo.yHotspot = hotSpot.Y;
|
||||
iconInfo.hbmColor = colorBitmap;
|
||||
iconInfo.hbmMask = maskBitmap;
|
||||
HCURSOR result = ::CreateIconIndirect(&iconInfo);
|
||||
::DeleteObject(colorBitmap);
|
||||
::DeleteObject(maskBitmap);
|
||||
return result;
|
||||
}
|
||||
|
||||
void WindowsWindow::DestroyCursorImage(void* image)
|
||||
{
|
||||
if (!image)
|
||||
return;
|
||||
::DestroyCursor((HCURSOR)image);
|
||||
}
|
||||
|
||||
void WindowsWindow::CheckForWindowResize()
|
||||
{
|
||||
// Skip for minimized window (GetClientRect for minimized window returns 0)
|
||||
@@ -763,76 +830,49 @@ void WindowsWindow::UpdateCursor()
|
||||
else if (_lastCursorHidden)
|
||||
{
|
||||
_lastCursorHidden = false;
|
||||
while(::ShowCursor(TRUE) < 0)
|
||||
while (::ShowCursor(TRUE) < 0)
|
||||
{
|
||||
if (_cursorHiddenSafetyCount >= 100)
|
||||
{
|
||||
LOG(Warning, "Cursor has failed to show.");
|
||||
break;
|
||||
}
|
||||
_cursorHiddenSafetyCount += 1;
|
||||
_cursorHiddenSafetyCount++;
|
||||
}
|
||||
_cursorHiddenSafetyCount = 0;
|
||||
}
|
||||
|
||||
int32 index = 0;
|
||||
switch (_cursor)
|
||||
const LPCWSTR cursors[] =
|
||||
{
|
||||
case CursorType::Default:
|
||||
break;
|
||||
case CursorType::Cross:
|
||||
index = 1;
|
||||
break;
|
||||
case CursorType::Hand:
|
||||
index = 2;
|
||||
break;
|
||||
case CursorType::Help:
|
||||
index = 3;
|
||||
break;
|
||||
case CursorType::IBeam:
|
||||
index = 4;
|
||||
break;
|
||||
case CursorType::No:
|
||||
index = 5;
|
||||
break;
|
||||
case CursorType::Wait:
|
||||
index = 11;
|
||||
break;
|
||||
case CursorType::SizeAll:
|
||||
index = 6;
|
||||
break;
|
||||
case CursorType::SizeNESW:
|
||||
index = 7;
|
||||
break;
|
||||
case CursorType::SizeNS:
|
||||
index = 8;
|
||||
break;
|
||||
case CursorType::SizeNWSE:
|
||||
index = 9;
|
||||
break;
|
||||
case CursorType::SizeWE:
|
||||
index = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
static const LPCWSTR cursors[] =
|
||||
{
|
||||
IDC_ARROW,
|
||||
IDC_CROSS,
|
||||
IDC_HAND,
|
||||
IDC_HELP,
|
||||
IDC_IBEAM,
|
||||
IDC_NO,
|
||||
IDC_SIZEALL,
|
||||
IDC_SIZENESW,
|
||||
IDC_SIZENS,
|
||||
IDC_SIZENWSE,
|
||||
IDC_SIZEWE,
|
||||
IDC_WAIT,
|
||||
IDC_ARROW, // Default
|
||||
IDC_CROSS, // Cross
|
||||
IDC_HAND, // Hand
|
||||
IDC_HELP, // Help
|
||||
IDC_IBEAM, // IBeam
|
||||
IDC_NO, // No
|
||||
IDC_WAIT, // Wait
|
||||
IDC_SIZEALL, // SizeAll
|
||||
IDC_SIZENESW, // SizeNESW
|
||||
IDC_SIZENS, // SizeNS
|
||||
IDC_SIZENWSE, // SizeNWSE
|
||||
IDC_SIZEWE, // SizeWE
|
||||
};
|
||||
static_assert(ARRAY_COUNT(cursors) + 2 == (int32)CursorType::MAX, "Invalid cursors count.");
|
||||
|
||||
HCURSOR cursor;
|
||||
if (_cursor == CursorType::Image)
|
||||
{
|
||||
static bool Once = true;
|
||||
if (!_cursorImage && Once)
|
||||
{
|
||||
Once = false;
|
||||
LOG(Error, "Missing cursor image to set.");
|
||||
}
|
||||
cursor = (HCURSOR)_cursorImage;
|
||||
}
|
||||
else
|
||||
cursor = LoadCursorW(nullptr, cursors[(int32)_cursor]);
|
||||
|
||||
ASSERT(index >= 0 && index < ARRAY_COUNT(cursors));
|
||||
const HCURSOR cursor = LoadCursorW(nullptr, cursors[index]);
|
||||
::SetCursor(cursor);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ class FLAXENGINE_API WindowsWindow : public WindowBase
|
||||
friend WindowsPlatform;
|
||||
|
||||
private:
|
||||
|
||||
Windows::HWND _handle;
|
||||
#if USE_EDITOR
|
||||
Windows::ULONG _refCount;
|
||||
@@ -29,16 +28,15 @@ private:
|
||||
bool _trackingMouse = false;
|
||||
bool _clipCursorSet = false;
|
||||
bool _lastCursorHidden = false;
|
||||
int _cursorHiddenSafetyCount = 0;
|
||||
float _opacity = 1.0f;
|
||||
bool _isDuringMaximize = false;
|
||||
int32 _cursorHiddenSafetyCount = 0;
|
||||
float _opacity = 1.0f;
|
||||
Windows::HANDLE _monitor = nullptr;
|
||||
Windows::LONG _clipCursorRect[4];
|
||||
int32 _regionWidth = 0, _regionHeight = 0;
|
||||
Float2 _minimizedScreenPosition = Float2::Zero;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WindowsWindow"/> class.
|
||||
/// </summary>
|
||||
@@ -51,7 +49,6 @@ public:
|
||||
~WindowsWindow();
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the window handle.
|
||||
/// </summary>
|
||||
@@ -80,7 +77,6 @@ public:
|
||||
void GetScreenInfo(int32& x, int32& y, int32& width, int32& height) const;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// The Windows messages procedure.
|
||||
/// </summary>
|
||||
@@ -91,13 +87,11 @@ public:
|
||||
Windows::LRESULT WndProc(Windows::UINT msg, Windows::WPARAM wParam, Windows::LPARAM lParam);
|
||||
|
||||
private:
|
||||
|
||||
void CheckForWindowResize();
|
||||
void UpdateCursor();
|
||||
void UpdateRegion();
|
||||
|
||||
public:
|
||||
|
||||
// [WindowBase]
|
||||
void* GetNativePtr() const override;
|
||||
void Show() override;
|
||||
@@ -130,9 +124,12 @@ public:
|
||||
void StartClippingCursor(const Rectangle& bounds) override;
|
||||
void EndClippingCursor() override;
|
||||
void SetCursor(CursorType type) override;
|
||||
void SetCursorImage(void* image) override;
|
||||
static void* LoadCursorImage(const StringView& path);
|
||||
static void* LoadCursorImage(const TextureData& image, const Int2& hotSpot = Int2::Zero);
|
||||
static void DestroyCursorImage(void* image);
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
// [IUnknown]
|
||||
Windows::HRESULT __stdcall QueryInterface(const Windows::IID& id, void** ppvObject) override;
|
||||
Windows::ULONG __stdcall AddRef() override;
|
||||
@@ -143,7 +140,6 @@ public:
|
||||
Windows::HRESULT __stdcall DragOver(Windows::DWORD grfKeyState, Windows::POINTL pt, Windows::DWORD* pdwEffect) override;
|
||||
Windows::HRESULT __stdcall DragLeave() override;
|
||||
Windows::HRESULT __stdcall Drop(Windows::IDataObject* pDataObj, Windows::DWORD grfKeyState, Windows::POINTL pt, Windows::DWORD* pdwEffect) override;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user