diff --git a/src/gui/editor.cpp b/src/gui/editor.cpp index c9a8294..13200b0 100644 --- a/src/gui/editor.cpp +++ b/src/gui/editor.cpp @@ -2,6 +2,7 @@ #include "widgets/button.h" #include "widgets/group.h" #include "widgets/menubar.h" +#include "widgets/window.h" #include "widgets/bpmcalculatorwidget.h" #include "tools/bpmcalculator.h" @@ -16,38 +17,46 @@ Editor::Editor(sf::RenderWindow& game_window, Callbacks&& callbacks, std::unique void Editor::input(const sf::Event& event) { - _menu_bar->input(event); + _group->input(event); } void Editor::update(const sf::Time& dt) { - _menu_bar->update(dt); - _bpm_widget->update(dt); + _group->update(dt); } void Editor::draw() const { - _game_window.draw(*_menu_bar); - _game_window.draw(*_bpm_widget); + _game_window.draw(*_group); } void Editor::enter() { + auto& group = _group; + _bpm_calculator = std::make_shared(_music); - _bpm_widget = std::make_shared(_bpm_calculator, _font); + std::shared_ptr bpm_widget = std::make_shared(_bpm_calculator, _font); + const auto bpm_widget_callback = [&group, bpm_widget=bpm_widget]() + { + bpm_widget->setVisibility(false); + group->unblock(); + }; const float window_width = _game_window.getSize().x; - _menu_bar = std::make_shared(_font); + auto menu_bar = std::make_shared(_font); auto bpm_button = std::make_shared("Calculate BPM", _font); - bpm_button->setCallback([&]() + + bpm_button->setCallback([&group, bpm_widget=bpm_widget]() { - _bpm_widget->setVisibility(true); + group->blockBy(bpm_widget); + bpm_widget->setVisibility(true); }); - _bpm_widget->setRect(sf::FloatRect(_game_window.getSize().x / 3, _game_window.getSize().y / 3, _game_window.getSize().x / 3, _game_window.getSize().y / 3)); - _bpm_widget->setVisibility(false); + bpm_widget->setRect(sf::FloatRect(_game_window.getSize().x / 3, _game_window.getSize().y / 3, _game_window.getSize().x / 3, _game_window.getSize().y / 3)); + bpm_widget->addBarButton("X", bpm_widget_callback); + bpm_widget->setVisibility(false); auto test_menu_2 = std::make_shared(); test_menu_2->setRect(sf::FloatRect{0, 0, 200, 27 * 5}); @@ -65,10 +74,10 @@ void Editor::enter() auto test_menu = std::make_shared(); test_menu->setRect(sf::FloatRect{0, 0, 200, 27 * 3}); - _menu_bar->setRect(sf::FloatRect(0, 0, window_width, 27)); - _menu_bar->addRootSubMenu("test", test_menu); - _menu_bar->addDependentSubmenu(test_menu_2); - _menu_bar->addDependentSubmenu(test_menu_3); + menu_bar->setRect(sf::FloatRect(0, 0, window_width, 27)); + menu_bar->addRootSubMenu("test", test_menu); + menu_bar->addDependentSubmenu(test_menu_2); + menu_bar->addDependentSubmenu(test_menu_3); test_cascade_button->setSubmenu(test_menu_2); @@ -85,13 +94,15 @@ void Editor::enter() _music->openFromFile("Uta-test.flac"); _music->setVolume(5); - _menu_bar->setVisibility(true); + menu_bar->setVisibility(true); + + _group = std::make_shared(); + _group->addChild(menu_bar); + _group->addChild(bpm_widget); } void Editor::leave() { - _menu_bar.reset(); - _bpm_calculator.reset(); - _bpm_widget.reset(); + _group.reset(); } diff --git a/src/gui/editor.h b/src/gui/editor.h index d698a41..e378838 100644 --- a/src/gui/editor.h +++ b/src/gui/editor.h @@ -5,9 +5,8 @@ #include "tools/resourceholder.h" #include -class MenuBar; -class BPMCalculatorWidget; class BPMCalculator; +class Group; class Editor : public GUIState { @@ -28,13 +27,12 @@ public: private: const std::shared_ptr _font; - std::shared_ptr _menu_bar; sf::RenderWindow& _game_window; Callbacks _callbacks; std::shared_ptr _music; std::shared_ptr _bpm_calculator; - std::shared_ptr _bpm_widget; + std::shared_ptr _group; }; diff --git a/src/gui/widgets/bpmcalculatorwidget.cpp b/src/gui/widgets/bpmcalculatorwidget.cpp index f022bd9..8b226c7 100644 --- a/src/gui/widgets/bpmcalculatorwidget.cpp +++ b/src/gui/widgets/bpmcalculatorwidget.cpp @@ -2,11 +2,10 @@ #include "tools/bpmcalculator.h" BPMCalculatorWidget::BPMCalculatorWidget(const std::shared_ptr& bpm_calculator, const std::shared_ptr& font) : + Window("BPM Calculation", font), _bpm_calculator(bpm_calculator), - _slider(std::make_shared(font)) + _slider(std::make_shared()) { - _widget_window.setFillColor(sf::Color(88, 57, 107)); - //addChild(_slider); } void BPMCalculatorWidget::input(const sf::Event& event) @@ -24,39 +23,38 @@ void BPMCalculatorWidget::input(const sf::Event& event) break; } - Widget::input(event); + Window::input(event); } void BPMCalculatorWidget::update(const sf::Time& dt) { - Widget::update(dt); + Window::update(dt); } void BPMCalculatorWidget::draw(sf::RenderTarget& target, sf::RenderStates states) const { + Window::draw(target, states); + if (_is_visible) - { - target.draw(_widget_window, states); - Widget::draw(target, states); - } + _slider->draw(target, states); } void BPMCalculatorWidget::setRect(const sf::FloatRect& rect) { - _widget_window.setPosition(rect.left, rect.top); - _widget_window.setSize({rect.width, rect.height}); - _slider->setRect(sf::FloatRect{rect.width / 3, rect.height / 2 - 50, rect.width / 3, 100}); + Window::setRect(rect); + _slider->setRect(sf::FloatRect{0, 0, rect.width / 8 * 6, 100}); + _slider->setPosition({_window_content.getGlobalBounds().left + rect.width / 8, + _window_content.getGlobalBounds().top + rect.height / 8 * 3}); } -void BPMCalculatorWidget::setPosition(const sf::Vector2f &position) +void BPMCalculatorWidget::move(const sf::Vector2f &delta) { - _widget_window.setPosition(position); - _slider->setRect(sf::FloatRect{_widget_window.getSize().x / 3, - _widget_window.getSize().y / 2 - 50, - _widget_window.getSize().x / 3, 100}); + Window::move(delta); + _slider->move(delta); } -bool BPMCalculatorWidget::isUnderMouse(int mouse_x, int mouse_y) const +void BPMCalculatorWidget::setPosition(const sf::Vector2f &position) { - return _is_visible && _widget_window.getGlobalBounds().contains(mouse_x, mouse_y); + Window::setPosition(position); + _slider->setPosition(position); } diff --git a/src/gui/widgets/bpmcalculatorwidget.h b/src/gui/widgets/bpmcalculatorwidget.h index 943dc57..9e44d43 100644 --- a/src/gui/widgets/bpmcalculatorwidget.h +++ b/src/gui/widgets/bpmcalculatorwidget.h @@ -1,14 +1,15 @@ #pragma once -#include "widget.h" +#include "window.h" #include "bpmslider.h" +#include "pushbutton.h" #include #include #include class BPMCalculator; -class BPMCalculatorWidget : public Widget +class BPMCalculatorWidget : public Window { public: explicit BPMCalculatorWidget(const std::shared_ptr& bpm_calculator, const std::shared_ptr &font); @@ -18,14 +19,10 @@ public: virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; 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 move(const sf::Vector2f& delta) override; private: std::shared_ptr _bpm_calculator; std::shared_ptr _slider; - - sf::RectangleShape _widget_window; - - std::function _on_click_callback; }; diff --git a/src/gui/widgets/bpmslider.cpp b/src/gui/widgets/bpmslider.cpp index 349bf27..4b81ffc 100644 --- a/src/gui/widgets/bpmslider.cpp +++ b/src/gui/widgets/bpmslider.cpp @@ -1,8 +1,9 @@ #include "bpmslider.h" -BPMSlider::BPMSlider(const std::shared_ptr &font) +BPMSlider::BPMSlider() { - _bpm_value.setFont(*font); + _slider_background.setFillColor(sf::Color::Black); + _slider_tick.setFillColor(sf::Color::Red); } void BPMSlider::input(const sf::Event& event) @@ -17,6 +18,8 @@ void BPMSlider::update(const sf::Time& dt) void BPMSlider::draw(sf::RenderTarget& target, sf::RenderStates states) const { + target.draw(_slider_background, states); + target.draw(_slider_tick, states); Widget::draw(target, states); } @@ -24,11 +27,21 @@ void BPMSlider::setRect(const sf::FloatRect& rect) { _slider_background.setPosition(rect.left, rect.top); _slider_background.setSize({rect.width, rect.height}); + + _slider_tick.setPosition(rect.left, rect.top); + _slider_tick.setSize({rect.width / 30, rect.height}); } void BPMSlider::setPosition(const sf::Vector2f& position) { _slider_background.setPosition(position); + _slider_tick.setPosition(position); +} + +void BPMSlider::move(const sf::Vector2f& delta) +{ + _slider_background.move(delta); + _slider_tick.move(delta); } bool BPMSlider::isUnderMouse(int mouse_x, int mouse_y) const diff --git a/src/gui/widgets/bpmslider.h b/src/gui/widgets/bpmslider.h index 81a1641..be56969 100644 --- a/src/gui/widgets/bpmslider.h +++ b/src/gui/widgets/bpmslider.h @@ -8,19 +8,19 @@ class BPMSlider : public Widget { public: - explicit BPMSlider(const std::shared_ptr &font); + explicit BPMSlider(); virtual void input(const sf::Event& event) override; virtual void update(const sf::Time& dt) override; virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; virtual void setRect(const sf::FloatRect& rect) override; virtual void setPosition(const sf::Vector2f& position) override; + virtual void move(const sf::Vector2f& delta) override; virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; private: sf::RectangleShape _slider_background; sf::RectangleShape _slider_tick; - sf::Text _bpm_value; }; diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index f6705df..cc4e83f 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -37,6 +37,13 @@ void Button::setPosition(const sf::Vector2f &position) _button_content.setPosition(position); } +void Button::move(const sf::Vector2f &delta) +{ + _button_content.move(delta); + _button_text.move(delta); + Widget::move(delta); +} + bool Button::isUnderMouse(int mouse_x, int mouse_y) const { return _is_visible && _button_content.getGlobalBounds().contains(mouse_x, mouse_y); diff --git a/src/gui/widgets/button.h b/src/gui/widgets/button.h index 343745e..cf121aa 100644 --- a/src/gui/widgets/button.h +++ b/src/gui/widgets/button.h @@ -14,6 +14,7 @@ public: virtual void update(const sf::Time& dt) override final; virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override final; virtual void setPosition(const sf::Vector2f& position) override final; + virtual void move(const sf::Vector2f& delta) override final; virtual bool isUnderMouse(int mouse_x, int mouse_y) const override final; virtual void setRect(const sf::FloatRect& rect) override; diff --git a/src/gui/widgets/group.cpp b/src/gui/widgets/group.cpp index 6587f24..332dcf0 100644 --- a/src/gui/widgets/group.cpp +++ b/src/gui/widgets/group.cpp @@ -26,6 +26,14 @@ void Group::setPosition(const sf::Vector2f& position) _rect.left = position.x; } +void Group::move(const sf::Vector2f& delta) +{ + _rect.top += delta.y; + _rect.left += delta.x; + + Widget::move(delta); +} + bool Group::isUnderMouse(int mouse_x, int mouse_y) const { return _rect.contains(mouse_x, mouse_y); diff --git a/src/gui/widgets/group.h b/src/gui/widgets/group.h index 7e71334..b3d9dc4 100644 --- a/src/gui/widgets/group.h +++ b/src/gui/widgets/group.h @@ -10,6 +10,7 @@ public: virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; virtual void setRect(const sf::FloatRect& rect) override; virtual void setPosition(const sf::Vector2f& position) override; + virtual void move(const sf::Vector2f& delta) override; virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; private: diff --git a/src/gui/widgets/menubar.cpp b/src/gui/widgets/menubar.cpp index 56027e4..965c9d3 100644 --- a/src/gui/widgets/menubar.cpp +++ b/src/gui/widgets/menubar.cpp @@ -54,6 +54,16 @@ void MenuBar::setPosition(const sf::Vector2f& position) _bar_rect.setPosition(position); } +void MenuBar::move(const sf::Vector2f &delta) +{ + _bar_rect.move(delta); + + Widget::move(delta); + + for (auto& menu : _submenus) + menu->move(delta); +} + bool MenuBar::isUnderMouse(int mouse_x, int mouse_y) const { bool bar_under_mouse = _bar_rect.getGlobalBounds().contains(mouse_x, mouse_y); diff --git a/src/gui/widgets/menubar.h b/src/gui/widgets/menubar.h index ec639d7..0183a59 100644 --- a/src/gui/widgets/menubar.h +++ b/src/gui/widgets/menubar.h @@ -16,6 +16,7 @@ public: virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; virtual void setRect(const sf::FloatRect& rect) override; virtual void setPosition(const sf::Vector2f& position) override; + virtual void move(const sf::Vector2f& delta) override; virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; virtual void setVisibility(bool is_visible = true) override; diff --git a/src/gui/widgets/menudrop.cpp b/src/gui/widgets/menudrop.cpp index 0c736fb..222c6e1 100644 --- a/src/gui/widgets/menudrop.cpp +++ b/src/gui/widgets/menudrop.cpp @@ -23,6 +23,16 @@ void MenuDrop::input(const sf::Event& event) break; case sf::Event::MouseButtonReleased: + if (isUnderMouse(event.mouseButton.x, event.mouseButton.y)) + { + setVisibility(false); + for (auto& submenu : _submenus) + { + submenu->unlock(); + submenu->setVisibility(false); + } + } + break; case sf::Event::MouseMoved: if (!isUnderMouse(event.mouseMove.x, event.mouseMove.y)) { @@ -66,6 +76,16 @@ void MenuDrop::setPosition(const sf::Vector2f& position) _content_rect.setPosition(position); } +void MenuDrop::move(const sf::Vector2f& delta) +{ + _content_rect.move(delta); + + Widget::move(delta); + + for (auto& submenu : _submenus) + submenu->move(delta); +} + bool MenuDrop::isUnderMouse(int mouse_x, int mouse_y) const { return _is_visible && _content_rect.getGlobalBounds().contains(mouse_x, mouse_y); diff --git a/src/gui/widgets/menudrop.h b/src/gui/widgets/menudrop.h index 1046bff..0bbac32 100644 --- a/src/gui/widgets/menudrop.h +++ b/src/gui/widgets/menudrop.h @@ -15,6 +15,7 @@ public: virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; virtual void setRect(const sf::FloatRect& rect) override; virtual void setPosition(const sf::Vector2f& position) override; + virtual void move(const sf::Vector2f& delta) override; virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; virtual void setVisibility(bool is_visible = true) override; diff --git a/src/gui/widgets/menuseparator.cpp b/src/gui/widgets/menuseparator.cpp index 44e2ad5..249b537 100644 --- a/src/gui/widgets/menuseparator.cpp +++ b/src/gui/widgets/menuseparator.cpp @@ -27,6 +27,11 @@ void MenuSeparator::setPosition(const sf::Vector2f& position) (void)position; } +void MenuSeparator::move(const sf::Vector2f& delta) +{ + (void)delta; +} + bool MenuSeparator::isUnderMouse(int mouse_x, int mouse_y) const { return _is_visible && _rect.contains(mouse_x, mouse_y); diff --git a/src/gui/widgets/menuseparator.h b/src/gui/widgets/menuseparator.h index fe3c522..7456276 100644 --- a/src/gui/widgets/menuseparator.h +++ b/src/gui/widgets/menuseparator.h @@ -12,6 +12,7 @@ public: virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; virtual void setRect(const sf::FloatRect& rect) override; virtual void setPosition(const sf::Vector2f& position) override; + virtual void move(const sf::Vector2f& delta) override; virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; private: diff --git a/src/gui/widgets/widget.cpp b/src/gui/widgets/widget.cpp index 75a2f9d..00c39ed 100644 --- a/src/gui/widgets/widget.cpp +++ b/src/gui/widgets/widget.cpp @@ -23,6 +23,12 @@ void Widget::draw(sf::RenderTarget& target, sf::RenderStates states) const child->draw(target, states); } +void Widget::move(const sf::Vector2f &delta) +{ + for (auto& child : _children) + child->move(delta); +} + void Widget::setVisibility(bool is_visible) { _is_visible = is_visible; diff --git a/src/gui/widgets/widget.h b/src/gui/widgets/widget.h index 0d81d44..9091d4d 100644 --- a/src/gui/widgets/widget.h +++ b/src/gui/widgets/widget.h @@ -16,6 +16,7 @@ public: virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const = 0; virtual void setRect(const sf::FloatRect& rect) = 0; virtual void setPosition(const sf::Vector2f& position) = 0; + virtual void move(const sf::Vector2f& delta) = 0; virtual bool isUnderMouse(int mouse_x, int mouse_y) const = 0; virtual void setVisibility(bool is_visible = true); diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp new file mode 100644 index 0000000..c918f9a --- /dev/null +++ b/src/gui/widgets/window.cpp @@ -0,0 +1,110 @@ +#include "window.h" +#include "pushbutton.h" + +Window::Window(const std::string& text, const std::shared_ptr& font) : + _font(font), + _is_dragging(false) +{ + _bar_title.setFont(*font); + _bar_title.setString(text); + _bar_title.setCharacterSize(12); + _bar_title.setFillColor(sf::Color(188, 157, 207)); + _bar.setFillColor(sf::Color(88, 57, 107)); + _window_content.setFillColor(sf::Color(188, 157, 207)); +} + +void Window::input(const sf::Event& event) +{ + Widget::input(event); + + switch (event.type) + { + default: + break; + + case sf::Event::MouseButtonPressed: + if (_bar.getGlobalBounds().contains(event.mouseButton.x, event.mouseButton.y)) + { + _is_dragging = true; + _previous_click_position = {static_cast(event.mouseButton.x), + static_cast(event.mouseButton.y)}; + } + break; + + case sf::Event::MouseButtonReleased: + _is_dragging = false; + break; + + case sf::Event::MouseMoved: + if (_is_dragging) + { + float x_mouse_diff = event.mouseMove.x - _previous_click_position.x; + float y_mouse_diff = event.mouseMove.y - _previous_click_position.y; + + _previous_click_position = {static_cast(event.mouseMove.x), + static_cast(event.mouseMove.y)}; + + move({x_mouse_diff, y_mouse_diff}); + } + break; + } +} + +void Window::update(const sf::Time& dt) +{ + Widget::update(dt); +} + +void Window::draw(sf::RenderTarget& target, sf::RenderStates states) const +{ + if (_is_visible) + { + target.draw(_window_content, states); + target.draw(_bar, states); + target.draw(_bar_title, states); + Widget::draw(target, states); + } +} + +void Window::setRect(const sf::FloatRect& rect) +{ + _window_content.setPosition(rect.left, rect.top); + _window_content.setSize({rect.width, rect.height}); + + _bar.setPosition(rect.left, rect.top); + _bar.setSize({rect.width, 30}); + _bar_title.setPosition(rect.left + 5, rect.top + 5); +} + +void Window::setPosition(const sf::Vector2f& position) +{ + _window_content.setPosition(position); + _bar.setPosition(position); + _bar_title.setPosition(position.x + 5, position.y + 5); +} + +void Window::move(const sf::Vector2f &delta) +{ + _window_content.move(delta); + _bar.move(delta); + _bar_title.move(delta); + + Widget::move(delta); +} + +bool Window::isUnderMouse(int mouse_x, int mouse_y) const +{ + return _is_visible && _window_content.getGlobalBounds().contains(mouse_x, mouse_y); +} + +void Window::addBarButton(const std::string &text, std::function callback) +{ + auto b = std::make_shared(text, _font, 20); + b->setCallback(callback); + b->setRect({_window_content.getGlobalBounds().left + _window_content.getSize().x - 35, + _window_content.getGlobalBounds().top, + 30, + 30}); + addChild(b); +} + diff --git a/src/gui/widgets/window.h b/src/gui/widgets/window.h new file mode 100644 index 0000000..ee52d40 --- /dev/null +++ b/src/gui/widgets/window.h @@ -0,0 +1,34 @@ +#pragma once + +#include "widget.h" + +#include +#include + +class Window : public Widget +{ +public: + explicit Window(const std::string& text, const std::shared_ptr &font); + + virtual void input(const sf::Event& event) override; + virtual void update(const sf::Time& dt) override; + virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; + virtual void setRect(const sf::FloatRect& rect) override; + virtual void setPosition(const sf::Vector2f& position) override; + virtual void move(const sf::Vector2f& delta) override; + virtual bool isUnderMouse(int mouse_x, int mouse_y) const override final; + + void addBarButton(const std::string& text, std::function callback); + +protected: + sf::RectangleShape _bar; + sf::RectangleShape _window_content; + sf::Text _bar_title; + + const std::shared_ptr _font; + +private: + bool _is_dragging; + sf::Vector2f _previous_click_position; +}; +