diff options
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/testpen.c')
-rw-r--r-- | src/contrib/SDL-3.2.20/test/testpen.c | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/test/testpen.c b/src/contrib/SDL-3.2.20/test/testpen.c new file mode 100644 index 0000000..bb6e7d2 --- /dev/null +++ b/src/contrib/SDL-3.2.20/test/testpen.c | |||
@@ -0,0 +1,287 @@ | |||
1 | /* | ||
2 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
3 | |||
4 | This software is provided 'as-is', without any express or implied | ||
5 | warranty. In no event will the authors be held liable for any damages | ||
6 | arising from the use of this software. | ||
7 | |||
8 | Permission is granted to anyone to use this software for any purpose, | ||
9 | including commercial applications, and to alter it and redistribute it | ||
10 | freely. | ||
11 | */ | ||
12 | |||
13 | #define SDL_MAIN_USE_CALLBACKS 1 | ||
14 | #include <SDL3/SDL_main.h> | ||
15 | #include <SDL3/SDL_test.h> | ||
16 | #include <SDL3/SDL_test_common.h> | ||
17 | |||
18 | typedef struct Pen | ||
19 | { | ||
20 | SDL_PenID pen; | ||
21 | Uint8 r, g, b; | ||
22 | float axes[SDL_PEN_AXIS_COUNT]; | ||
23 | float x; | ||
24 | float y; | ||
25 | Uint32 buttons; | ||
26 | bool eraser; | ||
27 | bool touching; | ||
28 | struct Pen *next; | ||
29 | } Pen; | ||
30 | |||
31 | static SDL_Renderer *renderer = NULL; | ||
32 | static SDLTest_CommonState *state = NULL; | ||
33 | static SDL_Texture *white_pixel = NULL; | ||
34 | static Pen pens; | ||
35 | |||
36 | |||
37 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
38 | { | ||
39 | int i; | ||
40 | |||
41 | SDL_srand(0); | ||
42 | |||
43 | /* Initialize test framework */ | ||
44 | state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); | ||
45 | if (!state) { | ||
46 | return SDL_APP_FAILURE; | ||
47 | } | ||
48 | |||
49 | /* Parse commandline */ | ||
50 | for (i = 1; i < argc;) { | ||
51 | int consumed = SDLTest_CommonArg(state, i); | ||
52 | if (consumed <= 0) { | ||
53 | static const char *options[] = { | ||
54 | NULL, | ||
55 | }; | ||
56 | SDLTest_CommonLogUsage(state, argv[0], options); | ||
57 | SDL_Quit(); | ||
58 | SDLTest_CommonDestroyState(state); | ||
59 | return 1; | ||
60 | } | ||
61 | i += consumed; | ||
62 | } | ||
63 | |||
64 | state->num_windows = 1; | ||
65 | |||
66 | /* Load the SDL library */ | ||
67 | if (!SDLTest_CommonInit(state)) { | ||
68 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); | ||
69 | return SDL_APP_FAILURE; | ||
70 | } | ||
71 | |||
72 | SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE); | ||
73 | |||
74 | renderer = state->renderers[0]; | ||
75 | if (!renderer) { | ||
76 | /* SDL_Log("Couldn't create renderer: %s", SDL_GetError()); */ | ||
77 | return SDL_APP_FAILURE; | ||
78 | } | ||
79 | |||
80 | white_pixel = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, 16, 16); | ||
81 | if (!white_pixel) { | ||
82 | SDL_Log("Couldn't create white_pixel texture: %s", SDL_GetError()); | ||
83 | return SDL_APP_FAILURE; | ||
84 | } else { | ||
85 | const SDL_Rect rect = { 0, 0, 16, 16 }; | ||
86 | Uint32 pixels[16 * 16]; | ||
87 | SDL_memset(pixels, 0xFF, sizeof (pixels)); | ||
88 | SDL_UpdateTexture(white_pixel, &rect, pixels, 16 * sizeof (Uint32)); | ||
89 | } | ||
90 | |||
91 | SDL_HideCursor(); | ||
92 | |||
93 | return SDL_APP_CONTINUE; | ||
94 | } | ||
95 | |||
96 | static Pen *FindPen(SDL_PenID which) | ||
97 | { | ||
98 | Pen *i; | ||
99 | for (i = pens.next; i != NULL; i = i->next) { | ||
100 | if (i->pen == which) { | ||
101 | return i; | ||
102 | } | ||
103 | } | ||
104 | return NULL; | ||
105 | } | ||
106 | |||
107 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
108 | { | ||
109 | Pen *pen = NULL; | ||
110 | |||
111 | switch (event->type) { | ||
112 | case SDL_EVENT_PEN_PROXIMITY_IN: { | ||
113 | pen = (Pen *) SDL_calloc(1, sizeof (*pen)); | ||
114 | if (!pen) { | ||
115 | SDL_Log("Out of memory!"); | ||
116 | return SDL_APP_FAILURE; | ||
117 | } | ||
118 | |||
119 | SDL_Log("Pen %" SDL_PRIu32 " enters proximity!", event->pproximity.which); | ||
120 | pen->pen = event->pproximity.which; | ||
121 | pen->r = (Uint8) SDL_rand(256); | ||
122 | pen->g = (Uint8) SDL_rand(256); | ||
123 | pen->b = (Uint8) SDL_rand(256); | ||
124 | pen->x = 320.0f; | ||
125 | pen->y = 240.0f; | ||
126 | pen->next = pens.next; | ||
127 | pens.next = pen; | ||
128 | |||
129 | return SDL_APP_CONTINUE; | ||
130 | } | ||
131 | |||
132 | case SDL_EVENT_PEN_PROXIMITY_OUT: { | ||
133 | Pen *prev = &pens; | ||
134 | Pen *i; | ||
135 | |||
136 | SDL_Log("Pen %" SDL_PRIu32 " leaves proximity!", event->pproximity.which); | ||
137 | for (i = pens.next; i != NULL; i = i->next) { | ||
138 | if (i->pen == event->pproximity.which) { | ||
139 | prev->next = i->next; | ||
140 | SDL_free(i); | ||
141 | break; | ||
142 | } | ||
143 | prev = i; | ||
144 | } | ||
145 | |||
146 | return SDL_APP_CONTINUE; | ||
147 | } | ||
148 | |||
149 | case SDL_EVENT_PEN_DOWN: | ||
150 | /*SDL_Log("Pen %" SDL_PRIu32 " down!", event->ptouch.which);*/ | ||
151 | pen = FindPen(event->ptouch.which); | ||
152 | if (pen) { | ||
153 | pen->touching = true; | ||
154 | pen->eraser = (event->ptouch.eraser != 0); | ||
155 | } | ||
156 | return SDL_APP_CONTINUE; | ||
157 | |||
158 | case SDL_EVENT_PEN_UP: | ||
159 | /*SDL_Log("Pen %" SDL_PRIu32 " up!", event->ptouch.which);*/ | ||
160 | pen = FindPen(event->ptouch.which); | ||
161 | if (pen) { | ||
162 | pen->touching = false; | ||
163 | pen->axes[SDL_PEN_AXIS_PRESSURE] = 0.0f; | ||
164 | } | ||
165 | return SDL_APP_CONTINUE; | ||
166 | |||
167 | case SDL_EVENT_PEN_BUTTON_DOWN: | ||
168 | /*SDL_Log("Pen %" SDL_PRIu32 " button %d down!", event->pbutton.which, (int) event->pbutton.button);*/ | ||
169 | pen = FindPen(event->ptouch.which); | ||
170 | if (pen) { | ||
171 | pen->buttons |= (1 << (event->pbutton.button-1)); | ||
172 | } | ||
173 | return SDL_APP_CONTINUE; | ||
174 | |||
175 | case SDL_EVENT_PEN_BUTTON_UP: | ||
176 | /*SDL_Log("Pen %" SDL_PRIu32 " button %d up!", event->pbutton.which, (int) event->pbutton.button);*/ | ||
177 | pen = FindPen(event->ptouch.which); | ||
178 | if (pen) { | ||
179 | pen->buttons &= ~(1 << (event->pbutton.button-1)); | ||
180 | } | ||
181 | return SDL_APP_CONTINUE; | ||
182 | |||
183 | case SDL_EVENT_PEN_MOTION: | ||
184 | /*SDL_Log("Pen %" SDL_PRIu32 " moved to (%f,%f)!", event->pmotion.which, event->pmotion.x, event->pmotion.y);*/ | ||
185 | pen = FindPen(event->ptouch.which); | ||
186 | if (pen) { | ||
187 | pen->x = event->pmotion.x; | ||
188 | pen->y = event->pmotion.y; | ||
189 | } | ||
190 | return SDL_APP_CONTINUE; | ||
191 | |||
192 | case SDL_EVENT_PEN_AXIS: | ||
193 | /*SDL_Log("Pen %" SDL_PRIu32 " axis %d is now %f!", event->paxis.which, (int) event->paxis.axis, event->paxis.value);*/ | ||
194 | pen = FindPen(event->ptouch.which); | ||
195 | if (pen && (event->paxis.axis < SDL_arraysize(pen->axes))) { | ||
196 | pen->axes[event->paxis.axis] = event->paxis.value; | ||
197 | } | ||
198 | return SDL_APP_CONTINUE; | ||
199 | |||
200 | case SDL_EVENT_KEY_DOWN: { | ||
201 | const SDL_Keycode sym = event->key.key; | ||
202 | if (sym == SDLK_ESCAPE || sym == SDLK_AC_BACK) { | ||
203 | SDL_Log("Key : Escape!"); | ||
204 | return SDL_APP_SUCCESS; | ||
205 | } | ||
206 | break; | ||
207 | } | ||
208 | |||
209 | case SDL_EVENT_QUIT: | ||
210 | return SDL_APP_SUCCESS; | ||
211 | |||
212 | default: | ||
213 | break; | ||
214 | } | ||
215 | |||
216 | return SDLTest_CommonEventMainCallbacks(state, event); | ||
217 | } | ||
218 | |||
219 | static void DrawOnePen(Pen *pen, int num) | ||
220 | { | ||
221 | int i; | ||
222 | |||
223 | /* draw button presses for this pen. A square for each in the pen's color, offset down the screen so they don't overlap. */ | ||
224 | SDL_SetRenderDrawColor(renderer, pen->r, pen->g, pen->b, 255); | ||
225 | for (i = 0; i < 8; i++) { /* we assume you don't have more than 8 buttons atm... */ | ||
226 | if (pen->buttons & (1 << i)) { | ||
227 | const SDL_FRect rect = { 30.0f * ((float) i), ((float) num) * 30.0f, 30.0f, 30.0f }; | ||
228 | SDL_RenderFillRect(renderer, &rect); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /* draw a square to represent pressure. Always green for eraser and blue for pen */ | ||
233 | /* we do this with a texture, so we can trivially rotate it, which SDL_RenderFillRect doesn't offer. */ | ||
234 | if (pen->axes[SDL_PEN_AXIS_PRESSURE] > 0.0f) { | ||
235 | const float size = (150.0f * pen->axes[SDL_PEN_AXIS_PRESSURE]) + 20.0f; | ||
236 | const float halfsize = size / 2.0f; | ||
237 | const SDL_FRect rect = { pen->x - halfsize, pen->y - halfsize, size, size }; | ||
238 | const SDL_FPoint center = { halfsize, halfsize }; | ||
239 | if (pen->eraser) { | ||
240 | SDL_SetTextureColorMod(white_pixel, 0, 255, 0); | ||
241 | } else { | ||
242 | SDL_SetTextureColorMod(white_pixel, 0, 0, 255); | ||
243 | } | ||
244 | SDL_RenderTextureRotated(renderer, white_pixel, NULL, &rect, pen->axes[SDL_PEN_AXIS_ROTATION], ¢er, SDL_FLIP_NONE); | ||
245 | } | ||
246 | |||
247 | /* draw a little square for position in the center of the pressure, with the pen-specific color. */ | ||
248 | { | ||
249 | const float distance = pen->touching ? 0.0f : SDL_clamp(pen->axes[SDL_PEN_AXIS_DISTANCE], 0.0f, 1.0f); | ||
250 | const float size = 10 + (30.0f * (1.0f - distance)); | ||
251 | const float halfsize = size / 2.0f; | ||
252 | const SDL_FRect rect = { pen->x - halfsize, pen->y - halfsize, size, size }; | ||
253 | const SDL_FPoint center = { halfsize, halfsize }; | ||
254 | SDL_SetTextureColorMod(white_pixel, pen->r, pen->g, pen->b); | ||
255 | SDL_RenderTextureRotated(renderer, white_pixel, NULL, &rect, pen->axes[SDL_PEN_AXIS_ROTATION], ¢er, SDL_FLIP_NONE); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
260 | { | ||
261 | int num = 0; | ||
262 | Pen *pen; | ||
263 | |||
264 | SDL_SetRenderDrawColor(renderer, 0x99, 0x99, 0x99, 255); | ||
265 | SDL_RenderClear(renderer); | ||
266 | |||
267 | for (pen = pens.next; pen != NULL; pen = pen->next, num++) { | ||
268 | DrawOnePen(pen, num); | ||
269 | } | ||
270 | |||
271 | SDL_RenderPresent(renderer); | ||
272 | |||
273 | return SDL_APP_CONTINUE; | ||
274 | } | ||
275 | |||
276 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
277 | { | ||
278 | Pen *i, *next; | ||
279 | for (i = pens.next; i != NULL; i = next) { | ||
280 | next = i->next; | ||
281 | SDL_free(i); | ||
282 | } | ||
283 | pens.next = NULL; | ||
284 | SDL_DestroyTexture(white_pixel); | ||
285 | SDLTest_CommonQuit(state); | ||
286 | } | ||
287 | |||