27 #include <boost/logic/tribool.hpp>
36 using cursor_ptr_t = std::unique_ptr<SDL_Cursor, std::function<void(SDL_Cursor*)>>;
55 std::array<cursor_data, cursor::NUM_CURSORS> available_cursors {{
57 {
nullptr, boost::indeterminate,
"normal.png",
"normal.png", 0, 0 },
58 {
nullptr, boost::indeterminate,
"wait-alt.png",
"wait.png", 0, 0 },
59 {
nullptr, boost::indeterminate,
"ibeam.png",
"ibeam.png", 14, 14 },
60 {
nullptr, boost::indeterminate,
"move.png",
"move.png", 0, 0 },
61 {
nullptr, boost::indeterminate,
"attack.png",
"attack.png", 0, 0 },
62 {
nullptr, boost::indeterminate,
"select.png",
"select.png", 0, 0 },
63 {
nullptr, boost::indeterminate,
"move_drag_alt.png",
"move_drag.png", 2, 20 },
64 {
nullptr, boost::indeterminate,
"attack_drag_alt.png",
"attack_drag.png", 3, 22 },
65 {
nullptr, boost::indeterminate,
"no_cursor.png",
"", 0, 0 }
67 {
nullptr, boost::indeterminate,
"normal.png",
"normal.png", 0, 0 },
68 {
nullptr, boost::indeterminate,
"wait.png",
"wait.png", 0, 0 },
69 {
nullptr, boost::indeterminate,
"ibeam.png",
"ibeam.png", 14, 14 },
70 {
nullptr, boost::indeterminate,
"move.png",
"move.png", 0, 0 },
71 {
nullptr, boost::indeterminate,
"attack.png",
"attack.png", 0, 0 },
72 {
nullptr, boost::indeterminate,
"select.png",
"select.png", 0, 0 },
73 {
nullptr, boost::indeterminate,
"move_drag.png",
"move_drag.png", 2, 20 },
74 {
nullptr, boost::indeterminate,
"attack_drag.png",
"attack_drag.png", 3, 22 },
75 {
nullptr, boost::indeterminate,
"no_cursor.png",
"", 0, 0 }
82 bool have_focus =
true;
84 bool use_color_cursors()
99 std::size_t cursor_width = 16;
101 std::size_t cursor_width =
surf->w;
102 if((cursor_width % 8) != 0) {
103 cursor_width += 8 - (cursor_width % 8);
107 std::vector<uint8_t>
data((cursor_width *
surf->h) / 8, 0);
108 std::vector<uint8_t> mask(
data.size(), 0);
113 const uint32_t*
const pixels = lock.pixels();
115 for(
int y = 0; y !=
surf->h; ++y) {
116 for(
int x = 0; x !=
surf->w; ++x) {
117 if(
static_cast<std::size_t
>(x) < cursor_width) {
119 SDL_GetRGBA(pixels[y *
surf->w + x],
surf->format, &r, &
g, &
b, &a);
121 const std::size_t
index = y * cursor_width + x;
122 const std::size_t shift = 7 - (
index % 8);
124 const uint8_t trans = (a < 128 ? 0 : 1) << shift;
125 const uint8_t
black = (trans == 0 || (r +
g +
b) / 3 > 128 ? 0 : 1) << shift;
128 mask[
index / 8] |= trans;
133 return SDL_CreateCursor(&
data[0], &mask[0], cursor_width,
surf->h, 0, 0);
138 const bool use_color = use_color_cursors();
139 cursor_data&
data = available_cursors[
type];
141 if(
data.cursor ==
nullptr || boost::indeterminate(
data.is_color) ||
data.is_color != use_color) {
142 static const std::string color_prefix =
"cursors/";
143 static const std::string bw_prefix =
"cursors-bw/";
149 data.cursor = cursor_ptr_t(SDL_CreateColorCursor(
surf,
data.hot_x,
data.hot_y), SDL_FreeCursor);
154 data.cursor = cursor_ptr_t(create_cursor(
surf), SDL_FreeCursor);
157 data.is_color = use_color;
160 return data.cursor.get();
167 SDL_ShowCursor(SDL_ENABLE);
173 SDL_ShowCursor(SDL_ENABLE);
180 current_cursor =
type;
187 SDL_Cursor* cursor_image = get_cursor(current_cursor);
191 SDL_SetCursor(cursor_image);
193 SDL_ShowCursor(SDL_ENABLE);
198 switch(current_cursor) {
218 return current_cursor;
231 : old_(current_cursor)
Helper class for pinning SDL surfaces into memory.
surface & make_neutral()
Converts this surface to a neutral format if it is not already.
void set_dragging(bool drag)
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
void set_focus(bool focus)
surface get_surface(const image::locator &i_locator, TYPE type, bool skip_cache)
Returns an image surface suitable for software manipulation.
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.