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

Menu directional movement support

This commit is contained in:
Daniel Evans 2014-01-01 00:37:16 +00:00
parent 7e418f1b6b
commit 4c595d0439
4 changed files with 116 additions and 17 deletions

View File

@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(menu_test_click_offset)
bool clickered = false; bool clickered = false;
sf::Font f; sf::Font f;
Menu test(f); Menu test(f);
test.offset = sf::Vector2f(200.f, 200.f); test.offset = glm::vec2(200.f, 200.f);
test.addEntry(Menu::lambda("Test", [&]{ clickered = true; })); test.addEntry(Menu::lambda("Test", [&]{ clickered = true; }));
BOOST_CHECK(! clickered ); BOOST_CHECK(! clickered );
@ -55,4 +55,42 @@ BOOST_AUTO_TEST_CASE(menu_test_click_offset)
BOOST_CHECK( clickered ); BOOST_CHECK( clickered );
} }
BOOST_AUTO_TEST_CASE(menu_test_active_index)
{
int clickindex = -1;
sf::Font f;
Menu test(f);
test.addEntry(Menu::lambda("Test1", [&]{ clickindex = 0; }));
test.addEntry(Menu::lambda("Test2", [&]{ clickindex = 1; }));
test.activate();
BOOST_CHECK( clickindex == 0 );
test.move( 1);
test.activate();
BOOST_CHECK( clickindex == 1 );
test.move(-1);
test.activate();
BOOST_CHECK( clickindex == 0 );
}
BOOST_AUTO_TEST_CASE(menu_test_hover_index)
{
int clickindex = -1;
sf::Font f;
Menu test(f);
test.addEntry(Menu::lambda("Test1", [&]{ clickindex = 0; }));
test.addEntry(Menu::lambda("Test2", [&]{ clickindex = 1; }));
test.hover(0.f, test.entries[0]->getHeight() - 0.1f);
BOOST_CHECK( test.activeEntry == 0 );
test.hover(0.f, test.entries[0]->getHeight() + 0.1f);
BOOST_CHECK( test.activeEntry == 1 );
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -4,6 +4,7 @@
#include <memory> #include <memory>
#include <SFML/Window.hpp> #include <SFML/Window.hpp>
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <glm/glm.hpp>
#include <functional> #include <functional>
class Menu class Menu
@ -12,7 +13,7 @@ class Menu
public: public:
Menu(const sf::Font& font) Menu(const sf::Font& font)
: font(font) {} : font(font), activeEntry(-1) {}
struct MenuEntry struct MenuEntry
{ {
@ -20,19 +21,19 @@ public:
MenuEntry(const std::string& n) : name(n) {} MenuEntry(const std::string& n) : name(n) {}
float getHeight() { return 30.f; } float getHeight() { return 38.f; }
virtual void draw(const sf::Font& font, sf::RenderWindow& window, sf::Vector2f& basis) virtual void draw(const sf::Font& font, sf::RenderWindow& window, glm::vec2& basis)
{ {
sf::Text t; sf::Text t;
t.setFont(font); t.setFont(font);
t.setPosition(basis); t.setPosition(basis.x, basis.y);
t.setString(name); t.setString(name);
window.draw(t); window.draw(t);
basis.y += getHeight(); basis.y += getHeight();
} }
virtual void activate(sf::Vector2f click) = 0; virtual void activate(float clickX, float clickY) = 0;
}; };
struct Entry : public MenuEntry struct Entry : public MenuEntry
@ -42,7 +43,7 @@ public:
Entry(const std::string& title, std::function<void (void)> cb) Entry(const std::string& title, std::function<void (void)> cb)
: MenuEntry(title), callback(cb) {} : MenuEntry(title), callback(cb) {}
void activate(sf::Vector2f click) { callback(); } void activate(float clickX, float clickY) { callback(); }
}; };
static std::shared_ptr<MenuEntry> lambda(const std::string& n, std::function<void (void)> callback) static std::shared_ptr<MenuEntry> lambda(const std::string& n, std::function<void (void)> callback)
@ -52,7 +53,12 @@ public:
std::vector<std::shared_ptr<MenuEntry>> entries; std::vector<std::shared_ptr<MenuEntry>> entries;
sf::Vector2f offset; /**
* Active Entry index
*/
int activeEntry;
glm::vec2 offset;
void addEntry(std::shared_ptr<MenuEntry> entry) void addEntry(std::shared_ptr<MenuEntry> entry)
{ {
@ -61,24 +67,47 @@ public:
void draw(sf::RenderWindow& window) void draw(sf::RenderWindow& window)
{ {
sf::Vector2f basis(offset); glm::vec2 basis(offset);
for(auto it = entries.begin(); for(size_t i = 0;
it != entries.end(); i < entries.size();
++it) ++i)
{ {
(*it)->draw(font, window, basis); if(activeEntry >= 0 && i == activeEntry) {
sf::RectangleShape rs(sf::Vector2f(500.f, entries[i]->getHeight()));
rs.setPosition(basis.x, basis.y);
rs.setFillColor(sf::Color::Cyan);
window.draw(rs);
}
entries[i]->draw(font, window, 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) void click(const float x, const float y)
{ {
sf::Vector2f c(x - offset.x, y - offset.y); glm::vec2 c(x - offset.x, y - offset.y);
for(auto it = entries.begin(); for(auto it = entries.begin();
it != entries.end(); it != entries.end();
++it) ++it)
{ {
if( c.y > 0.f && c.y < (*it)->getHeight() ) { if( c.y > 0.f && c.y < (*it)->getHeight() ) {
(*it)->activate(c); (*it)->activate(c.x, c.y);
return; return;
} }
else { else {
@ -86,6 +115,19 @@ public:
} }
} }
} }
// Activates the menu entry at the current active index.
void activate()
{
if(activeEntry < entries.size()) {
entries[activeEntry]->activate(0.f, 0.f);
}
}
void move(int movement)
{
activeEntry = std::min<const int>(entries.size()-1, std::max<const int>(0, activeEntry + movement));
}
}; };
#endif #endif

View File

@ -38,6 +38,25 @@ struct State
currentMenu->click(e.mouseButton.x, e.mouseButton.y); currentMenu->click(e.mouseButton.x, e.mouseButton.y);
} }
break; break;
case sf::Event::MouseMoved:
if(currentMenu) {
currentMenu->hover(e.mouseMove.x, e.mouseMove.y);
}
break;
case sf::Event::KeyPressed:
if(currentMenu) {
switch(e.key.code) {
case sf::Keyboard::Up:
currentMenu->move(-1);
break;
case sf::Keyboard::Down:
currentMenu->move(1);
break;
case sf::Keyboard::Return:
currentMenu->activate();
break;
}
}
default: break; default: break;
}; };
} }

View File

@ -649,7 +649,7 @@ GenericState pauseState(
[](State* self) [](State* self)
{ {
Menu *m = new Menu(font); Menu *m = new Menu(font);
m->offset = sf::Vector2f(50.f, 100.f); m->offset = glm::vec2(50.f, 100.f);
m->addEntry(Menu::lambda("Continue", [] { StateManager::get().exit(); })); m->addEntry(Menu::lambda("Continue", [] { StateManager::get().exit(); }));
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; })); m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
m->addEntry(Menu::lambda("Exit", [] { window.close(); })); m->addEntry(Menu::lambda("Exit", [] { window.close(); }));
@ -719,7 +719,7 @@ GenericState menuState(
[](State* self) [](State* self)
{ {
Menu *m = new Menu(font); Menu *m = new Menu(font);
m->offset = sf::Vector2f(50.f, 100.f); m->offset = glm::vec2(50.f, 100.f);
m->addEntry(Menu::lambda("Test", [] { StateManager::get().enter(&gameState); })); m->addEntry(Menu::lambda("Test", [] { StateManager::get().enter(&gameState); }));
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; })); m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
m->addEntry(Menu::lambda("Exit", [] { window.close(); })); m->addEntry(Menu::lambda("Exit", [] { window.close(); }));