Files
Taylor Richards 039880491a port to SDL3 (#7220)
Basic port from SDL2 to SDL3. Also updates imgui to 1.92.5.
2026-07-23 15:52:27 +02:00

196 lines
4.6 KiB
C++

#ifndef CURSOR_H
#define CURSOR_H
#include "globalincs/pstypes.h"
#include "io/timer.h"
#include <memory>
namespace io
{
namespace mouse
{
/**
* @brief A mouse cursor
*
* This class holds the SDL_Cursor objects which represent the individual animation frames
*/
class Cursor
{
private:
SCP_vector<SDL_Cursor*> mAnimationFrames; //!< The individual frames
int mBitmapHandle; //!< The bitmap of this cursor
UI_TIMESTAMP mBeginTimeStamp; //!< The UI timestamp when the animation was started, unused when not animated
size_t mLastFrame; //!< The last frame which was set
public:
Cursor(const Cursor&) = delete; // Not implemented
Cursor& operator=(const Cursor&) = delete; // Not implemented
/**
* @brief Default constructor
* @param bitmap The bitmap handle of the cursor. The cursor takes ownership over this handle
*/
explicit Cursor(int bitmap) : mBitmapHandle(bitmap), mLastFrame(static_cast<size_t>(-1)) {}
/**
* @brief Move constructor
*
* Transfers SDL resources to this newly constructed object
*/
Cursor(Cursor&& other) noexcept;
/**
* @brief Move operator
*
* Transfers SDL resources to this object
*/
Cursor& operator=(Cursor&& other) noexcept;
/**
* @brief Cursor destructor
*
* Frees the allocated SDL cursors
*/
~Cursor();
/**
* @brief Adds an animation frame
*
* @param frame The cursor frame to add
*/
void addFrame(SDL_Cursor* frame);
/**
* @brief Called to enable the cursor
* Either this function sets the cursor directly, or initializes values to #setCurrentFrame() works correctly
*/
void enable();
/**
* @brief Called to set the correct frame
*/
void setCurrentFrame();
/**
* @brief Query the cursors bitmap handle for bmpman
*/
int getBitmapHandle();
};
/**
* @brief Manages the cursor state of the game
*/
class CursorManager
{
private:
static CursorManager* mSingleton; //!< The singleton manager
SCP_vector<std::unique_ptr<Cursor>> mLoadedCursors; //!< A list of loaded cursors
Cursor* mCurrentCursor; //!< The current cursor
SCP_vector<std::pair<bool, bool>> mStatusStack; //!< Contains the stack of saved mouse statuses
/**
* @brief Default constructor
*
* @note This class should not be instantiated outside from this module
*/
CursorManager();
public:
/**
* @brief Releases the cursor resources
*/
~CursorManager();
/**
* @brief Loads a cursor
*
* Loads the specified file name as a cursor, by default this will try to load an animated cursor
*
* @param fileName The file name
* @param animated @c true to also load animated images
* @return The cursor or @c NULL if the process failed
*/
Cursor* loadCursor(const char* fileName, bool animated = true);
/**
* @brief Loads a cursor from a bitmap handle
* The returned cursor takes ownership over the passed handle.
*
* @param bitmapHandle The bitmap handle, must be a valid handle
* @return The new cursor
*/
Cursor* loadFromBitmap(int bitmapHandle);
/**
* @brief Sets the current cursor
* @param cursor The cursor instance to be set, may not be @c NULL
*/
void setCurrentCursor(Cursor* cursor);
/**
* @brief Show or hide the cursor.
*
* Optionally @c grab may be specified to grab or not grab the mouse when the cursor is hidden
*
* @param show @c true to show @c false to hide
* @param grab @c true to grab the mouse @c false to disable grabbing
*/
void showCursor(bool show, bool grab = false);
/**
* @brief Specifies if the cursor is shown
* @return @c true if shown ,@c false otherwise
*/
bool isCursorShown() { return mStatusStack.back().first; }
/**
* @brief Gets the current cursor
* @return The current cursor instance
*/
Cursor* getCurrentCursor() { return mCurrentCursor; }
/**
* @brief Pushes the current status onto the stack as a new entry
*/
void pushStatus();
/**
* @brief Removes the top status from the stack and restores the previous
* @returns The removed state
*/
std::pair<bool, bool> popStatus();
public:
/**
* @brief Gets the global CursorManager
* @return The CursorManager
*/
static CursorManager* get() { return mSingleton; }
/**
* @brief Initializes the Cursor system
*/
static void init();
/**
* @brief Do a cursor frame
* This is needed for animated cursors
*/
static void doFrame();
/**
* @brief Releases cursor resources
*/
static void shutdown();
};
}
}
#endif