Added joystick and gamepad element display in testgamepad

This commit is contained in:
Sam Lantinga 2023-07-10 17:06:42 -07:00
parent 4a53dc5b8d
commit d44ada59fb
6 changed files with 1348 additions and 307 deletions

39
test/gamepad_axis_arrow.h Normal file
View File

@ -0,0 +1,39 @@
unsigned char gamepad_axis_arrow_bmp[] = {
0x42, 0x4d, 0xaa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00,
0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00,
0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01,
0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x42, 0x47,
0x52, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0xc7, 0xc7, 0x7f, 0xc7, 0xc7,
0xc7, 0x02, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x02, 0xc7, 0xc7,
0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0x7f, 0xc7, 0xc7, 0xc7, 0x02, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7,
0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0x7f, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7,
0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0x7f, 0xc7, 0xc7,
0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0x7f, 0xc7, 0xc7, 0xc7, 0x02, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0x7f, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0x80, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0x80, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0x80, 0xc7, 0xc7,
0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0xc7, 0xc7, 0xc7, 0x80, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7,
0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0xff, 0xc7, 0xc7,
0xc7, 0x80, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7,
0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x80, 0xc7, 0xc7,
0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x01, 0xc7, 0xc7,
0xc7, 0x01, 0xc7, 0xc7, 0xc7, 0x02
};
unsigned int gamepad_axis_arrow_bmp_len = 426;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,63 @@
unsigned char gamepad_button_small_bmp[] = {
0x42, 0x4d, 0xca, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00,
0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00,
0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02,
0x00, 0x00, 0xd7, 0x0d, 0x00, 0x00, 0xd7, 0x0d, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x42, 0x47,
0x52, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x5d, 0x5d, 0x34, 0x5e, 0x5e,
0x5e, 0x7d, 0x5d, 0x5d, 0x5d, 0x7d, 0x5b, 0x5b, 0x5b, 0x7d, 0x57, 0x57,
0x57, 0x7d, 0x56, 0x56, 0x56, 0x7d, 0x55, 0x55, 0x55, 0x7d, 0x53, 0x53,
0x53, 0x7d, 0x52, 0x52, 0x52, 0x7d, 0x51, 0x51, 0x51, 0x7d, 0x4f, 0x4f,
0x4f, 0x7d, 0x4e, 0x4e, 0x4e, 0x34, 0x97, 0x97, 0x97, 0xc3, 0xc6, 0xc6,
0xc6, 0xf3, 0xc3, 0xc3, 0xc3, 0xf3, 0xc0, 0xc0, 0xc0, 0xf3, 0xbc, 0xbc,
0xbc, 0xf3, 0xba, 0xba, 0xba, 0xf3, 0xb7, 0xb7, 0xb7, 0xf3, 0xb3, 0xb3,
0xb3, 0xf3, 0xaf, 0xaf, 0xaf, 0xf3, 0xad, 0xad, 0xad, 0xf3, 0xaa, 0xaa,
0xaa, 0xf3, 0x7f, 0x7f, 0x7f, 0xc2, 0xa9, 0xa9, 0xa9, 0xdd, 0xd8, 0xd8,
0xd8, 0xff, 0xd5, 0xd5, 0xd5, 0xff, 0xd2, 0xd2, 0xd2, 0xff, 0xce, 0xce,
0xce, 0xff, 0xcb, 0xcb, 0xcb, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc4, 0xc4,
0xc4, 0xff, 0xc1, 0xc1, 0xc1, 0xff, 0xbd, 0xbd, 0xbd, 0xff, 0xbb, 0xbb,
0xbb, 0xff, 0x8e, 0x8e, 0x8e, 0xdd, 0xad, 0xad, 0xad, 0xde, 0xde, 0xde,
0xde, 0xff, 0xda, 0xda, 0xda, 0xff, 0xd7, 0xd7, 0xd7, 0xff, 0xd3, 0xd3,
0xd3, 0xff, 0xd0, 0xd0, 0xd0, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0xc9, 0xc9,
0xc9, 0xff, 0xc6, 0xc6, 0xc6, 0xff, 0xc2, 0xc2, 0xc2, 0xff, 0xbf, 0xbf,
0xbf, 0xff, 0x92, 0x92, 0x92, 0xde, 0xb0, 0xb0, 0xb0, 0xde, 0xe1, 0xe1,
0xe1, 0xff, 0xde, 0xde, 0xde, 0xff, 0xda, 0xda, 0xda, 0xff, 0xd7, 0xd7,
0xd7, 0xff, 0xd4, 0xd4, 0xd4, 0xff, 0xd0, 0xd0, 0xd0, 0xff, 0xcd, 0xcd,
0xcd, 0xff, 0xca, 0xca, 0xca, 0xff, 0xc6, 0xc6, 0xc6, 0xff, 0xc3, 0xc3,
0xc3, 0xff, 0x94, 0x94, 0x94, 0xde, 0xb2, 0xb2, 0xb2, 0xde, 0xe5, 0xe5,
0xe5, 0xff, 0xe2, 0xe2, 0xe2, 0xff, 0xde, 0xde, 0xde, 0xff, 0xdb, 0xdb,
0xdb, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xd4, 0xd4, 0xd4, 0xff, 0xd1, 0xd1,
0xd1, 0xff, 0xcd, 0xcd, 0xcd, 0xff, 0xca, 0xca, 0xca, 0xff, 0xc7, 0xc7,
0xc7, 0xff, 0x97, 0x97, 0x97, 0xde, 0xb5, 0xb5, 0xb5, 0xde, 0xe9, 0xe9,
0xe9, 0xff, 0xe6, 0xe6, 0xe6, 0xff, 0xe2, 0xe2, 0xe2, 0xff, 0xdf, 0xdf,
0xdf, 0xff, 0xdb, 0xdb, 0xdb, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xd5, 0xd5,
0xd5, 0xff, 0xd1, 0xd1, 0xd1, 0xff, 0xce, 0xce, 0xce, 0xff, 0xca, 0xca,
0xca, 0xff, 0x9a, 0x9a, 0x9a, 0xde, 0xb8, 0xb8, 0xb8, 0xde, 0xed, 0xed,
0xed, 0xff, 0xe9, 0xe9, 0xe9, 0xff, 0xe6, 0xe6, 0xe6, 0xff, 0xe3, 0xe3,
0xe3, 0xff, 0xdf, 0xdf, 0xdf, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0xd8, 0xd8,
0xd8, 0xff, 0xd5, 0xd5, 0xd5, 0xff, 0xd1, 0xd1, 0xd1, 0xff, 0xce, 0xce,
0xce, 0xff, 0x9d, 0x9d, 0x9d, 0xde, 0xbb, 0xbb, 0xbb, 0xde, 0xf1, 0xf1,
0xf1, 0xff, 0xed, 0xed, 0xed, 0xff, 0xe9, 0xe9, 0xe9, 0xff, 0xe6, 0xe6,
0xe6, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xdf, 0xdf, 0xdf, 0xff, 0xdc, 0xdc,
0xdc, 0xff, 0xd9, 0xd9, 0xd9, 0xff, 0xd5, 0xd5, 0xd5, 0xff, 0xd2, 0xd2,
0xd2, 0xff, 0xa0, 0xa0, 0xa0, 0xde, 0xbc, 0xbc, 0xbc, 0xdd, 0xf3, 0xf3,
0xf3, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xec, 0xec, 0xec, 0xff, 0xe9, 0xe9,
0xe9, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xe2, 0xe2, 0xe2, 0xff, 0xde, 0xde,
0xde, 0xff, 0xdb, 0xdb, 0xdb, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xd4, 0xd4,
0xd4, 0xff, 0xa1, 0xa1, 0xa1, 0xdd, 0xae, 0xae, 0xae, 0xc3, 0xe4, 0xe4,
0xe4, 0xf3, 0xe2, 0xe2, 0xe2, 0xf3, 0xde, 0xde, 0xde, 0xf3, 0xdb, 0xdb,
0xdb, 0xf3, 0xd8, 0xd8, 0xd8, 0xf3, 0xd6, 0xd6, 0xd6, 0xf3, 0xd2, 0xd2,
0xd2, 0xf3, 0xce, 0xce, 0xce, 0xf3, 0xcc, 0xcc, 0xcc, 0xf3, 0xc9, 0xc9,
0xc9, 0xf3, 0x95, 0x95, 0x95, 0xc2, 0x6b, 0x6b, 0x6b, 0x34, 0x6e, 0x6e,
0x6e, 0x7d, 0x6d, 0x6d, 0x6d, 0x7d, 0x6a, 0x6a, 0x6a, 0x7d, 0x68, 0x68,
0x68, 0x7d, 0x67, 0x67, 0x67, 0x7d, 0x66, 0x66, 0x66, 0x7d, 0x64, 0x64,
0x64, 0x7d, 0x62, 0x62, 0x62, 0x7d, 0x61, 0x61, 0x61, 0x7d, 0x60, 0x60,
0x60, 0x7d, 0x5c, 0x5c, 0x5c, 0x34
};
unsigned int gamepad_button_small_bmp_len = 714;

