1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-15 06:52:34 +02:00

Improve Menu system implementation

This commit is contained in:
Daniel Evans 2016-10-18 22:00:53 +01:00
parent 6a7802de87
commit 613d386488
9 changed files with 225 additions and 307 deletions

View File

@ -19,6 +19,9 @@ set(RWGAME_SOURCES
StateManager.cpp StateManager.cpp
State.cpp State.cpp
MenuSystem.hpp
MenuSystem.cpp
states/LoadingState.hpp states/LoadingState.hpp
states/LoadingState.cpp states/LoadingState.cpp
states/IngameState.hpp states/IngameState.hpp

0
rwgame/MenuSystem.cpp Normal file
View File

View File

@ -21,27 +21,35 @@ constexpr const char* kOptionsId = "FET_OPT";
constexpr const char* kQuitGameId = "FET_QG"; constexpr const char* kQuitGameId = "FET_QG";
} }
/**
* @brief Implements user navigable menus
*
* This is a temporary implementation
*/
class Menu { class Menu {
int font;
public: public:
Menu(int font = MenuDefaults::kFont) : font(font), activeEntry(-1) { /**
} * @brief Handles rendering and dispatch of menu items
*/
struct MenuEntry { class MenuEntry {
GameString text; GameString text;
float _size; float size;
std::function<void(void)> callback;
MenuEntry(const GameString& n, float size = 30.f) public:
: text(n), _size(size) { MenuEntry(const std::string& n, std::function<void(void)> cb)
: text(GameStringUtil::fromString(n)), size(30.f), callback(cb) {
}
MenuEntry(const GameString& n, std::function<void(void)> cb,
float size = 30.f)
: text(n), size(size), callback(cb) {
} }
float getHeight() { float getHeight() const {
return _size; return size;
} }
virtual void draw(int font, bool active, GameRenderer* r, void draw(int font, bool active, GameRenderer* r, glm::vec2& basis) {
glm::vec2& basis) {
TextRenderer::TextInfo ti; TextRenderer::TextInfo ti;
ti.font = font; ti.font = font;
ti.screenPosition = basis; ti.screenPosition = basis;
@ -56,16 +64,6 @@ public:
basis.y += getHeight(); basis.y += getHeight();
} }
virtual void activate(float clickX, float clickY) = 0;
};
struct Entry : public MenuEntry {
std::function<void(void)> callback;
Entry(const GameString& title, std::function<void(void)> cb, float size)
: MenuEntry(title, size), callback(cb) {
}
void activate(float clickX, float clickY) { void activate(float clickX, float clickY) {
RW_UNUSED(clickX); RW_UNUSED(clickX);
RW_UNUSED(clickY); RW_UNUSED(clickY);
@ -73,19 +71,28 @@ public:
} }
}; };
static std::shared_ptr<MenuEntry> lambda(const GameString& n, Menu(std::vector<MenuEntry> initial, int font = MenuDefaults::kFont)
std::function<void(void)> callback, : activeEntry(-1), font(font), entries(std::move(initial)) {
float size = 30.f) {
return std::shared_ptr<MenuEntry>(new Entry(n, callback, size));
} }
static std::shared_ptr<MenuEntry> lambda(const std::string& n, /**
std::function<void(void)> callback, * @brief creates a menu from the given menu items
float size = 30.f) { * @return a shared pointer to the menu with the items
return lambda(GameStringUtil::fromString(n), callback, size); */
static std::shared_ptr<Menu> create(std::vector<MenuEntry> items,
int font = MenuDefaults::kFont) {
return std::make_shared<Menu>(std::move(items), font);
} }
std::vector<std::shared_ptr<MenuEntry>> entries; Menu& lambda(const GameString& n, std::function<void()> callback) {
entries.emplace_back(n, callback, 30.f);
return *this;
}
Menu& lambda(const std::string& n, std::function<void(void)> callback) {
entries.emplace_back(GameStringUtil::fromString(n), callback, 30.f);
return *this;
}
/** /**
* Active Entry index * Active Entry index
@ -94,10 +101,6 @@ public:
glm::vec2 offset; glm::vec2 offset;
void addEntry(std::shared_ptr<MenuEntry> entry) {
entries.push_back(entry);
}
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) {
@ -105,18 +108,18 @@ public:
if (activeEntry >= 0 && i == (unsigned)activeEntry) { if (activeEntry >= 0 && i == (unsigned)activeEntry) {
active = true; active = true;
} }
entries[i]->draw(font, active, r, basis); entries[i].draw(font, active, r, basis);
} }
} }
void hover(const float x, const float y) { void hover(const float x, const float y) {
glm::vec2 c(x - offset.x, y - offset.y); glm::vec2 c(x - offset.x, y - offset.y);
for (size_t i = 0; i < entries.size(); ++i) { for (size_t i = 0; i < entries.size(); ++i) {
if (c.y > 0.f && c.y < entries[i]->getHeight()) { if (c.y > 0.f && c.y < entries[i].getHeight()) {
activeEntry = i; activeEntry = i;
return; return;
} else { } else {
c.y -= entries[i]->getHeight(); c.y -= entries[i].getHeight();
} }
} }
} }
@ -124,11 +127,11 @@ public:
void click(const float x, const float y) { void click(const float x, const float y) {
glm::vec2 c(x - offset.x, y - offset.y); glm::vec2 c(x - offset.x, y - offset.y);
for (auto it = entries.begin(); it != entries.end(); ++it) { for (auto it = entries.begin(); it != entries.end(); ++it) {
if (c.y > 0.f && c.y < (*it)->getHeight()) { if (c.y > 0.f && c.y < (*it).getHeight()) {
(*it)->activate(c.x, c.y); (*it).activate(c.x, c.y);
return; return;
} else { } else {
c.y -= (*it)->getHeight(); c.y -= (*it).getHeight();
} }
} }
} }
@ -136,7 +139,7 @@ public:
// Activates the menu entry at the current active index. // Activates the menu entry at the current active index.
void activate() { void activate() {
if (activeEntry >= 0 && (unsigned)activeEntry < entries.size()) { if (activeEntry >= 0 && (unsigned)activeEntry < entries.size()) {
entries[activeEntry]->activate(0.f, 0.f); entries[activeEntry].activate(0.f, 0.f);
} }
} }
@ -148,6 +151,14 @@ public:
activeEntry = entries.size() - 1; activeEntry = entries.size() - 1;
} }
} }
const std::vector<MenuEntry>& getEntries() const {
return entries;
}
private:
int font;
std::vector<MenuEntry> entries;
}; };
#endif #endif

View File

@ -12,13 +12,12 @@ class StateManager;
class State { class State {
public: public:
// Helper for global menu behaviour std::shared_ptr<Menu> menu;
Menu* currentMenu; std::shared_ptr<Menu> nextMenu;
Menu* nextMenu;
RWGame* game; RWGame* game;
State(RWGame* game) : currentMenu(nullptr), nextMenu(nullptr), game(game) { State(RWGame* game) : game(game) {
} }
virtual void enter() = 0; virtual void enter() = 0;
@ -33,24 +32,18 @@ public:
} }
virtual ~State() { virtual ~State() {
if (getCurrentMenu()) {
delete getCurrentMenu();
}
} }
void enterMenu(Menu* menu) { void enterMenu(const std::shared_ptr<Menu>& menu) {
nextMenu = menu; nextMenu = menu;
} }
Menu* getCurrentMenu() { Menu* getCurrentMenu() {
if (nextMenu) { if (nextMenu) {
if (currentMenu) { menu = nextMenu;
delete currentMenu;
}
currentMenu = nextMenu;
nextMenu = nullptr; nextMenu = nullptr;
} }
return currentMenu; return menu.get();
} }
virtual void handleEvent(const SDL_Event& e); virtual void handleEvent(const SDL_Event& e);
@ -72,8 +65,11 @@ public:
private: private:
bool hasexited_ = false; bool hasexited_ = false;
protected: protected:
void done() { hasexited_ = true; } void done() {
hasexited_ = true;
}
}; };
#endif #endif

View File

@ -11,6 +11,7 @@
#include "RWGame.hpp" #include "RWGame.hpp"
constexpr float kDebugEntryHeight = 14.f; constexpr float kDebugEntryHeight = 14.f;
constexpr int kDebugFont = 2;
const glm::vec2 kDebugMenuOffset = glm::vec2(10.f, 50.f); const glm::vec2 kDebugMenuOffset = glm::vec2(10.f, 50.f);
static void jumpCharacter(RWGame* game, CharacterObject* player, static void jumpCharacter(RWGame* game, CharacterObject* player,
@ -29,195 +30,119 @@ static void jumpCharacter(RWGame* game, CharacterObject* player,
} }
} }
Menu* DebugState::createDebugMenu() { std::shared_ptr<Menu> DebugState::createDebugMenu() {
CharacterObject* player = nullptr; CharacterObject* player = nullptr;
if (game->getPlayer()) { if (game->getPlayer()) {
player = game->getPlayer()->getCharacter(); player = game->getPlayer()->getCharacter();
} }
Menu* m = new Menu(2); auto menu = Menu::create(
m->offset = kDebugMenuOffset; {{"Jump to Debug Camera",
#if 0 [=] {
m->addEntry(Menu::lambda("Random Vehicle", [this] { jumpCharacter(game, player,
auto it = getWorld()->vehicleTypes.begin(); _debugCam.position +
std::uniform_int_distribution<int> uniform(0, 3); _debugCam.rotation * glm::vec3(3.f, 0.f, 0.f),
for(size_t i = 0, n = uniform(getWorld()->randomEngine); i != n; i++) { false);
it++; }},
} {"-Map", [=] { this->enterMenu(createMapMenu()); }},
spawnVehicle(it->first); {"-Vehicles", [=] { this->enterMenu(createVehicleMenu()); }},
}, entryHeight)); {"-AI", [=] { this->enterMenu(createAIMenu()); }},
m->addEntry(Menu::lambda("Open All Doors/Flaps", [=] { {"-Weapons", [=] { this->enterMenu(createWeaponMenu()); }},
auto pc = getWorld()->state->player->getCharacter(); {"Set Super Jump", [=] { player->setJumpSpeed(20.f); }},
auto pv = pc->getCurrentVehicle(); {"Set Normal Jump",
if( pv ) { [=] { player->setJumpSpeed(CharacterObject::DefaultJumpSpeed); }},
for(auto& it : pv->_hingedObjects) { {"Full Health", [=] { player->getCurrentState().health = 100.f; }},
pv->setHingeLocked(it.first, false); {"Full Armour", [=] { player->getCurrentState().armour = 100.f; }},
} {"Cull Here",
} [=] { game->getRenderer().setCullOverride(true, _debugCam); }}},
}, entryHeight)); kDebugFont);
m->addEntry(Menu::lambda("Spawn Pedestrians", [=] { menu->offset = kDebugMenuOffset;
glm::vec3 hit, normal;
if(game->hitWorldRay(hit, normal)) {
glm::vec3 spawnPos = hit + glm::vec3(-5, 0.f, 0.0) + normal;
size_t k = 1;
// Spawn every pedestrian.
for(auto it = getWorld()->pedestrianTypes.begin();
it != getWorld()->pedestrianTypes.end(); ++it) {
getWorld()->createPedestrian(it->first, spawnPos);
spawnPos += glm::vec3(2.5, 0, 0);
if((k++ % 6) == 0) { spawnPos += glm::vec3(-15, -2.5, 0); }
}
}
}, entryHeight));
int vehiclesMax = 16, i = 0;
for( auto& v : getWorld()->vehicleTypes ) {
if( (i++) > vehiclesMax ) break;
m->addEntry(Menu::lambda(v.second->handlingID, [=] {
spawnVehicle(v.first);
}, entryHeight));
}
#endif
m->addEntry(Menu::lambda("Jump to Debug Camera",
[=] {
jumpCharacter(game, player,
_debugCam.position +
_debugCam.rotation *
glm::vec3(3.f, 0.f, 0.f),
false);
},
kDebugEntryHeight));
m->addEntry(Menu::lambda("-Map", [=] { this->enterMenu(createMapMenu()); },
kDebugEntryHeight));
m->addEntry(Menu::lambda("-Vehicles",
[=] { this->enterMenu(createVehicleMenu()); },
kDebugEntryHeight));
m->addEntry(Menu::lambda("-AI", [=] { this->enterMenu(createAIMenu()); },
kDebugEntryHeight));
m->addEntry(Menu::lambda("-Weapons",
[=] { this->enterMenu(createWeaponMenu()); },
kDebugEntryHeight));
m->addEntry(Menu::lambda("Set Super Jump",
[=] { player->setJumpSpeed(20.f); },
kDebugEntryHeight));
m->addEntry(Menu::lambda(
"Set Normal Jump",
[=] { player->setJumpSpeed(CharacterObject::DefaultJumpSpeed); },
kDebugEntryHeight));
m->addEntry(Menu::lambda("Full Health",
[=] { player->getCurrentState().health = 100.f; },
kDebugEntryHeight));
m->addEntry(Menu::lambda("Full Armour",
[=] { player->getCurrentState().armour = 100.f; },
kDebugEntryHeight));
m->addEntry(Menu::lambda(
"Cull Here",
[=] { game->getRenderer().setCullOverride(true, _debugCam); },
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) {
m->addEntry(Menu::lambda( menu->lambda("Flip vehicle", [=] {
"Flip vehicle", cv->setRotation(cv->getRotation() *
[=] { glm::quat(glm::vec3(0.f, glm::pi<float>(), 0.f)));
cv->setRotation( });
cv->getRotation() *
glm::quat(glm::vec3(0.f, glm::pi<float>(), 0.f)));
},
kDebugEntryHeight));
} }
return m; return menu;
} }
Menu* DebugState::createMapMenu() { std::shared_ptr<Menu> DebugState::createMapMenu() {
CharacterObject* player = nullptr; CharacterObject* player = nullptr;
if (game->getPlayer()) { if (game->getPlayer()) {
player = game->getPlayer()->getCharacter(); player = game->getPlayer()->getCharacter();
} }
Menu* m = new Menu(2); auto menu = Menu::create(
m->offset = kDebugMenuOffset; {{"Back", [=] { enterMenu(createDebugMenu()); }},
{"Jump to Docks",
[=] {
jumpCharacter(game, player, glm::vec3(1390.f, -837.f, 100.f));
}},
{"Jump to Garage",
[=] { jumpCharacter(game, player, glm::vec3(270.f, -605.f, 40.f)); }},
{"Jump to Airport",
[=] {
jumpCharacter(game, player, glm::vec3(-950.f, -980.f, 12.f));
}},
{"Jump to Hideout",
[=] {
jumpCharacter(game, player, glm::vec3(875.0, -309.0, 100.0));
}},
{"Jump to Luigi's",
[=] {
jumpCharacter(game, player, glm::vec3(902.75, -425.56, 100.0));
}},
{"Jump to Hospital",
[=] {
jumpCharacter(game, player, glm::vec3(1123.77, -569.15, 100.0));
}},
{"Unsolid garage doors",
[=] {
m->addEntry(Menu::lambda("Back", std::vector<std::string> garageDoorModels{
[=] { this->enterMenu(createDebugMenu()); }, "8ballsuburbandoor", "amcogaragedoor",
kDebugEntryHeight)); "bankjobdoor", "bombdoor",
"crushercrush", "crushertop",
"door2_garage", "door3_garage",
"door4_garage", "door_bombshop",
"door_col_compnd_01", "door_col_compnd_02",
"door_col_compnd_03", "door_col_compnd_04",
"door_col_compnd_05", "door_jmsgrage",
"door_sfehousegrge", "double_garage_dr",
"impex_door", "impexpsubgrgdoor",
"ind_plyrwoor", "ind_slidedoor",
"jamesgrge_kb", "leveldoor2",
"oddjgaragdoor", "plysve_gragedoor",
"SalvGarage", "shedgaragedoor",
"Sub_sprayshopdoor", "towergaragedoor1",
"towergaragedoor2", "towergaragedoor3",
"vheistlocdoor"};
m->addEntry(Menu::lambda( auto gw = game->getWorld();
"Jump to Docks", for (auto& i : gw->instancePool.objects) {
[=] { jumpCharacter(game, player, glm::vec3(1390.f, -837.f, 100.f)); }, auto obj = static_cast<InstanceObject*>(i.second);
kDebugEntryHeight)); if (std::find(garageDoorModels.begin(),
m->addEntry(Menu::lambda( garageDoorModels.end(),
"Jump to Garage", obj->getModelInfo<BaseModelInfo>()->name) !=
[=] { jumpCharacter(game, player, glm::vec3(270.f, -605.f, 40.f)); }, garageDoorModels.end()) {
kDebugEntryHeight)); obj->setSolid(false);
m->addEntry(Menu::lambda( }
"Jump to Airport", }
[=] { jumpCharacter(game, player, glm::vec3(-950.f, -980.f, 12.f)); }, }}},
kDebugEntryHeight)); kDebugFont);
m->addEntry(Menu::lambda(
"Jump to Hideout",
[=] { jumpCharacter(game, player, glm::vec3(875.0, -309.0, 100.0)); },
kDebugEntryHeight));
m->addEntry(Menu::lambda(
"Jump to Luigi's",
[=] { jumpCharacter(game, player, glm::vec3(902.75, -425.56, 100.0)); },
kDebugEntryHeight));
m->addEntry(Menu::lambda(
"Jump to Hospital",
[=] {
jumpCharacter(game, player, glm::vec3(1123.77, -569.15, 100.0));
},
kDebugEntryHeight));
m->addEntry(Menu::lambda(
"Unsolid garage doors",
[=] {
std::vector<std::string> garageDoorModels{ menu->offset = kDebugMenuOffset;
"8ballsuburbandoor", "amcogaragedoor", return menu;
"bankjobdoor", "bombdoor",
"crushercrush", "crushertop",
"door2_garage", "door3_garage",
"door4_garage", "door_bombshop",
"door_col_compnd_01", "door_col_compnd_02",
"door_col_compnd_03", "door_col_compnd_04",
"door_col_compnd_05", "door_jmsgrage",
"door_sfehousegrge", "double_garage_dr",
"impex_door", "impexpsubgrgdoor",
"ind_plyrwoor", "ind_slidedoor",
"jamesgrge_kb", "leveldoor2",
"oddjgaragdoor", "plysve_gragedoor",
"SalvGarage", "shedgaragedoor",
"Sub_sprayshopdoor", "towergaragedoor1",
"towergaragedoor2", "towergaragedoor3",
"vheistlocdoor"};
auto gw = game->getWorld();
for (auto& i : gw->instancePool.objects) {
auto obj = static_cast<InstanceObject*>(i.second);
if (std::find(garageDoorModels.begin(), garageDoorModels.end(),
obj->getModelInfo<BaseModelInfo>()->name) !=
garageDoorModels.end()) {
obj->setSolid(false);
}
}
},
kDebugEntryHeight));
return m;
} }
Menu* DebugState::createVehicleMenu() { std::shared_ptr<Menu> DebugState::createVehicleMenu() {
Menu* m = new Menu(2); auto menu = Menu::create({{"Back", [=] { enterMenu(createDebugMenu()); }}},
m->offset = kDebugMenuOffset; kDebugFont);
m->addEntry(Menu::lambda("Back",
[=] { this->enterMenu(createDebugMenu()); },
kDebugEntryHeight));
const std::map<std::string, int> kVehicleTypes = { const std::map<std::string, int> kVehicleTypes = {
{"Landstalker", 90}, {"Taxi", 110}, {"Firetruck", 97}, {"Landstalker", 90}, {"Taxi", 110}, {"Firetruck", 97},
@ -228,20 +153,16 @@ Menu* DebugState::createVehicleMenu() {
}; };
for (auto& e : kVehicleTypes) { for (auto& e : kVehicleTypes) {
m->addEntry(Menu::lambda(e.first, [=] { spawnVehicle(e.second); }, menu->lambda(e.first, [=] { spawnVehicle(e.second); });
kDebugEntryHeight));
} }
return m; menu->offset = kDebugMenuOffset;
return menu;
} }
Menu* DebugState::createAIMenu() { std::shared_ptr<Menu> DebugState::createAIMenu() {
Menu* m = new Menu(2); auto menu = Menu::create(
m->offset = kDebugMenuOffset; {{"Back", [=] { this->enterMenu(createDebugMenu()); }}}, kDebugFont);
m->addEntry(Menu::lambda("Back",
[=] { this->enterMenu(createDebugMenu()); },
kDebugEntryHeight));
const std::map<std::string, int> kPedTypes = { const std::map<std::string, int> kPedTypes = {
{"Triad", 12}, {"Cop", 1}, {"SWAT", 2}, {"Triad", 12}, {"Cop", 1}, {"SWAT", 2},
@ -249,42 +170,35 @@ Menu* DebugState::createAIMenu() {
}; };
for (auto& e : kPedTypes) { for (auto& e : kPedTypes) {
m->addEntry(Menu::lambda(e.first + " Follower", menu->lambda(e.first + " Follower", [=] { spawnFollower(e.second); });
[=] { spawnFollower(e.second); },
kDebugEntryHeight));
} }
m->addEntry(Menu::lambda( menu->lambda("Kill All Peds", [=] {
"Kill All Peds", for (auto& p : game->getWorld()->pedestrianPool.objects) {
[=] { if (p.second->getLifetime() == GameObject::PlayerLifetime) {
for (auto& p : game->getWorld()->pedestrianPool.objects) { continue;
if (p.second->getLifetime() == GameObject::PlayerLifetime) {
continue;
}
p.second->takeDamage({p.second->getPosition(),
p.second->getPosition(), 100.f,
GameObject::DamageInfo::Explosion, 0.f});
} }
}, p.second->takeDamage({p.second->getPosition(),
kDebugEntryHeight)); p.second->getPosition(), 100.f,
return m; GameObject::DamageInfo::Explosion, 0.f});
}
});
menu->offset = kDebugMenuOffset;
return menu;
} }
Menu* DebugState::createWeaponMenu() { std::shared_ptr<Menu> DebugState::createWeaponMenu() {
Menu* m = new Menu(2); auto menu = Menu::create(
m->offset = kDebugMenuOffset; {{"Back", [=] { this->enterMenu(createDebugMenu()); }}}, kDebugFont);
m->addEntry(Menu::lambda("Back",
[=] { this->enterMenu(createDebugMenu()); },
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;
m->addEntry( menu->lambda(name, [=] { giveItem(i); });
Menu::lambda(name, [=] { giveItem(i); }, kDebugEntryHeight));
} }
return m; menu->offset = kDebugMenuOffset;
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)

View File

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

View File

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

View File

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

View File

@ -6,8 +6,7 @@ BOOST_AUTO_TEST_SUITE(MenuUnitTests)
BOOST_AUTO_TEST_CASE(menu_test_click) { BOOST_AUTO_TEST_CASE(menu_test_click) {
bool clickered = false; bool clickered = false;
Menu test(0); Menu test({{"Test", [&] { clickered = true; }}});
test.addEntry(Menu::lambda("Test", [&] { clickered = true; }));
BOOST_CHECK(!clickered); BOOST_CHECK(!clickered);
@ -16,7 +15,7 @@ BOOST_AUTO_TEST_CASE(menu_test_click) {
BOOST_CHECK(!clickered); BOOST_CHECK(!clickered);
float h = test.entries.at(0)->getHeight(); float h = test.getEntries().at(0).getHeight();
test.click(0.f, h + 1.f); test.click(0.f, h + 1.f);
@ -29,9 +28,8 @@ BOOST_AUTO_TEST_CASE(menu_test_click) {
BOOST_AUTO_TEST_CASE(menu_test_click_offset) { BOOST_AUTO_TEST_CASE(menu_test_click_offset) {
bool clickered = false; bool clickered = false;
Menu test(0); Menu test({{"Test", [&] { clickered = true; }}});
test.offset = glm::vec2(200.f, 200.f); test.offset = glm::vec2(200.f, 200.f);
test.addEntry(Menu::lambda("Test", [&] { clickered = true; }));
BOOST_CHECK(!clickered); BOOST_CHECK(!clickered);
@ -40,7 +38,7 @@ BOOST_AUTO_TEST_CASE(menu_test_click_offset) {
BOOST_CHECK(!clickered); BOOST_CHECK(!clickered);
float h = test.entries.at(0)->getHeight(); float h = test.getEntries().at(0).getHeight();
test.click(201.f, 200.f + h + 1.f); test.click(201.f, 200.f + h + 1.f);
@ -53,9 +51,8 @@ BOOST_AUTO_TEST_CASE(menu_test_click_offset) {
BOOST_AUTO_TEST_CASE(menu_test_active_index) { BOOST_AUTO_TEST_CASE(menu_test_active_index) {
int clickindex = -1; int clickindex = -1;
Menu test(0); Menu test({{"Test1", [&] { clickindex = 0; }},
test.addEntry(Menu::lambda("Test1", [&] { clickindex = 0; })); {"Test2", [&] { clickindex = 1; }}});
test.addEntry(Menu::lambda("Test2", [&] { clickindex = 1; }));
test.activate(); test.activate();
@ -79,14 +76,13 @@ BOOST_AUTO_TEST_CASE(menu_test_active_index) {
BOOST_AUTO_TEST_CASE(menu_test_hover_index) { BOOST_AUTO_TEST_CASE(menu_test_hover_index) {
int clickindex = -1; int clickindex = -1;
Menu test(0); Menu test({{"Test1", [&] { clickindex = 0; }},
test.addEntry(Menu::lambda("Test1", [&] { clickindex = 0; })); {"Test2", [&] { clickindex = 1; }}});
test.addEntry(Menu::lambda("Test2", [&] { clickindex = 1; }));
test.hover(0.f, test.entries[0]->getHeight() - 0.1f); test.hover(0.f, test.getEntries()[0].getHeight() - 0.1f);
BOOST_CHECK(test.activeEntry == 0); BOOST_CHECK(test.activeEntry == 0);
test.hover(0.f, test.entries[0]->getHeight() + 0.1f); test.hover(0.f, test.getEntries()[0].getHeight() + 0.1f);
BOOST_CHECK(test.activeEntry == 1); BOOST_CHECK(test.activeEntry == 1);
} }