summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-3.2.20/test/testpen.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-08-30 16:53:58 -0700
committer3gg <3gg@shellblade.net>2025-08-30 16:53:58 -0700
commit6aaedb813fa11ba0679c3051bc2eb28646b9506c (patch)
tree34acbfc9840e02cb4753e6306ea7ce978bf8b58e /src/contrib/SDL-3.2.20/test/testpen.c
parent8f228ade99dd3d4c8da9b78ade1815c9adf85c8f (diff)
Update to SDL3
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/testpen.c')
-rw-r--r--src/contrib/SDL-3.2.20/test/testpen.c287
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
18typedef 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
31static SDL_Renderer *renderer = NULL;
32static SDLTest_CommonState *state = NULL;
33static SDL_Texture *white_pixel = NULL;
34static Pen pens;
35
36
37SDL_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
96static 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
107SDL_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
219static 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], &center, 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], &center, SDL_FLIP_NONE);
256 }
257}
258
259SDL_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
276void 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