1 #include "cursor.h"
2
3 #include "core/config.h"
4 #include "core/png_read.h"
5 #include "game/system.h"
6 #include "graphics/color.h"
7 #include "input/cursor.h"
8 #include "platform/screen.h"
9 #include "platform/haiku/haiku.h"
10 #include "platform/switch/switch.h"
11 #include "platform/vita/vita.h"
12
13 #include "SDL.h"
14
15 #include <string.h>
16
17 static char cursor_path[64] = "Color_Cursors/";
18 static size_t cursor_path_offset;
19
20 static struct {
21 SDL_Cursor *cursors[CURSOR_MAX];
22 SDL_Surface *surfaces[CURSOR_MAX];
23 cursor_shape current_shape;
24 cursor_scale current_scale;
25 } data;
26
27 static const color_t mouse_colors[] = {
28 ALPHA_TRANSPARENT,
29 ALPHA_TRANSPARENT,
30 ALPHA_TRANSPARENT,
31 ALPHA_OPAQUE | COLOR_BLACK,
32 ALPHA_OPAQUE | COLOR_MOUSE_DARK_GRAY,
33 ALPHA_OPAQUE | COLOR_MOUSE_MEDIUM_GRAY,
34 ALPHA_OPAQUE | COLOR_MOUSE_LIGHT_GRAY,
35 ALPHA_OPAQUE | COLOR_WHITE
36 };
37
generate_cursor_surface(const cursor * c)38 static SDL_Surface *generate_cursor_surface(const cursor *c)
39 {
40 int size = platform_cursor_get_texture_size(c);
41 SDL_Surface *cursor_surface =
42 SDL_CreateRGBSurface(0, size, size, 32,
43 COLOR_CHANNEL_RED, COLOR_CHANNEL_GREEN, COLOR_CHANNEL_BLUE, COLOR_CHANNEL_ALPHA);
44 color_t *pixels = cursor_surface->pixels;
45 SDL_memset(pixels, 0, sizeof(color_t) * size * size);
46 if (!config_get(CONFIG_SCREEN_COLOR_CURSORS) ||
47 !png_read(cursor_path, pixels, size, size)) {
48 for (int y = 0; y < c->height; y++) {
49 for (int x = 0; x < c->width; x++) {
50 pixels[y * size + x] = mouse_colors[c->data[y * c->width + x] - 32];
51 }
52 }
53 }
54 return cursor_surface;
55 }
56
get_cursor_scale(int scale_percentage)57 static cursor_scale get_cursor_scale(int scale_percentage)
58 {
59 if (scale_percentage <= 100) {
60 return CURSOR_SCALE_1;
61 } else if (scale_percentage <= 150) {
62 return CURSOR_SCALE_1_5;
63 } else {
64 return CURSOR_SCALE_2;
65 }
66 }
67
system_init_cursors(int scale_percentage)68 void system_init_cursors(int scale_percentage)
69 {
70 data.current_scale = get_cursor_scale(scale_percentage);
71 for (int i = 0; i < CURSOR_MAX; i++) {
72 const cursor *c = input_cursor_data(i, data.current_scale);
73 if (data.surfaces[i]) {
74 SDL_FreeSurface(data.surfaces[i]);
75 }
76 if (data.cursors[i]) {
77 SDL_FreeCursor(data.cursors[i]);
78 }
79 data.surfaces[i] = generate_cursor_surface(c);
80 #ifndef PLATFORM_USE_SOFTWARE_CURSOR
81 data.cursors[i] = SDL_CreateColorCursor(data.surfaces[i], c->hotspot_x, c->hotspot_y);
82 #else
83 SDL_ShowCursor(SDL_DISABLE);
84 platform_screen_generate_mouse_cursor_texture(i, data.current_scale, data.surfaces[i]->pixels);
85 #endif
86 }
87 system_set_cursor(data.current_shape);
88 }
89
system_set_cursor(int cursor_id)90 void system_set_cursor(int cursor_id)
91 {
92 data.current_shape = cursor_id;
93 #ifndef PLATFORM_USE_SOFTWARE_CURSOR
94 SDL_SetCursor(data.cursors[cursor_id]);
95 #endif
96 }
97
platform_cursor_get_current_shape(void)98 cursor_shape platform_cursor_get_current_shape(void)
99 {
100 return data.current_shape;
101 }
102
platform_cursor_get_current_scale(void)103 cursor_scale platform_cursor_get_current_scale(void)
104 {
105 return data.current_scale;
106 }
107
platform_cursor_get_texture_size(const cursor * c)108 int platform_cursor_get_texture_size(const cursor *c)
109 {
110 int width;
111 int height;
112 if (config_get(CONFIG_SCREEN_COLOR_CURSORS)) {
113 if (!cursor_path_offset) {
114 cursor_path_offset = strlen(cursor_path);
115 }
116 strncpy(cursor_path + cursor_path_offset, c->png_path, 64 - cursor_path_offset);
117 if (!png_get_image_size(cursor_path, &width, &height)) {
118 width = c->width;
119 height = c->height;
120 }
121 } else {
122 width = c->width;
123 height = c->height;
124 }
125
126 int size = 32;
127 while (size < width || size < height) {
128 size *= 2;
129 }
130 return size;
131 }
132