2026-09-11 16:38:28 +02:00
|
|
|
#include "MenuSystem.h"
|
|
|
|
|
|
|
|
|
|
MenuSystem::MenuSystem() {}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::setRootScreenBuilder (ScreenBuilder fn) { rootBuilder = fn; }
|
|
|
|
|
|
|
|
|
|
void MenuSystem::rebuildRoot()
|
|
|
|
|
{
|
|
|
|
|
if (rootBuilder)
|
|
|
|
|
{
|
|
|
|
|
MenuScreen root = rootBuilder();
|
|
|
|
|
stack.clear();
|
|
|
|
|
stack.push_back (root);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::open()
|
|
|
|
|
{
|
|
|
|
|
wasOpen = true;
|
|
|
|
|
rebuildRoot();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::close()
|
|
|
|
|
{
|
|
|
|
|
stack.clear();
|
|
|
|
|
wasOpen = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::pushScreen (const MenuScreen& screen) { stack.push_back (screen); }
|
|
|
|
|
|
|
|
|
|
const MenuScreen& MenuSystem::current() const
|
|
|
|
|
{
|
|
|
|
|
if (stack.empty())
|
|
|
|
|
{
|
|
|
|
|
static MenuScreen empty;
|
|
|
|
|
empty.title = "";
|
|
|
|
|
empty.selected = 0;
|
|
|
|
|
return empty;
|
|
|
|
|
}
|
|
|
|
|
return stack.back();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::refreshCurrent()
|
|
|
|
|
{
|
|
|
|
|
if (! stack.empty())
|
|
|
|
|
{
|
|
|
|
|
int sel = stack.back().selected;
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
if (stack.empty() && rootBuilder)
|
|
|
|
|
{
|
|
|
|
|
MenuScreen root = rootBuilder();
|
|
|
|
|
root.selected = sel;
|
|
|
|
|
stack.push_back (root);
|
|
|
|
|
}
|
|
|
|
|
else if (! stack.empty())
|
|
|
|
|
{
|
|
|
|
|
stack.back().selected = sel;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::up()
|
|
|
|
|
{
|
|
|
|
|
if (stack.empty()) return;
|
|
|
|
|
auto& s = stack.back();
|
|
|
|
|
if (s.items.empty()) return;
|
|
|
|
|
|
|
|
|
|
int newSel = s.selected - 1;
|
|
|
|
|
while (newSel >= 0 && s.items[(size_t) newSel].kind == MenuItem::Separator)
|
|
|
|
|
--newSel;
|
2026-09-13 21:19:49 +02:00
|
|
|
if (newSel < 0)
|
|
|
|
|
{
|
|
|
|
|
newSel = (int) s.items.size() - 1;
|
|
|
|
|
while (newSel >= 0 && s.items[(size_t) newSel].kind == MenuItem::Separator)
|
|
|
|
|
--newSel;
|
|
|
|
|
}
|
2026-09-11 16:38:28 +02:00
|
|
|
if (newSel >= 0)
|
|
|
|
|
s.selected = newSel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::down()
|
|
|
|
|
{
|
|
|
|
|
if (stack.empty()) return;
|
|
|
|
|
auto& s = stack.back();
|
|
|
|
|
if (s.items.empty()) return;
|
|
|
|
|
|
|
|
|
|
int newSel = s.selected + 1;
|
|
|
|
|
while (newSel < (int) s.items.size() && s.items[(size_t) newSel].kind == MenuItem::Separator)
|
|
|
|
|
++newSel;
|
2026-09-13 21:19:49 +02:00
|
|
|
if (newSel >= (int) s.items.size())
|
|
|
|
|
{
|
|
|
|
|
newSel = 0;
|
|
|
|
|
while (newSel < (int) s.items.size() && s.items[(size_t) newSel].kind == MenuItem::Separator)
|
|
|
|
|
++newSel;
|
|
|
|
|
}
|
2026-09-11 16:38:28 +02:00
|
|
|
if (newSel < (int) s.items.size())
|
|
|
|
|
s.selected = newSel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::left()
|
|
|
|
|
{
|
|
|
|
|
if (stack.empty()) return;
|
|
|
|
|
auto& s = stack.back();
|
|
|
|
|
if (s.items.empty()) return;
|
|
|
|
|
auto& item = s.items[(size_t) s.selected];
|
|
|
|
|
if (item.kind == MenuItem::Value && item.onAdjust)
|
|
|
|
|
item.onAdjust (-0.02f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::right()
|
|
|
|
|
{
|
|
|
|
|
if (stack.empty()) return;
|
|
|
|
|
auto& s = stack.back();
|
|
|
|
|
if (s.items.empty()) return;
|
|
|
|
|
auto& item = s.items[(size_t) s.selected];
|
|
|
|
|
if (item.kind == MenuItem::Value && item.onAdjust)
|
|
|
|
|
item.onAdjust (0.02f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::enter()
|
|
|
|
|
{
|
|
|
|
|
if (stack.empty()) return;
|
|
|
|
|
auto& s = stack.back();
|
|
|
|
|
if (s.items.empty()) return;
|
|
|
|
|
auto& item = s.items[(size_t) s.selected];
|
|
|
|
|
if (item.onEnter)
|
|
|
|
|
item.onEnter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MenuSystem::escape()
|
|
|
|
|
{
|
|
|
|
|
if (stack.size() > 1)
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
else if (stack.size() == 1)
|
|
|
|
|
close();
|
|
|
|
|
}
|