Atlas - testpen.c

Home / ext / SDL / test Lines: 1 | Size: 9557 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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 bool in_proximity; 29 struct Pen *next; 30} Pen; 31 32static SDL_Renderer *renderer = NULL; 33static SDLTest_CommonState *state = NULL; 34static SDL_Texture *white_pixel = NULL; 35static Pen pens; 36 37 38SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) 39{ 40 int i; 41 42 SDL_srand(0); 43 44 /* Initialize test framework */ 45 state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); 46 if (!state) { 47 return SDL_APP_FAILURE; 48 } 49 50 /* Parse commandline */ 51 for (i = 1; i < argc;) { 52 int consumed = SDLTest_CommonArg(state, i); 53 if (consumed <= 0) { 54 static const char *options[] = { 55 NULL, 56 }; 57 SDLTest_CommonLogUsage(state, argv[0], options); 58 SDL_Quit(); 59 SDLTest_CommonDestroyState(state); 60 return 1; 61 } 62 i += consumed; 63 } 64 65 state->num_windows = 1; 66 67 /* Load the SDL library */ 68 if (!SDLTest_CommonInit(state)) { 69 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError()); 70 return SDL_APP_FAILURE; 71 } 72 73 SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE); 74 75 renderer = state->renderers[0]; 76 if (!renderer) { 77 /* SDL_Log("Couldn't create renderer: %s", SDL_GetError()); */ 78 return SDL_APP_FAILURE; 79 } 80 81 white_pixel = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, 16, 16); 82 if (!white_pixel) { 83 SDL_Log("Couldn't create white_pixel texture: %s", SDL_GetError()); 84 return SDL_APP_FAILURE; 85 } else { 86 const SDL_Rect rect = { 0, 0, 16, 16 }; 87 Uint32 pixels[16 * 16]; 88 SDL_memset(pixels, 0xFF, sizeof (pixels)); 89 SDL_UpdateTexture(white_pixel, &rect, pixels, 16 * sizeof (Uint32)); 90 } 91 92 SDL_HideCursor(); 93 94 return SDL_APP_CONTINUE; 95} 96 97static Pen *FindPen(SDL_PenID which) 98{ 99 Pen *i; 100 for (i = pens.next; i != NULL; i = i->next) { 101 if (i->pen == which) { 102 return i; 103 } 104 } 105 return NULL; 106} 107 108SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) 109{ 110 Pen *pen = NULL; 111 Pen *i = NULL; 112 113 switch (event->type) { 114 case SDL_EVENT_PEN_PROXIMITY_IN: 115 SDL_Log("Pen %" SDL_PRIu32 " enters proximity!", event->pproximity.which); 116 117 for (i = pens.next; i != NULL; i = i->next) { 118 if (i->pen == event->pproximity.which) { 119 pen = i; 120 break; 121 } 122 } 123 124 if (!pen) { 125 SDL_Log("This is the first time we've seen this pen."); 126 pen = (Pen *) SDL_calloc(1, sizeof (*pen)); 127 if (!pen) { 128 SDL_Log("Out of memory!"); 129 return SDL_APP_FAILURE; 130 } 131 132 pen->pen = event->pproximity.which; 133 pen->r = (Uint8) SDL_rand(256); 134 pen->g = (Uint8) SDL_rand(256); 135 pen->b = (Uint8) SDL_rand(256); 136 pen->x = 320.0f; 137 pen->y = 240.0f; 138 pen->next = pens.next; 139 pens.next = pen; 140 } 141 142 pen->in_proximity = true; 143 return SDL_APP_CONTINUE; 144 145 case SDL_EVENT_PEN_PROXIMITY_OUT: 146 SDL_Log("Pen %" SDL_PRIu32 " leaves proximity!", event->pproximity.which); 147 for (i = pens.next; i != NULL; i = i->next) { 148 if (i->pen == event->pproximity.which) { 149 i->in_proximity = false; 150 break; 151 } 152 } 153 return SDL_APP_CONTINUE; 154 155 case SDL_EVENT_PEN_DOWN: 156 /*SDL_Log("Pen %" SDL_PRIu32 " down!", event->ptouch.which);*/ 157 pen = FindPen(event->ptouch.which); 158 if (pen) { 159 pen->touching = true; 160 pen->eraser = (event->ptouch.eraser != 0); 161 } 162 return SDL_APP_CONTINUE; 163 164 case SDL_EVENT_PEN_UP: 165 /*SDL_Log("Pen %" SDL_PRIu32 " up!", event->ptouch.which);*/ 166 pen = FindPen(event->ptouch.which); 167 if (pen) { 168 pen->touching = false; 169 pen->axes[SDL_PEN_AXIS_PRESSURE] = 0.0f; 170 } 171 return SDL_APP_CONTINUE; 172 173 case SDL_EVENT_PEN_BUTTON_DOWN: 174 /*SDL_Log("Pen %" SDL_PRIu32 " button %d down!", event->pbutton.which, (int) event->pbutton.button);*/ 175 pen = FindPen(event->ptouch.which); 176 if (pen) { 177 pen->buttons |= (1 << (event->pbutton.button-1)); 178 } 179 return SDL_APP_CONTINUE; 180 181 case SDL_EVENT_PEN_BUTTON_UP: 182 /*SDL_Log("Pen %" SDL_PRIu32 " button %d up!", event->pbutton.which, (int) event->pbutton.button);*/ 183 pen = FindPen(event->ptouch.which); 184 if (pen) { 185 pen->buttons &= ~(1 << (event->pbutton.button-1)); 186 } 187 return SDL_APP_CONTINUE; 188 189 case SDL_EVENT_PEN_MOTION: 190 /*SDL_Log("Pen %" SDL_PRIu32 " moved to (%f,%f)!", event->pmotion.which, event->pmotion.x, event->pmotion.y);*/ 191 pen = FindPen(event->ptouch.which); 192 if (pen) { 193 pen->x = event->pmotion.x; 194 pen->y = event->pmotion.y; 195 } 196 return SDL_APP_CONTINUE; 197 198 case SDL_EVENT_PEN_AXIS: 199 /*SDL_Log("Pen %" SDL_PRIu32 " axis %d is now %f!", event->paxis.which, (int) event->paxis.axis, event->paxis.value);*/ 200 pen = FindPen(event->ptouch.which); 201 if (pen && (event->paxis.axis < SDL_arraysize(pen->axes))) { 202 pen->axes[event->paxis.axis] = event->paxis.value; 203 } 204 return SDL_APP_CONTINUE; 205 206 case SDL_EVENT_KEY_DOWN: { 207 const SDL_Keycode sym = event->key.key; 208 if (sym == SDLK_ESCAPE || sym == SDLK_AC_BACK) { 209 SDL_Log("Key : Escape!"); 210 return SDL_APP_SUCCESS; 211 } 212 break; 213 } 214 215 case SDL_EVENT_QUIT: 216 return SDL_APP_SUCCESS; 217 218 default: 219 break; 220 } 221 222 return SDLTest_CommonEventMainCallbacks(state, event); 223} 224 225static void DrawOnePen(Pen *pen, int num) 226{ 227 int i; 228 229 if (!pen->in_proximity) { 230 return; 231 } 232 233 /* draw button presses for this pen. A square for each in the pen's color, offset down the screen so they don't overlap. */ 234 SDL_SetRenderDrawColor(renderer, pen->r, pen->g, pen->b, 255); 235 for (i = 0; i < 8; i++) { /* we assume you don't have more than 8 buttons atm... */ 236 if (pen->buttons & (1 << i)) { 237 const SDL_FRect rect = { 30.0f * ((float) i), ((float) num) * 30.0f, 30.0f, 30.0f }; 238 SDL_RenderFillRect(renderer, &rect); 239 } 240 } 241 242 /* draw a square to represent pressure. Always green for eraser and blue for pen */ 243 /* we do this with a texture, so we can trivially rotate it, which SDL_RenderFillRect doesn't offer. */ 244 if (pen->axes[SDL_PEN_AXIS_PRESSURE] > 0.0f) { 245 const float size = (150.0f * pen->axes[SDL_PEN_AXIS_PRESSURE]) + 20.0f; 246 const float halfsize = size / 2.0f; 247 const SDL_FRect rect = { pen->x - halfsize, pen->y - halfsize, size, size }; 248 const SDL_FPoint center = { halfsize, halfsize }; 249 if (pen->eraser) { 250 SDL_SetTextureColorMod(white_pixel, 0, 255, 0); 251 } else { 252 SDL_SetTextureColorMod(white_pixel, 0, 0, 255); 253 } 254 SDL_RenderTextureRotated(renderer, white_pixel, NULL, &rect, pen->axes[SDL_PEN_AXIS_ROTATION], &center, SDL_FLIP_NONE); 255 } 256 257 /* draw a little square for position in the center of the pressure, with the pen-specific color. */ 258 { 259 const float distance = pen->touching ? 0.0f : SDL_clamp(pen->axes[SDL_PEN_AXIS_DISTANCE], 0.0f, 1.0f); 260 const float size = 10 + (30.0f * (1.0f - distance)); 261 const float halfsize = size / 2.0f; 262 const SDL_FRect rect = { pen->x - halfsize, pen->y - halfsize, size, size }; 263 const SDL_FPoint center = { halfsize, halfsize }; 264 SDL_SetTextureColorMod(white_pixel, pen->r, pen->g, pen->b); 265 SDL_RenderTextureRotated(renderer, white_pixel, NULL, &rect, pen->axes[SDL_PEN_AXIS_ROTATION], &center, SDL_FLIP_NONE); 266 } 267} 268 269SDL_AppResult SDL_AppIterate(void *appstate) 270{ 271 int num = 0; 272 Pen *pen; 273 274 SDL_SetRenderDrawColor(renderer, 0x99, 0x99, 0x99, 255); 275 SDL_RenderClear(renderer); 276 277 for (pen = pens.next; pen != NULL; pen = pen->next, num++) { 278 DrawOnePen(pen, num); 279 } 280 281 SDL_RenderPresent(renderer); 282 283 return SDL_APP_CONTINUE; 284} 285 286void SDL_AppQuit(void *appstate, SDL_AppResult result) 287{ 288 Pen *i, *next; 289 for (i = pens.next; i != NULL; i = next) { 290 next = i->next; 291 SDL_free(i); 292 } 293 pens.next = NULL; 294 SDL_DestroyTexture(white_pixel); 295 SDLTest_CommonQuit(state); 296} 297 298
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.