twn_input: singleton rework, twn_control.h and fixes
This commit is contained in:
		| @@ -16,14 +16,17 @@ | |||||||
| void handle_input(void) | void handle_input(void) | ||||||
| { | { | ||||||
|     State *state = ctx.udata; |     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 |     { // Left click | ||||||
|         for (int i = 0; i < LEFT_CLICK_ADD; i++) |         for (int i = 0; i < LEFT_CLICK_ADD; i++) | ||||||
|         { |         { | ||||||
|             if (state->bunniesCount < MAX_BUNNIES) |             if (state->bunniesCount < MAX_BUNNIES) | ||||||
|             { |             { | ||||||
|                 state->bunnies[state->bunniesCount].position = |                 state->bunnies[state->bunniesCount].position = input_get_action_position("add_a_bit"); | ||||||
|                     (Vec2){(float)ctx.input.mouse_window_position.x, (float)ctx.input.mouse_window_position.y}; |  | ||||||
|                 state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0; |                 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].speed.y = (float)(rand() % 500 - 250) / 60.0; | ||||||
|                 state->bunnies[state->bunniesCount].color = |                 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 |     { // Right click | ||||||
|         for (int i = 0; i < RIGHT_CLICK_ADD; i++) |         for (int i = 0; i < RIGHT_CLICK_ADD; i++) | ||||||
|         { |         { | ||||||
|             if (state->bunniesCount < MAX_BUNNIES) |             if (state->bunniesCount < MAX_BUNNIES) | ||||||
|             { |             { | ||||||
|                 state->bunnies[state->bunniesCount].position = |                 state->bunnies[state->bunniesCount].position = input_get_action_position("add_a_lot"); | ||||||
|                     (Vec2){(float)ctx.input.mouse_window_position.x, (float)ctx.input.mouse_window_position.y}; |  | ||||||
|                 state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0; |                 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].speed.y = (float)(rand() % 500 - 250) / 60.0; | ||||||
|                 state->bunnies[state->bunniesCount].color = |                 state->bunnies[state->bunniesCount].color = | ||||||
| @@ -53,8 +55,7 @@ void handle_input(void) | |||||||
|  |  | ||||||
| void game_tick(void) | void game_tick(void) | ||||||
| { | { | ||||||
|     static char bunny_count_text[64]; |     char bunny_count_text[64]; | ||||||
|     static char bunny_path[64] = "wabbit_alpha.png"; |  | ||||||
|  |  | ||||||
|     // State *state = ctx.udata; |     // State *state = ctx.udata; | ||||||
|     if (ctx.initialization_needed) |     if (ctx.initialization_needed) | ||||||
| @@ -62,7 +63,12 @@ void game_tick(void) | |||||||
|         // Allocating State struct to store data there |         // Allocating State struct to store data there | ||||||
|         if (!ctx.udata) |         if (!ctx.udata) | ||||||
|             ctx.udata = ccalloc(1, sizeof(State)); |             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; |     State *state = ctx.udata; | ||||||
| @@ -90,16 +96,16 @@ void game_tick(void) | |||||||
|  |  | ||||||
|     for (int i = 0; i < state->bunniesCount; i++) |     for (int i = 0; i < state->bunniesCount; i++) | ||||||
|     { // Draw each bunny based on their position and color, also scale accordingly |     { // 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, |                  m_set(rect, ((Rect){.x = (int)state->bunnies[i].position.x, | ||||||
|                                      .y = (int)state->bunnies[i].position.y, |                                      .y = (int)state->bunnies[i].position.y, | ||||||
|                                      .w = BUNNY_W * SPRITE_SCALE, |                                      .w = BUNNY_W * SPRITE_SCALE, | ||||||
|                                      .h = BUNNY_H * SPRITE_SCALE})), |                                      .h = BUNNY_H * SPRITE_SCALE})), | ||||||
|                  m_opt(color, (state->bunnies[i].color)), m_opt(stretch, true), ); |                  m_opt(color, (state->bunnies[i].color)), m_opt(stretch, true), ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Formatting text to display, might want to add FPS here too |     // Formatting text to display, might want to add FPS here too | ||||||
|     snprintf(bunny_count_text, 64, "Bunnies: %d", state->bunniesCount); |     snprintf(bunny_count_text, 64, "Bunnies: %d", state->bunniesCount); | ||||||
|  |  | ||||||
|     draw_text(bunny_count_text, (Vec2){0, 0}, 40, BLACK, "/fonts/kenney-pixel.ttf"); |     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]; |     Bunny bunnies[MAX_BUNNIES]; | ||||||
|     int bunniesCount; |     int bunniesCount; | ||||||
|     InputState mouse_state; |  | ||||||
| } State; | } State; | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -19,44 +19,44 @@ void game_tick(void) { | |||||||
|             state->scene = title_scene(state); |             state->scene = title_scene(state); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "debug_toggle"); |         input_add_action("debug_toggle"); | ||||||
|         input_bind_action_scancode(&ctx.input, "debug_toggle", SCANCODE_BACKSPACE); |         input_bind_action_control("debug_toggle", CONTROL_BACKSPACE); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "debug_dump_atlases"); |         input_add_action("debug_dump_atlases"); | ||||||
|         input_bind_action_scancode(&ctx.input, "debug_dump_atlases", SCANCODE_HOME); |         input_bind_action_control("debug_dump_atlases", CONTROL_HOME); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_left"); |         input_add_action("player_left"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_left", SCANCODE_A); |         input_bind_action_control("player_left", CONTROL_A); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_right"); |         input_add_action("player_right"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_right", SCANCODE_D); |         input_bind_action_control("player_right", CONTROL_D); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_forward"); |         input_add_action("player_forward"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_forward", SCANCODE_W); |         input_bind_action_control("player_forward", CONTROL_W); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_backward"); |         input_add_action("player_backward"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_backward", SCANCODE_S); |         input_bind_action_control("player_backward", CONTROL_S); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_jump"); |         input_add_action("player_jump"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_jump", SCANCODE_SPACE); |         input_bind_action_control("player_jump", CONTROL_SPACE); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_run"); |         input_add_action("player_run"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_run", SCANCODE_LSHIFT); |         input_bind_action_control("player_run", CONTROL_LSHIFT); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "ui_accept"); |         input_add_action("ui_accept"); | ||||||
|         input_bind_action_scancode(&ctx.input, "ui_accept", SCANCODE_RETURN); |         input_bind_action_control("ui_accept", CONTROL_RETURN); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "mouse_capture_toggle"); |         input_add_action("mouse_capture_toggle"); | ||||||
|         input_bind_action_scancode(&ctx.input, "mouse_capture_toggle", SCANCODE_ESCAPE); |         input_bind_action_control("mouse_capture_toggle", CONTROL_ESCAPE); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     State *state = ctx.udata; |     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; |         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(); |         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 */ |     /* apply horizontal damping when the player stops moving */ | ||||||
|     /* in other words, make it decelerate to a standstill */ |     /* in other words, make it decelerate to a standstill */ | ||||||
|     if (!input_is_action_pressed(input, "player_left") && |     if (!input_is_action_pressed("player_left") && | ||||||
|         !input_is_action_pressed(input, "player_right")) |         !input_is_action_pressed("player_right")) | ||||||
|     { |     { | ||||||
|         player->dx *= player->horizontal_damping; |         player->dx *= player->horizontal_damping; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     int input_dir = 0; |     int input_dir = 0; | ||||||
|     if (input_is_action_pressed(input, "player_left")) |     if (input_is_action_pressed("player_left")) | ||||||
|         input_dir = -1; |         input_dir = -1; | ||||||
|     if (input_is_action_pressed(input, "player_right")) |     if (input_is_action_pressed("player_right")) | ||||||
|         input_dir = 1; |         input_dir = 1; | ||||||
|     if (input_is_action_pressed(input, "player_left") && |     if (input_is_action_pressed("player_left") && | ||||||
|         input_is_action_pressed(input, "player_right")) |         input_is_action_pressed("player_right")) | ||||||
|         input_dir = 0; |         input_dir = 0; | ||||||
|  |  | ||||||
|     player->dx += (float)input_dir * player->run_horizontal_speed; |     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; |     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_air_timer = 0; | ||||||
|         player->jump_buffer_timer = player->jump_buffer_ticks; |         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) { |         if (player->action != PLAYER_ACTION_GROUND && player->jump_air_timer > 0) { | ||||||
|             player->current_gravity_multiplier = player->jump_boosted_multiplier; |             player->current_gravity_multiplier = player->jump_boosted_multiplier; | ||||||
|             player->dy += player->jump_force_increase; |             player->dy += player->jump_force_increase; | ||||||
| @@ -284,8 +284,8 @@ void player_destroy(Player *player) { | |||||||
| void player_calc(Player *player) { | void player_calc(Player *player) { | ||||||
|     update_timers(player); |     update_timers(player); | ||||||
|  |  | ||||||
|     input_move(&ctx.input, player); |     input_move(player); | ||||||
|     input_jump(&ctx.input, player); |     input_jump(player); | ||||||
|  |  | ||||||
|     player->rect.x += player->dx; |     player->rect.x += player->dx; | ||||||
|     update_collider_x(player); |     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 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 */ |     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)); |         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)); |         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)); |         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)); |         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; |         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; |         scn->cam.pos.y -= speed; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ static void title_tick(State *state) { | |||||||
|     SceneTitle *scn = (SceneTitle *)state->scene; |     SceneTitle *scn = (SceneTitle *)state->scene; | ||||||
|     (void)scn; |     (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); |         switch_to(state, ingame_scene); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -20,44 +20,44 @@ void game_tick(void) { | |||||||
|             state->scene = title_scene(state); |             state->scene = title_scene(state); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "debug_toggle"); |         input_add_action("debug_toggle"); | ||||||
|         input_bind_action_scancode(&ctx.input, "debug_toggle", SCANCODE_BACKSPACE); |         input_bind_action_control("debug_toggle", CONTROL_BACKSPACE); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "debug_dump_atlases"); |         input_add_action("debug_dump_atlases"); | ||||||
|         input_bind_action_scancode(&ctx.input, "debug_dump_atlases", SCANCODE_HOME); |         input_bind_action_control("debug_dump_atlases", CONTROL_HOME); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_left"); |         input_add_action("player_left"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_left", SCANCODE_A); |         input_bind_action_control("player_left", CONTROL_A); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_right"); |         input_add_action("player_right"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_right", SCANCODE_D); |         input_bind_action_control("player_right", CONTROL_D); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_forward"); |         input_add_action("player_forward"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_forward", SCANCODE_W); |         input_bind_action_control("player_forward", CONTROL_W); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_backward"); |         input_add_action("player_backward"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_backward", SCANCODE_S); |         input_bind_action_control("player_backward", CONTROL_S); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_jump"); |         input_add_action("player_jump"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_jump", SCANCODE_SPACE); |         input_bind_action_control("player_jump", CONTROL_SPACE); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "player_run"); |         input_add_action("player_run"); | ||||||
|         input_bind_action_scancode(&ctx.input, "player_run", SCANCODE_LSHIFT); |         input_bind_action_control("player_run", CONTROL_LSHIFT); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "ui_accept"); |         input_add_action("ui_accept"); | ||||||
|         input_bind_action_scancode(&ctx.input, "ui_accept", SCANCODE_RETURN); |         input_bind_action_control("ui_accept", CONTROL_RETURN); | ||||||
|  |  | ||||||
|         input_add_action(&ctx.input, "mouse_capture_toggle"); |         input_add_action("mouse_capture_toggle"); | ||||||
|         input_bind_action_scancode(&ctx.input, "mouse_capture_toggle", SCANCODE_ESCAPE); |         input_bind_action_control("mouse_capture_toggle", CONTROL_ESCAPE); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     State *state = ctx.udata; |     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; |         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(); |         textures_dump_atlases(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,10 +15,10 @@ | |||||||
| static void ingame_tick(State *state) { | static void ingame_tick(State *state) { | ||||||
|     SceneIngame *scn = (SceneIngame *)state->scene; |     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 */ |         const float sensitivity = 0.6f; /* TODO: put this in a better place */ | ||||||
|         scn->yaw += (float)ctx.input.mouse_relative_position.x * sensitivity; |         scn->yaw += (float)ctx.mouse_relative_position.x * sensitivity; | ||||||
|         scn->pitch -= (float)ctx.input.mouse_relative_position.y * sensitivity; |         scn->pitch -= (float)ctx.mouse_relative_position.y * sensitivity; | ||||||
|         scn->pitch = clampf(scn->pitch, -89.0f, 89.0f); |         scn->pitch = clampf(scn->pitch, -89.0f, 89.0f); | ||||||
|  |  | ||||||
|         const float yaw_rad = scn->yaw * (float)DEG2RAD; |         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 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 */ |     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)); |         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)); |         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)); |         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)); |         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; |         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; |         scn->cam.pos.y -= speed; | ||||||
|  |  | ||||||
|     /* toggle mouse capture with end key */ |     /* toggle mouse capture with end key */ | ||||||
|     if (input_is_action_just_pressed(&ctx.input, "mouse_capture_toggle")) { |     if (input_is_action_just_pressed("mouse_capture_toggle")) { | ||||||
|         input_set_mouse_captured(&ctx.input, !input_is_mouse_captured(&ctx.input)); |         input_set_mouse_captured(!input_is_mouse_captured()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     draw_camera(&scn->cam); |     draw_camera(&scn->cam); | ||||||
| @@ -111,7 +111,7 @@ Scene *ingame_scene(State *state) { | |||||||
|             m_opt(channel, "soundtrack"), |             m_opt(channel, "soundtrack"), | ||||||
|             m_opt(repeat, true)); |             m_opt(repeat, true)); | ||||||
|  |  | ||||||
|     input_set_mouse_captured(&ctx.input, true); |     input_set_mouse_captured(true); | ||||||
|  |  | ||||||
|     return (Scene *)new_scene; |     return (Scene *)new_scene; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ static void title_tick(State *state) { | |||||||
|     SceneTitle *scn = (SceneTitle *)state->scene; |     SceneTitle *scn = (SceneTitle *)state->scene; | ||||||
|     (void)scn; |     (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); |         switch_to(state, ingame_scene); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -8,12 +8,20 @@ | |||||||
| #include <stdint.h> | #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 { | 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 */ |     int64_t delta_time; /* preserves real time frame delta with no manipilation */ | ||||||
|     uint64_t tick_count; |     uint64_t tick_count; | ||||||
|  |  | ||||||
|  |     Vec2i mouse_window_position; | ||||||
|  |     Vec2i mouse_relative_position; | ||||||
|  |  | ||||||
|     /* set just once on startup */ |     /* set just once on startup */ | ||||||
|     uint64_t random_seed; |     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) */ |     /* 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 */ |     /* it can be changed at runtime; any resulting logic anomalies are bugs */ | ||||||
|     unsigned int update_multiplicity; |     unsigned int update_multiplicity; | ||||||
|  |  | ||||||
|  |     /* TODO: use Vec2i? */ | ||||||
|     int window_w; |     int window_w; | ||||||
|     int window_h; |     int window_h; | ||||||
|     int base_draw_w; |     int base_draw_w; | ||||||
|     int base_draw_h; |     int base_draw_h; | ||||||
|  |  | ||||||
|     /* you may read from and write to these from game code */ |  | ||||||
|     void *udata; |  | ||||||
|  |  | ||||||
|     bool debug; |     bool debug; | ||||||
|     bool is_running; |     bool is_running; | ||||||
|     bool window_size_has_changed; |     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_config.h" | ||||||
| #include "twn_types.h" | #include "twn_types.h" | ||||||
| #include "twn_engine_api.h" | #include "twn_engine_api.h" | ||||||
| #include "twn_scancode.h" | #include "twn_control.h" | ||||||
|  |  | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stddef.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 */ | TWN_API void input_add_action(const char *action_name); | ||||||
| typedef struct Button Button; | 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 */ | TWN_API Vec2 input_get_action_position(const char *action_name); | ||||||
| /* 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 */ | TWN_API void input_set_mouse_captured(bool enabled); | ||||||
|     /* it forgets the first Button to add the new one at the end */ | TWN_API bool input_is_mouse_captured(void); | ||||||
|     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); |  | ||||||
|  |  | ||||||
| #endif | #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_context.h" | ||||||
| #include "twn_textures_c.h" | #include "twn_textures_c.h" | ||||||
| #include "twn_audio_c.h" | #include "twn_audio_c.h" | ||||||
|  | #include "twn_input_c.h" | ||||||
| #include "twn_engine_api.h" | #include "twn_engine_api.h" | ||||||
| #include "rendering/twn_draw_c.h" | #include "rendering/twn_draw_c.h" | ||||||
|  |  | ||||||
| @@ -18,6 +19,8 @@ typedef struct EngineContext { | |||||||
|     /* user code facing context */ |     /* user code facing context */ | ||||||
|     Context game; |     Context game; | ||||||
|  |  | ||||||
|  |     InputState input; | ||||||
|  |  | ||||||
|     /* the program's actual argc and argv */ |     /* the program's actual argc and argv */ | ||||||
|     int argc; |     int argc; | ||||||
|     char **argv; |     char **argv; | ||||||
| @@ -64,6 +67,7 @@ typedef struct EngineContext { | |||||||
|     bool was_successful; |     bool was_successful; | ||||||
| } EngineContext; | } EngineContext; | ||||||
|  |  | ||||||
|  | /* TODO: does it need to be marked with TWN_API? */ | ||||||
| TWN_API extern EngineContext ctx; | TWN_API extern EngineContext ctx; | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										128
									
								
								src/twn_input.c
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								src/twn_input.c
									
									
									
									
									
								
							| @@ -1,5 +1,6 @@ | |||||||
| #include "twn_input_c.h" | #include "twn_input_c.h" | ||||||
| #include "twn_util.h" | #include "twn_util.h" | ||||||
|  | #include "twn_control.h" | ||||||
| #include "twn_engine_context_c.h" | #include "twn_engine_context_c.h" | ||||||
|  |  | ||||||
| #include <SDL2/SDL.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->just_changed = !action->is_pressed; | ||||||
|                 action->is_pressed = true; |                 action->is_pressed = true; | ||||||
|                 action->position.x = (float)input->mouse_window_position.x; |                 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: */ |                 /* TODO: */ | ||||||
|                 /* |                 /* | ||||||
| @@ -63,7 +64,7 @@ static void update_action_pressed_state(InputState *input, Action *action) { | |||||||
|  |  | ||||||
|  |  | ||||||
| static void input_bind_code_to_action(InputState *input, | static void input_bind_code_to_action(InputState *input, | ||||||
|                                       char *action_name, |                                       char const *action_name, | ||||||
|                                       ButtonSource source, |                                       ButtonSource source, | ||||||
|                                       union ButtonCode code) |                                       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, | static void input_unbind_code_from_action(InputState *input, | ||||||
|                                           char *action_name, |                                           char const *action_name, | ||||||
|                                           ButtonSource source, |                                           ButtonSource source, | ||||||
|                                           union ButtonCode code) |                                           union ButtonCode code) | ||||||
| { | { | ||||||
| @@ -193,6 +194,9 @@ void input_state_update(InputState *input) { | |||||||
|     SDL_GetRelativeMouseState(&input->mouse_relative_position.x, |     SDL_GetRelativeMouseState(&input->mouse_relative_position.x, | ||||||
|                               &input->mouse_relative_position.y); |                               &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) { |     for (size_t i = 0; i < shlenu(input->action_hash); ++i) { | ||||||
|         Action *action = &input->action_hash[i].value; |         Action *action = &input->action_hash[i].value; | ||||||
|         update_action_pressed_state(input, action); |         update_action_pressed_state(input, action); | ||||||
| @@ -200,76 +204,82 @@ void input_state_update(InputState *input) { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| void input_bind_action_scancode(InputState *input, | void input_bind_action_control(char const *action_name, | ||||||
|                                 char *action_name, |                                Control control) | ||||||
|                                 Scancode scancode) |  | ||||||
| { | { | ||||||
|     input_bind_code_to_action(input, |     SDL_assert_always(action_name); | ||||||
|                               action_name, |  | ||||||
|                               BUTTON_SOURCE_KEYBOARD_PHYSICAL, |  | ||||||
|                               (union ButtonCode) { .scancode = scancode }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |     if (CONTROL_SCANCODE_START <= control && control < CONTROL_SCANCODE_LIMIT) | ||||||
| void input_unbind_action_scancode(InputState *input, |         input_bind_code_to_action(&ctx.input, | ||||||
|                                   char *action_name, |  | ||||||
|                                   Scancode scancode) |  | ||||||
| { |  | ||||||
|     input_unbind_code_from_action(input, |  | ||||||
|                                   action_name, |                                   action_name, | ||||||
|                                   BUTTON_SOURCE_KEYBOARD_PHYSICAL, |                                   BUTTON_SOURCE_KEYBOARD_PHYSICAL, | ||||||
|                                   (union ButtonCode) { .scancode = scancode }); |                                   (union ButtonCode) { .scancode = (SDL_Scancode)control }); | ||||||
| } |  | ||||||
|  |  | ||||||
|  |     else if (CONTROL_MOUSECODE_START <= control && control < CONTROL_MOUSECODE_LIMIT) { | ||||||
| void input_bind_action_mouse(InputState *input, |         uint8_t const mouse_button = (uint8_t)(control - CONTROL_MOUSECODE_START); | ||||||
|                              char *action_name, |         input_bind_code_to_action(&ctx.input, | ||||||
|                              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, |  | ||||||
|                                   action_name, |                                   action_name, | ||||||
|                                   BUTTON_SOURCE_MOUSE, |                                   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) { | void input_unbind_action_control(char const *action_name, | ||||||
|     if (shgeti(input->action_hash, action_name) >= 0) { |                                  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); |         log_warn("(%s) Action \"%s\" is already registered.", __func__, action_name); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Action new_action = { 0 }; |     Action new_action = { 0 }; | ||||||
|     new_action.bindings = ccalloc(ctx.keybind_slots, sizeof *new_action.bindings); |     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) { | void input_delete_action(char const *action_name) { | ||||||
|     ActionHashItem *action = shgetp_null(input->action_hash, action_name); |     SDL_assert_always(action_name); | ||||||
|  |  | ||||||
|  |     ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name); | ||||||
|     if (action == NULL) { |     if (action == NULL) { | ||||||
|         log_warn("(%s) Action \"%s\" is not registered.", __func__, action_name); |         log_warn("(%s) Action \"%s\" is not registered.", __func__, action_name); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SDL_free(action->value.bindings); |     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) { | bool input_is_action_pressed(char const *action_name) { | ||||||
|     ActionHashItem *action = shgetp_null(input->action_hash, action_name); |     SDL_assert_always(action_name); | ||||||
|  |  | ||||||
|  |     ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name); | ||||||
|     if (action == NULL) { |     if (action == NULL) { | ||||||
|         log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name); |         log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name); | ||||||
|         return false; |         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) { | bool input_is_action_just_pressed(char const *action_name) { | ||||||
|     ActionHashItem *action = shgetp_null(input->action_hash, action_name); |     SDL_assert_always(action_name); | ||||||
|  |  | ||||||
|  |     ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name); | ||||||
|     if (action == NULL) { |     if (action == NULL) { | ||||||
|         log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name); |         log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name); | ||||||
|         return false; |         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) { | bool input_is_action_just_released(char const *action_name) { | ||||||
|     ActionHashItem *action = shgetp_null(input->action_hash, action_name); |     SDL_assert_always(action_name); | ||||||
|  |  | ||||||
|  |     ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name); | ||||||
|     if (action == NULL) { |     if (action == NULL) { | ||||||
|         log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name); |         log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name); | ||||||
|         return false; |         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) { | Vec2 input_get_action_position(char const *action_name) { | ||||||
|     ActionHashItem *action = shgetp_null(input->action_hash, action_name); |     SDL_assert_always(action_name); | ||||||
|  |  | ||||||
|  |     ActionHashItem *action = shgetp_null(ctx.input.action_hash, action_name); | ||||||
|     if (action == NULL) { |     if (action == NULL) { | ||||||
|         log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name); |         log_warn("(%s) Action \"%s\" does not exist.", __func__, action_name); | ||||||
|         return (Vec2) { 0 }; |         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_set_mouse_captured(bool enabled) { | ||||||
|     (void)input; |     if (SDL_SetRelativeMouseMode(enabled) != 0) | ||||||
|     /* TODO: returns -1 if not supported, but like... do we care? */ |         log_warn("(%s) Mouse capture isn't supported.", __func__); | ||||||
|     SDL_SetRelativeMouseMode(enabled); |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| bool input_is_mouse_captured(InputState *input) { | bool input_is_mouse_captured(void) { | ||||||
|     (void)input; |  | ||||||
|     return SDL_GetRelativeMouseMode(); |     return SDL_GetRelativeMouseMode(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| #ifndef INPUT_INTERNAL_API_H | #ifndef TWN_INPUT_C_H | ||||||
| #define INPUT_INTERNAL_API_H | #define TWN_INPUT_C_H | ||||||
|  |  | ||||||
| #include "twn_input.h" | #include "twn_input.h" | ||||||
| #include "twn_vec.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 */ | /* an input to which an action is bound */ | ||||||
| /* it is not limited to literal buttons */ | /* it is not limited to literal buttons */ | ||||||
| typedef struct Button { | typedef struct Button { | ||||||
| @@ -23,6 +32,45 @@ typedef struct Button { | |||||||
| } 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); | void input_reset_state(InputState *input); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -188,7 +188,7 @@ static void main_loop(void) { | |||||||
|  |  | ||||||
|             poll_events(); |             poll_events(); | ||||||
|  |  | ||||||
|             input_state_update(&ctx.game.input); |             input_state_update(&ctx.input); | ||||||
|  |  | ||||||
|             game_object_tick(); |             game_object_tick(); | ||||||
|  |  | ||||||
| @@ -634,7 +634,7 @@ static bool initialize(void) { | |||||||
|             ctx.keybind_slots = datum_keybind_slots.u.i; |             ctx.keybind_slots = datum_keybind_slots.u.i; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     input_state_init(&ctx.game.input); |     input_state_init(&ctx.input); | ||||||
|  |  | ||||||
|     /* scripting */ |     /* scripting */ | ||||||
|     /* |     /* | ||||||
| @@ -657,7 +657,7 @@ static void clean_up(void) { | |||||||
|     scripting_deinit(ctx); |     scripting_deinit(ctx); | ||||||
|     */ |     */ | ||||||
|  |  | ||||||
|     input_state_deinit(&ctx.game.input); |     input_state_deinit(&ctx.input); | ||||||
|     text_cache_deinit(&ctx.text_cache); |     text_cache_deinit(&ctx.text_cache); | ||||||
|     textures_cache_deinit(&ctx.texture_cache); |     textures_cache_deinit(&ctx.texture_cache); | ||||||
|  |  | ||||||
| @@ -675,7 +675,7 @@ static void clean_up(void) { | |||||||
|  |  | ||||||
|  |  | ||||||
| static void reset_state(void) { | static void reset_state(void) { | ||||||
|     input_reset_state(&ctx.game.input); |     input_reset_state(&ctx.input); | ||||||
|     textures_reset_state(); |     textures_reset_state(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user