Implement test drop menu and wrap up menu bar system
This commit is contained in:
parent
be0367bba0
commit
37391cfdfd
|
@ -27,7 +27,8 @@ private:
|
|||
std::shared_ptr<Game> _game;
|
||||
|
||||
void exec();
|
||||
void emplaceState(GUIState::Tag new_state);
|
||||
void pushState(GUIState::Tag new_state);
|
||||
void popState();
|
||||
};
|
||||
|
||||
#endif // APPLICATION_H
|
||||
|
|
|
@ -23,11 +23,12 @@ Application::Application() :
|
|||
_game_window.setMouseCursorGrabbed(false);
|
||||
_game_window.setVerticalSyncEnabled(true);
|
||||
|
||||
MainMenu::Callbacks callbacks = {[&](){ emplaceState(GUIState::Tag::EDITOR); }};
|
||||
MainMenu::Callbacks callbacks = {[&](){ pushState(GUIState::Tag::EDITOR); }};
|
||||
Editor::Callbacks editor_callbacks = {[&](){ popState(); }};
|
||||
|
||||
const auto main_menu = std::make_shared<MainMenu>(_game_window, std::move(callbacks));
|
||||
const auto game_state = std::make_shared<GameState>(_game_window, _game, GameState::Callbacks());
|
||||
const auto editor = std::make_shared<Editor>(_game_window, Editor::Callbacks(), std::make_unique<MusicSFML>());
|
||||
const auto editor = std::make_shared<Editor>(_game_window, std::move(editor_callbacks), std::make_unique<MusicSFML>());
|
||||
_states[GUIState::Tag::MAIN_MENU] = main_menu;
|
||||
_states[GUIState::Tag::GAME] = game_state;
|
||||
_states[GUIState::Tag::EDITOR] = editor;
|
||||
|
@ -95,9 +96,16 @@ void Application::draw()
|
|||
_game_window.display();
|
||||
}
|
||||
|
||||
void Application::emplaceState(GUIState::Tag new_state)
|
||||
void Application::pushState(GUIState::Tag new_state)
|
||||
{
|
||||
_state_stack.back()->leave();
|
||||
_state_stack.emplace_back(_states.at(new_state));
|
||||
_state_stack.back()->enter();
|
||||
}
|
||||
|
||||
void Application::popState()
|
||||
{
|
||||
_state_stack.back()->leave();
|
||||
_state_stack.pop_back();
|
||||
_state_stack.back()->enter();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,26 @@ Editor::Editor(sf::RenderWindow& game_window, Callbacks&& callbacks, std::unique
|
|||
const float window_width = game_window.getSize().x;
|
||||
//const float window_height = game_window.getSize().y;
|
||||
|
||||
auto bpm_button = std::make_shared<PushButton>("Calculate BPM");
|
||||
bpm_button->setCallback([&]()
|
||||
{
|
||||
_bpm_calculator->startListening(0);
|
||||
});
|
||||
|
||||
auto quit_button = std::make_shared<PushButton>("Quit");
|
||||
quit_button->setCallback(callbacks.onLeaveEditorState);
|
||||
|
||||
auto test_menu = std::make_shared<MenuDrop>();
|
||||
test_menu->setRect(sf::FloatRect{0, 0, 200, 27});
|
||||
|
||||
_menu_bar->setRect(sf::FloatRect(0, 0, window_width, 27));
|
||||
_menu_bar->addSubMenu("test", test_menu);
|
||||
|
||||
test_menu->addPushButton(bpm_button);
|
||||
test_menu->addPushButton(quit_button);
|
||||
|
||||
_music->openFromFile("Uta-test.flac");
|
||||
_music->setVolume(5);
|
||||
}
|
||||
|
||||
void Editor::input(const sf::Event& event)
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
|
||||
struct Callbacks
|
||||
{
|
||||
std::function<void(void)> onAppendGameState;
|
||||
std::function<void(void)> onLeaveEditorState;
|
||||
};
|
||||
|
||||
explicit Editor(sf::RenderWindow& game_window, Callbacks&& callbacks, std::unique_ptr<Music>&& music);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "mainmenu.h"
|
||||
#include "widgets/button.h"
|
||||
#include "widgets/pushbutton.h"
|
||||
#include "widgets/group.h"
|
||||
|
||||
MainMenu::MainMenu(sf::RenderWindow& game_window, Callbacks&& callbacks) :
|
||||
|
@ -9,11 +9,11 @@ MainMenu::MainMenu(sf::RenderWindow& game_window, Callbacks&& callbacks) :
|
|||
const float window_width = game_window.getSize().x;
|
||||
const float window_height = game_window.getSize().y;
|
||||
|
||||
std::shared_ptr<Button> button_start = std::make_shared<Button>("Start");
|
||||
std::shared_ptr<PushButton> button_start = std::make_shared<PushButton>("Start");
|
||||
button_start->setRect(sf::FloatRect(window_width / 3., window_height / 7. * 2, window_width / 3., window_height / 7.));
|
||||
button_start->setCallback(callbacks.onAppendGameState);
|
||||
|
||||
std::shared_ptr<Button> button_exit = std::make_shared<Button>("Exit");
|
||||
std::shared_ptr<PushButton> button_exit = std::make_shared<PushButton>("Exit");
|
||||
button_exit->setRect(sf::FloatRect(window_width / 3., window_height / 7. * 4, window_width / 3., window_height / 7.));
|
||||
button_exit->setCallback([&]()
|
||||
{
|
||||
|
|
|
@ -14,8 +14,11 @@ void Button::update()
|
|||
|
||||
void Button::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
target.draw(_button_content, states);
|
||||
target.draw(_button_text, states);
|
||||
if (_is_visible)
|
||||
{
|
||||
target.draw(_button_content, states);
|
||||
target.draw(_button_text, states);
|
||||
}
|
||||
|
||||
Widget::draw(target, states);
|
||||
}
|
||||
|
@ -36,11 +39,6 @@ bool Button::isUnderMouse(int mouse_x, int mouse_y) const
|
|||
return _is_visible && _button_content.getGlobalBounds().contains(mouse_x, mouse_y);
|
||||
}
|
||||
|
||||
void Button::setFillColor(sf::Color&& color)
|
||||
{
|
||||
_button_content.setFillColor(std::move(color));
|
||||
}
|
||||
|
||||
void Button::setText(const std::string& text)
|
||||
{
|
||||
_button_text.setString(text);
|
||||
|
|
|
@ -13,11 +13,11 @@ public:
|
|||
virtual void input(const sf::Event& event) override = 0;
|
||||
virtual void update() override final;
|
||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override final;
|
||||
virtual void setRect(const sf::FloatRect& rect) override final;
|
||||
virtual void setPosition(const sf::Vector2f& position) override final;
|
||||
virtual bool isUnderMouse(int mouse_x, int mouse_y) const override final;
|
||||
|
||||
virtual void setFillColor(sf::Color&& color);
|
||||
virtual void setRect(const sf::FloatRect& rect) override;
|
||||
|
||||
virtual void setText(const std::string& text);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -7,7 +7,8 @@ CascadeMenuButton::CascadeMenuButton(const std::string& text) :
|
|||
|
||||
void CascadeMenuButton::input(const sf::Event& event)
|
||||
{
|
||||
Button::input(event);
|
||||
if (!_submenu)
|
||||
return;
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
|
@ -29,7 +30,28 @@ void CascadeMenuButton::input(const sf::Event& event)
|
|||
}
|
||||
}
|
||||
|
||||
void CascadeMenuButton::setRect(const sf::FloatRect& rect)
|
||||
{
|
||||
Button::setRect(rect);
|
||||
resetRect(_submenu);
|
||||
}
|
||||
|
||||
void CascadeMenuButton::setSubmenu(const std::shared_ptr<MenuDrop>& submenu)
|
||||
{
|
||||
_submenu = submenu;
|
||||
resetRect(_submenu);
|
||||
}
|
||||
|
||||
const std::shared_ptr<MenuDrop> CascadeMenuButton::submenu() const
|
||||
{
|
||||
return _submenu;
|
||||
}
|
||||
|
||||
void CascadeMenuButton::resetRect(const std::shared_ptr<MenuDrop>& submenu)
|
||||
{
|
||||
if (submenu)
|
||||
{
|
||||
submenu->setPosition({_button_content.getPosition().x + _button_content.getSize().x,
|
||||
_button_content.getPosition().y});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,14 @@ class CascadeMenuButton : public Button
|
|||
public:
|
||||
explicit CascadeMenuButton(const std::string& text);
|
||||
virtual void input(const sf::Event& event) override final;
|
||||
virtual void setRect(const sf::FloatRect& rect) override final;
|
||||
|
||||
void setSubmenu(const std::shared_ptr<MenuDrop>& submenu);
|
||||
const std::shared_ptr<MenuDrop> submenu() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<MenuDrop> _submenu;
|
||||
|
||||
void resetRect(const std::shared_ptr<MenuDrop>& submenu);
|
||||
};
|
||||
|
||||
|
|
|
@ -9,6 +9,20 @@ MenuBar::MenuBar() :
|
|||
|
||||
void MenuBar::input(const sf::Event &event)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case sf::Event::MouseButtonReleased:
|
||||
if (!isUnderMouse(event.mouseButton.x, event.mouseButton.y))
|
||||
{
|
||||
for (auto& submenu : _submenus)
|
||||
submenu->unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Widget::input(event);
|
||||
}
|
||||
|
||||
|
@ -19,7 +33,9 @@ void MenuBar::update()
|
|||
|
||||
void MenuBar::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
target.draw(_bar_rect, states);
|
||||
if (_is_visible)
|
||||
target.draw(_bar_rect, states);
|
||||
|
||||
Widget::draw(target, states);
|
||||
}
|
||||
|
||||
|
@ -51,15 +67,32 @@ bool MenuBar::isUnderMouse(int mouse_x, int mouse_y) const
|
|||
|
||||
void MenuBar::addSubMenu(std::string name, const std::shared_ptr<MenuDrop>& submenu)
|
||||
{
|
||||
const auto new_button = std::make_shared<Button>(name);
|
||||
const auto new_button = std::make_shared<PushButton>(name);
|
||||
|
||||
std::size_t current_index = _amount_buttons;
|
||||
new_button->setRect(sf::FloatRect(current_index * _button_width, 0, _button_width, _bar_rect.getSize().y));
|
||||
new_button->setCallback([submenu=submenu]()
|
||||
{
|
||||
submenu->trigger();
|
||||
submenu->setVisibility(true);
|
||||
submenu->lock();
|
||||
});
|
||||
|
||||
new_button->setFillColor(sf::Color(171, 141, 189));
|
||||
submenu->setPosition({static_cast<float>(current_index * _button_width),
|
||||
_bar_rect.getSize().y});
|
||||
|
||||
new_button->setFillColors(sf::Color(171, 141, 189), sf::Color(48, 27, 57));
|
||||
addChild(new_button);
|
||||
addChild(submenu);
|
||||
|
||||
_submenus.emplace_back(submenu);
|
||||
|
||||
++_amount_buttons;
|
||||
}
|
||||
|
||||
void MenuBar::setVisibility(bool is_visible)
|
||||
{
|
||||
Widget::setVisibility(is_visible);
|
||||
|
||||
for (auto& submenu : _submenus)
|
||||
submenu->setVisibility(false);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
virtual void setRect(const sf::FloatRect& rect) override;
|
||||
virtual void setPosition(const sf::Vector2f& position) override;
|
||||
virtual bool isUnderMouse(int mouse_x, int mouse_y) const override;
|
||||
virtual void setVisibility(bool is_visible = true) override;
|
||||
|
||||
void addSubMenu(std::string name, const std::shared_ptr<MenuDrop>& submenu);
|
||||
|
||||
|
@ -24,4 +25,6 @@ private:
|
|||
sf::RectangleShape _bar_rect;
|
||||
std::size_t _amount_buttons;
|
||||
std::size_t _button_width;
|
||||
|
||||
std::vector<std::shared_ptr<MenuDrop>> _submenus;
|
||||
};
|
||||
|
|
|
@ -5,32 +5,43 @@ MenuDrop::MenuDrop() :
|
|||
_is_locked(false),
|
||||
_button_height(27),
|
||||
_button_index(0)
|
||||
{}
|
||||
{
|
||||
setVisibility(false);
|
||||
_content_rect.setFillColor(sf::Color(200, 200, 200));
|
||||
}
|
||||
|
||||
void MenuDrop::input(const sf::Event& event)
|
||||
{
|
||||
if (!_is_visible)
|
||||
return;
|
||||
|
||||
Widget::input(event);
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case sf::Event::MouseButtonReleased:
|
||||
case sf::Event::MouseMoved:
|
||||
if (isUnderMouse(event.mouseButton.x, event.mouseButton.y))
|
||||
if (!isUnderMouse(event.mouseButton.x, event.mouseButton.y))
|
||||
{
|
||||
Widget::input(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isLocked())
|
||||
if (!isLocked() && !hasActiveSubmenus())
|
||||
setVisibility(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MenuDrop::hasActiveSubmenus() const
|
||||
{
|
||||
return std::any_of(_submenus.begin(), _submenus.end(),
|
||||
[](const auto& submenu) -> bool
|
||||
{
|
||||
return submenu->_is_visible;
|
||||
});
|
||||
}
|
||||
|
||||
void MenuDrop::update()
|
||||
{
|
||||
Widget::update();
|
||||
|
@ -38,7 +49,9 @@ void MenuDrop::update()
|
|||
|
||||
void MenuDrop::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
target.draw(_content_rect);
|
||||
if (_is_visible)
|
||||
target.draw(_content_rect);
|
||||
|
||||
Widget::draw(target, states);
|
||||
}
|
||||
|
||||
|
@ -58,8 +71,24 @@ bool MenuDrop::isUnderMouse(int mouse_x, int mouse_y) const
|
|||
return _is_visible && _content_rect.getGlobalBounds().contains(mouse_x, mouse_y);
|
||||
}
|
||||
|
||||
void MenuDrop::addButton(const std::shared_ptr<Button>& button)
|
||||
void MenuDrop::setVisibility(bool is_visible)
|
||||
{
|
||||
Widget::setVisibility(is_visible);
|
||||
|
||||
if (!is_visible)
|
||||
_is_locked = false;
|
||||
}
|
||||
|
||||
void MenuDrop::addPushButton(const std::shared_ptr<PushButton>& button)
|
||||
{
|
||||
add(button);
|
||||
}
|
||||
|
||||
void MenuDrop::addCascadeButton(const std::shared_ptr<CascadeMenuButton>& button)
|
||||
{
|
||||
auto& submenu = button->submenu();
|
||||
submenu->setParent(_parent);
|
||||
_submenus.emplace_back();
|
||||
add(button);
|
||||
}
|
||||
|
||||
|
@ -79,6 +108,7 @@ void MenuDrop::add(const std::shared_ptr<Widget> &widget)
|
|||
_button_height));
|
||||
|
||||
addChild(widget);
|
||||
++_button_index;
|
||||
}
|
||||
|
||||
void MenuDrop::lock()
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "widget.h"
|
||||
#include "button.h"
|
||||
#include "pushbutton.h"
|
||||
#include "cascademenubutton.h"
|
||||
#include <SFML/Graphics/RectangleShape.hpp>
|
||||
|
||||
class MenuDrop : public Widget
|
||||
|
@ -15,8 +16,10 @@ public:
|
|||
virtual void setRect(const sf::FloatRect& rect) override;
|
||||
virtual void setPosition(const sf::Vector2f& position) override;
|
||||
virtual bool isUnderMouse(int mouse_x, int mouse_y) const override;
|
||||
virtual void setVisibility(bool is_visible = true) override;
|
||||
|
||||
void addButton(const std::shared_ptr<Button>& button);
|
||||
void addPushButton(const std::shared_ptr<PushButton>& button);
|
||||
void addCascadeButton(const std::shared_ptr<CascadeMenuButton>& button);
|
||||
void addSeparator();
|
||||
|
||||
void lock();
|
||||
|
@ -30,5 +33,8 @@ private:
|
|||
std::size_t _button_height;
|
||||
std::size_t _button_index;
|
||||
|
||||
std::vector<std::shared_ptr<MenuDrop>> _submenus;
|
||||
|
||||
void add(const std::shared_ptr<Widget>& widget);
|
||||
bool hasActiveSubmenus() const;
|
||||
};
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
PushButton::PushButton(const std::string& text) :
|
||||
Button(text),
|
||||
_pressed(false)
|
||||
{}
|
||||
{
|
||||
_color_idle = sf::Color(230, 230, 230);
|
||||
_color_pressed = sf::Color(200, 200, 200);
|
||||
}
|
||||
|
||||
void PushButton::input(const sf::Event& event)
|
||||
{
|
||||
Button::input(event);
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
default:
|
||||
|
@ -18,14 +19,14 @@ void PushButton::input(const sf::Event& event)
|
|||
if (isUnderMouse(event.mouseButton.x, event.mouseButton.y))
|
||||
{
|
||||
_pressed = true;
|
||||
_button_content.setFillColor(sf::Color(155, 155, 155));
|
||||
_button_content.setFillColor(sf::Color(_color_pressed));
|
||||
}
|
||||
break;
|
||||
|
||||
case sf::Event::MouseButtonReleased:
|
||||
if (_pressed)
|
||||
{
|
||||
_button_content.setFillColor(sf::Color::White);
|
||||
_button_content.setFillColor(_color_idle);
|
||||
_pressed = false;
|
||||
if (isUnderMouse(event.mouseButton.x, event.mouseButton.y))
|
||||
_on_click_callback();
|
||||
|
@ -38,3 +39,11 @@ void PushButton::setCallback(std::function<void(void)> callback)
|
|||
{
|
||||
_on_click_callback = callback;
|
||||
}
|
||||
|
||||
void PushButton::setFillColors(sf::Color&& idle_color, sf::Color&& pressed_color)
|
||||
{
|
||||
_color_idle = idle_color;
|
||||
_color_pressed = pressed_color;
|
||||
|
||||
_button_content.setFillColor(_pressed ? pressed_color : idle_color);
|
||||
}
|
||||
|
|
|
@ -9,8 +9,12 @@ public:
|
|||
virtual void input(const sf::Event& event) override final;
|
||||
|
||||
void setCallback(std::function<void(void)> callback);
|
||||
void setFillColors(sf::Color&& idle_color, sf::Color&& pressed_color);
|
||||
|
||||
private:
|
||||
sf::Color _color_idle;
|
||||
sf::Color _color_pressed;
|
||||
|
||||
bool _pressed;
|
||||
std::function<void(void)> _on_click_callback;
|
||||
};
|
||||
|
|
|
@ -2,8 +2,13 @@
|
|||
|
||||
void Widget::input(const sf::Event &event)
|
||||
{
|
||||
for (auto& child : _children)
|
||||
child->input(event);
|
||||
if (_blocker)
|
||||
_blocker->input(event);
|
||||
else
|
||||
{
|
||||
for (auto& child : _children)
|
||||
child->input(event);
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::update()
|
||||
|
@ -14,9 +19,6 @@ void Widget::update()
|
|||
|
||||
void Widget::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
if (!_is_visible)
|
||||
return;
|
||||
|
||||
for (auto& child : _children)
|
||||
child->draw(target, states);
|
||||
}
|
||||
|
@ -25,11 +27,33 @@ void Widget::setVisibility(bool is_visible)
|
|||
{
|
||||
_is_visible = is_visible;
|
||||
for (auto& child : _children)
|
||||
child->setVisibility(false);
|
||||
child->setVisibility(_is_visible);
|
||||
}
|
||||
|
||||
void Widget::addChild(const std::shared_ptr<Widget> &child)
|
||||
void Widget::addChild(const std::shared_ptr<Widget>& child)
|
||||
{
|
||||
child->_parent = shared_from_this();
|
||||
_children.emplace_back(child);
|
||||
child->setParent(shared_from_this());
|
||||
|
||||
const auto iterator = std::find(_children.begin(), _children.end(), child);
|
||||
if (iterator == _children.end())
|
||||
_children.emplace_back(child);
|
||||
}
|
||||
|
||||
void Widget::setParent(const std::shared_ptr<Widget>& parent)
|
||||
{
|
||||
if (_parent != parent)
|
||||
{
|
||||
_parent = parent;
|
||||
_parent->addChild(shared_from_this());
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::blockBy(const std::shared_ptr<Widget>& blocker)
|
||||
{
|
||||
_blocker = blocker;
|
||||
}
|
||||
|
||||
void Widget::unblock()
|
||||
{
|
||||
_blocker = nullptr;
|
||||
}
|
||||
|
|
|
@ -18,12 +18,16 @@ public:
|
|||
virtual void setPosition(const sf::Vector2f& position) = 0;
|
||||
virtual bool isUnderMouse(int mouse_x, int mouse_y) const = 0;
|
||||
|
||||
void setVisibility(bool is_visible = true);
|
||||
virtual void setVisibility(bool is_visible = true);
|
||||
void addChild(const std::shared_ptr<Widget>& child);
|
||||
void setParent(const std::shared_ptr<Widget>& parent);
|
||||
void blockBy(const std::shared_ptr<Widget>& blocker);
|
||||
void unblock();
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<Widget>> _children;
|
||||
std::shared_ptr<Widget> _parent;
|
||||
std::shared_ptr<Widget> _blocker;
|
||||
bool _is_visible = true;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue