mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-18 16:32:32 +02:00
Menu directional movement support
This commit is contained in:
parent
7e418f1b6b
commit
4c595d0439
@ -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()
|
||||||
|
@ -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
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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(); }));
|
||||||
|
Loading…
Reference in New Issue
Block a user