1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
#ifndef CURSOR_H
#define CURSOR_H
#pragma once
#include <SDL_mouse.h>
#include "globalincs/pstypes.h"
#include "cmdline/cmdline.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
Cursor(const Cursor&); // Not implemented
Cursor& operator=(const Cursor&); // Not implemented
public:
/**
* @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
|