View File

@ -10,13 +10,16 @@
freely.
*/
#include <SDL3/SDL.h>
#include <SDL3/SDL_test_font.h>
#include "gamepadutils.h"
#include "gamepad_front.h"
#include "gamepad_back.h"
#include "gamepad_touchpad.h"
#include "gamepad_button.h"
#include "gamepad_button_small.h"
#include "gamepad_axis.h"
#include "gamepad_axis_arrow.h"
/* This is indexed by SDL_GamepadButton. */
static const struct
@ -110,26 +113,6 @@ static SDL_Texture *CreateTexture(SDL_Renderer *renderer, unsigned char *data, u
if (src) {
surface = SDL_LoadBMP_RW(src, SDL_TRUE);
if (surface) {
if (surface->format->palette) {
SDL_SetSurfaceColorKey(surface, SDL_TRUE, *(Uint8 *)surface->pixels);
} else {
switch (surface->format->BitsPerPixel) {
case 15:
SDL_SetSurfaceColorKey(surface, SDL_TRUE,
(*(Uint16 *)surface->pixels) & 0x00007FFF);
break;
case 16:
SDL_SetSurfaceColorKey(surface, SDL_TRUE, *(Uint16 *)surface->pixels);
break;
case 24:
SDL_SetSurfaceColorKey(surface, SDL_TRUE,
(*(Uint32 *)surface->pixels) & 0x00FFFFFF);
break;
case 32:
SDL_SetSurfaceColorKey(surface, SDL_TRUE, *(Uint32 *)surface->pixels);
break;
}
}
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_DestroySurface(surface);
}
@ -490,3 +473,406 @@ void DestroyGamepadImage(GamepadImage *ctx)
SDL_free(ctx);
}
}
static const char *gamepad_button_names[] = {
"A",
"B",
"X",
"Y",
"Back",
"Guide",
"Start",
"Left Stick",
"Right Stick",
"Left Shoulder",
"Right Shoulder",
"DPAD Up",
"DPAD Down",
"DPAD Left",
"DPAD Right",
"Misc1",
"Paddle1",
"Paddle2",
"Paddle3",
"Paddle4",
"Touchpad",
};
SDL_COMPILE_TIME_ASSERT(gamepad_button_names, SDL_arraysize(gamepad_button_names) == SDL_GAMEPAD_BUTTON_MAX);
static const char *gamepad_axis_names[] = {
"LeftX",
"RightX",
"RightX",
"RightY",
"Left Trigger",
"Right Trigger",
};
SDL_COMPILE_TIME_ASSERT(gamepad_axis_names, SDL_arraysize(gamepad_axis_names) == SDL_GAMEPAD_AXIS_MAX);
struct GamepadDisplay
{
SDL_Renderer *renderer;
SDL_Texture *button_texture;
SDL_Texture *arrow_texture;
int button_width;
int button_height;
int arrow_width;
int arrow_height;
SDL_Rect area;
};
GamepadDisplay *CreateGamepadDisplay(SDL_Renderer *renderer)
{
GamepadDisplay *ctx = SDL_calloc(1, sizeof(*ctx));
if (ctx) {
ctx->renderer = renderer;
ctx->button_texture = CreateTexture(renderer, gamepad_button_small_bmp, gamepad_button_small_bmp_len);
SDL_QueryTexture(ctx->button_texture, NULL, NULL, &ctx->button_width, &ctx->button_height);
ctx->arrow_texture = CreateTexture(renderer, gamepad_axis_arrow_bmp, gamepad_axis_arrow_bmp_len);
SDL_QueryTexture(ctx->arrow_texture, NULL, NULL, &ctx->arrow_width, &ctx->arrow_height);
}
return ctx;
}
void SetGamepadDisplayArea(GamepadDisplay *ctx, int x, int y, int w, int h)
{
if (!ctx) {
return;
}
ctx->area.x = x;
ctx->area.y = y;
ctx->area.w = w;
ctx->area.h = h;
}
void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad)
{
float x, y;
int i;
char text[32];
const float margin = 8.0f;
const float center = ctx->area.w / 2.0f;
const float arrow_extent = 48.0f;
SDL_FRect dst, rect;
Uint8 r, g, b, a;
SDL_GetRenderDrawColor(ctx->renderer, &r, &g, &b, &a);
x = ctx->area.x + margin;
y = ctx->area.y + margin;
for (i = 0; i < SDL_GAMEPAD_BUTTON_MAX; ++i) {
if (SDL_GamepadHasButton(gamepad, (SDL_GamepadButton)i)) {
SDL_snprintf(text, sizeof(text), "%s:", gamepad_button_names[i]);
SDLTest_DrawString(ctx->renderer, x + center - SDL_strlen(text) * FONT_CHARACTER_SIZE, y, text);
if (SDL_GetGamepadButton(gamepad, (SDL_GamepadButton)i)) {
SDL_SetTextureColorMod(ctx->button_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->button_texture, 255, 255, 255);
}
dst.x = x + center + 2.0f;
dst.y = y + FONT_CHARACTER_SIZE / 2 - ctx->button_height / 2;
dst.w = (float)ctx->button_width;
dst.h = (float)ctx->button_height;
SDL_RenderTexture(ctx->renderer, ctx->button_texture, NULL, &dst);
y += ctx->button_height + 2.0f;
}
}
for (i = 0; i < SDL_GAMEPAD_AXIS_MAX; ++i) {
if (SDL_GamepadHasAxis(gamepad, (SDL_GamepadAxis)i)) {
SDL_bool has_negative = (i != SDL_GAMEPAD_AXIS_LEFT_TRIGGER && i != SDL_GAMEPAD_AXIS_RIGHT_TRIGGER);
Sint16 value = SDL_GetGamepadAxis(gamepad, (SDL_GamepadAxis)i);
SDL_snprintf(text, sizeof(text), "%s:", gamepad_axis_names[i]);
SDLTest_DrawString(ctx->renderer, x + center - SDL_strlen(text) * FONT_CHARACTER_SIZE, y, text);
dst.x = x + center + 2.0f;
dst.y = y + FONT_CHARACTER_SIZE / 2 - ctx->arrow_height / 2;
dst.w = (float)ctx->arrow_width;
dst.h = (float)ctx->arrow_height;
if (has_negative) {
if (value == SDL_MIN_SINT16) {
SDL_SetTextureColorMod(ctx->arrow_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->arrow_texture, 255, 255, 255);
}
SDL_RenderTextureRotated(ctx->renderer, ctx->arrow_texture, NULL, &dst, 0.0f, NULL, SDL_FLIP_HORIZONTAL);
}
dst.x += (float)ctx->arrow_width;
SDL_SetRenderDrawColor(ctx->renderer, 200, 200, 200, SDL_ALPHA_OPAQUE);
rect.x = dst.x + arrow_extent - 2.0f;
rect.y = dst.y;
rect.w = 4.0f;
rect.h = (float)ctx->arrow_height;
SDL_RenderFillRect(ctx->renderer, &rect);
SDL_SetRenderDrawColor(ctx->renderer, r, g, b, a);
if (value < 0) {
SDL_SetRenderDrawColor(ctx->renderer, 8, 200, 16, SDL_ALPHA_OPAQUE);
rect.w = ((float)value / SDL_MIN_SINT16) * arrow_extent;
rect.x = dst.x + arrow_extent - rect.w;
rect.y = dst.y + ctx->arrow_height * 0.25f;
rect.h = ctx->arrow_height / 2.0f;
SDL_RenderFillRect(ctx->renderer, &rect);
}
dst.x += arrow_extent;
if (value > 0) {
SDL_SetRenderDrawColor(ctx->renderer, 8, 200, 16, SDL_ALPHA_OPAQUE);
rect.w = ((float)value / SDL_MAX_SINT16) * arrow_extent;
rect.x = dst.x;
rect.y = dst.y + ctx->arrow_height * 0.25f;
rect.h = ctx->arrow_height / 2.0f;
SDL_RenderFillRect(ctx->renderer, &rect);
}
dst.x += arrow_extent;
if (value == SDL_MAX_SINT16) {
SDL_SetTextureColorMod(ctx->arrow_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->arrow_texture, 255, 255, 255);
}
SDL_RenderTexture(ctx->renderer, ctx->arrow_texture, NULL, &dst);
SDL_SetRenderDrawColor(ctx->renderer, r, g, b, a);
y += ctx->button_height + 2;
}
}
}
void DestroyGamepadDisplay(GamepadDisplay *ctx)
{
SDL_free(ctx);
}
struct JoystickDisplay
{
SDL_Renderer *renderer;
SDL_Texture *button_texture;
SDL_Texture *arrow_texture;
int button_width;
int button_height;
int arrow_width;
int arrow_height;
SDL_Rect area;
};
JoystickDisplay *CreateJoystickDisplay(SDL_Renderer *renderer)
{
JoystickDisplay *ctx = SDL_calloc(1, sizeof(*ctx));
if (ctx) {
ctx->renderer = renderer;
ctx->button_texture = CreateTexture(renderer, gamepad_button_small_bmp, gamepad_button_small_bmp_len);
SDL_QueryTexture(ctx->button_texture, NULL, NULL, &ctx->button_width, &ctx->button_height);
ctx->arrow_texture = CreateTexture(renderer, gamepad_axis_arrow_bmp, gamepad_axis_arrow_bmp_len);
SDL_QueryTexture(ctx->arrow_texture, NULL, NULL, &ctx->arrow_width, &ctx->arrow_height);
}
return ctx;
}
void SetJoystickDisplayArea(JoystickDisplay *ctx, int x, int y, int w, int h)
{
if (!ctx) {
return;
}
ctx->area.x = x;
ctx->area.y = y;
ctx->area.w = w;
ctx->area.h = h;
}
void RenderJoystickDisplay(JoystickDisplay *ctx, SDL_Joystick *joystick)
{
float x, y;
int i;
int nbuttons = SDL_GetNumJoystickButtons(joystick);
int naxes = SDL_GetNumJoystickAxes(joystick);
int nhats = SDL_GetNumJoystickHats(joystick);
char text[32];
const float margin = 8.0f;
const float center = 80.0f;
const float arrow_extent = 48.0f;
SDL_FRect dst, rect;
Uint8 r, g, b, a;
SDL_GetRenderDrawColor(ctx->renderer, &r, &g, &b, &a);
x = (float)ctx->area.x + margin;
y = (float)ctx->area.y + margin;
if (nbuttons > 0) {
SDLTest_DrawString(ctx->renderer, x, y, "BUTTONS");
y += FONT_LINE_HEIGHT + 2;
for (i = 0; i < nbuttons; ++i) {
SDL_snprintf(text, sizeof(text), "%2.d:", i);
SDLTest_DrawString(ctx->renderer, x, y, text);
if (SDL_GetJoystickButton(joystick, (Uint8)i)) {
SDL_SetTextureColorMod(ctx->button_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->button_texture, 255, 255, 255);
}
dst.x = x + FONT_CHARACTER_SIZE * SDL_strlen(text) + 2;
dst.y = y + FONT_CHARACTER_SIZE / 2 - ctx->button_height / 2;
dst.w = (float)ctx->button_width;
dst.h = (float)ctx->button_height;
SDL_RenderTexture(ctx->renderer, ctx->button_texture, NULL, &dst);
y += ctx->button_height + 2;
}
}
x = (float)ctx->area.x + margin + center + margin;
y = (float)ctx->area.y + margin;
if (naxes > 0) {
SDLTest_DrawString(ctx->renderer, x, y, "AXES");
y += FONT_LINE_HEIGHT + 2;
for (i = 0; i < naxes; ++i) {
Sint16 value = SDL_GetJoystickAxis(joystick, i);
SDL_snprintf(text, sizeof(text), "%d:", i);
SDLTest_DrawString(ctx->renderer, x, y, text);
dst.x = x + FONT_CHARACTER_SIZE * SDL_strlen(text) + 2.0f;
dst.y = y + FONT_CHARACTER_SIZE / 2 - ctx->arrow_height / 2;
dst.w = (float)ctx->arrow_width;
dst.h = (float)ctx->arrow_height;
if (value == SDL_MIN_SINT16) {
SDL_SetTextureColorMod(ctx->arrow_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->arrow_texture, 255, 255, 255);
}
SDL_RenderTextureRotated(ctx->renderer, ctx->arrow_texture, NULL, &dst, 0.0f, NULL, SDL_FLIP_HORIZONTAL);
dst.x += (float)ctx->arrow_width;
SDL_SetRenderDrawColor(ctx->renderer, 200, 200, 200, SDL_ALPHA_OPAQUE);
rect.x = dst.x + arrow_extent - 2.0f;
rect.y = dst.y;
rect.w = 4.0f;
rect.h = (float)ctx->arrow_height;
SDL_RenderFillRect(ctx->renderer, &rect);
SDL_SetRenderDrawColor(ctx->renderer, r, g, b, a);
if (value < 0) {
SDL_SetRenderDrawColor(ctx->renderer, 8, 200, 16, SDL_ALPHA_OPAQUE);
rect.w = ((float)value / SDL_MIN_SINT16) * arrow_extent;
rect.x = dst.x + arrow_extent - rect.w;
rect.y = dst.y + ctx->arrow_height * 0.25f;
rect.h = ctx->arrow_height / 2.0f;
SDL_RenderFillRect(ctx->renderer, &rect);
}
dst.x += arrow_extent;
if (value > 0) {
SDL_SetRenderDrawColor(ctx->renderer, 8, 200, 16, SDL_ALPHA_OPAQUE);
rect.w = ((float)value / SDL_MAX_SINT16) * arrow_extent;
rect.x = dst.x;
rect.y = dst.y + ctx->arrow_height * 0.25f;
rect.h = ctx->arrow_height / 2.0f;
SDL_RenderFillRect(ctx->renderer, &rect);
}
dst.x += arrow_extent;
if (value == SDL_MAX_SINT16) {
SDL_SetTextureColorMod(ctx->arrow_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->arrow_texture, 255, 255, 255);
}
SDL_RenderTexture(ctx->renderer, ctx->arrow_texture, NULL, &dst);
SDL_SetRenderDrawColor(ctx->renderer, r, g, b, a);
y += ctx->button_height + 2;
}
}
y += FONT_LINE_HEIGHT + 2;
if (nhats > 0) {
SDLTest_DrawString(ctx->renderer, x, y, "HATS");
y += FONT_LINE_HEIGHT + 2 + 1.5f * ctx->button_height - FONT_CHARACTER_SIZE / 2;
for (i = 0; i < nhats; ++i) {
Uint8 value = SDL_GetJoystickHat(joystick, i);
SDL_snprintf(text, sizeof(text), "%d:", i);
SDLTest_DrawString(ctx->renderer, x, y, text);
if (value & SDL_HAT_LEFT) {
SDL_SetTextureColorMod(ctx->button_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->button_texture, 255, 255, 255);
}
dst.x = x + FONT_CHARACTER_SIZE * SDL_strlen(text) + 2;
dst.y = y + FONT_CHARACTER_SIZE / 2 - ctx->button_height / 2;
dst.w = (float)ctx->button_width;
dst.h = (float)ctx->button_height;
SDL_RenderTexture(ctx->renderer, ctx->button_texture, NULL, &dst);
if (value & SDL_HAT_UP) {
SDL_SetTextureColorMod(ctx->button_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->button_texture, 255, 255, 255);
}
dst.x += (float)ctx->button_width;
dst.y -= (float)ctx->button_height;
SDL_RenderTexture(ctx->renderer, ctx->button_texture, NULL, &dst);
if (value & SDL_HAT_DOWN) {
SDL_SetTextureColorMod(ctx->button_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->button_texture, 255, 255, 255);
}
dst.y += (float)ctx->button_height * 2;
SDL_RenderTexture(ctx->renderer, ctx->button_texture, NULL, &dst);
if (value & SDL_HAT_RIGHT) {
SDL_SetTextureColorMod(ctx->button_texture, 10, 255, 21);
} else {
SDL_SetTextureColorMod(ctx->button_texture, 255, 255, 255);
}
dst.x += (float)ctx->button_width;
dst.y = y + FONT_CHARACTER_SIZE / 2 - ctx->button_height / 2;
SDL_RenderTexture(ctx->renderer, ctx->button_texture, NULL, &dst);
y += 3 * ctx->button_height + 2;
}
}
}
void DestroyJoystickDisplay(JoystickDisplay *ctx)
{
SDL_free(ctx);
}

