#ifndef _GAME_MENUSYSTEM_HPP_ #define _GAME_MENUSYSTEM_HPP_ #include #include #include #include #include #include class Menu { int font; public: Menu(int font) : font(font), activeEntry(-1) {} struct MenuEntry { std::string name; float _size; MenuEntry(const std::string& n, float size = 30.f) : name(n), _size(size) { std::transform(name.begin(), name.end(), name.begin(), toupper); } float getHeight() { return _size; } virtual void draw(int font, bool active, GameRenderer* r, glm::vec2& basis) { TextRenderer::TextInfo ti; ti.font = font; ti.screenPosition = basis; ti.text = name; 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(); } virtual void activate(float clickX, float clickY) = 0; }; struct Entry : public MenuEntry { std::function callback; Entry(const std::string& title, std::function cb, float size) : MenuEntry(title, size), callback(cb) {} void activate(float clickX, float clickY) { callback(); } }; static std::shared_ptr lambda(const std::string& n, std::function callback, float size = 30.f) { return std::shared_ptr(new Entry(n, callback, size)); } std::vector> entries; /** * Active Entry index */ int activeEntry; glm::vec2 offset; void addEntry(std::shared_ptr entry) { entries.push_back(entry); } 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; } entries[i]->draw(font, active, r, basis); } } 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) { if( c.y > 0.f && c.y < entries[i]->getHeight() ) { activeEntry = i; return; } else { c.y -= entries[i]->getHeight(); } } } 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) { if( c.y > 0.f && c.y < (*it)->getHeight() ) { (*it)->activate(c.x, c.y); return; } else { c.y -= (*it)->getHeight(); } } } // Activates the menu entry at the current active index. void activate() { if(activeEntry >= 0 && (unsigned) activeEntry < entries.size()) { entries[activeEntry]->activate(0.f, 0.f); } } void move(int movement) { activeEntry = std::min(entries.size()-1, std::max(0, activeEntry + movement)); } }; #endif