twn_input: singleton rework, twn_control.h and fixes
This commit is contained in:
parent
aef3f6444e
commit
0ede612bec
@ -16,14 +16,17 @@
|
||||
void handle_input(void)
|
||||
{
|
||||
State *state = ctx.udata;
|
||||
if (ctx.input.mouse_state == 1 && ctx.input.mouse_window_position.y > 60)
|
||||
|
||||
if (ctx.mouse_window_position.y <= 60)
|
||||
return;
|
||||
|
||||
if (input_is_action_pressed("add_a_bit"))
|
||||
{ // Left click
|
||||
for (int i = 0; i < LEFT_CLICK_ADD; i++)
|
||||
{
|
||||
if (state->bunniesCount < MAX_BUNNIES)
|
||||
{
|
||||
state->bunnies[state->bunniesCount].position =
|
||||
(Vec2){(float)ctx.input.mouse_window_position.x, (float)ctx.input.mouse_window_position.y};
|
||||
state->bunnies[state->bunniesCount].position = input_get_action_position("add_a_bit");
|
||||
state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0;
|
||||
state->bunnies[state->bunniesCount].speed.y = (float)(rand() % 500 - 250) / 60.0;
|
||||
state->bunnies[state->bunniesCount].color =
|
||||
@ -33,14 +36,13 @@ void handle_input(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.input.mouse_state == 4)
|
||||
if (input_is_action_pressed("add_a_lot"))
|
||||
{ // Right click
|
||||
for (int i = 0; i < RIGHT_CLICK_ADD; i++)
|
||||
{
|
||||
if (state->bunniesCount < MAX_BUNNIES)
|
||||
{
|
||||
state->bunnies[state->bunniesCount].position =
|
||||
(Vec2){(float)ctx.input.mouse_window_position.x, (float)ctx.input.mouse_window_position.y};
|
||||
state->bunnies[state->bunniesCount].position = input_get_action_position("add_a_lot");
|
||||
state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0;
|
||||
state->bunnies[state->bunniesCount].speed.y = (float)(rand() % 500 - 250) / 60.0;
|
||||
state->bunnies[state->bunniesCount].color =
|
||||
@ -53,8 +55,7 @@ void handle_input(void)
|
||||
|
||||
void game_tick(void)
|
||||
{
|
||||
static char bunny_count_text[64];
|
||||
static char bunny_path[64] = "wabbit_alpha.png";
|
||||
char bunny_count_text[64];
|
||||
|
||||
// State *state = ctx.udata;
|
||||
if (ctx.initialization_needed)
|
||||
@ -62,7 +63,12 @@ void game_tick(void)
|
||||
// Allocating State struct to store data there
|
||||
if (!ctx.udata)
|
||||
ctx.udata = ccalloc(1, sizeof(State));
|
||||
((State *)ctx.udata)->bunniesCount = 0;
|
||||
|
||||
input_add_action("add_a_bit");
|
||||
input_bind_action_control("add_a_bit", CONTROL_LEFT_MOUSE);
|
||||
|
||||
input_add_action("add_a_lot");
|
||||
input_bind_action_control("add_a_lot", CONTROL_RIGHT_MOUSE);
|
||||
}
|
||||
|
||||
State *state = ctx.udata;
|
||||
@ -90,16 +96,16 @@ void game_tick(void)
|
||||
|
||||
for (int i = 0; i < state->bunniesCount; i++)
|
||||
{ // Draw each bunny based on their position and color, also scale accordingly
|
||||
m_sprite(m_set(path, bunny_path),
|
||||
m_sprite(m_set(path, "wabbit_alpha.png"),
|
||||
m_set(rect, ((Rect){.x = (int)state->bunnies[i].position.x,
|
||||
.y = (int)state->bunnies[i].position.y,
|
||||
.w = BUNNY_W * SPRITE_SCALE,
|
||||
.h = BUNNY_H * SPRITE_SCALE})),
|
||||
m_opt(color, (state->bunnies[i].color)), m_opt(stretch, true), );
|
||||
}
|
||||
|
||||
// Formatting text to display, might want to add FPS here too
|
||||
snprintf(bunny_count_text, 64, "Bunnies: %d", state->bunniesCount);
|
||||
|
||||
draw_text(bunny_count_text, (Vec2){0, 0}, 40, BLACK, "/fonts/kenney-pixel.ttf");
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ typedef struct State
|
||||
{
|
||||
Bunny bunnies[MAX_BUNNIES];
|
||||
int bunniesCount;
|
||||
InputState mouse_state;
|
||||
} State;
|
||||
|
||||
#endif
|
||||
|
@ -19,44 +19,44 @@ void game_tick(void) {
|
||||
state->scene = title_scene(state);
|
||||
}
|
||||
|
||||
input_add_action(&ctx.input, "debug_toggle");
|
||||
input_bind_action_scancode(&ctx.input, "debug_toggle", SCANCODE_BACKSPACE);
|
||||
input_add_action("debug_toggle");
|
||||
input_bind_action_control("debug_toggle", CONTROL_BACKSPACE);
|
||||
|
||||
input_add_action(&ctx.input, "debug_dump_atlases");
|
||||
input_bind_action_scancode(&ctx.input, "debug_dump_atlases", SCANCODE_HOME);
|
||||
input_add_action("debug_dump_atlases");
|
||||
input_bind_action_control("debug_dump_atlases", CONTROL_HOME);
|
||||
|
||||
input_add_action(&ctx.input, "player_left");
|
||||
input_bind_action_scancode(&ctx.input, "player_left", SCANCODE_A);
|
||||
input_add_action("player_left");
|
||||
input_bind_action_control("player_left", CONTROL_A);
|
||||
|
||||
input_add_action(&ctx.input, "player_right");
|
||||
input_bind_action_scancode(&ctx.input, "player_right", SCANCODE_D);
|
||||
input_add_action("player_right");
|
||||
input_bind_action_control("player_right", CONTROL_D);
|
||||
|
||||
input_add_action(&ctx.input, "player_forward");
|
||||
input_bind_action_scancode(&ctx.input, "player_forward", SCANCODE_W);
|
||||
input_add_action("player_forward");
|
||||
input_bind_action_control("player_forward", CONTROL_W);
|
||||
|
||||
input_add_action(&ctx.input, "player_backward");
|
||||
input_bind_action_scancode(&ctx.input, "player_backward", SCANCODE_S);
|
||||
input_add_action("player_backward");
|
||||
input_bind_action_control("player_backward", CONTROL_S);
|
||||
|
||||
input_add_action(&ctx.input, "player_jump");
|
||||
input_bind_action_scancode(&ctx.input, "player_jump", SCANCODE_SPACE);
|
||||
input_add_action("player_jump");
|
||||
input_bind_action_control("player_jump", CONTROL_SPACE);
|
||||
|
||||
input_add_action(&ctx.input, "player_run");
|
||||
input_bind_action_scancode(&ctx.input, "player_run", SCANCODE_LSHIFT);
|
||||
input_add_action("player_run");
|
||||
input_bind_action_control("player_run", CONTROL_LSHIFT);
|
||||
|
||||
input_add_action(&ctx.input, "ui_accept");
|
||||
input_bind_action_scancode(&ctx.input, "ui_accept", SCANCODE_RETURN);
|
||||
input_add_action("ui_accept");
|
||||
input_bind_action_control("ui_accept", CONTROL_RETURN);
|
||||
|
||||
input_add_action(&ctx.input, "mouse_capture_toggle");
|
||||
input_bind_action_scancode(&ctx.input, "mouse_capture_toggle", SCANCODE_ESCAPE);
|
||||
input_add_action("mouse_capture_toggle");
|
||||
input_bind_action_control("mouse_capture_toggle", CONTROL_ESCAPE);
|
||||
}
|
||||
|
||||
State *state = ctx.udata;
|
||||
|
||||
if (input_is_action_just_pressed(&ctx.input, "debug_toggle")) {
|
||||
if (input_is_action_just_pressed("debug_toggle")) {
|
||||
ctx.debug = !ctx.debug;
|
||||
}
|
||||
|
||||
if (input_is_action_just_pressed(&ctx.input, "debug_dump_atlases")) {
|
||||
if (input_is_action_just_pressed("debug_dump_atlases")) {
|
||||
textures_dump_atlases();
|
||||
}
|
||||
|
||||
|
@ -17,22 +17,22 @@ static void update_timers(Player *player) {
|
||||
}
|
||||
|
||||
|
||||
static void input_move(InputState *input, Player *player) {
|
||||
static void input_move(Player *player) {
|
||||
/* apply horizontal damping when the player stops moving */
|
||||
/* in other words, make it decelerate to a standstill */
|
||||
if (!input_is_action_pressed(input, "player_left") &&
|
||||
!input_is_action_pressed(input, "player_right"))
|
||||
if (!input_is_action_pressed("player_left") &&
|
||||
!input_is_action_pressed("player_right"))
|
||||
{
|
||||
player->dx *= player->horizontal_damping;
|
||||
}
|
||||
|
||||
int input_dir = 0;
|
||||
if (input_is_action_pressed(input, "player_left"))
|
||||
if (input_is_action_pressed("player_left"))
|
||||
input_dir = -1;
|
||||
if (input_is_action_pressed(input, "player_right"))
|
||||
if (input_is_action_pressed("player_right"))
|
||||
input_dir = 1;
|
||||
if (input_is_action_pressed(input, "player_left") &&
|
||||
input_is_action_pressed(input, "player_right"))
|
||||
if (input_is_action_pressed("player_left") &&
|
||||
input_is_action_pressed("player_right"))
|
||||
input_dir = 0;
|
||||
|
||||
player->dx += (float)input_dir * player->run_horizontal_speed;
|
||||
@ -53,10 +53,10 @@ static void jump(Player *player) {
|
||||
}
|
||||
|
||||
|
||||
static void input_jump(InputState *input, Player *player) {
|
||||
static void input_jump(Player *player) {
|
||||
player->current_gravity_multiplier = player->jump_default_multiplier;
|
||||
|
||||
if (input_is_action_just_pressed(input, "player_jump")) {
|
||||
if (input_is_action_just_pressed("player_jump")) {
|
||||
player->jump_air_timer = 0;
|
||||
player->jump_buffer_timer = player->jump_buffer_ticks;
|
||||
|
||||
@ -65,7 +65,7 @@ static void input_jump(InputState *input, Player *player) {
|
||||
}
|
||||
}
|
||||
|
||||
if (input_is_action_pressed(input, "player_jump")) {
|
||||
if (input_is_action_pressed("player_jump")) {
|
||||
if (player->action != PLAYER_ACTION_GROUND && player->jump_air_timer > 0) {
|
||||
player->current_gravity_multiplier = player->jump_boosted_multiplier;
|
||||
player->dy += player->jump_force_increase;
|
||||
@ -284,8 +284,8 @@ void player_destroy(Player *player) {
|
||||
void player_calc(Player *player) {
|
||||
update_timers(player);
|
||||
|
||||
input_move(&ctx.input, player);
|
||||
input_jump(&ctx.input, player);
|
||||
input_move(player);
|
||||
input_jump(player);
|
||||
|
||||
player->rect.x += player->dx;
|
||||
update_collider_x(player);
|
||||
|
@ -16,22 +16,22 @@ static void ingame_tick(State *state) {
|
||||
|
||||
const Vec3 right = m_vec_norm(m_vec_cross(scn->cam.target, scn->cam.up));
|
||||
const float speed = 0.04f; /* TODO: put this in a better place */
|
||||
if (input_is_action_pressed(&ctx.input, "player_left"))
|
||||
if (input_is_action_pressed("player_left"))
|
||||
scn->cam.pos = vec3_sub(scn->cam.pos, m_vec_scale(right, speed));
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_right"))
|
||||
if (input_is_action_pressed("player_right"))
|
||||
scn->cam.pos = vec3_add(scn->cam.pos, m_vec_scale(right, speed));
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_forward"))
|
||||
if (input_is_action_pressed("player_forward"))
|
||||
scn->cam.pos = vec3_add(scn->cam.pos, m_vec_scale(scn->cam.target, speed));
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_backward"))
|
||||
if (input_is_action_pressed("player_backward"))
|
||||
scn->cam.pos = vec3_sub(scn->cam.pos, m_vec_scale(scn->cam.target, speed));
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_jump"))
|
||||
if (input_is_action_pressed("player_jump"))
|
||||
scn->cam.pos.y += speed;
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_run"))
|
||||
if (input_is_action_pressed("player_run"))
|
||||
scn->cam.pos.y -= speed;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ static void title_tick(State *state) {
|
||||
SceneTitle *scn = (SceneTitle *)state->scene;
|
||||
(void)scn;
|
||||
|
||||
if (input_is_action_just_pressed(&state->ctx->input, "ui_accept")) {
|
||||
if (input_is_action_just_pressed("ui_accept")) {
|
||||
switch_to(state, ingame_scene);
|
||||
return;
|
||||
}
|
||||
|
@ -20,44 +20,44 @@ void game_tick(void) {
|
||||
state->scene = title_scene(state);
|
||||
}
|
||||
|
||||
input_add_action(&ctx.input, "debug_toggle");
|
||||
input_bind_action_scancode(&ctx.input, "debug_toggle", SCANCODE_BACKSPACE);
|
||||
input_add_action("debug_toggle");
|
||||
input_bind_action_control("debug_toggle", CONTROL_BACKSPACE);
|
||||
|
||||
input_add_action(&ctx.input, "debug_dump_atlases");
|
||||
input_bind_action_scancode(&ctx.input, "debug_dump_atlases", SCANCODE_HOME);
|
||||
input_add_action("debug_dump_atlases");
|
||||
input_bind_action_control("debug_dump_atlases", CONTROL_HOME);
|
||||
|
||||
input_add_action(&ctx.input, "player_left");
|
||||
input_bind_action_scancode(&ctx.input, "player_left", SCANCODE_A);
|
||||
input_add_action("player_left");
|
||||
input_bind_action_control("player_left", CONTROL_A);
|
||||
|
||||
input_add_action(&ctx.input, "player_right");
|
||||
input_bind_action_scancode(&ctx.input, "player_right", SCANCODE_D);
|
||||
input_add_action("player_right");
|
||||
input_bind_action_control("player_right", CONTROL_D);
|
||||
|
||||
input_add_action(&ctx.input, "player_forward");
|
||||
input_bind_action_scancode(&ctx.input, "player_forward", SCANCODE_W);
|
||||
input_add_action("player_forward");
|
||||
input_bind_action_control("player_forward", CONTROL_W);
|
||||
|
||||
input_add_action(&ctx.input, "player_backward");
|
||||
input_bind_action_scancode(&ctx.input, "player_backward", SCANCODE_S);
|
||||
input_add_action("player_backward");
|
||||
input_bind_action_control("player_backward", CONTROL_S);
|
||||
|
||||
input_add_action(&ctx.input, "player_jump");
|
||||
input_bind_action_scancode(&ctx.input, "player_jump", SCANCODE_SPACE);
|
||||
input_add_action("player_jump");
|
||||
input_bind_action_control("player_jump", CONTROL_SPACE);
|
||||
|
||||
input_add_action(&ctx.input, "player_run");
|
||||
input_bind_action_scancode(&ctx.input, "player_run", SCANCODE_LSHIFT);
|
||||
input_add_action("player_run");
|
||||
input_bind_action_control("player_run", CONTROL_LSHIFT);
|
||||
|
||||
input_add_action(&ctx.input, "ui_accept");
|
||||
input_bind_action_scancode(&ctx.input, "ui_accept", SCANCODE_RETURN);
|
||||
input_add_action("ui_accept");
|
||||
input_bind_action_control("ui_accept", CONTROL_RETURN);
|
||||
|
||||
input_add_action(&ctx.input, "mouse_capture_toggle");
|
||||
input_bind_action_scancode(&ctx.input, "mouse_capture_toggle", SCANCODE_ESCAPE);
|
||||
input_add_action("mouse_capture_toggle");
|
||||
input_bind_action_control("mouse_capture_toggle", CONTROL_ESCAPE);
|
||||
}
|
||||
|
||||
State *state = ctx.udata;
|
||||
|
||||
if (input_is_action_just_pressed(&ctx.input, "debug_toggle")) {
|
||||
if (input_is_action_just_pressed("debug_toggle")) {
|
||||
ctx.debug = !ctx.debug;
|
||||
}
|
||||
|
||||
if (input_is_action_just_pressed(&ctx.input, "debug_dump_atlases")) {
|
||||
if (input_is_action_just_pressed("debug_dump_atlases")) {
|
||||
textures_dump_atlases();
|
||||
}
|
||||
|
||||
|
@ -15,10 +15,10 @@
|
||||
static void ingame_tick(State *state) {
|
||||
SceneIngame *scn = (SceneIngame *)state->scene;
|
||||
|
||||
if (input_is_mouse_captured(&ctx.input)) {
|
||||
if (input_is_mouse_captured()) {
|
||||
const float sensitivity = 0.6f; /* TODO: put this in a better place */
|
||||
scn->yaw += (float)ctx.input.mouse_relative_position.x * sensitivity;
|
||||
scn->pitch -= (float)ctx.input.mouse_relative_position.y * sensitivity;
|
||||
scn->yaw += (float)ctx.mouse_relative_position.x * sensitivity;
|
||||
scn->pitch -= (float)ctx.mouse_relative_position.y * sensitivity;
|
||||
scn->pitch = clampf(scn->pitch, -89.0f, 89.0f);
|
||||
|
||||
const float yaw_rad = scn->yaw * (float)DEG2RAD;
|
||||
@ -33,27 +33,27 @@ static void ingame_tick(State *state) {
|
||||
|
||||
const Vec3 right = m_vec_norm(m_vec_cross(scn->cam.target, scn->cam.up));
|
||||
const float speed = 0.04f; /* TODO: put this in a better place */
|
||||
if (input_is_action_pressed(&ctx.input, "player_left"))
|
||||
if (input_is_action_pressed("player_left"))
|
||||
scn->cam.pos = vec3_sub(scn->cam.pos, m_vec_scale(right, speed));
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_right"))
|
||||
if (input_is_action_pressed("player_right"))
|
||||
scn->cam.pos = vec3_add(scn->cam.pos, m_vec_scale(right, speed));
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_forward"))
|
||||
if (input_is_action_pressed("player_forward"))
|
||||
scn->cam.pos = vec3_add(scn->cam.pos, m_vec_scale(scn->cam.target, speed));
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_backward"))
|
||||
if (input_is_action_pressed("player_backward"))
|
||||
scn->cam.pos = vec3_sub(scn->cam.pos, m_vec_scale(scn->cam.target, speed));
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_jump"))
|
||||
if (input_is_action_pressed("player_jump"))
|
||||
scn->cam.pos.y += speed;
|
||||
|
||||
if (input_is_action_pressed(&ctx.input, "player_run"))
|
||||
if (input_is_action_pressed("player_run"))
|
||||
scn->cam.pos.y -= speed;
|
||||
|
||||
/* toggle mouse capture with end key */
|
||||
if (input_is_action_just_pressed(&ctx.input, "mouse_capture_toggle")) {
|
||||
input_set_mouse_captured(&ctx.input, !input_is_mouse_captured(&ctx.input));
|
||||
if (input_is_action_just_pressed("mouse_capture_toggle")) {
|
||||
input_set_mouse_captured(!input_is_mouse_captured());
|
||||
}
|
||||
|
||||
draw_camera(&scn->cam);
|
||||
@ -111,7 +111,7 @@ Scene *ingame_scene(State *state) {
|
||||
m_opt(channel, "soundtrack"),
|
||||
m_opt(repeat, true));
|
||||
|
||||
input_set_mouse_captured(&ctx.input, true);
|
||||
input_set_mouse_captured(true);
|
||||
|
||||
return (Scene *)new_scene;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ static void title_tick(State *state) {
|
||||
SceneTitle *scn = (SceneTitle *)state->scene;
|
||||
(void)scn;
|
||||
|
||||
if (input_is_action_just_pressed(&state->ctx->input, "ui_accept")) {
|
||||
if (input_is_action_just_pressed("ui_accept")) {
|
||||
switch_to(state, ingame_scene);
|
||||
return;
|
||||
}
|
||||
|
@ -8,12 +8,20 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/* context that is valid for current frame */
|
||||
/* changes to it should not have an effect, unless specified */
|
||||
/* TODO: ensure the statement above */
|
||||
typedef struct Context {
|
||||
InputState input;
|
||||
/* you may read from and write to these from game code */
|
||||
void *udata;
|
||||
|
||||
/* TODO: is it what we actually want? */
|
||||
int64_t delta_time; /* preserves real time frame delta with no manipilation */
|
||||
uint64_t tick_count;
|
||||
|
||||
Vec2i mouse_window_position;
|
||||
Vec2i mouse_relative_position;
|
||||
|
||||
/* set just once on startup */
|
||||
uint64_t random_seed;
|
||||
|
||||
@ -21,14 +29,13 @@ typedef struct Context {
|
||||
/* use it to simulate low framerate (e.g. at 60 tps, set to 2 for 30 fps) */
|
||||
/* it can be changed at runtime; any resulting logic anomalies are bugs */
|
||||
unsigned int update_multiplicity;
|
||||
|
||||
/* TODO: use Vec2i? */
|
||||
int window_w;
|
||||
int window_h;
|
||||
int base_draw_w;
|
||||
int base_draw_h;
|
||||
|
||||
/* you may read from and write to these from game code */
|
||||
void *udata;
|
||||
|
||||
bool debug;
|
||||
bool is_running;
|
||||
bool window_size_has_changed;
|
||||
|
433
include/twn_control.h
Normal file
433
include/twn_control.h
Normal file
@ -0,0 +1,433 @@
|
||||
#ifndef TWN_CONTROL_H
|
||||
#define TWN_CONTROL_H
|
||||
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2024 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, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* based on SDL2 */
|
||||
/* main difference is that we combine mouse and scancode sources into one enum space */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONTROL_SCANCODE_START = 0,
|
||||
CONTROL_UNKNOWN = 0,
|
||||
|
||||
/**
|
||||
* \name Usage page 0x07
|
||||
*
|
||||
* These values are from usage page 0x07 (USB keyboard page).
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
CONTROL_A = 4,
|
||||
CONTROL_B = 5,
|
||||
CONTROL_C = 6,
|
||||
CONTROL_D = 7,
|
||||
CONTROL_E = 8,
|
||||
CONTROL_F = 9,
|
||||
CONTROL_G = 10,
|
||||
CONTROL_H = 11,
|
||||
CONTROL_I = 12,
|
||||
CONTROL_J = 13,
|
||||
CONTROL_K = 14,
|
||||
CONTROL_L = 15,
|
||||
CONTROL_M = 16,
|
||||
CONTROL_N = 17,
|
||||
CONTROL_O = 18,
|
||||
CONTROL_P = 19,
|
||||
CONTROL_Q = 20,
|
||||
CONTROL_R = 21,
|
||||
CONTROL_S = 22,
|
||||
CONTROL_T = 23,
|
||||
CONTROL_U = 24,
|
||||
CONTROL_V = 25,
|
||||
CONTROL_W = 26,
|
||||
CONTROL_X = 27,
|
||||
CONTROL_Y = 28,
|
||||
CONTROL_Z = 29,
|
||||
|
||||
CONTROL_1 = 30,
|
||||
CONTROL_2 = 31,
|
||||
CONTROL_3 = 32,
|
||||
CONTROL_4 = 33,
|
||||
CONTROL_5 = 34,
|
||||
CONTROL_6 = 35,
|
||||
CONTROL_7 = 36,
|
||||
CONTROL_8 = 37,
|
||||
CONTROL_9 = 38,
|
||||
CONTROL_0 = 39,
|
||||
|
||||
CONTROL_RETURN = 40,
|
||||
CONTROL_ESCAPE = 41,
|
||||
CONTROL_BACKSPACE = 42,
|
||||
CONTROL_TAB = 43,
|
||||
CONTROL_SPACE = 44,
|
||||
|
||||
CONTROL_MINUS = 45,
|
||||
CONTROL_EQUALS = 46,
|
||||
CONTROL_LEFTBRACKET = 47,
|
||||
CONTROL_RIGHTBRACKET = 48,
|
||||
CONTROL_BACKSLASH = 49, /**< Located at the lower left of the return
|
||||
* key on ISO keyboards and at the right end
|
||||
* of the QWERTY row on ANSI keyboards.
|
||||
* Produces REVERSE SOLIDUS (backslash) and
|
||||
* VERTICAL LINE in a US layout, REVERSE
|
||||
* SOLIDUS and VERTICAL LINE in a UK Mac
|
||||
* layout, NUMBER SIGN and TILDE in a UK
|
||||
* Windows layout, DOLLAR SIGN and POUND SIGN
|
||||
* in a Swiss German layout, NUMBER SIGN and
|
||||
* APOSTROPHE in a German layout, GRAVE
|
||||
* ACCENT and POUND SIGN in a French Mac
|
||||
* layout, and ASTERISK and MICRO SIGN in a
|
||||
* French Windows layout.
|
||||
*/
|
||||
CONTROL_NONUSHASH = 50, /**< ISO USB keyboards actually use this code
|
||||
* instead of 49 for the same key, but all
|
||||
* OSes I've seen treat the two codes
|
||||
* identically. So, as an implementor, unless
|
||||
* your keyboard generates both of those
|
||||
* codes and your OS treats them differently,
|
||||
* you should generate CONTROL_BACKSLASH
|
||||
* instead of this code. As a user, you
|
||||
* should not rely on this code because SDL
|
||||
* will never generate it with most (all?)
|
||||
* keyboards.
|
||||
*/
|
||||
CONTROL_SEMICOLON = 51,
|
||||
CONTROL_APOSTROPHE = 52,
|
||||
CONTROL_GRAVE = 53, /**< Located in the top left corner (on both ANSI
|
||||
* and ISO keyboards). Produces GRAVE ACCENT and
|
||||
* TILDE in a US Windows layout and in US and UK
|
||||
* Mac layouts on ANSI keyboards, GRAVE ACCENT
|
||||
* and NOT SIGN in a UK Windows layout, SECTION
|
||||
* SIGN and PLUS-MINUS SIGN in US and UK Mac
|
||||
* layouts on ISO keyboards, SECTION SIGN and
|
||||
* DEGREE SIGN in a Swiss German layout (Mac:
|
||||
* only on ISO keyboards), CIRCUMFLEX ACCENT and
|
||||
* DEGREE SIGN in a German layout (Mac: only on
|
||||
* ISO keyboards), SUPERSCRIPT TWO and TILDE in a
|
||||
* French Windows layout, COMMERCIAL AT and
|
||||
* NUMBER SIGN in a French Mac layout on ISO
|
||||
* keyboards, and LESS-THAN SIGN and GREATER-THAN
|
||||
* SIGN in a Swiss German, German, or French Mac
|
||||
* layout on ANSI keyboards.
|
||||
*/
|
||||
CONTROL_COMMA = 54,
|
||||
CONTROL_PERIOD = 55,
|
||||
CONTROL_SLASH = 56,
|
||||
|
||||
CONTROL_CAPSLOCK = 57,
|
||||
|
||||
CONTROL_F1 = 58,
|
||||
CONTROL_F2 = 59,
|
||||
CONTROL_F3 = 60,
|
||||
CONTROL_F4 = 61,
|
||||
CONTROL_F5 = 62,
|
||||
CONTROL_F6 = 63,
|
||||
CONTROL_F7 = 64,
|
||||
CONTROL_F8 = 65,
|
||||
CONTROL_F9 = 66,
|
||||
CONTROL_F10 = 67,
|
||||
CONTROL_F11 = 68,
|
||||
CONTROL_F12 = 69,
|
||||
|
||||
CONTROL_PRINTSCREEN = 70,
|
||||
CONTROL_SCROLLLOCK = 71,
|
||||
CONTROL_PAUSE = 72,
|
||||
CONTROL_INSERT = 73, /**< insert on PC, help on some Mac keyboards (but
|
||||
does send code 73, not 117) */
|
||||
CONTROL_HOME = 74,
|
||||
CONTROL_PAGEUP = 75,
|
||||
CONTROL_DELETE = 76,
|
||||
CONTROL_END = 77,
|
||||
CONTROL_PAGEDOWN = 78,
|
||||
CONTROL_RIGHT = 79,
|
||||
CONTROL_LEFT = 80,
|
||||
CONTROL_DOWN = 81,
|
||||
CONTROL_UP = 82,
|
||||
|
||||
CONTROL_NUMLOCKCLEAR = 83, /**< num lock on PC, clear on Mac keyboards
|
||||
*/
|
||||
CONTROL_KP_DIVIDE = 84,
|
||||
CONTROL_KP_MULTIPLY = 85,
|
||||
CONTROL_KP_MINUS = 86,
|
||||
CONTROL_KP_PLUS = 87,
|
||||
CONTROL_KP_ENTER = 88,
|
||||
CONTROL_KP_1 = 89,
|
||||
CONTROL_KP_2 = 90,
|
||||
CONTROL_KP_3 = 91,
|
||||
CONTROL_KP_4 = 92,
|
||||
CONTROL_KP_5 = 93,
|
||||
CONTROL_KP_6 = 94,
|
||||
CONTROL_KP_7 = 95,
|
||||
CONTROL_KP_8 = 96,
|
||||
CONTROL_KP_9 = 97,
|
||||
CONTROL_KP_0 = 98,
|
||||
CONTROL_KP_PERIOD = 99,
|
||||
|
||||
CONTROL_NONUSBACKSLASH = 100, /**< This is the additional key that ISO
|
||||
* keyboards have over ANSI ones,
|
||||
* located between left shift and Y.
|
||||
* Produces GRAVE ACCENT and TILDE in a
|
||||
* US or UK Mac layout, REVERSE SOLIDUS
|
||||
* (backslash) and VERTICAL LINE in a
|
||||
* US or UK Windows layout, and
|
||||
* LESS-THAN SIGN and GREATER-THAN SIGN
|
||||
* in a Swiss German, German, or French
|
||||
* layout. */
|
||||
CONTROL_APPLICATION = 101, /**< windows contextual menu, compose */
|
||||
CONTROL_POWER = 102, /**< The USB document says this is a status flag,
|
||||
* not a physical key - but some Mac keyboards
|
||||
* do have a power key. */
|
||||
CONTROL_KP_EQUALS = 103,
|
||||
CONTROL_F13 = 104,
|
||||
CONTROL_F14 = 105,
|
||||
CONTROL_F15 = 106,
|
||||
CONTROL_F16 = 107,
|
||||
CONTROL_F17 = 108,
|
||||
CONTROL_F18 = 109,
|
||||
CONTROL_F19 = 110,
|
||||
CONTROL_F20 = 111,
|
||||
CONTROL_F21 = 112,
|
||||
CONTROL_F22 = 113,
|
||||
CONTROL_F23 = 114,
|
||||
CONTROL_F24 = 115,
|
||||
CONTROL_EXECUTE = 116,
|
||||
CONTROL_HELP = 117, /**< AL Integrated Help Center */
|
||||
CONTROL_MENU = 118, /**< Menu (show menu) */
|
||||
CONTROL_SELECT = 119,
|
||||
CONTROL_STOP = 120, /**< AC Stop */
|
||||
CONTROL_AGAIN = 121, /**< AC Redo/Repeat */
|
||||
CONTROL_UNDO = 122, /**< AC Undo */
|
||||
CONTROL_CUT = 123, /**< AC Cut */
|
||||
CONTROL_COPY = 124, /**< AC Copy */
|
||||
CONTROL_PASTE = 125, /**< AC Paste */
|
||||
CONTROL_FIND = 126, /**< AC Find */
|
||||
CONTROL_MUTE = 127,
|
||||
CONTROL_VOLUMEUP = 128,
|
||||
CONTROL_VOLUMEDOWN = 129,
|
||||
/* not sure whether there's a reason to enable these */
|
||||
/* CONTROL_LOCKINGCAPSLOCK = 130, */
|
||||
/* CONTROL_LOCKINGNUMLOCK = 131, */
|
||||
/* CONTROL_LOCKINGSCROLLLOCK = 132, */
|
||||
CONTROL_KP_COMMA = 133,
|
||||
CONTROL_KP_EQUALSAS400 = 134,
|
||||
|
||||
CONTROL_INTERNATIONAL1 = 135, /**< used on Asian keyboards, see
|
||||
footnotes in USB doc */
|
||||
CONTROL_INTERNATIONAL2 = 136,
|
||||
CONTROL_INTERNATIONAL3 = 137, /**< Yen */
|
||||
CONTROL_INTERNATIONAL4 = 138,
|
||||
CONTROL_INTERNATIONAL5 = 139,
|
||||
CONTROL_INTERNATIONAL6 = 140,
|
||||
CONTROL_INTERNATIONAL7 = 141,
|
||||
CONTROL_INTERNATIONAL8 = 142,
|
||||
CONTROL_INTERNATIONAL9 = 143,
|
||||
CONTROL_LANG1 = 144, /**< Hangul/English toggle */
|
||||
CONTROL_LANG2 = 145, /**< Hanja conversion */
|
||||
CONTROL_LANG3 = 146, /**< Katakana */
|
||||
CONTROL_LANG4 = 147, /**< Hiragana */
|
||||
CONTROL_LANG5 = 148, /**< Zenkaku/Hankaku */
|
||||
CONTROL_LANG6 = 149, /**< reserved */
|
||||
CONTROL_LANG7 = 150, /**< reserved */
|
||||
CONTROL_LANG8 = 151, /**< reserved */
|
||||
CONTROL_LANG9 = 152, /**< reserved */
|
||||
|
||||
CONTROL_ALTERASE = 153, /**< Erase-Eaze */
|
||||
CONTROL_SYSREQ = 154,
|
||||
CONTROL_CANCEL = 155, /**< AC Cancel */
|
||||
CONTROL_CLEAR = 156,
|
||||
CONTROL_PRIOR = 157,
|
||||
CONTROL_RETURN2 = 158,
|
||||
CONTROL_SEPARATOR = 159,
|
||||
CONTROL_OUT = 160,
|
||||
CONTROL_OPER = 161,
|
||||
CONTROL_CLEARAGAIN = 162,
|
||||
CONTROL_CRSEL = 163,
|
||||
CONTROL_EXSEL = 164,
|
||||
|
||||
CONTROL_KP_00 = 176,
|
||||
CONTROL_KP_000 = 177,
|
||||
CONTROL_THOUSANDSSEPARATOR = 178,
|
||||
CONTROL_DECIMALSEPARATOR = 179,
|
||||
CONTROL_CURRENCYUNIT = 180,
|
||||
CONTROL_CURRENCYSUBUNIT = 181,
|
||||
CONTROL_KP_LEFTPAREN = 182,
|
||||
CONTROL_KP_RIGHTPAREN = 183,
|
||||
CONTROL_KP_LEFTBRACE = 184,
|
||||
CONTROL_KP_RIGHTBRACE = 185,
|
||||
CONTROL_KP_TAB = 186,
|
||||
CONTROL_KP_BACKSPACE = 187,
|
||||
CONTROL_KP_A = 188,
|
||||
CONTROL_KP_B = 189,
|
||||
CONTROL_KP_C = 190,
|
||||
CONTROL_KP_D = 191,
|
||||
CONTROL_KP_E = 192,
|
||||
CONTROL_KP_F = 193,
|
||||
CONTROL_KP_XOR = 194,
|
||||
CONTROL_KP_POWER = 195,
|
||||
CONTROL_KP_PERCENT = 196,
|
||||
CONTROL_KP_LESS = 197,
|
||||
CONTROL_KP_GREATER = 198,
|
||||
CONTROL_KP_AMPERSAND = 199,
|
||||
CONTROL_KP_DBLAMPERSAND = 200,
|
||||
CONTROL_KP_VERTICALBAR = 201,
|
||||
CONTROL_KP_DBLVERTICALBAR = 202,
|
||||
CONTROL_KP_COLON = 203,
|
||||
CONTROL_KP_HASH = 204,
|
||||
CONTROL_KP_SPACE = 205,
|
||||
CONTROL_KP_AT = 206,
|
||||
CONTROL_KP_EXCLAM = 207,
|
||||
CONTROL_KP_MEMSTORE = 208,
|
||||
CONTROL_KP_MEMRECALL = 209,
|
||||
CONTROL_KP_MEMCLEAR = 210,
|
||||
CONTROL_KP_MEMADD = 211,
|
||||
CONTROL_KP_MEMSUBTRACT = 212,
|
||||
CONTROL_KP_MEMMULTIPLY = 213,
|
||||
CONTROL_KP_MEMDIVIDE = 214,
|
||||
CONTROL_KP_PLUSMINUS = 215,
|
||||
CONTROL_KP_CLEAR = 216,
|
||||
CONTROL_KP_CLEARENTRY = 217,
|
||||
CONTROL_KP_BINARY = 218,
|
||||
CONTROL_KP_OCTAL = 219,
|
||||
CONTROL_KP_DECIMAL = 220,
|
||||
CONTROL_KP_HEXADECIMAL = 221,
|
||||
|
||||
CONTROL_LCTRL = 224,
|
||||
CONTROL_LSHIFT = 225,
|
||||
CONTROL_LALT = 226, /**< alt, option */
|
||||
CONTROL_LGUI = 227, /**< windows, command (apple), meta */
|
||||
CONTROL_RCTRL = 228,
|
||||
CONTROL_RSHIFT = 229,
|
||||
CONTROL_RALT = 230, /**< alt gr, option */
|
||||
CONTROL_RGUI = 231, /**< windows, command (apple), meta */
|
||||
|
||||
CONTROL_MODE = 257, /**< I'm not sure if this is really not covered
|
||||
* by any of the above, but since there's a
|
||||
* special KMOD_MODE for it I'm adding it here
|
||||
*/
|
||||
|
||||
/* @} *//* Usage page 0x07 */
|
||||
|
||||
/**
|
||||
* \name Usage page 0x0C
|
||||
*
|
||||
* These values are mapped from usage page 0x0C (USB consumer page).
|
||||
* See https://usb.org/sites/default/files/hut1_2.pdf
|
||||
*
|
||||
* There are way more keys in the spec than we can represent in the
|
||||
* current scancode range, so pick the ones that commonly come up in
|
||||
* real world usage.
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
CONTROL_AUDIONEXT = 258,
|
||||
CONTROL_AUDIOPREV = 259,
|
||||
CONTROL_AUDIOSTOP = 260,
|
||||
CONTROL_AUDIOPLAY = 261,
|
||||
CONTROL_AUDIOMUTE = 262,
|
||||
CONTROL_MEDIASELECT = 263,
|
||||
CONTROL_WWW = 264, /**< AL Internet Browser */
|
||||
CONTROL_MAIL = 265,
|
||||
CONTROL_CALCULATOR = 266, /**< AL Calculator */
|
||||
CONTROL_COMPUTER = 267,
|
||||
CONTROL_AC_SEARCH = 268, /**< AC Search */
|
||||
CONTROL_AC_HOME = 269, /**< AC Home */
|
||||
CONTROL_AC_BACK = 270, /**< AC Back */
|
||||
CONTROL_AC_FORWARD = 271, /**< AC Forward */
|
||||
CONTROL_AC_STOP = 272, /**< AC Stop */
|
||||
CONTROL_AC_REFRESH = 273, /**< AC Refresh */
|
||||
CONTROL_AC_BOOKMARKS = 274, /**< AC Bookmarks */
|
||||
|
||||
/* @} *//* Usage page 0x0C */
|
||||
|
||||
/**
|
||||
* \name Walther keys
|
||||
*
|
||||
* These are values that Christian Walther added (for mac keyboard?).
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
CONTROL_BRIGHTNESSDOWN = 275,
|
||||
CONTROL_BRIGHTNESSUP = 276,
|
||||
CONTROL_DISPLAYSWITCH = 277, /**< display mirroring/dual display
|
||||
switch, video mode switch */
|
||||
CONTROL_KBDILLUMTOGGLE = 278,
|
||||
CONTROL_KBDILLUMDOWN = 279,
|
||||
CONTROL_KBDILLUMUP = 280,
|
||||
CONTROL_EJECT = 281,
|
||||
CONTROL_SLEEP = 282, /**< SC System Sleep */
|
||||
|
||||
CONTROL_APP1 = 283,
|
||||
CONTROL_APP2 = 284,
|
||||
|
||||
/* @} *//* Walther keys */
|
||||
|
||||
/**
|
||||
* \name Usage page 0x0C (additional media keys)
|
||||
*
|
||||
* These values are mapped from usage page 0x0C (USB consumer page).
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
CONTROL_AUDIOREWIND = 285,
|
||||
CONTROL_AUDIOFASTFORWARD = 286,
|
||||
|
||||
/* @} *//* Usage page 0x0C (additional media keys) */
|
||||
|
||||
/**
|
||||
* \name Mobile keys
|
||||
*
|
||||
* These are values that are often used on mobile phones.
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
CONTROL_SOFTLEFT = 287, /**< Usually situated below the display on phones and
|
||||
used as a multi-function feature key for selecting
|
||||
a software defined function shown on the bottom left
|
||||
of the display. */
|
||||
CONTROL_SOFTRIGHT = 288, /**< Usually situated below the display on phones and
|
||||
used as a multi-function feature key for selecting
|
||||
a software defined function shown on the bottom right
|
||||
of the display. */
|
||||
CONTROL_CALL = 289, /**< Used for accepting phone calls. */
|
||||
CONTROL_ENDCALL = 290, /**< Used for rejecting phone calls. */
|
||||
|
||||
/* @} *//* Mobile keys */
|
||||
|
||||
/* Add any other keys here. */
|
||||
|
||||
CONTROL_SCANCODE_LIMIT = 512, /**< not a key, just marks the number of scancodes
|
||||
for array bounds */
|
||||
|
||||
CONTROL_MOUSECODE_START = 512,
|
||||
|
||||
CONTROL_LEFT_MOUSE = 513,
|
||||
CONTROL_RIGHT_MOUSE = 515,
|
||||
CONTROL_MIDDLE_MOUSE = 514,
|
||||
CONTROL_X1 = 516,
|
||||
CONTROL_X2 = 517,
|
||||
|
||||
CONTROL_MOUSECODE_LIMIT = 532,
|
||||
|
||||
} Control;
|
||||
|
||||
#endif
|
@ -4,87 +4,26 @@
|
||||
#include "twn_config.h"
|
||||
#include "twn_types.h"
|
||||
#include "twn_engine_api.h"
|
||||
#include "twn_scancode.h"
|
||||
#include "twn_control.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum ButtonSource {
|
||||
BUTTON_SOURCE_NOT_SET,
|
||||
BUTTON_SOURCE_KEYBOARD_PHYSICAL,
|
||||
BUTTON_SOURCE_KEYBOARD_CHARACTER,
|
||||
BUTTON_SOURCE_GAMEPAD,
|
||||
BUTTON_SOURCE_MOUSE,
|
||||
} ButtonSource;
|
||||
|
||||
TWN_API void input_bind_action_control(const char *action_name, Control control);
|
||||
TWN_API void input_unbind_action_control(const char *action_name, Control control);
|
||||
|
||||
/* internal */
|
||||
typedef struct Button Button;
|
||||
TWN_API void input_add_action(const char *action_name);
|
||||
TWN_API void input_delete_action(const char *action_name);
|
||||
|
||||
TWN_API bool input_is_action_pressed(const char *action_name);
|
||||
TWN_API bool input_is_action_just_pressed(const char *action_name);
|
||||
TWN_API bool input_is_action_just_released(const char *action_name);
|
||||
|
||||
/* represents the collective state of a group of buttons */
|
||||
/* that is, changes in the states of any of the bound buttons will affect it */
|
||||
typedef struct Action {
|
||||
size_t num_bindings;
|
||||
TWN_API Vec2 input_get_action_position(const char *action_name);
|
||||
|
||||
/* if you bind more than the number set in the configuration file */
|
||||
/* it forgets the first Button to add the new one at the end */
|
||||
Button *bindings;
|
||||
|
||||
Vec2 position; /* set if applicable, e.g. mouse click */
|
||||
bool is_pressed;
|
||||
bool just_changed;
|
||||
} Action;
|
||||
|
||||
|
||||
typedef struct ActionHashItem {
|
||||
char *key;
|
||||
Action value;
|
||||
} ActionHashItem;
|
||||
|
||||
|
||||
/* TODO: don't assume SDL button mask */
|
||||
typedef struct InputState {
|
||||
uint32_t mouse_state; /* SDL mouse button bitmask */
|
||||
Vec2i mouse_window_position;
|
||||
Vec2i mouse_relative_position;
|
||||
ButtonSource last_active_source;
|
||||
bool is_anything_just_pressed;
|
||||
|
||||
/* engine state */
|
||||
ActionHashItem *action_hash;
|
||||
const uint8_t *keyboard_state; /* array of booleans indexed by scancode */
|
||||
} InputState;
|
||||
|
||||
|
||||
TWN_API void input_state_init(InputState *input);
|
||||
TWN_API void input_state_deinit(InputState *input);
|
||||
TWN_API void input_state_update(InputState *input);
|
||||
|
||||
TWN_API void input_bind_action_scancode(InputState *input,
|
||||
char *action_name,
|
||||
Scancode scancode);
|
||||
TWN_API void input_unbind_action_scancode(InputState *input,
|
||||
char *action_name,
|
||||
Scancode scancode);
|
||||
TWN_API void input_bind_action_mouse(InputState *input,
|
||||
char *action_name,
|
||||
uint8_t mouse_button);
|
||||
TWN_API void input_unbind_action_mouse(InputState *input,
|
||||
char *action_name,
|
||||
uint8_t mouse_button);
|
||||
|
||||
TWN_API void input_add_action(InputState *input, char *action_name);
|
||||
TWN_API void input_delete_action(InputState *input, char *action_name);
|
||||
|
||||
TWN_API bool input_is_action_pressed(InputState *input, char *action_name);
|
||||
TWN_API bool input_is_action_just_pressed(InputState *input, char *action_name);
|
||||
TWN_API bool input_is_action_just_released(InputState *input, char *action_name);
|
||||
|
||||
TWN_API Vec2 input_get_action_position(InputState *input, char *action_name);
|
||||
|
||||
TWN_API void input_set_mouse_captured(InputState *input, bool value);
|
||||
TWN_API bool input_is_mouse_captured(InputState *input);
|
||||
TWN_API void input_set_mouse_captured(bool enabled);
|
||||
TWN_API bool input_is_mouse_captured(void);
|
||||
|
||||
#endif
|
||||
|
@ -1,420 +0,0 @@
|
||||
#ifndef TWN_SCANCODE_H
|
||||
#define TWN_SCANCODE_H
|
||||
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2024 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, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* based on SDL2 */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SCANCODE_UNKNOWN = 0,
|
||||
|
||||
/**
|
||||
* \name Usage page 0x07
|
||||
*
|
||||
* These values are from usage page 0x07 (USB keyboard page).
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
SCANCODE_A = 4,
|
||||
SCANCODE_B = 5,
|
||||
SCANCODE_C = 6,
|
||||
SCANCODE_D = 7,
|
||||
SCANCODE_E = 8,
|
||||
SCANCODE_F = 9,
|
||||
SCANCODE_G = 10,
|
||||
SCANCODE_H = 11,
|
||||
SCANCODE_I = 12,
|
||||
SCANCODE_J = 13,
|
||||
SCANCODE_K = 14,
|
||||
SCANCODE_L = 15,
|
||||
SCANCODE_M = 16,
|
||||
SCANCODE_N = 17,
|
||||
SCANCODE_O = 18,
|
||||
SCANCODE_P = 19,
|
||||
SCANCODE_Q = 20,
|
||||
SCANCODE_R = 21,
|
||||
SCANCODE_S = 22,
|
||||
SCANCODE_T = 23,
|
||||
SCANCODE_U = 24,
|
||||
SCANCODE_V = 25,
|
||||
SCANCODE_W = 26,
|
||||
SCANCODE_X = 27,
|
||||
SCANCODE_Y = 28,
|
||||
SCANCODE_Z = 29,
|
||||
|
||||
SCANCODE_1 = 30,
|
||||
SCANCODE_2 = 31,
|
||||
SCANCODE_3 = 32,
|
||||
SCANCODE_4 = 33,
|
||||
SCANCODE_5 = 34,
|
||||
SCANCODE_6 = 35,
|
||||
SCANCODE_7 = 36,
|
||||
SCANCODE_8 = 37,
|
||||
SCANCODE_9 = 38,
|
||||
SCANCODE_0 = 39,
|
||||
|
||||
SCANCODE_RETURN = 40,
|
||||
SCANCODE_ESCAPE = 41,
|
||||
SCANCODE_BACKSPACE = 42,
|
||||
SCANCODE_TAB = 43,
|
||||
SCANCODE_SPACE = 44,
|
||||
|
||||
SCANCODE_MINUS = 45,
|
||||
SCANCODE_EQUALS = 46,
|
||||
SCANCODE_LEFTBRACKET = 47,
|
||||
SCANCODE_RIGHTBRACKET = 48,
|
||||
SCANCODE_BACKSLASH = 49, /**< Located at the lower left of the return
|
||||
* key on ISO keyboards and at the right end
|
||||
* of the QWERTY row on ANSI keyboards.
|
||||
* Produces REVERSE SOLIDUS (backslash) and
|
||||
* VERTICAL LINE in a US layout, REVERSE
|
||||
* SOLIDUS and VERTICAL LINE in a UK Mac
|
||||
* layout, NUMBER SIGN and TILDE in a UK
|
||||
* Windows layout, DOLLAR SIGN and POUND SIGN
|
||||
* in a Swiss German layout, NUMBER SIGN and
|
||||
* APOSTROPHE in a German layout, GRAVE
|
||||
* ACCENT and POUND SIGN in a French Mac
|
||||
* layout, and ASTERISK and MICRO SIGN in a
|
||||
* French Windows layout.
|
||||
*/
|
||||
SCANCODE_NONUSHASH = 50, /**< ISO USB keyboards actually use this code
|
||||
* instead of 49 for the same key, but all
|
||||
* OSes I've seen treat the two codes
|
||||
* identically. So, as an implementor, unless
|
||||
* your keyboard generates both of those
|
||||
* codes and your OS treats them differently,
|
||||
* you should generate SCANCODE_BACKSLASH
|
||||
* instead of this code. As a user, you
|
||||
* should not rely on this code because SDL
|
||||
* will never generate it with most (all?)
|
||||
* keyboards.
|
||||
*/
|
||||
SCANCODE_SEMICOLON = 51,
|
||||
SCANCODE_APOSTROPHE = 52,
|
||||
SCANCODE_GRAVE = 53, /**< Located in the top left corner (on both ANSI
|
||||
* and ISO keyboards). Produces GRAVE ACCENT and
|
||||
* TILDE in a US Windows layout and in US and UK
|
||||
* Mac layouts on ANSI keyboards, GRAVE ACCENT
|
||||
* and NOT SIGN in a UK Windows layout, SECTION
|
||||
* SIGN and PLUS-MINUS SIGN in US and UK Mac
|
||||
* layouts on ISO keyboards, SECTION SIGN and
|
||||
* DEGREE SIGN in a Swiss German layout (Mac:
|
||||
* only on ISO keyboards), CIRCUMFLEX ACCENT and
|
||||
* DEGREE SIGN in a German layout (Mac: only on
|
||||
* ISO keyboards), SUPERSCRIPT TWO and TILDE in a
|
||||
* French Windows layout, COMMERCIAL AT and
|
||||
* NUMBER SIGN in a French Mac layout on ISO
|
||||
* keyboards, and LESS-THAN SIGN and GREATER-THAN
|
||||
* SIGN in a Swiss German, German, or French Mac
|
||||
* layout on ANSI keyboards.
|
||||
*/
|
||||
SCANCODE_COMMA = 54,
|
||||
SCANCODE_PERIOD = 55,
|
||||
SCANCODE_SLASH = 56,
|
||||
|
||||
SCANCODE_CAPSLOCK = 57,
|
||||
|
||||
SCANCODE_F1 = 58,
|
||||
SCANCODE_F2 = 59,
|
||||
SCANCODE_F3 = 60,
|
||||
SCANCODE_F4 = 61,
|
||||
SCANCODE_F5 = 62,
|
||||
SCANCODE_F6 = 63,
|
||||
SCANCODE_F7 = 64,
|
||||
SCANCODE_F8 = 65,
|
||||
SCANCODE_F9 = 66,
|
||||
SCANCODE_F10 = 67,
|
||||
SCANCODE_F11 = 68,
|
||||
SCANCODE_F12 = 69,
|
||||
|
||||
SCANCODE_PRINTSCREEN = 70,
|
||||
SCANCODE_SCROLLLOCK = 71,
|
||||
SCANCODE_PAUSE = 72,
|
||||
SCANCODE_INSERT = 73, /**< insert on PC, help on some Mac keyboards (but
|
||||
does send code 73, not 117) */
|
||||
SCANCODE_HOME = 74,
|
||||
SCANCODE_PAGEUP = 75,
|
||||
SCANCODE_DELETE = 76,
|
||||
SCANCODE_END = 77,
|
||||
SCANCODE_PAGEDOWN = 78,
|
||||
SCANCODE_RIGHT = 79,
|
||||
SCANCODE_LEFT = 80,
|
||||
SCANCODE_DOWN = 81,
|
||||
SCANCODE_UP = 82,
|
||||
|
||||
SCANCODE_NUMLOCKCLEAR = 83, /**< num lock on PC, clear on Mac keyboards
|
||||
*/
|
||||
SCANCODE_KP_DIVIDE = 84,
|
||||
SCANCODE_KP_MULTIPLY = 85,
|
||||
SCANCODE_KP_MINUS = 86,
|
||||
SCANCODE_KP_PLUS = 87,
|
||||
SCANCODE_KP_ENTER = 88,
|
||||
SCANCODE_KP_1 = 89,
|
||||
SCANCODE_KP_2 = 90,
|
||||
SCANCODE_KP_3 = 91,
|
||||
SCANCODE_KP_4 = 92,
|
||||
SCANCODE_KP_5 = 93,
|
||||
SCANCODE_KP_6 = 94,
|
||||
SCANCODE_KP_7 = 95,
|
||||
SCANCODE_KP_8 = 96,
|
||||
SCANCODE_KP_9 = 97,
|
||||
SCANCODE_KP_0 = 98,
|
||||
SCANCODE_KP_PERIOD = 99,
|
||||
|
||||
SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO
|
||||
* keyboards have over ANSI ones,
|
||||
* located between left shift and Y.
|
||||
* Produces GRAVE ACCENT and TILDE in a
|
||||
* US or UK Mac layout, REVERSE SOLIDUS
|
||||
* (backslash) and VERTICAL LINE in a
|
||||
* US or UK Windows layout, and
|
||||
* LESS-THAN SIGN and GREATER-THAN SIGN
|
||||
* in a Swiss German, German, or French
|
||||
* layout. */
|
||||
SCANCODE_APPLICATION = 101, /**< windows contextual menu, compose */
|
||||
SCANCODE_POWER = 102, /**< The USB document says this is a status flag,
|
||||
* not a physical key - but some Mac keyboards
|
||||
* do have a power key. */
|
||||
SCANCODE_KP_EQUALS = 103,
|
||||
SCANCODE_F13 = 104,
|
||||
SCANCODE_F14 = 105,
|
||||
SCANCODE_F15 = 106,
|
||||
SCANCODE_F16 = 107,
|
||||
SCANCODE_F17 = 108,
|
||||
SCANCODE_F18 = 109,
|
||||
SCANCODE_F19 = 110,
|
||||
SCANCODE_F20 = 111,
|
||||
SCANCODE_F21 = 112,
|
||||
SCANCODE_F22 = 113,
|
||||
SCANCODE_F23 = 114,
|
||||
SCANCODE_F24 = 115,
|
||||
SCANCODE_EXECUTE = 116,
|
||||
SCANCODE_HELP = 117, /**< AL Integrated Help Center */
|
||||
SCANCODE_MENU = 118, /**< Menu (show menu) */
|
||||
SCANCODE_SELECT = 119,
|
||||
SCANCODE_STOP = 120, /**< AC Stop */
|
||||
SCANCODE_AGAIN = 121, /**< AC Redo/Repeat */
|
||||
SCANCODE_UNDO = 122, /**< AC Undo */
|
||||
SCANCODE_CUT = 123, /**< AC Cut */
|
||||
SCANCODE_COPY = 124, /**< AC Copy */
|
||||
SCANCODE_PASTE = 125, /**< AC Paste */
|
||||
SCANCODE_FIND = 126, /**< AC Find */
|
||||
SCANCODE_MUTE = 127,
|
||||
SCANCODE_VOLUMEUP = 128,
|
||||
SCANCODE_VOLUMEDOWN = 129,
|
||||
/* not sure whether there's a reason to enable these */
|
||||
/* SCANCODE_LOCKINGCAPSLOCK = 130, */
|
||||
/* SCANCODE_LOCKINGNUMLOCK = 131, */
|
||||
/* SCANCODE_LOCKINGSCROLLLOCK = 132, */
|
||||
SCANCODE_KP_COMMA = 133,
|
||||
SCANCODE_KP_EQUALSAS400 = 134,
|
||||
|
||||
SCANCODE_INTERNATIONAL1 = 135, /**< used on Asian keyboards, see
|
||||
footnotes in USB doc */
|
||||
SCANCODE_INTERNATIONAL2 = 136,
|
||||
SCANCODE_INTERNATIONAL3 = 137, /**< Yen */
|
||||
SCANCODE_INTERNATIONAL4 = 138,
|
||||
SCANCODE_INTERNATIONAL5 = 139,
|
||||
SCANCODE_INTERNATIONAL6 = 140,
|
||||
SCANCODE_INTERNATIONAL7 = 141,
|
||||
SCANCODE_INTERNATIONAL8 = 142,
|
||||
SCANCODE_INTERNATIONAL9 = 143,
|
||||
SCANCODE_LANG1 = 144, /**< Hangul/English toggle */
|
||||
SCANCODE_LANG2 = 145, /**< Hanja conversion */
|
||||
SCANCODE_LANG3 = 146, /**< Katakana */
|
||||
SCANCODE_LANG4 = 147, /**< Hiragana */
|
||||
SCANCODE_LANG5 = 148, /**< Zenkaku/Hankaku */
|
||||
SCANCODE_LANG6 = 149, /**< reserved */
|
||||
SCANCODE_LANG7 = 150, /**< reserved */
|
||||
SCANCODE_LANG8 = 151, /**< reserved */
|
||||
SCANCODE_LANG9 = 152, /**< reserved */
|
||||
|
||||
SCANCODE_ALTERASE = 153, /**< Erase-Eaze */
|
||||
SCANCODE_SYSREQ = 154,
|
||||
SCANCODE_CANCEL = 155, /**< AC Cancel */
|
||||
SCANCODE_CLEAR = 156,
|
||||
SCANCODE_PRIOR = 157,
|
||||
SCANCODE_RETURN2 = 158,
|
||||
SCANCODE_SEPARATOR = 159,
|
||||
SCANCODE_OUT = 160,
|
||||
SCANCODE_OPER = 161,
|
||||
SCANCODE_CLEARAGAIN = 162,
|
||||
SCANCODE_CRSEL = 163,
|
||||
SCANCODE_EXSEL = 164,
|
||||
|
||||
SCANCODE_KP_00 = 176,
|
||||
SCANCODE_KP_000 = 177,
|
||||
SCANCODE_THOUSANDSSEPARATOR = 178,
|
||||
SCANCODE_DECIMALSEPARATOR = 179,
|
||||
SCANCODE_CURRENCYUNIT = 180,
|
||||
SCANCODE_CURRENCYSUBUNIT = 181,
|
||||
SCANCODE_KP_LEFTPAREN = 182,
|
||||
SCANCODE_KP_RIGHTPAREN = 183,
|
||||
SCANCODE_KP_LEFTBRACE = 184,
|
||||
SCANCODE_KP_RIGHTBRACE = 185,
|
||||
SCANCODE_KP_TAB = 186,
|
||||
SCANCODE_KP_BACKSPACE = 187,
|
||||
SCANCODE_KP_A = 188,
|
||||
SCANCODE_KP_B = 189,
|
||||
SCANCODE_KP_C = 190,
|
||||
SCANCODE_KP_D = 191,
|
||||
SCANCODE_KP_E = 192,
|
||||
SCANCODE_KP_F = 193,
|
||||
SCANCODE_KP_XOR = 194,
|
||||
SCANCODE_KP_POWER = 195,
|
||||
SCANCODE_KP_PERCENT = 196,
|
||||
SCANCODE_KP_LESS = 197,
|
||||
SCANCODE_KP_GREATER = 198,
|
||||
SCANCODE_KP_AMPERSAND = 199,
|
||||
SCANCODE_KP_DBLAMPERSAND = 200,
|
||||
SCANCODE_KP_VERTICALBAR = 201,
|
||||
SCANCODE_KP_DBLVERTICALBAR = 202,
|
||||
SCANCODE_KP_COLON = 203,
|
||||
SCANCODE_KP_HASH = 204,
|
||||
SCANCODE_KP_SPACE = 205,
|
||||
SCANCODE_KP_AT = 206,
|
||||
SCANCODE_KP_EXCLAM = 207,
|
||||
SCANCODE_KP_MEMSTORE = 208,
|
||||
SCANCODE_KP_MEMRECALL = 209,
|
||||
SCANCODE_KP_MEMCLEAR = 210,
|
||||
SCANCODE_KP_MEMADD = 211,
|
||||
SCANCODE_KP_MEMSUBTRACT = 212,
|
||||
SCANCODE_KP_MEMMULTIPLY = 213,
|
||||
SCANCODE_KP_MEMDIVIDE = 214,
|
||||
SCANCODE_KP_PLUSMINUS = 215,
|
||||
SCANCODE_KP_CLEAR = 216,
|
||||
SCANCODE_KP_CLEARENTRY = 217,
|
||||
SCANCODE_KP_BINARY = 218,
|
||||
SCANCODE_KP_OCTAL = 219,
|
||||
SCANCODE_KP_DECIMAL = 220,
|
||||
SCANCODE_KP_HEXADECIMAL = 221,
|
||||
|
||||
SCANCODE_LCTRL = 224,
|
||||
SCANCODE_LSHIFT = 225,
|
||||
SCANCODE_LALT = 226, /**< alt, option */
|
||||
SCANCODE_LGUI = 227, /**< windows, command (apple), meta */
|
||||
SCANCODE_RCTRL = 228,
|
||||
SCANCODE_RSHIFT = 229,
|
||||
SCANCODE_RALT = 230, /**< alt gr, option */
|
||||
SCANCODE_RGUI = 231, /**< windows, command (apple), meta */
|
||||
|
||||
SCANCODE_MODE = 257, /**< I'm not sure if this is really not covered
|
||||
* by any of the above, but since there's a
|
||||
* special KMOD_MODE for it I'm adding it here
|
||||
*/
|
||||
|
||||
/* @} *//* Usage page 0x07 */
|
||||
|
||||
/**
|
||||
* \name Usage page 0x0C
|
||||
*
|
||||
* These values are mapped from usage page 0x0C (USB consumer page).
|
||||
* See https://usb.org/sites/default/files/hut1_2.pdf
|
||||
*
|
||||
* There are way more keys in the spec than we can represent in the
|
||||
* current scancode range, so pick the ones that commonly come up in
|
||||
* real world usage.
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
SCANCODE_AUDIONEXT = 258,
|
||||
SCANCODE_AUDIOPREV = 259,
|
||||
SCANCODE_AUDIOSTOP = 260,
|
||||
SCANCODE_AUDIOPLAY = 261,
|
||||
SCANCODE_AUDIOMUTE = 262,
|
||||
SCANCODE_MEDIASELECT = 263,
|
||||
SCANCODE_WWW = 264, /**< AL Internet Browser */
|
||||
SCANCODE_MAIL = 265,
|
||||
SCANCODE_CALCULATOR = 266, /**< AL Calculator */
|
||||
SCANCODE_COMPUTER = 267,
|
||||
SCANCODE_AC_SEARCH = 268, /**< AC Search */
|
||||
SCANCODE_AC_HOME = 269, /**< AC Home */
|
||||
SCANCODE_AC_BACK = 270, /**< AC Back */
|
||||
SCANCODE_AC_FORWARD = 271, /**< AC Forward */
|
||||
SCANCODE_AC_STOP = 272, /**< AC Stop */
|
||||
SCANCODE_AC_REFRESH = 273, /**< AC Refresh */
|
||||
SCANCODE_AC_BOOKMARKS = 274, /**< AC Bookmarks */
|
||||
|
||||
/* @} *//* Usage page 0x0C */
|
||||
|
||||
/**
|
||||
* \name Walther keys
|
||||
*
|
||||
* These are values that Christian Walther added (for mac keyboard?).
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
SCANCODE_BRIGHTNESSDOWN = 275,
|
||||
SCANCODE_BRIGHTNESSUP = 276,
|
||||
SCANCODE_DISPLAYSWITCH = 277, /**< display mirroring/dual display
|
||||
switch, video mode switch */
|
||||
SCANCODE_KBDILLUMTOGGLE = 278,
|
||||
SCANCODE_KBDILLUMDOWN = 279,
|
||||
SCANCODE_KBDILLUMUP = 280,
|
||||
SCANCODE_EJECT = 281,
|
||||
SCANCODE_SLEEP = 282, /**< SC System Sleep */
|
||||
|
||||
SCANCODE_APP1 = 283,
|
||||
SCANCODE_APP2 = 284,
|
||||
|
||||
/* @} *//* Walther keys */
|
||||
|
||||
/**
|
||||
* \name Usage page 0x0C (additional media keys)
|
||||
*
|
||||
* These values are mapped from usage page 0x0C (USB consumer page).
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
SCANCODE_AUDIOREWIND = 285,
|
||||
SCANCODE_AUDIOFASTFORWARD = 286,
|
||||
|
||||
/* @} *//* Usage page 0x0C (additional media keys) */
|
||||
|
||||
/**
|
||||
* \name Mobile keys
|
||||
*
|
||||
* These are values that are often used on mobile phones.
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
SCANCODE_SOFTLEFT = 287, /**< Usually situated below the display on phones and
|
||||
used as a multi-function feature key for selecting
|
||||
a software defined function shown on the bottom left
|
||||
of the display. */
|
||||
SCANCODE_SOFTRIGHT = 288, /**< Usually situated below the display on phones and
|
||||
used as a multi-function feature key for selecting
|
||||
a software defined function shown on the bottom right
|
||||
of the display. */
|
||||
SCANCODE_CALL = 289, /**< Used for accepting phone calls. */
|
||||
SCANCODE_ENDCALL = 290, /**< Used for rejecting phone calls. */
|
||||
|
||||
/* @} *//* Mobile keys */
|
||||
|
||||
/* Add any other keys here. */
|
||||
|
||||
NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes
|
||||
for array bounds */
|
||||
} Scancode;
|
||||
|
||||
#endif
|
@ -4,6 +4,7 @@
|
||||
#include "twn_context.h"
|
||||
#include "twn_textures_c.h"
|
||||
#include "twn_audio_c.h"
|
||||
#include "twn_input_c.h"
|
||||
#include "twn_engine_api.h"
|
||||
#include "rendering/twn_draw_c.h"
|
||||
|
||||
@ -18,6 +19,8 @@ typedef struct EngineContext {
|
||||
/* user code facing context */
|
||||
Context game;
|
||||
|
||||
InputState input;
|
||||
|
||||
/* the program's actual argc and argv */
|
||||
int argc;
|
||||
char **argv;
|
||||
@ -64,6 +67,7 @@ typedef struct EngineContext {
|
||||
bool was_successful;
|
||||
} EngineContext;
|
||||
|
||||
/* TODO: does it need to be marked with TWN_API? */
|
||||
TWN_API extern EngineContext ctx;
|
||||
|
||||
#endif
|
||||
|
128
src/twn_input.c
128
src/twn_input.c
@ -1,5 +1,6 @@
|
||||
#include "twn_input_c.h"
|
||||
#include "twn_util.h"
|
||||
#include "twn_control.h"
|
||||
#include "twn_engine_context_c.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
@ -38,7 +39,7 @@ static void update_action_pressed_state(InputState *input, Action *action) {
|
||||
action->just_changed = !action->is_pressed;
|
||||
action->is_pressed = true;
|
||||
action->position.x = (float)input->mouse_window_position.x;
|
||||
action->position.x = (float)input->mouse_window_position.x;
|
||||
action->position.y = (float)input->mouse_window_position.y;
|
||||
|
||||
/* TODO: */
|
||||
/*
|
||||
@ -63,7 +64,7 @@ static void update_action_pressed_state(InputState *input, Action *action) {
|
||||
|
||||
|
||||
static void input_bind_code_to_action(InputState *input,
|
||||
char *action_name,
|
||||
char const *action_name,
|
||||
ButtonSource source,
|
||||
union ButtonCode code)
|
||||
{
|
||||
@ -120,7 +121,7 @@ static void input_bind_code_to_action(InputState *input,
|
||||
|
||||
|
||||
static void input_unbind_code_from_action(InputState *input,
|
||||
char *action_name,
|
||||
char const *action_name,
|
||||
ButtonSource source,
|
||||
union ButtonCode code)
|
||||
{
|
||||
@ -193,6 +194,9 @@ void input_state_update(InputState *input) {
|
||||
SDL_GetRelativeMouseState(&input->mouse_relative_position.x,
|
||||
&input->mouse_relative_position.y);
|
||||
|
||||
ctx.game.mouse_window_position = input->mouse_window_position;
|
||||
ctx.game.mouse_relative_position = input->mouse_relative_position;
|
||||
|
||||
for (size_t i = 0; i < shlenu(input->action_hash); ++i) {
|
||||
Action *action = &input->action_hash[i].value;
|
||||
update_action_pressed_state(input, action);
|
||||
@ -200,76 +204,82 @@ void input_state_update(InputState *input) {
|
||||
}
|
||||
|
||||
|
||||
void input_bind_action_scancode(InputState *input,
|
||||
char *action_name,
|
||||
Scancode scancode)
|
||||
void input_bind_action_control(char const *action_name,
|
||||
Control control)
|
||||
{
|
||||
input_bind_code_to_action(input,
|
||||
action_name,
|
||||
BUTTON_SOURCE_KEYBOARD_PHYSICAL,
|
||||
(union ButtonCode) { .scancode = scancode });
|
||||
}
|
||||
SDL_assert_always(action_name);
|
||||
|
||||
|
||||
void input_unbind_action_scancode(InputState *input,
|
||||
char *action_name,
|
||||
Scancode scancode)
|
||||
{
|
||||
input_unbind_code_from_action(input,
|
||||
if (CONTROL_SCANCODE_START <= control && control < CONTROL_SCANCODE_LIMIT)
|
||||
input_bind_code_to_action(&ctx.input,
|
||||
action_name,
|
||||
BUTTON_SOURCE_KEYBOARD_PHYSICAL,
|
||||
(union ButtonCode) { .scancode = scancode });
|
||||
}
|
||||
(union ButtonCode) { .scancode = (SDL_Scancode)control });
|
||||
|
||||
|
||||
void input_bind_action_mouse(InputState *input,
|
||||
char *action_name,
|
||||
uint8_t mouse_button)
|
||||
{
|
||||
input_bind_code_to_action(input,
|
||||
action_name,
|
||||
BUTTON_SOURCE_MOUSE,
|
||||
(union ButtonCode) { .mouse_button = mouse_button});
|
||||
}
|
||||
|
||||
|
||||
void input_unbind_action_mouse(InputState *input,
|
||||
char *action_name,
|
||||
uint8_t mouse_button)
|
||||
{
|
||||
input_unbind_code_from_action(input,
|
||||
else if (CONTROL_MOUSECODE_START <= control && control < CONTROL_MOUSECODE_LIMIT) {
|
||||
uint8_t const mouse_button = (uint8_t)(control - CONTROL_MOUSECODE_START);
|
||||
input_bind_code_to_action(&ctx.input,
|
||||
action_name,
|
||||
BUTTON_SOURCE_MOUSE,
|
||||
(union ButtonCode) { .mouse_button = mouse_button});
|
||||
(union ButtonCode) { .mouse_button = SDL_BUTTON(mouse_button)});
|
||||
} else
|
||||
log_warn("(%s) Invalid control value given: %i.", __func__, control);
|
||||
}
|
||||
|
||||
|
||||
void input_add_action(InputState *input, char *action_name) {
|
||||
if (shgeti(input->action_hash, action_name) >= 0) {
|
||||
void input_unbind_action_control(char const *action_name,
|
||||
Control control)
|
||||
{
|
||||
SDL_assert_always(action_name);
|
||||
|
||||
if (CONTROL_SCANCODE_START <= control && control < CONTROL_SCANCODE_LIMIT)
|
||||
input_unbind_code_from_action(&ctx.input,
|
||||
action_name,
|
||||
BUTTON_SOURCE_KEYBOARD_PHYSICAL,
|
||||
(union ButtonCode) { .scancode = (SDL_Scancode)control });
|
||||
|
||||
else if (CONTROL_MOUSECODE_START <= control && control < CONTROL_MOUSECODE_LIMIT) {
|
||||
uint8_t const mouse_button = (uint8_t)(control - CONTROL_MOUSECODE_START);
|
||||
input_unbind_code_from_action(&ctx.input,
|
||||
action_name,
|
||||
BUTTON_SOURCE_MOUSE,
|
||||
(union ButtonCode) { .mouse_button = SDL_BUTTON(mouse_button)});
|
||||
} else
|
||||
log_warn("(%s) Invalid control value given: %i.", __func__, control);
|
||||
}
|
||||
|
||||
|
||||
void input_add_action(char const *action_name) {
|
||||
SDL_assert_always(action_name);
|
||||
|
||||
if (shgeti(ctx.input.action_hash, action_name) >= 0) {
|
||||
log_warn("(%s) Action \"%s\" is already registered.", __func__, action_name);
|
||||
return;
|
||||
}
|
||||
|
||||
Action new_action = { 0 };
|
||||
new_action.bindings = ccalloc(ctx.keybind_slots, sizeof *new_action.bindings);
|
||||
shput(input->action_hash, action_name, new_action);
|
||||
shput(ctx.input.action_hash, action_name, new_action);
|
||||
}
|
||||
|
||||
|
||||
void input_delete_action(InputState *input, char *action_name) {
|
||||
ActionHashItem *action = shgetp_null(input->action_hash, action_name);
|
||||
void input_delete_action(char const *action_name) {
|
||||
SDL_assert_always(action_name);
|
||||
|
||||
ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name);
|
||||
if (action == NULL) {
|
||||
log_warn("(%s) Action \"%s\" is not registered.", __func__, action_name);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_free(action->value.bindings);
|
||||
shdel(input->action_hash, action_name);
|
||||
shdel(ctx.input.action_hash, action_name);
|
||||
}
|
||||
|
||||
|
||||
bool input_is_action_pressed(InputState *input, char *action_name) {
|
||||
ActionHashItem *action = shgetp_null(input->action_hash, action_name);
|
||||
bool input_is_action_pressed(char const *action_name) {
|
||||
SDL_assert_always(action_name);
|
||||
|
||||
ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name);
|
||||
if (action == NULL) {
|
||||
log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name);
|
||||
return false;
|
||||
@ -278,8 +288,10 @@ bool input_is_action_pressed(InputState *input, char *action_name) {
|
||||
}
|
||||
|
||||
|
||||
bool input_is_action_just_pressed(InputState *input, char *action_name) {
|
||||
ActionHashItem *action = shgetp_null(input->action_hash, action_name);
|
||||
bool input_is_action_just_pressed(char const *action_name) {
|
||||
SDL_assert_always(action_name);
|
||||
|
||||
ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name);
|
||||
if (action == NULL) {
|
||||
log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name);
|
||||
return false;
|
||||
@ -288,8 +300,10 @@ bool input_is_action_just_pressed(InputState *input, char *action_name) {
|
||||
}
|
||||
|
||||
|
||||
bool input_is_action_just_released(InputState *input, char *action_name) {
|
||||
ActionHashItem *action = shgetp_null(input->action_hash, action_name);
|
||||
bool input_is_action_just_released(char const *action_name) {
|
||||
SDL_assert_always(action_name);
|
||||
|
||||
ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name);
|
||||
if (action == NULL) {
|
||||
log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name);
|
||||
return false;
|
||||
@ -298,8 +312,10 @@ bool input_is_action_just_released(InputState *input, char *action_name) {
|
||||
}
|
||||
|
||||
|
||||
Vec2 input_get_action_position(InputState *input, char *action_name) {
|
||||
ActionHashItem *action = shgetp_null(input->action_hash, action_name);
|
||||
Vec2 input_get_action_position(char const *action_name) {
|
||||
SDL_assert_always(action_name);
|
||||
|
||||
ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name);
|
||||
if (action == NULL) {
|
||||
log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name);
|
||||
return (Vec2) { 0 };
|
||||
@ -309,15 +325,13 @@ Vec2 input_get_action_position(InputState *input, char *action_name) {
|
||||
}
|
||||
|
||||
|
||||
void input_set_mouse_captured(InputState *input, bool enabled) {
|
||||
(void)input;
|
||||
/* TODO: returns -1 if not supported, but like... do we care? */
|
||||
SDL_SetRelativeMouseMode(enabled);
|
||||
void input_set_mouse_captured(bool enabled) {
|
||||
if (SDL_SetRelativeMouseMode(enabled) != 0)
|
||||
log_warn("(%s) Mouse capture isn't supported.", __func__);
|
||||
}
|
||||
|
||||
|
||||
bool input_is_mouse_captured(InputState *input) {
|
||||
(void)input;
|
||||
bool input_is_mouse_captured(void) {
|
||||
return SDL_GetRelativeMouseMode();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef INPUT_INTERNAL_API_H
|
||||
#define INPUT_INTERNAL_API_H
|
||||
#ifndef TWN_INPUT_C_H
|
||||
#define TWN_INPUT_C_H
|
||||
|
||||
#include "twn_input.h"
|
||||
#include "twn_vec.h"
|
||||
@ -15,6 +15,15 @@ union ButtonCode {
|
||||
};
|
||||
|
||||
|
||||
typedef enum ButtonSource {
|
||||
BUTTON_SOURCE_NOT_SET,
|
||||
BUTTON_SOURCE_KEYBOARD_PHYSICAL,
|
||||
BUTTON_SOURCE_KEYBOARD_CHARACTER,
|
||||
BUTTON_SOURCE_GAMEPAD,
|
||||
BUTTON_SOURCE_MOUSE,
|
||||
} ButtonSource;
|
||||
|
||||
|
||||
/* an input to which an action is bound */
|
||||
/* it is not limited to literal buttons */
|
||||
typedef struct Button {
|
||||
@ -23,6 +32,45 @@ typedef struct Button {
|
||||
} Button;
|
||||
|
||||
|
||||
/* represents the collective state of a group of buttons */
|
||||
/* that is, changes in the states of any of the bound buttons will affect it */
|
||||
typedef struct Action {
|
||||
size_t num_bindings;
|
||||
|
||||
/* if you bind more than the number set in the configuration file */
|
||||
/* it forgets the first Button to add the new one at the end */
|
||||
Button *bindings;
|
||||
|
||||
Vec2 position; /* set if applicable, e.g. mouse click */
|
||||
bool is_pressed;
|
||||
bool just_changed;
|
||||
} Action;
|
||||
|
||||
|
||||
typedef struct ActionHashItem {
|
||||
char *key;
|
||||
Action value;
|
||||
} ActionHashItem;
|
||||
|
||||
|
||||
typedef struct InputState {
|
||||
const uint8_t *keyboard_state; /* array of booleans indexed by scancode */
|
||||
ActionHashItem *action_hash;
|
||||
Vec2i mouse_window_position;
|
||||
Vec2i mouse_relative_position;
|
||||
uint32_t mouse_state; /* SDL mouse button bitmask */
|
||||
ButtonSource last_active_source;
|
||||
bool is_anything_just_pressed;
|
||||
bool mouse_captured;
|
||||
} InputState;
|
||||
|
||||
|
||||
void input_state_init(InputState *input);
|
||||
|
||||
void input_state_deinit(InputState *input);
|
||||
|
||||
void input_state_update(InputState *input);
|
||||
|
||||
void input_reset_state(InputState *input);
|
||||
|
||||
#endif
|
||||
|
@ -188,7 +188,7 @@ static void main_loop(void) {
|
||||
|
||||
poll_events();
|
||||
|
||||
input_state_update(&ctx.game.input);
|
||||
input_state_update(&ctx.input);
|
||||
|
||||
game_object_tick();
|
||||
|
||||
@ -634,7 +634,7 @@ static bool initialize(void) {
|
||||
ctx.keybind_slots = datum_keybind_slots.u.i;
|
||||
}
|
||||
}
|
||||
input_state_init(&ctx.game.input);
|
||||
input_state_init(&ctx.input);
|
||||
|
||||
/* scripting */
|
||||
/*
|
||||
@ -657,7 +657,7 @@ static void clean_up(void) {
|
||||
scripting_deinit(ctx);
|
||||
*/
|
||||
|
||||
input_state_deinit(&ctx.game.input);
|
||||
input_state_deinit(&ctx.input);
|
||||
text_cache_deinit(&ctx.text_cache);
|
||||
textures_cache_deinit(&ctx.texture_cache);
|
||||
|
||||
@ -675,7 +675,7 @@ static void clean_up(void) {
|
||||
|
||||
|
||||
static void reset_state(void) {
|
||||
input_reset_state(&ctx.game.input);
|
||||
input_reset_state(&ctx.input);
|
||||
textures_reset_state();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user