#include "scene_impl.h" #include "assets_tag.h" #include "keymaps.h" #include /** * A potential performance tweak is to reduce the lookup. * The number of configurable actions should be fixed and * therefore would be known on scene init. * * So delegate all lookup on scene init. * Then, only call lookup on key changes. */ static const char* get_action_name(ActionType_t action) { /** * This is sort of a hack to get it done. * In theory, the engine should provide a way to register a name for an action * However, i didn't plan that far and this is the only place that needs it * Maybe in the next version of the engine... * * I could hardcode this to be array, but nah... */ switch (action) { case ACTION_UP: return "Up"; case ACTION_DOWN: return "Down"; case ACTION_LEFT: return "Left"; case ACTION_RIGHT: return "Right"; case ACTION_JUMP: case ACTION_CONFIRM: return "Confirm/Jump"; case ACTION_EXIT: return "Return"; case ACTION_LOOKAHEAD: return "Look"; default: return "Undefined"; } } static void options_scene_render_func(Scene_t* scene) { OptionSceneData_t* data = &(CONTAINER_OF(scene, OptionScene_t, scene)->data); KeyBindInfo_t keybind_info; char buffer[64]; int y_offset = 16; uint16_t line = 0; BeginTextureMode(scene->layers.render_layers[0].layer_tex); ClearBackground((Color){0,0,0,0}); if (line == data->curr_selection) { DrawText(">>", 0, y_offset, 12, WHITE); } float vol = GetMasterVolume(); sprintf(buffer, "Volume : %.1f", vol); DrawText(buffer, 32, y_offset, 12, WHITE); y_offset += 12; line++; sc_array_foreach(&data->keybinds_info, keybind_info) { if (line == data->curr_selection) { DrawText(">>", 0, y_offset, 12, WHITE); } sprintf(buffer, "%s : %s %d", keybind_info.action_name, keybind_info.key_name, keybind_info.key); DrawText(buffer, 32, y_offset, 12, WHITE); y_offset += 12; line++; } if (line == data->curr_selection) { DrawText(">>", 0, y_offset, 12, WHITE); } DrawText("OK", 32, y_offset, 12, WHITE); y_offset += 12; line++; if (line == data->curr_selection) { DrawText(">>", 0, y_offset, 12, WHITE); } DrawText("Cancel", 32, y_offset, 12, WHITE); y_offset += 12; line++; EndTextureMode(); } static void exec_component_function(Scene_t* scene, uint16_t sel) { printf("Sel: %u\n", sel); if (sel == 0) { // Volume option, does nothing return; } sel--; uint16_t n_binds = sc_map_size_64(&scene->engine->keybinds); if (sel >= n_binds) { // Either OK or Cancel // Both will return to menu scene sel -= n_binds; // TODO: add check to save keybinds change_scene(scene->engine, MAIN_MENU_SCENE); } else { // Keybind options // TODO: This should change the scene mode // Engine need to record last key released } } static void options_do_action(Scene_t* scene, ActionType_t action, bool pressed) { OptionSceneData_t* data = &(CONTAINER_OF(scene, OptionScene_t, scene)->data); switch(data->mode) { case OPTIONS_NORMAL_MODE: { uint16_t new_selection = data->curr_selection; if (!pressed) { switch(action) { case ACTION_UP: if (new_selection > 0) { data->curr_selection--; } break; case ACTION_DOWN: if (new_selection < data->n_selections - 1) { data->curr_selection++; } break; case ACTION_LEFT: // Left and right only works on volume option if (new_selection == 0) { } break; case ACTION_RIGHT: if (new_selection == 0) { } break; case ACTION_CONFIRM: exec_component_function(scene, new_selection); break; case ACTION_EXIT: if(scene->engine != NULL) { change_scene(scene->engine, MAIN_MENU_SCENE); } break; default: break; } } } break; case OPTIONS_KEYBIND_MODE: break; } } void init_options_scene(OptionScene_t* scene) { init_scene(&scene->scene, &options_do_action, 0); scene->scene.bg_colour = BLACK; add_scene_layer( &scene->scene, scene->scene.engine->intended_window_size.x, scene->scene.engine->intended_window_size.y, (Rectangle){ 0, 0, scene->scene.engine->intended_window_size.x, scene->scene.engine->intended_window_size.y } ); scene->data.curr_selection = 0; scene->data.mode = OPTIONS_NORMAL_MODE; // 3 extra options: Volume, Ok, Cancel scene->data.n_selections = sc_map_size_64(&scene->scene.engine->keybinds) + 3; sc_array_init(&scene->data.keybinds_info); { int key; ActionType_t action; sc_map_foreach(&scene->scene.engine->keybinds, action, key) { KeyBindInfo_t keybind = { .action_name = get_action_name(action), .key_name = ExtGetKeyName(key), .action = action, .key = key, }; sc_array_add(&scene->data.keybinds_info, keybind); } } // The number of actions that can be key-binds is constant. // So can just init once. 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); sc_map_put_64(&scene->scene.action_map, get_keybind_or_default(scene->scene.engine, ACTION_DOWN, KEY_DOWN), ACTION_DOWN); sc_map_put_64(&scene->scene.action_map, get_keybind_or_default(scene->scene.engine, ACTION_LEFT, KEY_LEFT), ACTION_LEFT); sc_map_put_64(&scene->scene.action_map, get_keybind_or_default(scene->scene.engine, ACTION_RIGHT, KEY_RIGHT), ACTION_RIGHT); sc_map_put_64(&scene->scene.action_map, get_keybind_or_default(scene->scene.engine, ACTION_JUMP, KEY_ENTER), ACTION_CONFIRM); sc_map_put_64(&scene->scene.action_map, get_keybind_or_default(scene->scene.engine, ACTION_EXIT, KEY_Q), ACTION_EXIT); sc_map_put_64(&scene->scene.action_map, KEY_ENTER, ACTION_CONFIRM); sc_map_put_64(&scene->scene.action_map, KEY_BACKSPACE, ACTION_EXIT); } void free_options_scene(OptionScene_t* scene) { sc_array_term(&scene->data.keybinds_info); free_scene(&scene->scene); }