diff --git a/src/include/cursor.h b/src/include/cursor.h index 21bfa72b6..664000b73 100644 --- a/src/include/cursor.h +++ b/src/include/cursor.h @@ -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 diff --git a/src/video/cursor.cpp b/src/video/cursor.cpp index d0cd1b2b9..9dd6bba57 100644 --- a/src/video/cursor.cpp +++ b/src/video/cursor.cpp @@ -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; } /** diff --git a/src/video/sdl.cpp b/src/video/sdl.cpp index 552ceca83..04c739023 100644 --- a/src/video/sdl.cpp +++ b/src/video/sdl.cpp @@ -820,7 +820,6 @@ void RealizeVideoMemory() } NumRects = 0; } - HideCursor(); } /**