1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 03:12:36 +01:00
openrw/rwgame/MenuSystem.hpp

165 lines
4.5 KiB
C++
Raw Normal View History

2013-12-25 20:54:22 +01:00
#ifndef _GAME_MENUSYSTEM_HPP_
#define _GAME_MENUSYSTEM_HPP_
2016-09-09 22:13:20 +02:00
#include <algorithm>
#include <functional>
2014-01-01 01:37:16 +01:00
#include <glm/glm.hpp>
2016-09-09 22:13:20 +02:00
#include <memory>
2015-02-07 23:55:06 +01:00
#include <render/GameRenderer.hpp>
2016-09-09 22:13:20 +02:00
#include <string>
2013-12-25 20:54:22 +01:00
/**
* Default values for menus that should match the look and feel of the original
*/
2016-09-09 22:13:20 +02:00
namespace MenuDefaults {
constexpr int kFont = 1;
constexpr const char* kStartGameId = "FET_SAN";
constexpr const char* kResumeGameId = "FEM_RES";
constexpr const char* kLoadGameId = "FET_LG";
constexpr const char* kDebugId = "FEM_DBG";
constexpr const char* kOptionsId = "FET_OPT";
constexpr const char* kQuitGameId = "FET_QG";
}
2016-10-18 23:00:53 +02:00
/**
* @brief Implements user navigable menus
*
* This is a temporary implementation
*/
2016-09-09 22:13:20 +02:00
class Menu {
2013-12-25 20:54:22 +01:00
public:
2016-10-18 23:00:53 +02:00
/**
* @brief Handles rendering and dispatch of menu items
*/
class MenuEntry {
2016-09-09 22:13:20 +02:00
GameString text;
2016-10-18 23:00:53 +02:00
float size;
std::function<void(void)> callback;
2016-09-09 22:13:20 +02:00
2016-10-18 23:00:53 +02:00
public:
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) {
2016-09-09 22:13:20 +02:00
}
2016-10-18 23:00:53 +02:00
float getHeight() const {
return size;
2016-09-09 22:13:20 +02:00
}
2016-10-18 23:00:53 +02:00
void draw(int font, bool active, GameRenderer* r, glm::vec2& basis) {
2016-09-09 22:13:20 +02:00
TextRenderer::TextInfo ti;
ti.font = font;
ti.screenPosition = basis;
ti.text = text;
ti.size = getHeight();
if (!active) {
ti.baseColour = glm::u8vec3(255);
} else {
ti.baseColour = glm::u8vec3(255, 255, 0);
}
r->text.renderText(ti);
basis.y += getHeight();
}
void activate(float clickX, float clickY) {
RW_UNUSED(clickX);
RW_UNUSED(clickY);
callback();
}
};
2016-10-18 23:00:53 +02:00
Menu(std::vector<MenuEntry> initial, int font = MenuDefaults::kFont)
: activeEntry(-1), font(font), entries(std::move(initial)) {
2016-09-09 22:13:20 +02:00
}
2016-10-18 23:00:53 +02:00
/**
* @brief creates a menu from the given menu items
* @return a shared pointer to the menu with the items
*/
static std::shared_ptr<Menu> create(std::vector<MenuEntry> items,
int font = MenuDefaults::kFont) {
return std::make_shared<Menu>(std::move(items), font);
2016-09-09 22:13:20 +02:00
}
2016-10-18 23:00:53 +02:00
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;
}
2016-09-09 22:13:20 +02:00
/**
* Active Entry index
*/
int activeEntry;
glm::vec2 offset;
void draw(GameRenderer* r) {
glm::vec2 basis(offset);
for (size_t i = 0; i < entries.size(); ++i) {
bool active = false;
if (activeEntry >= 0 && i == (unsigned)activeEntry) {
active = true;
}
2016-10-18 23:00:53 +02:00
entries[i].draw(font, active, r, basis);
2016-09-09 22:13:20 +02:00
}
}
void hover(const float x, const float y) {
glm::vec2 c(x - offset.x, y - offset.y);
for (size_t i = 0; i < entries.size(); ++i) {
2016-10-18 23:00:53 +02:00
if (c.y > 0.f && c.y < entries[i].getHeight()) {
2016-09-09 22:13:20 +02:00
activeEntry = i;
return;
} else {
2016-10-18 23:00:53 +02:00
c.y -= entries[i].getHeight();
2016-09-09 22:13:20 +02:00
}
}
}
void click(const float x, const float y) {
glm::vec2 c(x - offset.x, y - offset.y);
for (auto it = entries.begin(); it != entries.end(); ++it) {
2016-10-18 23:00:53 +02:00
if (c.y > 0.f && c.y < (*it).getHeight()) {
(*it).activate(c.x, c.y);
2016-09-09 22:13:20 +02:00
return;
} else {
2016-10-18 23:00:53 +02:00
c.y -= (*it).getHeight();
2016-09-09 22:13:20 +02:00
}
}
}
// Activates the menu entry at the current active index.
void activate() {
if (activeEntry >= 0 && (unsigned)activeEntry < entries.size()) {
2016-10-18 23:00:53 +02:00
entries[activeEntry].activate(0.f, 0.f);
2016-09-09 22:13:20 +02:00
}
}
void move(int movement) {
activeEntry += movement;
if (activeEntry >= int(entries.size())) {
activeEntry = 0;
} else if (activeEntry < 0) {
activeEntry = entries.size() - 1;
}
}
2016-10-18 23:00:53 +02:00
const std::vector<MenuEntry>& getEntries() const {
return entries;
}
private:
int font;
std::vector<MenuEntry> entries;
2013-12-25 20:54:22 +01:00
};
2014-06-01 19:26:53 +02:00
#endif