123 lines
3.9 KiB
Plaintext
123 lines
3.9 KiB
Plaintext
#include "menu.nvgt"
|
|
#include "audio_paths.nvgt"
|
|
|
|
// Applies common menu sounds from a directory.
|
|
// Looks for both .ogg and .wav files automatically.
|
|
void menu_apply_default_sounds(menu@ menuRef, const string soundDir = "sounds/menu") {
|
|
if (@menuRef is null) {
|
|
return;
|
|
}
|
|
|
|
menuRef.click_sound = resolve_audio_path(soundDir + "/menu_move");
|
|
menuRef.select_sound = resolve_audio_path(soundDir + "/menu_select");
|
|
menuRef.edge_sound = resolve_audio_path(soundDir + "/menu_edge");
|
|
menuRef.wrap_sound = resolve_audio_path(soundDir + "/menu_wrap");
|
|
menuRef.open_sound = resolve_audio_path(soundDir + "/menu_open");
|
|
menuRef.close_sound = resolve_audio_path(soundDir + "/menu_close");
|
|
}
|
|
|
|
// Minimal blocking list menu.
|
|
// Returns selected index or -1 on empty input/escape.
|
|
int menu_run_simple(const string introText, string[]@ options, bool wrap = true, int startIndex = 0, const string soundDir = "sounds/menu") {
|
|
if (@options is null || options.length() == 0) {
|
|
return -1;
|
|
}
|
|
|
|
menu menuRef;
|
|
menu_apply_default_sounds(menuRef, soundDir);
|
|
menuRef.intro_text = introText;
|
|
menuRef.wrap = wrap;
|
|
menuRef.focus_first_item = true;
|
|
menuRef.add_items(options);
|
|
|
|
if (startIndex >= 0 && startIndex < int(options.length())) {
|
|
menuRef.focused_item = startIndex;
|
|
}
|
|
|
|
return menuRef.run();
|
|
}
|
|
|
|
// Returns a-z for menu prefix filtering, or empty string when no letter key was pressed.
|
|
string menu_get_filter_letter() {
|
|
if (key_pressed(KEY_A)) return "a";
|
|
if (key_pressed(KEY_B)) return "b";
|
|
if (key_pressed(KEY_C)) return "c";
|
|
if (key_pressed(KEY_D)) return "d";
|
|
if (key_pressed(KEY_E)) return "e";
|
|
if (key_pressed(KEY_F)) return "f";
|
|
if (key_pressed(KEY_G)) return "g";
|
|
if (key_pressed(KEY_H)) return "h";
|
|
if (key_pressed(KEY_I)) return "i";
|
|
if (key_pressed(KEY_J)) return "j";
|
|
if (key_pressed(KEY_K)) return "k";
|
|
if (key_pressed(KEY_L)) return "l";
|
|
if (key_pressed(KEY_M)) return "m";
|
|
if (key_pressed(KEY_N)) return "n";
|
|
if (key_pressed(KEY_O)) return "o";
|
|
if (key_pressed(KEY_P)) return "p";
|
|
if (key_pressed(KEY_Q)) return "q";
|
|
if (key_pressed(KEY_R)) return "r";
|
|
if (key_pressed(KEY_S)) return "s";
|
|
if (key_pressed(KEY_T)) return "t";
|
|
if (key_pressed(KEY_U)) return "u";
|
|
if (key_pressed(KEY_V)) return "v";
|
|
if (key_pressed(KEY_W)) return "w";
|
|
if (key_pressed(KEY_X)) return "x";
|
|
if (key_pressed(KEY_Y)) return "y";
|
|
if (key_pressed(KEY_Z)) return "z";
|
|
return "";
|
|
}
|
|
|
|
// Applies a prefix filter to menu options.
|
|
void menu_apply_prefix_filter(const string &in filterText, const string[]@ options, int[]@ filteredIndices, string[]@ filteredOptions) {
|
|
filteredIndices.resize(0);
|
|
filteredOptions.resize(0);
|
|
|
|
if (@options is null) {
|
|
return;
|
|
}
|
|
|
|
string filterLower = filterText.lower();
|
|
for (uint optionIndex = 0; optionIndex < options.length(); optionIndex++) {
|
|
if (filterLower.length() == 0) {
|
|
filteredIndices.insert_last(optionIndex);
|
|
filteredOptions.insert_last(options[optionIndex]);
|
|
continue;
|
|
}
|
|
|
|
string optionLower = options[optionIndex].lower();
|
|
if (optionLower.length() >= filterLower.length() && optionLower.substr(0, filterLower.length()) == filterLower) {
|
|
filteredIndices.insert_last(optionIndex);
|
|
filteredOptions.insert_last(options[optionIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Updates filter text from keyboard input and reapplies filtering.
|
|
bool menu_update_prefix_filter(string &inout filterText, const string[]@ options, int[]@ filteredIndices, string[]@ filteredOptions, int &inout selection) {
|
|
bool filterChanged = false;
|
|
|
|
if (key_pressed(KEY_BACK) && filterText.length() > 0) {
|
|
filterText = filterText.substr(0, filterText.length() - 1);
|
|
filterChanged = true;
|
|
}
|
|
|
|
string filterLetter = menu_get_filter_letter();
|
|
if (filterLetter != "") {
|
|
filterText += filterLetter;
|
|
filterChanged = true;
|
|
}
|
|
|
|
if (filterChanged) {
|
|
menu_apply_prefix_filter(filterText, options, filteredIndices, filteredOptions);
|
|
if (selection < 0) {
|
|
selection = 0;
|
|
}
|
|
if (selection >= int(filteredOptions.length())) {
|
|
selection = 0;
|
|
}
|
|
}
|
|
|
|
return filterChanged;
|
|
}
|