Implement key recording for rebind
Changelog: - Update engine to record last key released - Update option scene to get the last key pressed for binding - Does not actually change the keybind yetmain
parent
5c3428da56
commit
16de3bb70e
|
@ -17,6 +17,7 @@ void init_engine(GameEngine_t* engine, Vector2 starting_win_size)
|
|||
engine->intended_window_size = starting_win_size;
|
||||
InitWindow(starting_win_size.x, starting_win_size.y, "raylib");
|
||||
engine->base_canvas = LoadRenderTexture(starting_win_size.x, starting_win_size.y);
|
||||
engine->last_input_key = KEY_NULL;
|
||||
}
|
||||
|
||||
void deinit_engine(GameEngine_t* engine)
|
||||
|
@ -49,22 +50,32 @@ int get_keybind_or_default(GameEngine_t* engine, ActionType_t action, int defaul
|
|||
|
||||
void process_inputs(GameEngine_t* engine, Scene_t* scene)
|
||||
{
|
||||
engine->last_input_key = KEY_NULL;
|
||||
Vector2 raw_mouse_pos = GetMousePosition();
|
||||
scene->mouse_pos = raw_mouse_pos;
|
||||
|
||||
// For flexibility, key that are not mapped to an action are still recorded
|
||||
// pay a little performance to do two checks.
|
||||
|
||||
unsigned int sz = sc_queue_size(&engine->key_buffer);
|
||||
// Process any existing pressed key
|
||||
for (size_t i = 0; i < sz; i++)
|
||||
{
|
||||
int button = sc_queue_del_first(&engine->key_buffer);
|
||||
ActionType_t action = sc_map_get_64(&scene->action_map, button);
|
||||
if (IsKeyReleased(button))
|
||||
bool pressed = !IsKeyReleased(button);
|
||||
if (!pressed)
|
||||
{
|
||||
do_action(scene, action, false);
|
||||
engine->last_input_key = button;
|
||||
}
|
||||
else
|
||||
|
||||
ActionType_t action = sc_map_get_64(&scene->action_map, button);
|
||||
if (sc_map_found(&scene->action_map))
|
||||
{
|
||||
do_action(scene, action, pressed);
|
||||
}
|
||||
|
||||
if (pressed)
|
||||
{
|
||||
do_action(scene, action, true);
|
||||
sc_queue_add_last(&engine->key_buffer, button);
|
||||
}
|
||||
}
|
||||
|
@ -75,8 +86,10 @@ void process_inputs(GameEngine_t* engine, Scene_t* scene)
|
|||
int button = GetKeyPressed();
|
||||
if (button == 0) break;
|
||||
ActionType_t action = sc_map_get_64(&scene->action_map, button);
|
||||
if (!sc_map_found(&scene->action_map)) continue;
|
||||
do_action(scene, action, true);
|
||||
if (sc_map_found(&scene->action_map))
|
||||
{
|
||||
do_action(scene, action, true);
|
||||
}
|
||||
sc_queue_add_last(&engine->key_buffer, button);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@ typedef struct GameEngine {
|
|||
// an absolute reference
|
||||
Vector2 intended_window_size;
|
||||
RenderTexture2D base_canvas;
|
||||
|
||||
// ad-hoc addition. Next version should be a configurable key buffer
|
||||
int last_input_key;
|
||||
} GameEngine_t;
|
||||
|
||||
#define SCENE_ACTIVE_BIT (1 << 0) // Systems Active
|
||||
|
|
|
@ -90,12 +90,56 @@ static void options_scene_render_func(Scene_t* scene)
|
|||
DrawText("Cancel", 32, y_offset, 12, WHITE);
|
||||
y_offset += 12;
|
||||
line++;
|
||||
|
||||
if (data->mode == OPTIONS_KEYBIND_MODE)
|
||||
{
|
||||
y_offset += 36;
|
||||
DrawText("Press a Key...", 32, y_offset, 12, WHITE);
|
||||
}
|
||||
|
||||
EndTextureMode();
|
||||
}
|
||||
|
||||
static void wait_for_keymap_input(Scene_t* scene)
|
||||
{
|
||||
/**
|
||||
* Due to engine design limitation, I canot remove
|
||||
* the system when placed into the array
|
||||
* So, this will have to run as part of the loop
|
||||
* Even though it is only used in a particular mode
|
||||
* It's a small performance penalty for unfortunate design
|
||||
*/
|
||||
|
||||
OptionSceneData_t* data = &(CONTAINER_OF(scene, OptionScene_t, scene)->data);
|
||||
if (data->mode == OPTIONS_NORMAL_MODE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->mode == OPTIONS_KEYBIND_READY_MODE)
|
||||
{
|
||||
// Keys are processed before system Update
|
||||
// Need to skip the current frame to get the next key
|
||||
// This state is to do just that.
|
||||
data->mode = OPTIONS_KEYBIND_MODE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (scene->engine->last_input_key == KEY_NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Key inputted: %d\n", scene->engine->last_input_key);
|
||||
|
||||
data->keybinds_info.elems[data->curr_selection - 1].key = scene->engine->last_input_key;
|
||||
data->keybinds_info.elems[data->curr_selection - 1].key_name = ExtGetKeyName(scene->engine->last_input_key);
|
||||
data->mode = OPTIONS_NORMAL_MODE;
|
||||
}
|
||||
|
||||
static void exec_component_function(Scene_t* scene, uint16_t sel)
|
||||
{
|
||||
OptionSceneData_t* data = &(CONTAINER_OF(scene, OptionScene_t, scene)->data);
|
||||
printf("Sel: %u\n", sel);
|
||||
if (sel == 0)
|
||||
{
|
||||
|
@ -116,9 +160,8 @@ static void exec_component_function(Scene_t* scene, uint16_t sel)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Keybind options
|
||||
// TODO: This should change the scene mode
|
||||
// Engine need to record last key released
|
||||
// Keybind options, but need to wait one frame
|
||||
data->mode = OPTIONS_KEYBIND_READY_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,7 +216,7 @@ static void options_do_action(Scene_t* scene, ActionType_t action, bool pressed)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case OPTIONS_KEYBIND_MODE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -219,6 +262,7 @@ void init_options_scene(OptionScene_t* scene)
|
|||
// The number of actions that can be key-binds is constant.
|
||||
// So can just init once.
|
||||
|
||||
sc_array_add(&scene->scene.systems, &wait_for_keymap_input);
|
||||
sc_array_add(&scene->scene.systems, &options_scene_render_func);
|
||||
|
||||
sc_map_put_64(&scene->scene.action_map, get_keybind_or_default(scene->scene.engine, ACTION_UP, KEY_UP), ACTION_UP);
|
||||
|
|
|
@ -137,6 +137,7 @@ typedef struct LevelSelectScene {
|
|||
|
||||
typedef enum OptionSceneMode {
|
||||
OPTIONS_NORMAL_MODE,
|
||||
OPTIONS_KEYBIND_READY_MODE,
|
||||
OPTIONS_KEYBIND_MODE,
|
||||
}OptionSceneMode_t;
|
||||
|
||||
|
|
Loading…
Reference in New Issue