View File

@ -10,24 +10,6 @@
freely.
*/
/* Joystick element display */
typedef struct JoystickDisplay JoystickDisplay;
extern JoystickDisplay *CreateJoystickDisplay(SDL_Renderer *renderer);
extern void SetJoystickDisplayArea(JoystickDisplay *ctx, int x, int y, int w, int h);
extern void UpdateJoystickDisplayFromJoystick(JoystickDisplay *ctx, SDL_Joystick *joystick);
extern void RenderJoystickDisplay(JoystickDisplay *ctx);
/* Gamepad element display */
typedef struct GamepadDisplay GamepadDisplay;
extern GamepadDisplay *CreateGamepadDisplay(SDL_Renderer *renderer);
extern void SetGamepadDisplayArea(GamepadDisplay *ctx, int x, int y, int w, int h);
extern void UpdateGamepadDisplayFromGamepad(GamepadDisplay *ctx, SDL_Gamepad *joystick);
extern void RenderGamepadDisplay(GamepadDisplay *ctx);
/* Gamepad image */
typedef struct GamepadImage GamepadImage;
@ -53,3 +35,21 @@ extern void UpdateGamepadImageFromGamepad(GamepadImage *ctx, SDL_Gamepad *gamepa
extern void RenderGamepadImage(GamepadImage *ctx);
extern void DestroyGamepadImage(GamepadImage *ctx);
/* Gamepad element display */
typedef struct GamepadDisplay GamepadDisplay;
extern GamepadDisplay *CreateGamepadDisplay(SDL_Renderer *renderer);
extern void SetGamepadDisplayArea(GamepadDisplay *ctx, int x, int y, int w, int h);
extern void RenderGamepadDisplay(GamepadDisplay *ctx, SDL_Gamepad *gamepad);
extern void DestroyGamepadDisplay(GamepadDisplay *ctx);
/* Joystick element display */
typedef struct JoystickDisplay JoystickDisplay;
extern JoystickDisplay *CreateJoystickDisplay(SDL_Renderer *renderer);
extern void SetJoystickDisplayArea(JoystickDisplay *ctx, int x, int y, int w, int h);
extern void RenderJoystickDisplay(JoystickDisplay *ctx, SDL_Joystick *joystick);
extern void DestroyJoystickDisplay(JoystickDisplay *ctx);

View File

@ -23,8 +23,14 @@
#include <emscripten/emscripten.h>
#endif
#define SCREEN_WIDTH 512
#define SCREEN_HEIGHT 480
#define TITLE_HEIGHT 32
#define PANEL_SPACING 25
#define PANEL_WIDTH 250
#define GAMEPAD_WIDTH 512
#define GAMEPAD_HEIGHT 480
#define SCREEN_WIDTH (PANEL_WIDTH + PANEL_SPACING + GAMEPAD_WIDTH + PANEL_SPACING + PANEL_WIDTH)
#define SCREEN_HEIGHT (TITLE_HEIGHT + GAMEPAD_HEIGHT)
/* This is indexed by SDL_JoystickPowerLevel + 1. */
static const char *power_level_strings[] = {
@ -40,6 +46,8 @@ SDL_COMPILE_TIME_ASSERT(power_level_strings, SDL_arraysize(power_level_strings)
static SDL_Window *window = NULL;
static SDL_Renderer *screen = NULL;
static GamepadImage *image = NULL;
static GamepadDisplay *gamepad_elements = NULL;
static JoystickDisplay *joystick_elements = NULL;
static SDL_bool retval = SDL_FALSE;
static SDL_bool done = SDL_FALSE;
static SDL_bool set_LED = SDL_FALSE;
@ -685,6 +693,10 @@ static void loop(void *arg)
UpdateGamepadImageFromGamepad(image, gamepad);
RenderGamepadImage(image);
SDL_SetRenderDrawColor(screen, 0x10, 0x10, 0x10, SDL_ALPHA_OPAQUE);
RenderGamepadDisplay(gamepad_elements, gamepad);
RenderJoystickDisplay(joystick_elements, SDL_GetGamepadJoystick(gamepad));
/* Update LED based on left thumbstick position */
{
Sint16 x = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTX);
@ -853,6 +865,13 @@ int main(int argc, char *argv[])
SDL_DestroyWindow(window);
return 2;
}
SetGamepadImagePosition(image, PANEL_WIDTH + PANEL_SPACING, TITLE_HEIGHT);
gamepad_elements = CreateGamepadDisplay(screen);
SetGamepadDisplayArea(gamepad_elements, 0, TITLE_HEIGHT, PANEL_WIDTH, GAMEPAD_HEIGHT);
joystick_elements = CreateJoystickDisplay(screen);
SetJoystickDisplayArea(joystick_elements, PANEL_WIDTH + PANEL_SPACING + GAMEPAD_WIDTH + PANEL_SPACING, TITLE_HEIGHT, PANEL_WIDTH, GAMEPAD_HEIGHT);
/* Process the initial gamepad list */
loop(NULL);
@ -881,6 +900,8 @@ int main(int argc, char *argv[])
CloseVirtualGamepad();
DestroyGamepadImage(image);
DestroyGamepadDisplay(gamepad_elements);
DestroyJoystickDisplay(joystick_elements);
SDL_DestroyRenderer(screen);
SDL_DestroyWindow(window);
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD);