Browse Source

🎉 Hardware cursor: Enable safe parts by default

Enables safe parts of the hardware cursor by default:

1. Disabled for items due to the jumping glitch.
2. Limited to 128px size due to buggy large cursors on some systems.
pull/2321/head
Gleb Mazovetskiy 5 years ago
parent
commit
65906f8332
  1. 51
      Source/hwcursor.cpp
  2. 12
      Source/options.cpp
  3. 8
      Source/options.h

51
Source/hwcursor.cpp

@ -29,6 +29,27 @@ enum class HotpointPosition {
Center,
};
Size ScaledSize(Size size)
{
if (renderer != nullptr) {
float scaleX;
float scaleY;
SDL_RenderGetScale(renderer, &scaleX, &scaleY);
size.width *= scaleX; // NOLINT(bugprone-narrowing-conversions)
size.height *= scaleY; // NOLINT(bugprone-narrowing-conversions)
}
return size;
}
bool IsCursorSizeAllowed(Size size)
{
if (sgOptions.Graphics.nHardwareCursorMaxSize <= 0)
return true;
size = ScaledSize(size);
return size.width <= sgOptions.Graphics.nHardwareCursorMaxSize
&& size.height <= sgOptions.Graphics.nHardwareCursorMaxSize;
}
Point GetHotpointPosition(const SDL_Surface &surface, HotpointPosition position)
{
switch (position) {
@ -42,23 +63,18 @@ Point GetHotpointPosition(const SDL_Surface &surface, HotpointPosition position)
bool SetHardwareCursor(SDL_Surface *surface, HotpointPosition hotpointPosition)
{
float scaleX;
float scaleY;
if (renderer != nullptr) {
SDL_RenderGetScale(renderer, &scaleX, &scaleY);
}
SDLCursorUniquePtr newCursor;
if (renderer == nullptr || (scaleX == 1.0F && scaleY == 1.0F)) {
const Size size { surface->w, surface->h };
const Size scaledSize = ScaledSize(size);
if (size == scaledSize) {
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) };
const int scaledW = static_cast<int>(surface->w * scaleX);
const int scaledH = static_cast<int>(surface->h * scaleY);
SDLSurfaceUniquePtr scaledSurface { SDL_CreateRGBSurfaceWithFormat(0, scaledW, scaledH, 32, SDL_PIXELFORMAT_ARGB8888) };
SDLSurfaceUniquePtr scaledSurface { SDL_CreateRGBSurfaceWithFormat(0, scaledSize.width, scaledSize.height, 32, SDL_PIXELFORMAT_ARGB8888) };
SDL_BlitScaled(converted.get(), nullptr, scaledSurface.get(), nullptr);
const Point hotpoint = GetHotpointPosition(*scaledSurface, hotpointPosition);
newCursor = SDLCursorUniquePtr { SDL_CreateColorCursor(scaledSurface.get(), hotpoint.x, hotpoint.y) };
@ -73,12 +89,18 @@ bool SetHardwareCursor(SDL_Surface *surface, HotpointPosition hotpointPosition)
bool SetHardwareCursorFromSprite(int pcurs)
{
const bool isItem = IsItemSprite(pcurs);
if (isItem && !sgOptions.Graphics.bHardwareCursorForItems)
return false;
const int outlineWidth = isItem ? 1 : 0;
auto size = GetInvItemSize(pcurs);
size.width += 2 * outlineWidth;
size.height += 2 * outlineWidth;
if (!IsCursorSizeAllowed(size))
return false;
auto out = Surface::Alloc(size.width, size.height);
SDL_SetSurfacePalette(out.surface, Palette);
@ -113,13 +135,18 @@ void SetHardwareCursor(CursorInfo cursorInfo)
case CursorType::UserInterface:
// ArtCursor is null while loading the game on the progress screen,
// called via palette fade from ShowProgress.
if (ArtCursor.surface != nullptr)
CurrentCursorInfo.SetEnabled(SetHardwareCursor(ArtCursor.surface.get(), HotpointPosition::TopLeft));
if (ArtCursor.surface != nullptr) {
CurrentCursorInfo.SetEnabled(
IsCursorSizeAllowed(Size { ArtCursor.surface->w, ArtCursor.surface->h })
&& SetHardwareCursor(ArtCursor.surface.get(), HotpointPosition::TopLeft));
}
break;
case CursorType::Unknown:
CurrentCursorInfo.SetEnabled(false);
break;
}
if (!CurrentCursorInfo.Enabled())
SetHardwareCursorVisible(false);
#endif
}

12
Source/options.cpp

@ -168,10 +168,10 @@ void LoadOptions()
sgOptions.Graphics.bBlendedTransparancy = GetIniBool("Graphics", "Blended Transparency", true);
sgOptions.Graphics.nGammaCorrection = GetIniInt("Graphics", "Gamma Correction", 100);
sgOptions.Graphics.bColorCycling = GetIniBool("Graphics", "Color Cycling", true);
#ifndef USE_SDL1
sgOptions.Graphics.bHardwareCursor = GetIniBool("Graphics", "Hardware Cursor", false);
#else
sgOptions.Graphics.bHardwareCursor = false;
#if SDL_VERSION_ATLEAST(2, 0, 0)
sgOptions.Graphics.bHardwareCursor = GetIniBool("Graphics", "Hardware Cursor", true);
sgOptions.Graphics.bHardwareCursorForItems = GetIniBool("Graphics", "Hardware Cursor For Items", false);
sgOptions.Graphics.nHardwareCursorMaxSize = GetIniInt("Graphics", "Hardware Cursor Maximum Size", 128);
#endif
sgOptions.Graphics.bFPSLimit = GetIniBool("Graphics", "FPS Limiter", true);
sgOptions.Graphics.bShowFPS = (GetIniInt("Graphics", "Show FPS", 0) != 0);
@ -252,8 +252,10 @@ void SaveOptions()
SetIniValue("Graphics", "Blended Transparency", sgOptions.Graphics.bBlendedTransparancy);
SetIniValue("Graphics", "Gamma Correction", sgOptions.Graphics.nGammaCorrection);
SetIniValue("Graphics", "Color Cycling", sgOptions.Graphics.bColorCycling);
#ifndef USE_SDL1
#if SDL_VERSION_ATLEAST(2, 0, 0)
SetIniValue("Graphics", "Hardware Cursor", sgOptions.Graphics.bHardwareCursor);
SetIniValue("Graphics", "Hardware Cursor For Items", sgOptions.Graphics.bHardwareCursorForItems);
SetIniValue("Graphics", "Hardware Cursor Maximum Size", sgOptions.Graphics.nHardwareCursorMaxSize);
#endif
SetIniValue("Graphics", "FPS Limiter", sgOptions.Graphics.bFPSLimit);
SetIniValue("Graphics", "Show FPS", sgOptions.Graphics.bShowFPS);

8
Source/options.h

@ -2,6 +2,8 @@
#include <cstdint>
#include <SDL_version.h>
#include "pack.h"
namespace devilution {
@ -61,8 +63,14 @@ struct GraphicsOptions {
int nGammaCorrection;
/** @brief Enable color cycling animations. */
bool bColorCycling;
#if SDL_VERSION_ATLEAST(2, 0, 0)
/** @brief Use a hardware cursor (SDL2 only). */
bool bHardwareCursor;
/** @brief Use a hardware cursor for items. */
bool bHardwareCursorForItems;
/** @brief Maximum width / height for the hardware cursor. Larger cursors fall back to software. */
int nHardwareCursorMaxSize;
#endif
/** @brief Enable FPS Limit. */
bool bFPSLimit;
/** @brief Show FPS, even without the -f command line flag. */

Loading…
Cancel
Save