console utils
This commit is contained in:
parent
82cca59ddd
commit
51d3c8e6f2
4 changed files with 184 additions and 10 deletions
13
.vscode/settings.json
vendored
Normal file
13
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"ostream": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"limits": "cpp"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +1,49 @@
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "utilsconsole.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int main(void) {;
|
int main(void) {;
|
||||||
gfxInitDefault();
|
gfxInitDefault();
|
||||||
consoleInit(GFX_TOP, NULL);
|
consoleInit(GFX_BOTTOM, NULL);
|
||||||
bool value = false;
|
|
||||||
while (aptMainLoop()) {
|
|
||||||
hidScanInput();
|
|
||||||
if (hidKeysDown() & KEY_A)
|
|
||||||
value = !value;
|
|
||||||
|
|
||||||
gspWaitForVBlank();
|
int a = 0;
|
||||||
GSPGPU_SetLedForceOff(value);
|
int b = 2;
|
||||||
gfxFlushBuffers();
|
int c = -10;
|
||||||
gfxSwapBuffers();
|
while (aptMainLoop()) {
|
||||||
|
static const s_uc_menu_element menu[] = {
|
||||||
|
{"a", true, &a, 0, 10},
|
||||||
|
{"b", true, &b, 0, 2},
|
||||||
|
{"c", true, &c, -10, 10},
|
||||||
|
{"Show", false, NULL, 0, 0},
|
||||||
|
{"Test quick menu", false, NULL, 0, 0},
|
||||||
|
};
|
||||||
|
static auto menuVec = vector<s_uc_menu_element>(menu, menu + 5);
|
||||||
|
int ans = uc_menu(menuVec);
|
||||||
|
if (ans == 3) {
|
||||||
|
cout << "a: " << a << ", b: " << b << ", c: " << c << endl;
|
||||||
|
uc_pause();
|
||||||
|
}
|
||||||
|
else if (ans == 4) {
|
||||||
|
while (aptMainLoop()) {
|
||||||
|
ans = uc_menu_quick("hello", "hola", "bonjour", "Go back");
|
||||||
|
switch (ans) {
|
||||||
|
case 0:
|
||||||
|
cout << "bye" << endl;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
cout << "adios" << endl;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
cout << "au revoir" << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ans == 3)
|
||||||
|
break;
|
||||||
|
uc_pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gfxExit();
|
gfxExit();
|
||||||
}
|
}
|
87
source/utilsconsole.cpp
Normal file
87
source/utilsconsole.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#include <3ds.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "utilsconsole.hpp"
|
||||||
|
|
||||||
|
int uc_menu(vector<s_uc_menu_element> &elements) {
|
||||||
|
static void *lastElements = NULL;
|
||||||
|
static size_t selected = 0;
|
||||||
|
|
||||||
|
bool confirmed = false;
|
||||||
|
|
||||||
|
if (&elements != lastElements) {
|
||||||
|
// init if new menu
|
||||||
|
consoleClear();
|
||||||
|
lastElements = &elements;
|
||||||
|
selected = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// read inputs
|
||||||
|
hidScanInput();
|
||||||
|
if (hidKeysDown() & KEY_UP) {
|
||||||
|
if (selected-- == 0)
|
||||||
|
selected += elements.size();
|
||||||
|
}
|
||||||
|
else if (hidKeysDown() & KEY_DOWN) {
|
||||||
|
if (++selected >= elements.size())
|
||||||
|
selected -= elements.size();
|
||||||
|
}
|
||||||
|
else if (!elements[selected].is_number_prompt) {
|
||||||
|
if (hidKeysDown() & KEY_A) {
|
||||||
|
confirmed = true;
|
||||||
|
lastElements = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (hidKeysDown() & KEY_LEFT)
|
||||||
|
if (*elements[selected].value > elements[selected].min)
|
||||||
|
(*elements[selected].value)--;
|
||||||
|
if (hidKeysDown() & KEY_RIGHT)
|
||||||
|
if (*elements[selected].value < elements[selected].max)
|
||||||
|
(*elements[selected].value)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// display
|
||||||
|
cout << "\e[H\e[0m";
|
||||||
|
for (size_t i = 0; i < elements.size(); i++) {
|
||||||
|
cout << (i == selected && !confirmed ? "\e[7m" : "")
|
||||||
|
<< elements[i].name << "\e[0m";
|
||||||
|
if (elements[i].is_number_prompt)
|
||||||
|
cout
|
||||||
|
<< ((*(elements[i].value) == elements[i].min) ? " " : " <")
|
||||||
|
<< *(elements[i].value)
|
||||||
|
<< ((*(elements[i].value) == elements[i].max) ? " " : ">");
|
||||||
|
cout << "\e[0K" << endl;
|
||||||
|
}
|
||||||
|
if (!confirmed)
|
||||||
|
cout << "\e[2m" << "[Up/Down] Move / "
|
||||||
|
<< (elements[selected].is_number_prompt ?
|
||||||
|
"[Left/Right] Modify" : "(A) Confirm") << "\e[0K" << endl;
|
||||||
|
else
|
||||||
|
cout << "\e[2mOK.\e[0K\e[0m" << endl;
|
||||||
|
|
||||||
|
return confirmed ? selected : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uc_menu_quick(const char *str, ...) {
|
||||||
|
va_list arguments;
|
||||||
|
auto elements = vector<s_uc_menu_element>();
|
||||||
|
for (va_start(arguments, str); str; str = va_arg(arguments, const char *))
|
||||||
|
elements.push_back({str, false, NULL, 0, 0});
|
||||||
|
|
||||||
|
int r = -1;
|
||||||
|
while (r < 0 && aptMainLoop())
|
||||||
|
r = uc_menu(elements);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uc_pause(void) {
|
||||||
|
cout << "\e[0;2mPress (A) to continue...\e[0m" << endl;
|
||||||
|
while (aptMainLoop()) {
|
||||||
|
hidScanInput();
|
||||||
|
if (hidKeysDown() & KEY_A)
|
||||||
|
break;
|
||||||
|
gfxFlushBuffers();
|
||||||
|
}
|
||||||
|
}
|
46
source/utilsconsole.hpp
Normal file
46
source/utilsconsole.hpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* utilsconsole.hpp (uc_*)
|
||||||
|
* Utility functions for the console.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/// @brief To use with uc_menu(): Represent an element of the menu.
|
||||||
|
typedef struct {
|
||||||
|
/// @brief Displayed name.
|
||||||
|
string name;
|
||||||
|
/// @brief true if this button can be used to change the value of a number.
|
||||||
|
bool is_number_prompt;
|
||||||
|
/// @brief Only if is_number_prompt is true: the number to change.
|
||||||
|
int *value;
|
||||||
|
/// @brief Only if is_number_prompt is true: the minimum value possible for
|
||||||
|
/// value.
|
||||||
|
int min;
|
||||||
|
/// @brief Only if is_number_prompt is true: the maximum value possible for
|
||||||
|
/// value.
|
||||||
|
int max;
|
||||||
|
} s_uc_menu_element;
|
||||||
|
|
||||||
|
/// @brief Display a menu with several items in the console.
|
||||||
|
/// @details
|
||||||
|
/// Non-blocking function, must be called in loop.
|
||||||
|
/// Only one menu can work at the same time. 'elements' must not change in
|
||||||
|
/// address.
|
||||||
|
/// @param elements A pointer to a vector of all the elements of the menu.
|
||||||
|
/// @return The index of the confirmed element. If none, return -1.
|
||||||
|
int uc_menu(vector<s_uc_menu_element> &elements);
|
||||||
|
|
||||||
|
/// @brief Display a menu quickly using only confirm buttons.
|
||||||
|
/// @details
|
||||||
|
/// Blocking function. Will return -1 if aptMainLoop() becomes false.
|
||||||
|
/// @param str Text representing each element. The last parameter must be NULL.
|
||||||
|
/// @return The index of the confirmed element.
|
||||||
|
int uc_menu_quick(const char *str, ...);
|
||||||
|
|
||||||
|
/// @brief Blocks the program until the user presses A.
|
||||||
|
/// @details Will also return if aptMainLoop() becomes false.
|
||||||
|
void uc_pause(void);
|
Loading…
Add table
Reference in a new issue