diff options
author | kdx <kikoodx@paranoici.org> | 2023-10-05 17:20:38 +0200 |
---|---|---|
committer | kdx <kikoodx@paranoici.org> | 2023-10-05 17:27:03 +0200 |
commit | 48aab2cbf0456fb90a92ddd8819926892acc70b3 (patch) | |
tree | 450d1cc4085e45e7950ff6d02629778f3559a199 | |
parent | 60ddda47ed683ff458e580c7ea85f3b447896b12 (diff) | |
download | input-48aab2cbf0456fb90a92ddd8819926892acc70b3.tar.gz |
major update
-rw-r--r-- | input.c | 391 | ||||
-rw-r--r-- | input.h | 75 |
2 files changed, 345 insertions, 121 deletions
@@ -1,138 +1,309 @@ #include "input.h" -#include "TZR.h" -#include <assert.h> - -enum { - BIND_SCANCODE, -}; - -struct { - const char *name; - struct { - unsigned int type; - union { - SDL_Scancode sc; - }; - } binds[INPUT_MAX_BINDS]; - int nb_binds; -} input[INPUT_MAX_ACTIONS] = {0}; -static int nb_actions = 0; + +#ifndef foreach +#define foreach(E, L) for (__auto_type E = (L); E != NULL; E = E->next) +#endif +#ifndef plog +#define plog(...) \ + printf("\x1b[94mLOG %s:%s:%d\x1b[0m \t", \ + __FILE_NAME__, __FUNCTION__, __LINE__), \ + printf(__VA_ARGS__), putchar('\n') +#endif +#ifndef panic +#define panic(...) plog(__VA_ARGS__), exit(EXIT_FAILURE) +#endif + +static InputAction _actions = {0}; +static InputAxis _axis = {0}; void -input_new(const char *bind) +input_deinit(void) { - assert(nb_actions < INPUT_MAX_ACTIONS); - input[nb_actions].name = bind; - nb_actions += 1; + InputAction *action = _actions.next; + while (action != NULL) { + InputBind *bind = action->binds.next; + while (bind != NULL) { + const __auto_type next = bind->next; + free(bind); + bind = next; + } + const __auto_type next = action->next; + free(action); + action = next; + } + InputAxis *axis = _axis.next; + while (axis != NULL) { + InputPair *pair = axis->pairs.next; + while (pair != NULL) { + const __auto_type next = pair->next; + free(pair); + pair = next; + } + const __auto_type next = axis->next; + free(axis); + axis = next; + } } void -input_clear(const char *bind) +input_new_action(const char *tag) { - for (int i = 0; i < nb_actions; i++) - if (strcmp(bind, input[i].name) == 0) { - input[i].nb_binds = 0; - return; - } - fprintf(stderr, "input_clear: bind '%s' not found\n", bind); - assert(0); + InputAction *action = malloc(sizeof(InputAction)); + if (action == NULL) + panic("malloc failed"); + memset(action, 0, sizeof(*action)); + + strncpy(action->tag, tag, INPUT_TAG_LEN - 1); + action->next = _actions.next; + _actions.next = action; } void -input_bind_scancode(const char *bind, SDL_Scancode sc) -{ - for (int i = 0; i < nb_actions; i++) - if (strcmp(bind, input[i].name) == 0) { - assert(input[i].nb_binds < INPUT_MAX_BINDS); - input[i].binds[input[i].nb_binds].type = BIND_SCANCODE; - input[i].binds[input[i].nb_binds].sc = sc; - input[i].nb_binds += 1; - return; - } - fprintf(stderr, "input_bind_scancode: bind '%s' not found\n", bind); - assert(0); +input_new_axis(const char *tag) +{ + InputAxis *axis = malloc(sizeof(InputAxis)); + if (axis == NULL) + panic("malloc failed"); + memset(axis, 0, sizeof(*axis)); + + strncpy(axis->tag, tag, INPUT_TAG_LEN - 1); + axis->next = _axis.next; + _axis.next = axis; +} + +InputAction * +_input_get_action(const char *tag) +{ + foreach (e, _actions.next) + if (strcmp(e->tag, tag) == 0) + return e; + plog("action '%s' not found", tag); + return NULL; +} + +InputBind * +_input_new_bind(const char *tag, InputBindType ibt) +{ + InputAction *action = _input_get_action(tag); + if (action == NULL) { + plog("_input_get_action failed"); + return NULL; + } + + InputBind *bind = malloc(sizeof(InputBind)); + if (bind == NULL) + panic("walloc failed"); + memset(bind, 0, sizeof(*bind)); + + bind->type = ibt; + bind->next = action->binds.next; + action->binds.next = bind; + return bind; +} + +void +input_bind_action_sc(const char *tag, SDL_Scancode sc) +{ + InputBind *bind = _input_new_bind(tag, IBT_SCANCODE); + if (bind == NULL) + panic("_input_new_bind failed"); + bind->sc = sc; +} + +void +input_bind_action_cb(const char *tag, uint8_t cb) +{ + InputBind *bind = _input_new_bind(tag, IBT_CONBUTTON); + if (bind == NULL) + panic("_input_new_bind failed"); + bind->cb = cb; +} + +void +input_bind_action_mb(const char *tag, uint8_t mb) +{ + InputBind *bind = _input_new_bind(tag, IBT_MOUSEBUTTON); + if (bind == NULL) + panic("_input_new_bind failed"); + bind->mb = mb; } bool -input_down(const char *bind) -{ - for (int i = 0; i < nb_actions; i++) { - if (strcmp(bind, input[i].name) == 0) { - for (int k = 0; k < input[i].nb_binds; k++) - switch (input[i].binds[k].type) { - case BIND_SCANCODE: - if (TZR_IsKeyDown(input[i].binds[k].sc)) - return true; - break; - default: - __builtin_unreachable(); - } - return false; - } +input_down(const char *tag) +{ + InputAction *action = _input_get_action(tag); + if (action == NULL) + panic("_input_get_action failed"); + + foreach (e, action->binds.next) switch (e->type) { + case IBT_SCANCODE: if (TZR_IsKeyDown(e->sc)) return true; break; + case IBT_CONBUTTON: if (TZR_JoystickDown(e->cb)) return true; break; + case IBT_MOUSEBUTTON: if (TZR_MouseDown(e->mb)) return true; break; + default: __builtin_unreachable(); } - fprintf(stderr, "input_down: bind '%s' not found\n", bind); - assert(0); + return false; } bool -input_up(const char *bind) -{ - for (int i = 0; i < nb_actions; i++) { - if (strcmp(bind, input[i].name) == 0) { - for (int k = 0; k < input[i].nb_binds; k++) - switch (input[i].binds[k].type) { - case BIND_SCANCODE: - if (TZR_IsKeyUp(input[i].binds[k].sc)) - return true; - break; - default: - __builtin_unreachable(); - } - return false; - } +input_up(const char *tag) +{ + InputAction *action = _input_get_action(tag); + if (action == NULL) + panic("_input_get_action failed"); + + foreach (e, action->binds.next) switch (e->type) { + case IBT_SCANCODE: if (TZR_IsKeyDown(e->sc)) return false; break; + case IBT_CONBUTTON: if (TZR_JoystickDown(e->cb)) return false; break; + case IBT_MOUSEBUTTON: if (TZR_MouseDown(e->mb)) return false; break; + default: __builtin_unreachable(); } - fprintf(stderr, "input_up: bind '%s' not found\n", bind); - assert(0); + return true; } bool -input_pressed(const char *bind) -{ - for (int i = 0; i < nb_actions; i++) { - if (strcmp(bind, input[i].name) == 0) { - for (int k = 0; k < input[i].nb_binds; k++) - switch (input[i].binds[k].type) { - case BIND_SCANCODE: - if (TZR_IsKeyPressed(input[i].binds[k].sc)) - return true; - break; - default: - __builtin_unreachable(); - } - return false; - } +input_pressed(const char *tag) +{ + InputAction *action = _input_get_action(tag); + if (action == NULL) + panic("_input_get_action failed"); + + foreach (e, action->binds.next) switch (e->type) { + case IBT_SCANCODE: if (TZR_IsKeyPressed(e->sc)) return true; break; + case IBT_CONBUTTON: if (TZR_JoystickPressed(e->cb)) return true; break; + case IBT_MOUSEBUTTON: if (TZR_MousePressed(e->mb)) return true; break; + default: __builtin_unreachable(); } - fprintf(stderr, "input_pressed: bind '%s' not found\n", bind); - assert(0); + return false; } bool -input_released(const char *bind) -{ - for (int i = 0; i < nb_actions; i++) { - if (strcmp(bind, input[i].name) == 0) { - for (int k = 0; k < input[i].nb_binds; k++) - switch (input[i].binds[k].type) { - case BIND_SCANCODE: - if (TZR_IsKeyReleased(input[i].binds[k].sc)) - return true; - break; - default: - __builtin_unreachable(); - } - return false; - } +input_released(const char *tag) +{ + InputAction *action = _input_get_action(tag); + if (action == NULL) + panic("_input_get_action failed"); + + foreach (e, action->binds.next) switch (e->type) { + case IBT_SCANCODE: if (TZR_IsKeyReleased(e->sc)) return true; break; + case IBT_CONBUTTON: if (TZR_JoystickReleased(e->cb)) return true; break; + case IBT_MOUSEBUTTON: if (TZR_MouseReleased(e->mb)) return true; break; + default: __builtin_unreachable(); + } + return false; +} + +InputAxis * +_input_get_axis(const char *tag) +{ + foreach (e, _axis.next) + if (strcmp(e->tag, tag) == 0) + return e; + plog("axis '%s' not found", tag); + return NULL; +} + +InputPair * +_input_new_pair(const char *tag, InputPairType ipt) +{ + InputAxis *axis = _input_get_axis(tag); + if (axis == NULL) { + plog("_input_get_axis failed"); + return NULL; + } + + InputPair *pair = malloc(sizeof(InputPair)); + if (pair == NULL) + panic("malloc failed"); + memset(pair, 0, sizeof(*pair)); + + pair->type = ipt; + pair->next = axis->pairs.next; + axis->pairs.next = pair; + return pair; +} + +void +input_bind_axis_gc(const char *tag, SDL_GameControllerAxis ax) +{ + InputPair *pair = _input_new_pair(tag, IPT_STICK); + if (pair == NULL) + panic("_input_new_pair failed"); + + switch (ax) { + case SDL_CONTROLLER_AXIS_LEFTX: + pair->stick = TZR_JoystickLeftX; + break; + case SDL_CONTROLLER_AXIS_LEFTY: + pair->stick = TZR_JoystickLeftY; + break; + case SDL_CONTROLLER_AXIS_RIGHTX: + pair->stick = TZR_JoystickRightX; + break; + case SDL_CONTROLLER_AXIS_RIGHTY: + pair->stick = TZR_JoystickRightY; + break; + default: + panic("unknown axis '%d'", ax); + } +} + +void +input_bind_axis_act(const char *tag, const char *a0, const char *a1) +{ + InputPair *pair = _input_new_pair(tag, IPT_ACTION); + if (pair == NULL) + panic("_input_new_pair failed"); + + strncpy(pair->left, a0, INPUT_TAG_LEN - 1); + strncpy(pair->right, a1, INPUT_TAG_LEN - 1); +} + +int +input_axis(const char *tag) +{ + InputAxis *axis = _input_get_axis(tag); + if (axis == NULL) + panic("_input_get_axis failed"); + + foreach (e, axis->pairs.next) switch (e->type) { + case IPT_ACTION: { + const __auto_type diff = input_down(e->right) - input_down(e->left); + if (diff) + return diff; + break; + } + case IPT_STICK: { + const __auto_type diff = e->stick(); + if (diff) + return (diff > 0) - (diff < 0); + break; + } + default: __builtin_unreachable(); + } + return 0; +} + +float +input_axisf(const char *tag) +{ + InputAxis *axis = _input_get_axis(tag); + if (axis == NULL) + panic("_input_get_axis failed"); + + foreach (e, axis->pairs.next) switch (e->type) { + case IPT_ACTION: { + const __auto_type diff = input_down(e->right) - input_down(e->left); + if (diff) + return diff; + break; + } + case IPT_STICK: { + const __auto_type diff = e->stick(); + if (diff) + return diff; + break; + } + default: __builtin_unreachable(); } - fprintf(stderr, "input_released: bind '%s' not found\n", bind); - assert(0); + return 0; } @@ -1,17 +1,70 @@ #pragma once -#include <SDL2/SDL_scancode.h> +#include "TZR.h" #include <stdbool.h> -enum { - INPUT_MAX_ACTIONS = 16, - INPUT_MAX_BINDS = 4 +#define INPUT_TAG_LEN 32 + +typedef enum InputBindType { + IBT_SCANCODE, + IBT_CONBUTTON, + IBT_MOUSEBUTTON +} InputBindType; + +typedef struct InputBind InputBind; +struct InputBind { + InputBindType type; + union { + SDL_Scancode sc; + uint8_t cb; + uint8_t mb; + }; + InputBind *next; +}; + +typedef struct InputAction InputAction; +struct InputAction { + char tag[INPUT_TAG_LEN]; + InputBind binds; + InputAction *next; +}; + +typedef enum InputPairType { + IPT_ACTION, + IPT_STICK +} InputPairType; + +typedef struct InputPair InputPair; +struct InputPair { + InputPairType type; + union { + struct { + char left[INPUT_TAG_LEN]; + char right[INPUT_TAG_LEN]; + }; + float (*stick)(void); + }; + InputPair *next; +}; + +typedef struct InputAxis InputAxis; +struct InputAxis { + char tag[INPUT_TAG_LEN]; + InputPair pairs; + InputAxis *next; }; void input_deinit(void); -void input_new(const char *action); -void input_clear(const char *action); -void input_bind_scancode(const char *action, SDL_Scancode sc); -bool input_down(const char *action); -bool input_up(const char *action); -bool input_pressed(const char *action); -bool input_released(const char *action); +void input_new_action(const char *tag); +void input_new_axis(const char *tag); +void input_bind_action_sc(const char *tag, SDL_Scancode sc); +void input_bind_action_cb(const char *tag, uint8_t cb); +void input_bind_action_mb(const char *tag, uint8_t mb); +void input_bind_axis_gc(const char *tag, SDL_GameControllerAxis ax); +void input_bind_axis_act(const char *tag, const char *l, const char *r); + +bool input_down(const char *tag); +bool input_up(const char *tag); +bool input_pressed(const char *tag); +bool input_released(const char *tag); +int input_axis(const char *tag); +float input_axisf(const char *tag); |