mirror of
https://github.com/diasurgical/DevilutionX.git
synced 2026-10-12 02:13:06 +00:00
Hardware Cursor: Use item hotpoint
For a hardware item cursor, set the hotpoint to the center instead of manually setting the cursor position.
This commit is contained in:
+26
-6
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "DiabloUI/diabloui.h"
|
||||
|
||||
#include "appfat.h"
|
||||
#include "cursor.h"
|
||||
#include "engine.h"
|
||||
#include "utils/display.h"
|
||||
@@ -23,7 +24,23 @@ CursorInfo CurrentCursorInfo;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDLCursorUniquePtr CurrentCursor;
|
||||
|
||||
void SetHardwareCursor(SDL_Surface *surface)
|
||||
enum class HotpointPosition {
|
||||
TopLeft,
|
||||
Center,
|
||||
};
|
||||
|
||||
Point GetHotpointPosition(const SDL_Surface &surface, HotpointPosition position)
|
||||
{
|
||||
switch (position) {
|
||||
case HotpointPosition::TopLeft:
|
||||
return { 0, 0 };
|
||||
case HotpointPosition::Center:
|
||||
return { surface.w / 2, surface.h / 2 };
|
||||
}
|
||||
app_fatal("Unhandled enum value");
|
||||
}
|
||||
|
||||
void SetHardwareCursor(SDL_Surface *surface, HotpointPosition hotpointPosition)
|
||||
{
|
||||
float scaleX;
|
||||
float scaleY;
|
||||
@@ -33,7 +50,8 @@ void SetHardwareCursor(SDL_Surface *surface)
|
||||
|
||||
SDLCursorUniquePtr newCursor;
|
||||
if (renderer == nullptr || (scaleX == 1.0F && scaleY == 1.0F)) {
|
||||
newCursor = SDLCursorUniquePtr { SDL_CreateColorCursor(surface, 0, 0) };
|
||||
const Point hotpoint = GetHotpointPosition(*surface, hotpointPosition);
|
||||
newCursor = SDLCursorUniquePtr { SDL_CreateColorCursor(surface, hotpoint.x, hotpoint.y) };
|
||||
} else {
|
||||
// SDL does not support BlitScaled from 8-bit to RGBA.
|
||||
SDLSurfaceUniquePtr converted { SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0) };
|
||||
@@ -42,7 +60,8 @@ void SetHardwareCursor(SDL_Surface *surface)
|
||||
const int scaledH = surface->h * scaleY; // NOLINT(bugprone-narrowing-conversions)
|
||||
SDLSurfaceUniquePtr scaledSurface { SDL_CreateRGBSurfaceWithFormat(0, scaledW, scaledH, 32, SDL_PIXELFORMAT_ARGB8888) };
|
||||
SDL_BlitScaled(converted.get(), nullptr, scaledSurface.get(), nullptr);
|
||||
newCursor = SDLCursorUniquePtr { SDL_CreateColorCursor(scaledSurface.get(), 0, 0) };
|
||||
const Point hotpoint = GetHotpointPosition(*scaledSurface, hotpointPosition);
|
||||
newCursor = SDLCursorUniquePtr { SDL_CreateColorCursor(scaledSurface.get(), hotpoint.x, hotpoint.y) };
|
||||
}
|
||||
SDL_SetCursor(newCursor.get());
|
||||
CurrentCursor = std::move(newCursor);
|
||||
@@ -50,7 +69,8 @@ void SetHardwareCursor(SDL_Surface *surface)
|
||||
|
||||
void SetHardwareCursorFromSprite(int pcurs)
|
||||
{
|
||||
const int outlineWidth = IsItemSprite(pcurs) ? 1 : 0;
|
||||
const bool isItem = IsItemSprite(pcurs);
|
||||
const int outlineWidth = isItem ? 1 : 0;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
@@ -68,7 +88,7 @@ void SetHardwareCursorFromSprite(int pcurs)
|
||||
SDL_SetColorKey(out.surface, 1, TransparentColor);
|
||||
CelDrawCursor(out, { outlineWidth, height - outlineWidth }, pcurs);
|
||||
|
||||
SetHardwareCursor(out.surface);
|
||||
SetHardwareCursor(out.surface, isItem ? HotpointPosition::Center : HotpointPosition::TopLeft);
|
||||
out.Free();
|
||||
}
|
||||
#endif
|
||||
@@ -92,7 +112,7 @@ void SetHardwareCursor(CursorInfo cursorInfo)
|
||||
// ArtCursor is null while loading the game on the progress screen,
|
||||
// called via palette fade from ShowProgress.
|
||||
if (ArtCursor.surface != nullptr)
|
||||
SetHardwareCursor(ArtCursor.surface.get());
|
||||
SetHardwareCursor(ArtCursor.surface.get(), HotpointPosition::TopLeft);
|
||||
break;
|
||||
case CursorType::Unknown:
|
||||
break;
|
||||
|
||||
+8
-4
@@ -11,6 +11,7 @@
|
||||
#include "cursor.h"
|
||||
#include "engine/render/cel_render.hpp"
|
||||
#include "engine/render/text_render.hpp"
|
||||
#include "hwcursor.hpp"
|
||||
#include "minitext.h"
|
||||
#include "options.h"
|
||||
#include "plrmsg.h"
|
||||
@@ -808,8 +809,8 @@ void CheckInvPaste(int pnum, Point cursorPosition)
|
||||
auto &player = plr[pnum];
|
||||
|
||||
SetICursor(player.HoldItem._iCurs + CURSOR_FIRSTITEM);
|
||||
int i = cursorPosition.x + (icursW / 2);
|
||||
int j = cursorPosition.y + (icursH / 2);
|
||||
int i = cursorPosition.x + (IsHardwareCursorEnabled() ? 0 : (icursW / 2));
|
||||
int j = cursorPosition.y + (IsHardwareCursorEnabled() ? 0 : (icursH / 2));
|
||||
int sx = icursW28;
|
||||
int sy = icursH28;
|
||||
bool done = false;
|
||||
@@ -1177,7 +1178,7 @@ void CheckInvPaste(int pnum, Point cursorPosition)
|
||||
}
|
||||
CalcPlrInv(pnum, true);
|
||||
if (pnum == myplr) {
|
||||
if (cn == CURSOR_HAND)
|
||||
if (cn == CURSOR_HAND && !IsHardwareCursorEnabled())
|
||||
SetCursorPos(MouseX + (cursW / 2), MouseY + (cursH / 2));
|
||||
NewCursor(cn);
|
||||
}
|
||||
@@ -1416,7 +1417,10 @@ void CheckInvCut(int pnum, Point cursorPosition, bool automaticMove)
|
||||
holdItem._itype = ITYPE_NONE;
|
||||
} else {
|
||||
NewCursor(holdItem._iCurs + CURSOR_FIRSTITEM);
|
||||
SetCursorPos(cursorPosition.x - (cursW / 2), MouseY - (cursH / 2));
|
||||
if (!IsHardwareCursorEnabled()) {
|
||||
// For a hardware cursor, we set the "hot point" to the center of the item instead.
|
||||
SetCursorPos(cursorPosition.x - (cursW / 2), cursorPosition.y - (cursH / 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user