use sdl hardware cursor to decouple the cursor speed from the game speed

This commit is contained in:
Tim Felgentreff 2022-01-31 14:44:25 +01:00
parent 9f4eddb375
commit 98fe0c87a8
3 changed files with 56 additions and 34 deletions

View file

@ -106,7 +106,7 @@
-- Includes
----------------------------------------------------------------------------*/
#include <SDL.h>
#include <vec2i.h>
/*----------------------------------------------------------------------------
@ -127,6 +127,8 @@ public:
CCursor() : HotPos(0, 0),
SpriteFrame(0), FrameRate(0), G(NULL) {}
~CCursor();
std::string Ident; /// Identifier to reference it
std::string Race; /// Race name
@ -138,6 +140,12 @@ public:
// --- FILLED UP ---
CGraphic *G; /// Cursor sprite image
SDL_Cursor *GetSDLCursor();
private:
std::vector<SDL_Cursor*> SdlCursors;
std::vector<SDL_Surface*> SdlCursorSurfaces;
};
/// Cursor config reference

View file

@ -81,11 +81,46 @@ CUnitType *CursorBuilding; /// building cursor
/*--- DRAW SPRITE CURSOR ---------------------------------------------------*/
CCursor *GameCursor; /// current shown cursor-type
static CCursor *ActuallyVisibleGameCursor;
static int VisibleGameCursorFrame;
static SDL_Surface *HiddenSurface;
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
SDL_Cursor *CCursor::GetSDLCursor()
{
if (SdlCursors.size() <= SpriteFrame) {
// slow path
for (int i = SdlCursors.size(); i <= SpriteFrame; i++) {
G->Load();
SDL_Surface *cursorFrame = SDL_CreateRGBSurfaceWithFormat(0, G->getWidth(), G->getHeight(), TheScreen->format->BitsPerPixel, TheScreen->format->format);
G->DrawFrame(i, 0, 0, cursorFrame);
printf("%s\n", SDL_GetError());
SdlCursorSurfaces.push_back(cursorFrame);
SDL_Cursor *cur = SDL_CreateColorCursor(cursorFrame, HotPos.x, HotPos.y);
if (!cur) {
printf("%s\n", SDL_GetError());
}
SdlCursors.push_back(cur);
}
}
return SdlCursors[SpriteFrame];
}
CCursor::~CCursor()
{
for (auto sdlCur : SdlCursors) {
SDL_FreeCursor(sdlCur);
}
for (auto sdlSurface : SdlCursorSurfaces) {
SDL_FreeSurface(sdlSurface);
}
}
/**
** Load all cursor sprites.
**
@ -256,38 +291,21 @@ void DrawCursor()
// Cursor may not exist if we are loading a game or something.
// Only draw it if it exists
if (GameCursor == NULL || IsDemoMode()) {
SDL_ShowCursor(SDL_DISABLE);
ActuallyVisibleGameCursor = NULL;
return;
}
const PixelPos pos = CursorScreenPos - GameCursor->HotPos;
if (!GameRunning && !Editor.Running) {
if (!HiddenSurface
|| HiddenSurface->w != GameCursor->G->getWidth()
|| HiddenSurface->h != GameCursor->G->getHeight()) {
if (HiddenSurface) {
VideoPaletteListRemove(HiddenSurface);
SDL_FreeSurface(HiddenSurface);
}
HiddenSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
GameCursor->G->getWidth(),
GameCursor->G->getHeight(),
TheScreen->format->BitsPerPixel,
TheScreen->format->Rmask,
TheScreen->format->Gmask,
TheScreen->format->Bmask,
TheScreen->format->Amask);
// Last, Normal cursor. This is a (hardware) cursor drawn by SDL, so only needs to be set if something changed
if (ActuallyVisibleGameCursor != GameCursor || GameCursor->SpriteFrame != VisibleGameCursorFrame) {
if (!GameCursor->G->IsLoaded()) {
GameCursor->G->Load();
}
SDL_Rect srcRect = { Sint16(pos.x), Sint16(pos.y), Uint16(GameCursor->G->getWidth()), Uint16(GameCursor->G->getHeight())};
SDL_BlitSurface(TheScreen, &srcRect, HiddenSurface, NULL);
SDL_SetCursor(GameCursor->GetSDLCursor());
SDL_ShowCursor(SDL_ENABLE);
ActuallyVisibleGameCursor = GameCursor;
VisibleGameCursorFrame = GameCursor->SpriteFrame;
}
// Last, Normal cursor.
if (!GameCursor->G->IsLoaded()) {
GameCursor->G->Load();
}
GameCursor->G->DrawFrameClip(GameCursor->SpriteFrame, pos.x, pos.y);
}
/**
@ -295,11 +313,8 @@ void DrawCursor()
*/
void HideCursor()
{
if (!GameRunning && !Editor.Running && GameCursor) {
const PixelPos pos = CursorScreenPos - GameCursor->HotPos;
SDL_Rect dstRect = {Sint16(pos.x), Sint16(pos.y), 0, 0 };
SDL_BlitSurface(HiddenSurface, NULL, TheScreen, &dstRect);
}
SDL_ShowCursor(SDL_DISABLE);
ActuallyVisibleGameCursor = NULL;
}
/**

View file

@ -820,7 +820,6 @@ void RealizeVideoMemory()
}
NumRects = 0;
}
HideCursor();
}
/**