#include #include #include #include #include #include "ui.h" #include "save.h" #include "map.h" #define FB_MAX_COLS 80 #define FB_MAX_LINES 45 #define MSG_MAX_LINE_LEN 45 #define MSG_START_COL (FB_MAX_COLS-MSG_MAX_LINE_LEN) #define MSG_MAX_LEN (MSG_MAX_LINE_LEN*FB_MAX_LINES) #define FB_MIDDLE_LINE (FB_MAX_LINES/2) // this converts to string #define STR_(X) #X // this makes sure the argument is expanded before converting to string #define STR(X) STR_(X) MenuItem main_menu_items[6] = { {"Add Missing Koroks to Map", &sortKoroksByDistance}, {"Erase Completed Korok Pins", &eraseCompletedKorokPins}, {"Erase All Map Pins", &eraseMapPins}, {"Convert Invalid Map Pins", &convertInvalidMapPinIcons}, {"Save and Exit", &saveAndExitApp}, {"Exit w/o Saving", &exitApp} }; Menu main_menu = { .HeaderStr = "BOTW KOROK COMPLETER", .ItemCount = 6, .Menu_Items = main_menu_items }; MenuItem confirm_menu_items[2] = { {"No, cancel!", NULL}, {"Yes, do it!", NULL} }; Menu confirm_menu = { .HeaderStr = "ARE YOU SURE??", .ItemCount = 2, .Menu_Items = confirm_menu_items }; Menu *current_menu; Menu *previous_menu; char MSG_BUFFER[FB_MAX_LINES][MSG_MAX_LINE_LEN+1]; u32 msg_buf_write_line = 0; u32 msg_buf_line_count = 0; bool exit_state = false; bool confirmed = false; void _clearScreen() { printf(CONSOLE_ESC(2J)); //clear screen and reset home cursor } void loadMenu(Menu* menu) { current_menu = menu; current_menu->StartLine = FB_MIDDLE_LINE - (current_menu->ItemCount / 2); current_menu->SelectedIndex = 0; _clearScreen(); _drawMenu(); _drawMessagePane(); } void _drawMenu() { //new code printfAtCursor(2, current_menu->StartLine-2, current_menu->HeaderStr); printfAtCursor(2, current_menu->StartLine, ">"); for (int i = 0; i < current_menu->ItemCount; i++) { printfAtCursor(4, current_menu->StartLine+i, current_menu->Menu_Items[i].ItemStr); } //end new code /*/old code printfAtCursor(2, MENU_START_COL-2, "BOTW KOROK COMPLETER"); printfAtCursor(2, MENU_START_COL, "> Add Missing Koroks to Map"); printfAtCursor(2, MENU_START_COL+1, " Erase all map pins"); printfAtCursor(2, MENU_START_COL+2, " Convert invalid map pins"); printfAtCursor(2, MENU_START_COL+3, " Save and Exit"); printfAtCursor(2, MENU_START_COL+4, " Exit w/o Saving"); //end old code*/ //print vertical line between menu and messages panel for (int i = 1; i <= FB_MAX_LINES; i++) { printfAtCursor(FB_MAX_COLS - MSG_MAX_LINE_LEN - 2, i, "|"); } } void initUI() { loadMenu(&main_menu); } void exitApp() { exit_state = true; } void saveAndExitApp() { closeAndCommitSave(); exitApp(); } void handleMenuButtonPress(u64 button) { //clear menu cursor printfAtCursor(2, current_menu->StartLine+current_menu->SelectedIndex, " "); switch (button) { case HidNpadButton_Down: if (current_menu->SelectedIndex == current_menu->ItemCount - 1) { current_menu->SelectedIndex = 0; } else { current_menu->SelectedIndex++; } break; case HidNpadButton_Up: if (current_menu->SelectedIndex == 0) { current_menu->SelectedIndex = current_menu->ItemCount-1; } else { current_menu->SelectedIndex--; } break; case HidNpadButton_A: //run menu function, using menu item index: position - start_line current_menu->Menu_Items[current_menu->SelectedIndex].ItemFunc(); break; default: break; } //print menu cursor printfAtCursor(2, current_menu->StartLine+current_menu->SelectedIndex, ">"); } bool handleButtonPress(u64 button) { if (button & HidNpadButton_Plus) { return true; } // exit if + button pressed handleMenuButtonPress(button); return exit_state; } /*u32 handleMenuButtonPress(u64 button) { switch (button) { case HidNpadButton_Down: printf(CONSOLE_ESC(%d;2H) " ", menu_pos); if (menu_pos == MENU_END_LINE) { menu_pos = MENU_START_LINE; } else { menu_pos++; } printf(CONSOLE_ESC(%d;2H) ">", menu_pos); break; case HidNpadButton_Up: printf(CONSOLE_ESC(%d;2H) " ", menu_pos); if (menu_pos == MENU_START_LINE) { menu_pos = MENU_END_LINE; } else { menu_pos--; } printf(CONSOLE_ESC(%d;2H) ">", menu_pos); break; case HidNpadButton_A: return menu_pos; break; default: break; } return (enum menu_items)none; } bool handleButtonPress(u64 button) { switch(handleMenuButtonPress(button)) { case add_missing_koroks: sortKoroksByDistance(); break; case erase_all_map_pins: eraseMapPins(); break; case convert_invalid_map_pins: convertInvalidMapPinIcons(); break; case save_file: writeSave(); closeAndCommitSave(); return true; break; case exit_app: return true; break; default: break; } return false; }*/ void _confirm_no() { loadMenu(previous_menu); } void confirmThenRunElse(func_t yes_func, func_t no_func) { //save current menu previous_menu = current_menu; confirm_menu.Menu_Items[1].ItemFunc = yes_func; confirm_menu.Menu_Items[0].ItemFunc = no_func; loadMenu(&confirm_menu); } void confirmThenRun(func_t yes_func) { confirmThenRunElse(yes_func, &_confirm_no); } void printfAtCursor(u32 x_pos, u32 y_pos, const char* format, ...) { va_list args; va_start(args, format); _setCursorPos(x_pos, y_pos); vprintf(format, args); va_end(args); } void _setCursorPos(u32 x_pos, u32 y_pos) { if (x_pos >= 1 && x_pos <= FB_MAX_COLS && y_pos >= 1 && y_pos <= FB_MAX_LINES) { printf(CONSOLE_ESC(%d;%dH) , y_pos, x_pos); } } void printMessage(const char* format, ...) { //get variable args va_list args; va_start(args, format); //process the format string char message[MSG_MAX_LEN-FB_MAX_LINES]; vsnprintf(message, MSG_MAX_LEN-FB_MAX_LINES, format, args); va_end(args); //find out how many lines we are about to add to the buffer/print size_t length = strlen(message); u32 num_of_lines = length / MSG_MAX_LINE_LEN; if (length%MSG_MAX_LINE_LEN != 0) {num_of_lines++;} char *line; for (int i = 0; i < num_of_lines; i++) { //extract the next set of characters and store in line line = strndup(message + (MSG_MAX_LINE_LEN*i), MSG_MAX_LINE_LEN); //clear previous line memset(MSG_BUFFER[msg_buf_write_line], 0, MSG_MAX_LINE_LEN+1); //copy line to MSG_BUFFER at write_ptr strncpy(MSG_BUFFER[msg_buf_write_line], line, MSG_MAX_LINE_LEN); MSG_BUFFER[msg_buf_write_line][MSG_MAX_LINE_LEN] = '\0'; msg_buf_write_line++; //free original line after we've copied it free(line); //if count is below max lines, then increase count if (msg_buf_line_count < FB_MAX_LINES) { msg_buf_line_count++; } // if the next write line is past the last index, set the next index to 0. if (msg_buf_write_line == FB_MAX_LINES) { msg_buf_write_line = 0; } _drawMessagePane(); } } void _drawMessagePane() { //print all lines in buffer, from top to bottom, oldest to newest if (msg_buf_line_count > 0) { u32 start_line = 0; if (msg_buf_line_count == FB_MAX_LINES) { start_line = msg_buf_write_line; } for (int i = 0; i < msg_buf_line_count; i++) { _setCursorPos(MSG_START_COL, i+1); printf("%-" STR(MSG_MAX_LINE_LEN) "s", MSG_BUFFER[(start_line + i) % FB_MAX_LINES]); } } }