1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-25 03:42:48 +01:00

Further refactor of menu managment

This commit is contained in:
Filip Gawin 2018-12-26 21:48:16 +01:00
parent d5541ac91f
commit c49b4bbd50
8 changed files with 166 additions and 153 deletions

View File

@ -3,6 +3,7 @@
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <initializer_list>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <string> #include <string>
@ -71,18 +72,14 @@ public:
} }
}; };
Menu(std::vector<MenuEntry> initial, int font = MenuDefaults::kFont, Menu(std::initializer_list<MenuEntry>&& initial,
const glm::vec2& offset = glm::vec2(), int font = MenuDefaults::kFont,
float size = 30.f) float size = 30.f)
: activeEntry(-1), font(font), size(size), entries(std::move(initial)) { : activeEntry(-1)
} , offset(offset)
, font(font)
/** , size(size)
* @brief creates a menu from the given menu items , entries(initial) {
* @return optional of menu with the items
*/
static std::optional<Menu> create(std::vector<MenuEntry> items,
int font = MenuDefaults::kFont, float size = 30.f) {
return std::make_optional<Menu>(std::move(items), font, size);
} }
Menu& lambda(const GameString& n, std::function<void()> callback) { Menu& lambda(const GameString& n, std::function<void()> callback) {
@ -100,8 +97,6 @@ public:
*/ */
int activeEntry; int activeEntry;
glm::vec2 offset{};
void draw(GameRenderer* r) { void draw(GameRenderer* r) {
glm::vec2 basis(offset); glm::vec2 basis(offset);
for (size_t i = 0; i < entries.size(); ++i) { for (size_t i = 0; i < entries.size(); ++i) {
@ -159,6 +154,7 @@ public:
} }
private: private:
glm::vec2 offset{};
int font; int font;
float size; float size;
std::vector<MenuEntry> entries; std::vector<MenuEntry> entries;

View File

@ -6,8 +6,23 @@ const ViewCamera defaultView{{-250.f, -550.f, 75.f},
glm::angleAxis(glm::radians(5.f), glm::angleAxis(glm::radians(5.f),
glm::vec3(0.f, 1.f, 0.f))}; glm::vec3(0.f, 1.f, 0.f))};
State::State(RWGame *game) : game(game) {
}
void State::draw(GameRenderer *r) {
auto& menu = getCurrentMenu();
if (menu) {
menu->draw(r);
}
}
std::optional<Menu> &State::getCurrentMenu() {
refreshMenu();
return menu;
}
void State::handleEvent(const SDL_Event& e) { void State::handleEvent(const SDL_Event& e) {
auto m = getCurrentMenu(); auto& m = getCurrentMenu();
if (!m) return; if (!m) return;
switch (e.type) { switch (e.type) {
@ -52,3 +67,18 @@ GameWorld* State::getWorld() const {
GameWindow& State::getWindow() { GameWindow& State::getWindow() {
return game->getWindow(); return game->getWindow();
} }
bool State::hasExited() const {
return hasExited_;
}
void State::refreshMenu() {
if (nextMenu) {
menu = std::move(nextMenu);
nextMenu = std::nullopt;
}
}
void State::done() {
hasExited_ = true;
}

View File

@ -16,39 +16,25 @@ class StateManager;
class State { class State {
public: public:
std::optional<Menu> menu;
std::optional<Menu> nextMenu;
RWGame* game; RWGame* game;
State(RWGame* game) : game(game) { State(RWGame* game);
}
virtual void enter() = 0; virtual void enter() = 0;
virtual void exit() = 0; virtual void exit() = 0;
virtual void tick(float dt) = 0; virtual void tick(float dt) = 0;
virtual void draw(GameRenderer* r) { virtual void draw(GameRenderer* r);
if (getCurrentMenu()) {
getCurrentMenu()->draw(r);
}
}
virtual ~State() = default; virtual ~State() = default;
template<typename T> template<typename T>
void enterMenu(T&& menu) { void setNextMenu(T&& menu) {
nextMenu = std::forward<T>(menu); nextMenu = std::forward<T>(menu);
} }
Menu* getCurrentMenu() { std::optional<Menu>& getCurrentMenu();
if (nextMenu) {
menu = std::move(nextMenu);
nextMenu = std::nullopt;
}
return &*menu;
}
virtual void handleEvent(const SDL_Event& e); virtual void handleEvent(const SDL_Event& e);
@ -63,17 +49,18 @@ public:
GameWorld* getWorld() const; GameWorld* getWorld() const;
GameWindow& getWindow(); GameWindow& getWindow();
bool hasExited() const { bool hasExited() const;
return hasexited_;
}
private: private:
bool hasexited_ = false; bool hasExited_ = false;
void refreshMenu();
protected: protected:
void done() { std::optional<Menu> menu;
hasexited_ = true; std::optional<Menu> nextMenu;
}
void done();
}; };
#endif #endif

View File

@ -33,13 +33,13 @@ static void jumpCharacter(RWGame* game, CharacterObject* player,
} }
} }
std::optional<Menu> DebugState::createDebugMenu() { Menu DebugState::createDebugMenu() {
CharacterObject* player = nullptr; CharacterObject* player = nullptr;
if (game->getWorld()->getPlayer()) { if (game->getWorld()->getPlayer()) {
player = game->getWorld()->getPlayer()->getCharacter(); player = game->getWorld()->getPlayer()->getCharacter();
} }
auto menu = Menu::create( Menu menu{
{{"Jump to Debug Camera", {{"Jump to Debug Camera",
[=] { [=] {
jumpCharacter(game, player, jumpCharacter(game, player,
@ -47,12 +47,12 @@ std::optional<Menu> DebugState::createDebugMenu() {
_debugCam.rotation * glm::vec3(3.f, 0.f, 0.f), _debugCam.rotation * glm::vec3(3.f, 0.f, 0.f),
false); false);
}}, }},
{"-Map", [=] { this->enterMenu(createMapMenu()); }}, {"-Map", [=] { setNextMenu(createMapMenu()); }},
{"-Vehicles", [=] { this->enterMenu(createVehicleMenu()); }}, {"-Vehicles", [=] { setNextMenu(createVehicleMenu()); }},
{"-AI", [=] { this->enterMenu(createAIMenu()); }}, {"-AI", [=] { setNextMenu(createAIMenu()); }},
{"-Weapons", [=] { this->enterMenu(createWeaponMenu()); }}, {"-Weapons", [=] { setNextMenu(createWeaponMenu()); }},
{"-Weather", [=] { this->enterMenu(createWeatherMenu()); }}, {"-Weather", [=] { setNextMenu(createWeatherMenu()); }},
{"-Missions", [=] { this->enterMenu(createMissionsMenu()); }}, {"-Missions", [=] { setNextMenu(createMissionsMenu()); }},
{"Set Super Jump", [=] { player->setJumpSpeed(20.f); }}, {"Set Super Jump", [=] { player->setJumpSpeed(20.f); }},
{"Set Normal Jump", {"Set Normal Jump",
[=] { player->setJumpSpeed(CharacterObject::DefaultJumpSpeed); }}, [=] { player->setJumpSpeed(CharacterObject::DefaultJumpSpeed); }},
@ -60,14 +60,14 @@ std::optional<Menu> DebugState::createDebugMenu() {
{"Full Armour", [=] { player->getCurrentState().armour = 100.f; }}, {"Full Armour", [=] { player->getCurrentState().armour = 100.f; }},
{"Cull Here", {"Cull Here",
[=] { game->getRenderer().setCullOverride(true, _debugCam); }}}, [=] { game->getRenderer().setCullOverride(true, _debugCam); }}},
kDebugFont, kDebugEntryHeight); kDebugMenuOffset,
kDebugFont,
menu->offset = kDebugMenuOffset; kDebugEntryHeight};
// Optional block if the player is in a vehicle // Optional block if the player is in a vehicle
auto cv = player->getCurrentVehicle(); auto cv = player->getCurrentVehicle();
if (cv) { if (cv) {
menu->lambda("Flip vehicle", [=] { menu.lambda("Flip vehicle", [=] {
cv->setRotation(cv->getRotation() * cv->setRotation(cv->getRotation() *
glm::quat(glm::vec3(0.f, glm::pi<float>(), 0.f))); glm::quat(glm::vec3(0.f, glm::pi<float>(), 0.f)));
}); });
@ -76,14 +76,14 @@ std::optional<Menu> DebugState::createDebugMenu() {
return menu; return menu;
} }
std::optional<Menu> DebugState::createMapMenu() { Menu DebugState::createMapMenu() {
CharacterObject* player = nullptr; CharacterObject* player = nullptr;
if (game->getWorld()->getPlayer()) { if (game->getWorld()->getPlayer()) {
player = game->getWorld()->getPlayer()->getCharacter(); player = game->getWorld()->getPlayer()->getCharacter();
} }
auto menu = Menu::create( Menu menu{
{{"Back", [=] { enterMenu(createDebugMenu()); }}, {{"Back", [=] { setNextMenu(createDebugMenu()); }},
{"Jump to Docks", {"Jump to Docks",
[=] { [=] {
jumpCharacter(game, player, glm::vec3(1390.f, -837.f, 100.f)); jumpCharacter(game, player, glm::vec3(1390.f, -837.f, 100.f));
@ -108,24 +108,24 @@ std::optional<Menu> DebugState::createMapMenu() {
}}, }},
{"Unsolid garage doors", {"Unsolid garage doors",
[=] { [=] {
static constexpr std::array<char const*, 33> garageDoorModels{{ static constexpr std::array<char const*, 33> garageDoorModels{
"8ballsuburbandoor", "amcogaragedoor", {"8ballsuburbandoor", "amcogaragedoor",
"bankjobdoor", "bombdoor", "bankjobdoor", "bombdoor",
"crushercrush", "crushertop", "crushercrush", "crushertop",
"door2_garage", "door3_garage", "door2_garage", "door3_garage",
"door4_garage", "door_bombshop", "door4_garage", "door_bombshop",
"door_col_compnd_01", "door_col_compnd_02", "door_col_compnd_01", "door_col_compnd_02",
"door_col_compnd_03", "door_col_compnd_04", "door_col_compnd_03", "door_col_compnd_04",
"door_col_compnd_05", "door_jmsgrage", "door_col_compnd_05", "door_jmsgrage",
"door_sfehousegrge", "double_garage_dr", "door_sfehousegrge", "double_garage_dr",
"impex_door", "impexpsubgrgdoor", "impex_door", "impexpsubgrgdoor",
"ind_plyrwoor", "ind_slidedoor", "ind_plyrwoor", "ind_slidedoor",
"jamesgrge_kb", "leveldoor2", "jamesgrge_kb", "leveldoor2",
"oddjgaragdoor", "plysve_gragedoor", "oddjgaragdoor", "plysve_gragedoor",
"SalvGarage", "shedgaragedoor", "SalvGarage", "shedgaragedoor",
"Sub_sprayshopdoor", "towergaragedoor1", "Sub_sprayshopdoor", "towergaragedoor1",
"towergaragedoor2", "towergaragedoor3", "towergaragedoor2", "towergaragedoor3",
"vheistlocdoor"}}; "vheistlocdoor"}};
auto gw = game->getWorld(); auto gw = game->getWorld();
for (auto& [id, instancePtr] : gw->instancePool.objects) { for (auto& [id, instancePtr] : gw->instancePool.objects) {
@ -138,15 +138,20 @@ std::optional<Menu> DebugState::createMapMenu() {
} }
} }
}}}, }}},
kDebugFont, kDebugEntryHeight); kDebugMenuOffset,
kDebugFont,
kDebugEntryHeight};
menu->offset = kDebugMenuOffset;
return menu; return menu;
} }
std::optional<Menu> DebugState::createVehicleMenu() { Menu DebugState::createVehicleMenu() {
auto menu = Menu::create({{"Back", [=] { enterMenu(createDebugMenu()); }}}, Menu menu{
kDebugFont, kDebugEntryHeight); {{"Back", [=] { setNextMenu(createDebugMenu()); }}},
kDebugMenuOffset,
kDebugFont,
kDebugEntryHeight,
};
static constexpr std::array<std::tuple<char const*, unsigned int>, 19> static constexpr std::array<std::tuple<char const*, unsigned int>, 19>
kVehicleTypes{{{"Landstalker", 90}, kVehicleTypes{{{"Landstalker", 90},
@ -170,17 +175,17 @@ std::optional<Menu> DebugState::createVehicleMenu() {
{"Infernus", 101}}}; {"Infernus", 101}}};
for (const auto& [name, id] : kVehicleTypes) { for (const auto& [name, id] : kVehicleTypes) {
menu->lambda(name, [this, id = id] { spawnVehicle(id); }); menu.lambda(name, [this, id = id] { spawnVehicle(id); });
} }
menu->offset = kDebugMenuOffset;
return menu; return menu;
} }
std::optional<Menu> DebugState::createAIMenu() { Menu DebugState::createAIMenu() {
auto menu = Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
Menu::create({{"Back", [=] { this->enterMenu(createDebugMenu()); }}}, kDebugMenuOffset,
kDebugFont, kDebugEntryHeight); kDebugFont,
kDebugEntryHeight};
static constexpr std::array<std::tuple<char const*, unsigned int>, 6> static constexpr std::array<std::tuple<char const*, unsigned int>, 6>
kPedTypes{{ kPedTypes{{
@ -193,10 +198,10 @@ std::optional<Menu> DebugState::createAIMenu() {
}}; }};
for (const auto& [name, id] : kPedTypes) { for (const auto& [name, id] : kPedTypes) {
menu->lambda(name, [this, id = id] { spawnFollower(id); }); menu.lambda(name, [this, id = id] { spawnFollower(id); });
} }
menu->lambda("Kill All Peds", [=] { menu.lambda("Kill All Peds", [=] {
for (auto& [id, pedestrianPtr] : for (auto& [id, pedestrianPtr] :
game->getWorld()->pedestrianPool.objects) { game->getWorld()->pedestrianPool.objects) {
if (pedestrianPtr->getLifetime() == GameObject::PlayerLifetime) { if (pedestrianPtr->getLifetime() == GameObject::PlayerLifetime) {
@ -208,44 +213,44 @@ std::optional<Menu> DebugState::createAIMenu() {
} }
}); });
menu->offset = kDebugMenuOffset;
return menu; return menu;
} }
std::optional<Menu> DebugState::createWeaponMenu() { Menu DebugState::createWeaponMenu() {
auto menu = Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
Menu::create({{"Back", [=] { this->enterMenu(createDebugMenu()); }}}, kDebugMenuOffset,
kDebugFont, kDebugEntryHeight); kDebugFont,
kDebugEntryHeight};
for (int i = 1; i < kMaxInventorySlots; ++i) { for (int i = 1; i < kMaxInventorySlots; ++i) {
auto& name = getWorld()->data->weaponData[i].name; auto& name = getWorld()->data->weaponData[i].name;
menu->lambda(name, [=] { giveItem(i); }); menu.lambda(name, [=] { giveItem(i); });
} }
menu->offset = kDebugMenuOffset;
return menu; return menu;
} }
std::optional<Menu> DebugState::createWeatherMenu() { Menu DebugState::createWeatherMenu() {
auto menu = Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
Menu::create({{"Back", [=] { this->enterMenu(createDebugMenu()); }}}, kDebugMenuOffset,
kDebugFont, kDebugEntryHeight); kDebugFont,
kDebugEntryHeight};
static constexpr std::array<char const*, 4> w{{"Sunny", "Cloudy", "Rainy", "Foggy"}}; static constexpr std::array<char const*, 4> w{{"Sunny", "Cloudy", "Rainy", "Foggy"}};
for (std::size_t i = 0; i < w.size(); ++i) { for (std::size_t i = 0; i < w.size(); ++i) {
menu->lambda(w[i], menu.lambda(w[i],
[=] { game->getWorld()->state->basic.nextWeather = static_cast<std::uint16_t>(i); }); [=] { game->getWorld()->state->basic.nextWeather = static_cast<std::uint16_t>(i); });
} }
menu->offset = kDebugMenuOffset;
return menu; return menu;
} }
std::optional<Menu> DebugState::createMissionsMenu() { Menu DebugState::createMissionsMenu() {
auto menu = Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
Menu::create({{"Back", [=] { this->enterMenu(createDebugMenu()); }}}, kDebugMenuOffset,
kDebugFont, kDebugEntryHeightMissions); kDebugFont,
kDebugEntryHeightMissions};
static constexpr std::array<char const*, 80> w{{ static constexpr std::array<char const*, 80> w{{
"Intro Movie", "Intro Movie",
@ -331,7 +336,7 @@ std::optional<Menu> DebugState::createMissionsMenu() {
}}; }};
for (std::size_t i = 0; i < w.size(); ++i) { for (std::size_t i = 0; i < w.size(); ++i) {
menu->lambda(w[i], [=] { menu.lambda(w[i], [=] {
ScriptMachine* vm = game->getScriptVM(); ScriptMachine* vm = game->getScriptVM();
if (vm) { if (vm) {
@ -356,13 +361,12 @@ std::optional<Menu> DebugState::createMissionsMenu() {
}); });
} }
menu->offset = kDebugMenuOffset;
return menu; return menu;
} }
DebugState::DebugState(RWGame* game, const glm::vec3& vp, const glm::quat& vd) DebugState::DebugState(RWGame* game, const glm::vec3& vp, const glm::quat& vd)
: State(game), _invertedY(game->getConfig().getInputInvertY()) { : State(game), _invertedY(game->getConfig().getInputInvertY()) {
this->enterMenu(createDebugMenu()); this->setNextMenu(createDebugMenu());
_debugCam.position = vp; _debugCam.position = vp;
_debugCam.rotation = vd; _debugCam.rotation = vd;

View File

@ -11,13 +11,13 @@ class DebugState final : public State {
bool _sonicMode = false; bool _sonicMode = false;
bool _invertedY; bool _invertedY;
std::optional<Menu> createDebugMenu(); Menu createDebugMenu();
std::optional<Menu> createMapMenu(); Menu createMapMenu();
std::optional<Menu> createVehicleMenu(); Menu createVehicleMenu();
std::optional<Menu> createAIMenu(); Menu createAIMenu();
std::optional<Menu> createWeaponMenu(); Menu createWeaponMenu();
std::optional<Menu> createWeatherMenu(); Menu createWeatherMenu();
std::optional<Menu> createMissionsMenu(); Menu createMissionsMenu();
public: public:
DebugState(RWGame* game, const glm::vec3& vp = {}, DebugState(RWGame* game, const glm::vec3& vp = {},

View File

@ -13,7 +13,7 @@ MenuState::MenuState(RWGame* game) : State(game) {
void MenuState::enterMainMenu() { void MenuState::enterMainMenu() {
auto& t = game->getGameData().texts; auto& t = game->getGameData().texts;
auto menu = Menu::create( Menu menu{
{{t.text(MenuDefaults::kStartGameId), {{t.text(MenuDefaults::kStartGameId),
[=] { StateManager::get().enter<IngameState>(game); }}, [=] { StateManager::get().enter<IngameState>(game); }},
{t.text(MenuDefaults::kLoadGameId), [=] { enterLoadMenu(); }}, {t.text(MenuDefaults::kLoadGameId), [=] { enterLoadMenu(); }},
@ -22,14 +22,14 @@ void MenuState::enterMainMenu() {
{t.text(MenuDefaults::kOptionsId), {t.text(MenuDefaults::kOptionsId),
[] { RW_UNIMPLEMENTED("Options Menu"); }}, [] { RW_UNIMPLEMENTED("Options Menu"); }},
{t.text(MenuDefaults::kQuitGameId), {t.text(MenuDefaults::kQuitGameId),
[] { StateManager::get().clear(); }}}); [] { StateManager::get().clear(); }}},
menu->offset = glm::vec2(200.f, 200.f); glm::vec2(200.f, 200.f)};
enterMenu(menu); setNextMenu(std::move(menu));
} }
void MenuState::enterLoadMenu() { void MenuState::enterLoadMenu() {
auto menu = Menu::create({{"BACK", [=] { enterMainMenu(); }}}); Menu menu{{{"BACK", [=] { enterMainMenu(); }}}, glm::vec2(20.f, 30.f)};
auto saves = SaveGame::getAllSaveGameInfo(); auto saves = SaveGame::getAllSaveGameInfo();
for (SaveGameInfo& save : saves) { for (SaveGameInfo& save : saves) {
@ -46,14 +46,13 @@ void MenuState::enterLoadMenu() {
StateManager::get().enter<IngameState>(game, false); StateManager::get().enter<IngameState>(game, false);
game->loadGame(save.savePath); game->loadGame(save.savePath);
}; };
menu->lambda(name, loadsave); menu.lambda(name, loadsave);
} else { } else {
menu->lambda("CORRUPT", [=] {}); menu.lambda("CORRUPT", [=] {});
} }
} }
menu->offset = glm::vec2(20.f, 30.f);
enterMenu(menu); setNextMenu(std::move(menu));
} }
void MenuState::enter() { void MenuState::enter() {

View File

@ -6,14 +6,13 @@
PauseState::PauseState(RWGame* game) : State(game) { PauseState::PauseState(RWGame* game) : State(game) {
auto& t = game->getGameData().texts; auto& t = game->getGameData().texts;
auto menu = Menu::create( Menu menu{{{t.text(MenuDefaults::kResumeGameId), [&] { done(); }},
{{t.text(MenuDefaults::kResumeGameId), [&] { done(); }}, {t.text(MenuDefaults::kOptionsId),
{t.text(MenuDefaults::kOptionsId), [] { std::cout << "Options" << std::endl; }},
[] { std::cout << "Options" << std::endl; }}, {t.text(MenuDefaults::kQuitGameId),
{t.text(MenuDefaults::kQuitGameId), [] { StateManager::get().clear(); }}},
[] { StateManager::get().clear(); }}}); glm::vec2(200.f, 200.f)};
menu->offset = glm::vec2(200.f, 200.f); setNextMenu(menu);
enterMenu(menu);
} }
void PauseState::enter() { void PauseState::enter() {

View File

@ -4,79 +4,77 @@
BOOST_AUTO_TEST_SUITE(MenuTests) BOOST_AUTO_TEST_SUITE(MenuTests)
BOOST_AUTO_TEST_CASE(menu_test_click) { BOOST_AUTO_TEST_CASE(menu_test_click) {
bool clickered = false; bool clicked = false;
Menu test({{"Test", [&] { clickered = true; }}}); Menu test({{"Test", [&] { clicked = true; }}});
BOOST_CHECK(!clickered); BOOST_CHECK(!clicked);
// Click underneath the menu item. // Click underneath the menu item.
test.click(0.f, -1.f); test.click(0.f, -1.f);
BOOST_CHECK(!clickered); BOOST_CHECK(!clicked);
float h = 30.f; float h = 30.f;
test.click(0.f, h + 1.f); test.click(0.f, h + 1.f);
BOOST_CHECK(!clickered); BOOST_CHECK(!clicked);
test.click(0.f, h / 2.f); test.click(0.f, h / 2.f);
BOOST_CHECK(clickered); BOOST_CHECK(clicked);
} }
BOOST_AUTO_TEST_CASE(menu_test_click_offset) { BOOST_AUTO_TEST_CASE(menu_test_click_offset) {
bool clickered = false; bool clicked = false;
Menu test({{"Test", [&] { clickered = true; }}}); Menu test({{"Test", [&] { clicked = true; }}}, glm::vec2(200.f, 200.f));
test.offset = glm::vec2(200.f, 200.f); BOOST_CHECK(!clicked);
BOOST_CHECK(!clickered);
// Click underneath the menu item. // Click underneath the menu item.
test.click(201.f, -1.f); test.click(201.f, -1.f);
BOOST_CHECK(!clickered); BOOST_CHECK(!clicked);
float h = 30.f; float h = 30.f;
test.click(201.f, 200.f + h + 1.f); test.click(201.f, 200.f + h + 1.f);
BOOST_CHECK(!clickered); BOOST_CHECK(!clicked);
test.click(201.f, 200.f + h / 2.f); test.click(201.f, 200.f + h / 2.f);
BOOST_CHECK(clickered); BOOST_CHECK(clicked);
} }
BOOST_AUTO_TEST_CASE(menu_test_active_index) { BOOST_AUTO_TEST_CASE(menu_test_active_index) {
int clickindex = -1; int clickIndex = -1;
Menu test({{"Test1", [&] { clickindex = 0; }}, Menu test({{"Test1", [&] { clickIndex = 0; }},
{"Test2", [&] { clickindex = 1; }}}); {"Test2", [&] { clickIndex = 1; }}});
test.activate(); test.activate();
BOOST_CHECK(clickindex == -1); BOOST_CHECK(clickIndex == -1);
test.move(1); test.move(1);
test.activate(); test.activate();
BOOST_CHECK(clickindex == 0); BOOST_CHECK(clickIndex == 0);
test.move(1); test.move(1);
test.activate(); test.activate();
BOOST_CHECK(clickindex == 1); BOOST_CHECK(clickIndex == 1);
test.move(-1); test.move(-1);
test.activate(); test.activate();
BOOST_CHECK(clickindex == 0); BOOST_CHECK(clickIndex == 0);
} }
BOOST_AUTO_TEST_CASE(menu_test_hover_index) { BOOST_AUTO_TEST_CASE(menu_test_hover_index) {
int clickindex = -1; int clickIndex = -1;
Menu test({{"Test1", [&] { clickindex = 0; }}, Menu test({{"Test1", [&] { clickIndex = 0; }},
{"Test2", [&] { clickindex = 1; }}}); {"Test2", [&] { clickIndex = 1; }}});
test.hover(0.f, 30.f - 0.1f); test.hover(0.f, 30.f - 0.1f);
BOOST_CHECK(test.activeEntry == 0); BOOST_CHECK(test.activeEntry == 0);