123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /*
- Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely.
- */
- #define SDL_MAIN_USE_CALLBACKS 1
- #include <SDL3/SDL_main.h>
- #include <SDL3/SDL_test.h>
- #include <SDL3/SDL_test_common.h>
- typedef struct Pen
- {
- SDL_PenID pen;
- Uint8 r, g, b;
- float axes[SDL_PEN_AXIS_COUNT];
- float x;
- float y;
- Uint32 buttons;
- bool eraser;
- bool touching;
- struct Pen *next;
- } Pen;
- static SDL_Renderer *renderer = NULL;
- static SDLTest_CommonState *state = NULL;
- static SDL_Texture *white_pixel = NULL;
- static Pen pens;
- SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
- {
- int i;
- SDL_srand(0);
- /* Initialize test framework */
- state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
- if (!state) {
- return SDL_APP_FAILURE;
- }
- /* Parse commandline */
- for (i = 1; i < argc;) {
- int consumed = SDLTest_CommonArg(state, i);
- if (consumed <= 0) {
- static const char *options[] = {
- NULL,
- };
- SDLTest_CommonLogUsage(state, argv[0], options);
- SDL_Quit();
- SDLTest_CommonDestroyState(state);
- return 1;
- }
- i += consumed;
- }
- state->num_windows = 1;
- /* Load the SDL library */
- if (!SDLTest_CommonInit(state)) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError());
- return SDL_APP_FAILURE;
- }
- SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
- renderer = state->renderers[0];
- if (!renderer) {
- /* SDL_Log("Couldn't create renderer: %s", SDL_GetError()); */
- return SDL_APP_FAILURE;
- }
- white_pixel = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, 16, 16);
- if (!white_pixel) {
- SDL_Log("Couldn't create white_pixel texture: %s", SDL_GetError());
- return SDL_APP_FAILURE;
- } else {
- const SDL_Rect rect = { 0, 0, 16, 16 };
- Uint32 pixels[16 * 16];
- SDL_memset(pixels, 0xFF, sizeof (pixels));
- SDL_UpdateTexture(white_pixel, &rect, pixels, 16 * sizeof (Uint32));
- }
- SDL_HideCursor();
- return SDL_APP_CONTINUE;
- }
- static Pen *FindPen(SDL_PenID which)
- {
- Pen *i;
- for (i = pens.next; i != NULL; i = i->next) {
- if (i->pen == which) {
- return i;
- }
- }
- return NULL;
- }
- SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
- {
- Pen *pen = NULL;
- switch (event->type) {
- case SDL_EVENT_PEN_PROXIMITY_IN: {
- pen = (Pen *) SDL_calloc(1, sizeof (*pen));
- if (!pen) {
- SDL_Log("Out of memory!");
- return SDL_APP_FAILURE;
- }
- SDL_Log("Pen %" SDL_PRIu32 " enters proximity!", event->pproximity.which);
- pen->pen = event->pproximity.which;
- pen->r = (Uint8) SDL_rand(256);
- pen->g = (Uint8) SDL_rand(256);
- pen->b = (Uint8) SDL_rand(256);
- pen->x = 320.0f;
- pen->y = 240.0f;
- pen->next = pens.next;
- pens.next = pen;
- return SDL_APP_CONTINUE;
- }
- case SDL_EVENT_PEN_PROXIMITY_OUT: {
- Pen *prev = &pens;
- Pen *i;
- SDL_Log("Pen %" SDL_PRIu32 " leaves proximity!", event->pproximity.which);
- for (i = pens.next; i != NULL; i = i->next) {
- if (i->pen == event->pproximity.which) {
- prev->next = i->next;
- SDL_free(i);
- break;
- }
- prev = i;
- }
- return SDL_APP_CONTINUE;
- }
- case SDL_EVENT_PEN_DOWN:
- /*SDL_Log("Pen %" SDL_PRIu32 " down!", event->ptouch.which);*/
- pen = FindPen(event->ptouch.which);
- if (pen) {
- pen->touching = true;
- pen->eraser = (event->ptouch.eraser != 0);
- }
- return SDL_APP_CONTINUE;
- case SDL_EVENT_PEN_UP:
- /*SDL_Log("Pen %" SDL_PRIu32 " up!", event->ptouch.which);*/
- pen = FindPen(event->ptouch.which);
- if (pen) {
- pen->touching = false;
- pen->axes[SDL_PEN_AXIS_PRESSURE] = 0.0f;
- }
- return SDL_APP_CONTINUE;
- case SDL_EVENT_PEN_BUTTON_DOWN:
- /*SDL_Log("Pen %" SDL_PRIu32 " button %d down!", event->pbutton.which, (int) event->pbutton.button);*/
- pen = FindPen(event->ptouch.which);
- if (pen) {
- pen->buttons |= (1 << (event->pbutton.button-1));
- }
- return SDL_APP_CONTINUE;
- case SDL_EVENT_PEN_BUTTON_UP:
- /*SDL_Log("Pen %" SDL_PRIu32 " button %d up!", event->pbutton.which, (int) event->pbutton.button);*/
- pen = FindPen(event->ptouch.which);
- if (pen) {
- pen->buttons &= ~(1 << (event->pbutton.button-1));
- }
- return SDL_APP_CONTINUE;
- case SDL_EVENT_PEN_MOTION:
- /*SDL_Log("Pen %" SDL_PRIu32 " moved to (%f,%f)!", event->pmotion.which, event->pmotion.x, event->pmotion.y);*/
- pen = FindPen(event->ptouch.which);
- if (pen) {
- pen->x = event->pmotion.x;
- pen->y = event->pmotion.y;
- }
- return SDL_APP_CONTINUE;
- case SDL_EVENT_PEN_AXIS:
- /*SDL_Log("Pen %" SDL_PRIu32 " axis %d is now %f!", event->paxis.which, (int) event->paxis.axis, event->paxis.value);*/
- pen = FindPen(event->ptouch.which);
- if (pen && (event->paxis.axis < SDL_arraysize(pen->axes))) {
- pen->axes[event->paxis.axis] = event->paxis.value;
- }
- return SDL_APP_CONTINUE;
- case SDL_EVENT_KEY_DOWN: {
- const SDL_Keycode sym = event->key.key;
- if (sym == SDLK_ESCAPE || sym == SDLK_AC_BACK) {
- SDL_Log("Key : Escape!");
- return SDL_APP_SUCCESS;
- }
- break;
- }
- case SDL_EVENT_QUIT:
- return SDL_APP_SUCCESS;
- default:
- break;
- }
- return SDLTest_CommonEventMainCallbacks(state, event);
- }
- static void DrawOnePen(Pen *pen, int num)
- {
- int i;
- /* draw button presses for this pen. A square for each in the pen's color, offset down the screen so they don't overlap. */
- SDL_SetRenderDrawColor(renderer, pen->r, pen->g, pen->b, 255);
- for (i = 0; i < 8; i++) { /* we assume you don't have more than 8 buttons atm... */
- if (pen->buttons & (1 << i)) {
- const SDL_FRect rect = { 30.0f * ((float) i), ((float) num) * 30.0f, 30.0f, 30.0f };
- SDL_RenderFillRect(renderer, &rect);
- }
- }
- /* draw a square to represent pressure. Always green for eraser and blue for pen */
- /* we do this with a texture, so we can trivially rotate it, which SDL_RenderFillRect doesn't offer. */
- if (pen->axes[SDL_PEN_AXIS_PRESSURE] > 0.0f) {
- const float size = (150.0f * pen->axes[SDL_PEN_AXIS_PRESSURE]) + 20.0f;
- const float halfsize = size / 2.0f;
- const SDL_FRect rect = { pen->x - halfsize, pen->y - halfsize, size, size };
- const SDL_FPoint center = { halfsize, halfsize };
- if (pen->eraser) {
- SDL_SetTextureColorMod(white_pixel, 0, 255, 0);
- } else {
- SDL_SetTextureColorMod(white_pixel, 0, 0, 255);
- }
- SDL_RenderTextureRotated(renderer, white_pixel, NULL, &rect, pen->axes[SDL_PEN_AXIS_ROTATION], ¢er, SDL_FLIP_NONE);
- }
- /* draw a little square for position in the center of the pressure, with the pen-specific color. */
- {
- const float distance = pen->touching ? 0.0f : SDL_clamp(pen->axes[SDL_PEN_AXIS_DISTANCE], 0.0f, 1.0f);
- const float size = 10 + (30.0f * (1.0f - distance));
- const float halfsize = size / 2.0f;
- const SDL_FRect rect = { pen->x - halfsize, pen->y - halfsize, size, size };
- const SDL_FPoint center = { halfsize, halfsize };
- SDL_SetTextureColorMod(white_pixel, pen->r, pen->g, pen->b);
- SDL_RenderTextureRotated(renderer, white_pixel, NULL, &rect, pen->axes[SDL_PEN_AXIS_ROTATION], ¢er, SDL_FLIP_NONE);
- }
- }
- SDL_AppResult SDL_AppIterate(void *appstate)
- {
- int num = 0;
- Pen *pen;
- SDL_SetRenderDrawColor(renderer, 0x99, 0x99, 0x99, 255);
- SDL_RenderClear(renderer);
- for (pen = pens.next; pen != NULL; pen = pen->next, num++) {
- DrawOnePen(pen, num);
- }
- SDL_RenderPresent(renderer);
- return SDL_APP_CONTINUE;
- }
- void SDL_AppQuit(void *appstate, SDL_AppResult result)
- {
- Pen *i, *next;
- for (i = pens.next; i != NULL; i = next) {
- next = i->next;
- SDL_free(i);
- }
- pens.next = NULL;
- SDL_DestroyTexture(white_pixel);
- SDLTest_CommonQuit(state);
- }
|