
In this tutorial th goal is to be able to use a graphic tablet to draw something on the screen.
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
if (!SDL_CreateWindowAndRenderer("SDL3 Pen Down", 800, 600, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
We need a render texture to be able to draw on it with the graphic tablet
SDL_Texture *render_target = NULL;
int w, h;
SDL_GetRenderOutputSize(renderer, &w, &h);
render_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h);
if (!render_target) {
SDL_Log("Couldn't create render target: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
We want to make the screen white if nothing is drawn.
SDL_SetRenderTarget(renderer, render_target);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
float pressure = 0.0f;
float previous_touch_x = -1.0f;
float previous_touch_y = -1.0f;
float tilt_x = 0.0f;
float tilt_y = 0.0f;
bool running = true; // if the event loop is running
In this part we will see how to handle the graphics
Before processing the motion of the tablet we will first check if everything is working by displaying some debug informations.
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_EVENT_QUIT:
running = false;
break;
case SDL_EVENT_PEN_DOWN:
printf("Pen down detected!\n");
printf("Pen ID: %" SDL_PRIu32 "\n", event.ptouch.which);
printf("Window ID: %" SDL_PRIu32 "\n", event.ptouch.windowID);
printf("Position: (%f, %f)\n", event.ptouch.x, event.ptouch.y);
break;
}
}
}
Now it's time to use the motion event to handle the drawing of the line only if the pressure is set.
case SDL_EVENT_PEN_MOTION:
if (pressure > 0.0f) {
if (previous_touch_x >= 0.0f) {
SDL_SetRenderTarget(renderer, render_target);
SDL_SetRenderDrawColorFloat(renderer, 0, 0, 0, pressure);
SDL_RenderLine(renderer, previous_touch_x, previous_touch_y, event.pmotion.x, event.pmotion.y);
}
previous_touch_x = event.pmotion.x;
previous_touch_y = event.pmotion.y;
} else {
previous_touch_x = previous_touch_y = -1.0f;
}
break;
In this event we set the pressure and record the tilt informations.
case SDL_EVENT_PEN_AXIS:
if (event.paxis.axis == SDL_PEN_AXIS_PRESSURE) {
pressure = event.paxis.value;
printf("Pressure: %f\n", pressure);
} else if(event.paxis.axis == SDL_PEN_AXIS_XTILT) {
tilt_x = event.paxis.value;
} else if(event.paxis.axis == SDL_PEN_AXIS_YTILT) {
tilt_y = event.paxis.value;
}
break;
char debug_text[1024];
// Clear the screen
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
// Render the render texture
SDL_RenderTexture(renderer, render_target, NULL, NULL);
// Display the tilt informations
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
SDL_snprintf(debug_text, sizeof(debug_text), "Tilt: %f %f", tilt_x, tilt_y);
SDL_RenderDebugText(renderer, 0, 8, debug_text);
SDL_RenderPresent(renderer);
Need another OS ? => Windows, Mac, Linux