diff --git a/meson.build b/meson.build index e3e98a7..d8b88e3 100644 --- a/meson.build +++ b/meson.build @@ -51,10 +51,12 @@ sources = [ 'src/Screens/MusicSelect/MusicPreview.cpp', 'src/Screens/MusicSelect/MusicSelect.hpp', 'src/Screens/MusicSelect/MusicSelect.cpp', - 'src/Screens/MusicSelect/OptionMenu.hpp', - # 'src/Screens/MusicSelect/OptionMenu.cpp', - 'src/Screens/MusicSelect/Panel.hpp', - 'src/Screens/MusicSelect/Panel.cpp', + 'src/Screens/MusicSelect/OptionPage.hpp', + 'src/Screens/MusicSelect/OptionPage.cpp', + 'src/Screens/MusicSelect/Panels/Panel.hpp', + 'src/Screens/MusicSelect/Panels/Panel.cpp', + 'src/Screens/MusicSelect/Panels/SubpagePanel.hpp', + 'src/Screens/MusicSelect/Panels/SubpagePanel.cpp', 'src/Screens/MusicSelect/PanelLayout.hpp', 'src/Screens/MusicSelect/PanelLayout.cpp', 'src/Screens/MusicSelect/Ribbon.hpp', diff --git a/src/Resources/Marker.cpp b/src/Resources/Marker.cpp index 7375300..9450206 100644 --- a/src/Resources/Marker.cpp +++ b/src/Resources/Marker.cpp @@ -78,12 +78,12 @@ namespace Resources { // Duration check // We do not allow any marker animation to take longer than the jubeat standard of 16 frames at 30 fps - // For that we check that : + // For that we make sure that : // count/fps <= 16/30 // Which is mathematically equivalent to checking that : // count*30 <= 16*fps // Which allows us to avoid having to cast to float - if (metadata.count*30 <= 16*m_metadata.fps) { + if (metadata.count*30 > 16*m_metadata.fps) { std::stringstream ss; ss << "Marker animation for sprite sheet "; ss << (m_folder/metadata.sprite_sheet).string(); @@ -95,7 +95,7 @@ namespace Resources { } } - sf::Texture& Marker::get_sprite_sheet_from_enum(const MarkerAnimation& state) { + const sf::Texture& Marker::get_sprite_sheet_from_enum(const MarkerAnimation& state) const { switch (state) { case MarkerAnimation::APPROACH: return m_approach; @@ -120,7 +120,7 @@ namespace Resources { } } - MarkerAnimationMetadata& Marker::get_metadata_from_enum(const MarkerAnimation& state) { + const MarkerAnimationMetadata& Marker::get_metadata_from_enum(const MarkerAnimation& state) const { switch (state) { case MarkerAnimation::APPROACH: return m_metadata.approach; @@ -145,7 +145,7 @@ namespace Resources { } } - std::optional Marker::get_sprite(const MarkerAnimation& state, const float& seconds) { + std::optional Marker::get_sprite(const MarkerAnimation& state, float seconds) const { auto raw_frame = static_cast(std::floor(seconds*m_metadata.fps)); if (raw_frame >= 0) { if (state == MarkerAnimation::APPROACH) { @@ -162,7 +162,7 @@ namespace Resources { } } - std::optional Marker::get_sprite(const MarkerAnimation& state, const std::size_t frame) { + std::optional Marker::get_sprite(const MarkerAnimation& state, const std::size_t frame) const { auto& meta = get_metadata_from_enum(state); if (frame >= meta.count) { return {}; diff --git a/src/Resources/Marker.hpp b/src/Resources/Marker.hpp index 3b62c72..17900e7 100644 --- a/src/Resources/Marker.hpp +++ b/src/Resources/Marker.hpp @@ -66,11 +66,11 @@ namespace Resources { struct Marker { Marker(const ghc::filesystem::path& marker_folder); - std::optional get_sprite(const MarkerAnimation& state, const float& seconds); - std::optional get_sprite(const MarkerAnimation& state, const std::size_t frame); + std::optional get_sprite(const MarkerAnimation& state, float seconds) const; + std::optional get_sprite(const MarkerAnimation& state, const std::size_t frame) const; void load_and_check(sf::Texture& spritesheet, const MarkerAnimationMetadata& metadata); - sf::Texture& get_sprite_sheet_from_enum(const MarkerAnimation& state); - MarkerAnimationMetadata& get_metadata_from_enum(const MarkerAnimation& state); + const sf::Texture& get_sprite_sheet_from_enum(const MarkerAnimation& state) const; + const MarkerAnimationMetadata& get_metadata_from_enum(const MarkerAnimation& state) const; ghc::filesystem::path m_folder; MarkerMetadata m_metadata; diff --git a/src/Screens/MusicSelect/MusicSelect.cpp b/src/Screens/MusicSelect/MusicSelect.cpp index 3e0dc34..0e53d89 100644 --- a/src/Screens/MusicSelect/MusicSelect.cpp +++ b/src/Screens/MusicSelect/MusicSelect.cpp @@ -7,6 +7,7 @@ #include "../../Data/Buttons.hpp" #include "../../Data/KeyMapping.hpp" +#include "Panels/Panel.hpp" #include "PanelLayout.hpp" MusicSelect::Screen::Screen( @@ -15,7 +16,7 @@ MusicSelect::Screen::Screen( const Resources::Markers& t_markers ) : song_list(t_song_list), - resources(t_preferences), + resources(t_preferences, t_markers), markers(t_markers), ribbon(PanelLayout::title_sort(t_song_list, resources), resources), song_info(resources), diff --git a/src/Screens/MusicSelect/MusicSelect.hpp b/src/Screens/MusicSelect/MusicSelect.hpp index 8246862..0aef33d 100644 --- a/src/Screens/MusicSelect/MusicSelect.hpp +++ b/src/Screens/MusicSelect/MusicSelect.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include "../../Data/Song.hpp" @@ -15,10 +16,11 @@ #include "SongInfo.hpp" #include "SharedResources.hpp" #include "ButtonHighlight.hpp" -#include "OptionMenu.hpp" +#include "OptionPage.hpp" namespace MusicSelect { + class SongPanel; // The music select screen is created only once // it loads a cache of available songs in the song_list attribute class Screen { @@ -43,7 +45,6 @@ namespace MusicSelect { SongInfo song_info; std::optional> selected_panel; ButtonHighlight button_highlight; - std::stack options_state; Drawables::BlackFrame black_frame; diff --git a/src/Screens/MusicSelect/OptionMenu.hpp b/src/Screens/MusicSelect/OptionMenu.hpp deleted file mode 100644 index 33f15e3..0000000 --- a/src/Screens/MusicSelect/OptionMenu.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -#include "SharedResources.hpp" -#include "../../Data/Buttons.hpp" - -namespace MusicSelect { - class OptionPage : public sf::Drawable, public sf::Transformable, public HoldsSharedResources { - public: - virtual void click(const Data::Button& button) = 0; - virtual ~OptionPage() = default; - }; - - class MainOptionPage final : public OptionPage { - public: - MainOptionPage(); - void click(const Data::Button& button); - private: - void draw(sf::RenderTarget& target, sf::RenderStates states); - }; -} diff --git a/src/Screens/MusicSelect/OptionPage.cpp b/src/Screens/MusicSelect/OptionPage.cpp new file mode 100644 index 0000000..23c38c0 --- /dev/null +++ b/src/Screens/MusicSelect/OptionPage.cpp @@ -0,0 +1,28 @@ +#include "OptionPage.hpp" + +#include + +#include "Ribbon.hpp" +#include "Panels/SubpagePanel.hpp" + +namespace MusicSelect { + MainOptionPage::MainOptionPage(SharedResources& resources) : + OptionPage(resources), + Ribbon(MainOptionPage::create_layout(resources), resources) + { + + } + + void MainOptionPage::click(const Data::Button& button) { + click_on(button); + } + + PanelLayout MainOptionPage::create_layout(SharedResources& resources) { + std::vector> subpages; + jbcoe::polymorphic_value marker_select{MarkerSelect{resources}}; + subpages.emplace_back(SubpagePanel{resources, marker_select, "markers"}); + return PanelLayout{subpages, resources}; + } + + +} diff --git a/src/Screens/MusicSelect/OptionPage.hpp b/src/Screens/MusicSelect/OptionPage.hpp new file mode 100644 index 0000000..3faf253 --- /dev/null +++ b/src/Screens/MusicSelect/OptionPage.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include "../../Data/Buttons.hpp" +#include "Ribbon.hpp" +#include "SharedResources.hpp" + + +namespace MusicSelect { + + class PanelLayout; + + class OptionPage : public sf::Drawable, public sf::Transformable, public HoldsSharedResources { + public: + OptionPage(SharedResources& resources) : HoldsSharedResources(resources) {}; + virtual void click(const Data::Button& button) = 0; + virtual ~OptionPage() = default; + }; + + class MainOptionPage final : public OptionPage, public Ribbon { + public: + MainOptionPage(SharedResources& resources); + void click(const Data::Button& button) override; + private: + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; + static PanelLayout create_layout(SharedResources& resources); + }; + + class MarkerSelect final : public OptionPage, public Ribbon { + public: + MarkerSelect(SharedResources& resources); + void click(const Data::Button& button) override; + private: + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; + static PanelLayout create_layout(SharedResources& resources); + }; +} diff --git a/src/Screens/MusicSelect/PanelLayout.cpp b/src/Screens/MusicSelect/PanelLayout.cpp index 2ddf1cf..362e3c6 100644 --- a/src/Screens/MusicSelect/PanelLayout.cpp +++ b/src/Screens/MusicSelect/PanelLayout.cpp @@ -1,5 +1,7 @@ #include "PanelLayout.hpp" +#include "Panels/Panel.hpp" + namespace MusicSelect { PanelLayout::PanelLayout( const std::map>>& categories, @@ -29,7 +31,7 @@ namespace MusicSelect { } PanelLayout::PanelLayout( - const std::vector> panels, + const std::vector>& panels, SharedResources& resources ) { std::vector> current_column; diff --git a/src/Screens/MusicSelect/PanelLayout.hpp b/src/Screens/MusicSelect/PanelLayout.hpp index 51506e2..a490198 100644 --- a/src/Screens/MusicSelect/PanelLayout.hpp +++ b/src/Screens/MusicSelect/PanelLayout.hpp @@ -5,16 +5,17 @@ #include -#include "Panel.hpp" -#include "SharedResources.hpp" #include "../../Data/Song.hpp" +#include "SharedResources.hpp" namespace MusicSelect { + + class Panel; // PanelLayout restricts the ways you can create a scrollable grid of panels class PanelLayout : public std::vector,3>> { public: explicit PanelLayout(const std::map>>& categories, SharedResources& resources); - explicit PanelLayout(const std::vector> panels, SharedResources& resources); + explicit PanelLayout(const std::vector>& panels, SharedResources& resources); static PanelLayout red_empty_layout(SharedResources& resources); static PanelLayout title_sort(const Data::SongList& song_list, SharedResources& resources); private: diff --git a/src/Screens/MusicSelect/Panels/MarkerPanel.cpp b/src/Screens/MusicSelect/Panels/MarkerPanel.cpp new file mode 100644 index 0000000..4fb8a58 --- /dev/null +++ b/src/Screens/MusicSelect/Panels/MarkerPanel.cpp @@ -0,0 +1,33 @@ +#include "MarkerPanel.hpp" + +#include + +namespace MusicSelect { + MarkerPanel::MarkerPanel(SharedResources& resources, const Resources::Marker& marker) : + Panel(resources), + m_marker(marker) + { + if (m_resources.m_preferences.options.marker == marker.m_metadata.name) { + selected_since.emplace(); + } + }; + + void MarkerPanel::click(Ribbon&, const Data::Button&) { + if (not selected_since) { + selected_since.emplace(); + m_resources.m_preferences.options.marker = m_marker.m_metadata.name; + } + }; + + void MarkerPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const { + states.transform *= getTransform(); + float animation_time = 0.f; + if (selected_since) { + auto animation_time = std::fmodf(selected_since->getElapsedTime().asSeconds(), 2.f) - 1.f; + } + auto sprite = m_marker.get_sprite(Resources::MarkerAnimation::APPROACH, 0.f); + if (sprite) { + target.draw(*sprite, states); + } + }; +} diff --git a/src/Screens/MusicSelect/Panels/MarkerPanel.hpp b/src/Screens/MusicSelect/Panels/MarkerPanel.hpp new file mode 100644 index 0000000..5ac7508 --- /dev/null +++ b/src/Screens/MusicSelect/Panels/MarkerPanel.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include + +#include "../../../Resources/Marker.hpp" +#include "Panel.hpp" + +namespace MusicSelect { + class MarkerPanel final : public Panel { + public: + MarkerPanel(SharedResources& resources, const Resources::Marker& marker) : Panel(resources), m_marker(marker) {}; + void click(Ribbon&, const Data::Button&) override; + private: + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; + const Resources::Marker& m_marker; + std::optional selected_since; + }; +} \ No newline at end of file diff --git a/src/Screens/MusicSelect/Panel.cpp b/src/Screens/MusicSelect/Panels/Panel.cpp similarity index 98% rename from src/Screens/MusicSelect/Panel.cpp rename to src/Screens/MusicSelect/Panels/Panel.cpp index f6b2027..a27a682 100644 --- a/src/Screens/MusicSelect/Panel.cpp +++ b/src/Screens/MusicSelect/Panels/Panel.cpp @@ -4,11 +4,11 @@ #include -#include "../../Toolkit/HSL.hpp" -#include "../../Toolkit/NormalizedOrigin.hpp" +#include "../../../Toolkit/HSL.hpp" +#include "../../../Toolkit/NormalizedOrigin.hpp" -#include "MusicSelect.hpp" -#include "SharedResources.hpp" +#include "../Ribbon.hpp" +#include "../SharedResources.hpp" namespace MusicSelect { Panel::Panel(SharedResources& resources) : HoldsSharedResources(resources) { diff --git a/src/Screens/MusicSelect/Panel.hpp b/src/Screens/MusicSelect/Panels/Panel.hpp similarity index 92% rename from src/Screens/MusicSelect/Panel.hpp rename to src/Screens/MusicSelect/Panels/Panel.hpp index 8dc3e7b..76eda55 100644 --- a/src/Screens/MusicSelect/Panel.hpp +++ b/src/Screens/MusicSelect/Panels/Panel.hpp @@ -6,10 +6,10 @@ #include #include -#include "../../Data/Song.hpp" -#include "../../Toolkit/AffineTransform.hpp" -#include "DensityGraph.hpp" -#include "SharedResources.hpp" +#include "../../../Data/Song.hpp" +#include "../../../Toolkit/AffineTransform.hpp" +#include "../DensityGraph.hpp" +#include "../SharedResources.hpp" namespace MusicSelect { @@ -56,7 +56,7 @@ namespace MusicSelect { class CategoryPanel final : public Panel { public: - explicit CategoryPanel(SharedResources& resources, const std::string& t_label) : Panel(resources), m_label(t_label) {}; + CategoryPanel(SharedResources& resources, const std::string& t_label) : Panel(resources), m_label(t_label) {}; void click(Ribbon& ribbon, const Data::Button& button) override; private: void draw(sf::RenderTarget& target, sf::RenderStates states) const override; diff --git a/src/Screens/MusicSelect/Panels/SubpagePanel.cpp b/src/Screens/MusicSelect/Panels/SubpagePanel.cpp new file mode 100644 index 0000000..956d000 --- /dev/null +++ b/src/Screens/MusicSelect/Panels/SubpagePanel.cpp @@ -0,0 +1,34 @@ +#include "SubpagePanel.hpp" + +#include "../OptionPage.hpp" + +namespace MusicSelect { + void SubpagePanel::click(Ribbon&, const Data::Button&) { + m_resources.options_state.push(m_subpage); + } + + void SubpagePanel::draw(sf::RenderTarget& target, sf::RenderStates states) const { + states.transform *= getTransform(); + sf::RectangleShape frame{{get_size()*0.9f, get_size()*0.9f}}; + frame.setFillColor(sf::Color::Black); + frame.setOutlineThickness(1.f); + frame.setOutlineColor(sf::Color::White); + frame.setOrigin(frame.getSize().x / 2.f, frame.getSize().y / 2.f); + frame.setPosition(get_size()/2.f, get_size()/2.f); + target.draw(frame, states); + + sf::Text message; + message.setFont(m_resources.fallback_font.medium); + message.setString(sf::String::fromUtf8(m_name.begin(), m_name.end())); + message.setCharacterSize(static_cast(0.1f*get_size())); + message.setFillColor(sf::Color::White); + auto bounds = message.getLocalBounds(); + message.setOrigin(bounds.left+bounds.width*0.5f, bounds.top+bounds.height*0.5f); + auto biggest_side = std::max(bounds.width, bounds.height); + if (biggest_side > get_size()*0.8f) { + message.setScale(get_size()*0.8f / biggest_side, get_size()*0.8f / biggest_side); + } + message.setPosition(get_size()*0.5f, get_size()*0.5f); + target.draw(message, states); + } +} \ No newline at end of file diff --git a/src/Screens/MusicSelect/Panels/SubpagePanel.hpp b/src/Screens/MusicSelect/Panels/SubpagePanel.hpp new file mode 100644 index 0000000..183f2d9 --- /dev/null +++ b/src/Screens/MusicSelect/Panels/SubpagePanel.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +#include "Panel.hpp" + +namespace MusicSelect { + + class OptionPage; + + class SubpagePanel final : public Panel { + public: + SubpagePanel( + SharedResources& resources, + const jbcoe::polymorphic_value& subpage, + const std::string& name + ) : + Panel(resources), + m_subpage(subpage), + m_name(name) + {}; + void click(Ribbon& ribbon, const Data::Button& button) override; + private: + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; + jbcoe::polymorphic_value m_subpage; + std::string m_name; + }; +} \ No newline at end of file diff --git a/src/Screens/MusicSelect/Ribbon.cpp b/src/Screens/MusicSelect/Ribbon.cpp index a0bbbbe..2f13273 100644 --- a/src/Screens/MusicSelect/Ribbon.cpp +++ b/src/Screens/MusicSelect/Ribbon.cpp @@ -11,7 +11,7 @@ #include "../../Data/Song.hpp" #include "../../Toolkit/QuickRNG.hpp" -#include "Panel.hpp" +#include "Panels/Panel.hpp" namespace MusicSelect { diff --git a/src/Screens/MusicSelect/Ribbon.hpp b/src/Screens/MusicSelect/Ribbon.hpp index fb2e0d1..b08480e 100644 --- a/src/Screens/MusicSelect/Ribbon.hpp +++ b/src/Screens/MusicSelect/Ribbon.hpp @@ -12,11 +12,12 @@ #include "../../Toolkit/Debuggable.hpp" #include "../../Toolkit/EasingFunctions.hpp" #include "SharedResources.hpp" -#include "Panel.hpp" #include "PanelLayout.hpp" namespace MusicSelect { + class Panel; + enum class Direction { Right, Left, diff --git a/src/Screens/MusicSelect/SharedResources.cpp b/src/Screens/MusicSelect/SharedResources.cpp index d04326a..1e6129c 100644 --- a/src/Screens/MusicSelect/SharedResources.cpp +++ b/src/Screens/MusicSelect/SharedResources.cpp @@ -4,7 +4,8 @@ #include "../../Toolkit/HSL.hpp" -#include "Panel.hpp" +#include "OptionPage.hpp" +#include "Panels/Panel.hpp" namespace MusicSelect { @@ -24,10 +25,9 @@ namespace MusicSelect { } } - SharedResources::SharedResources(Data::Preferences& p) : + SharedResources::SharedResources(Data::Preferences& p, const Resources::Markers& m) : Data::HoldsPreferences(p), - covers(), - fallback_cover() + markers(m) { covers.reserve(256); if (not fallback_cover.loadFromFile("assets/textures/fallback_cover.png")) { diff --git a/src/Screens/MusicSelect/SharedResources.hpp b/src/Screens/MusicSelect/SharedResources.hpp index d1d5bdd..15f0dbb 100644 --- a/src/Screens/MusicSelect/SharedResources.hpp +++ b/src/Screens/MusicSelect/SharedResources.hpp @@ -3,10 +3,12 @@ #include #include +#include #include #include #include +#include "../../Resources/Marker.hpp" #include "../../Resources/TextureCache.hpp" #include "../../Data/Preferences.hpp" #include "../../Data/Song.hpp" @@ -17,6 +19,7 @@ namespace MusicSelect { class SelectablePanel; + class OptionPage; struct TimedSelectedPanel { TimedSelectedPanel(SelectablePanel& s) : panel(s), first_click(), last_click() {}; @@ -35,7 +38,7 @@ namespace MusicSelect { // Holds everything that needs to be shared by all levels of the class hierarchy struct SharedResources : public Data::HoldsPreferences { - SharedResources(Data::Preferences& p); + SharedResources(Data::Preferences& p, const Resources::Markers& m); Textures::TextureCache covers; sf::Texture fallback_cover; @@ -55,6 +58,10 @@ namespace MusicSelect { sf::Color get_chart_color(const std::string& chart); MusicPreview music_preview; + + std::stack> options_state; + + const Resources::Markers& markers; }; // Proxy for HoldsPreferences diff --git a/src/Screens/MusicSelect/SongInfo.cpp b/src/Screens/MusicSelect/SongInfo.cpp index 3bcc9c9..9aa3b5f 100644 --- a/src/Screens/MusicSelect/SongInfo.cpp +++ b/src/Screens/MusicSelect/SongInfo.cpp @@ -8,7 +8,7 @@ #include "../../Toolkit/EasingFunctions.hpp" #include "../../Toolkit/NormalizedOrigin.hpp" -#include "Panel.hpp" +#include "Panels/Panel.hpp" namespace MusicSelect {