Show song cover on HUD
This commit is contained in:
parent
3dd50d463b
commit
c61b470f55
@ -41,8 +41,10 @@ sources = [
|
|||||||
'src/Screens/MusicSelect/MusicSelect.cpp',
|
'src/Screens/MusicSelect/MusicSelect.cpp',
|
||||||
'src/Screens/MusicSelect/Panel.hpp',
|
'src/Screens/MusicSelect/Panel.hpp',
|
||||||
'src/Screens/MusicSelect/Panel.cpp',
|
'src/Screens/MusicSelect/Panel.cpp',
|
||||||
'src/Screens/MusicSelect/Resources.hpp',
|
'src/Screens/MusicSelect/SharedResources.hpp',
|
||||||
'src/Screens/MusicSelect/Resources.cpp',
|
'src/Screens/MusicSelect/SharedResources.cpp',
|
||||||
|
'src/Screens/MusicSelect/SongInfo.hpp',
|
||||||
|
'src/Screens/MusicSelect/SongInfo.cpp',
|
||||||
'src/Screens/MusicSelect/Ribbon.hpp',
|
'src/Screens/MusicSelect/Ribbon.hpp',
|
||||||
'src/Screens/MusicSelect/Ribbon.cpp',
|
'src/Screens/MusicSelect/Ribbon.cpp',
|
||||||
# 'src/Screens/Result.hpp',
|
# 'src/Screens/Result.hpp',
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
#include <SFML/System.hpp>
|
#include <SFML/System.hpp>
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
// By convention all axis-independant lengths are expressed as a ratio of the screen WIDTH (see panel_size and spacing)
|
// By convention all axis-independant lengths are expressed as a ratio of the screen WIDTH
|
||||||
|
// see panel_size and panel_spacing for example
|
||||||
struct Screen {
|
struct Screen {
|
||||||
std::size_t width = 768;
|
std::size_t width = 768;
|
||||||
std::size_t height = 1360;
|
std::size_t height = 1360;
|
||||||
@ -47,27 +48,35 @@ namespace Data {
|
|||||||
Layout layout;
|
Layout layout;
|
||||||
|
|
||||||
Preferences() : screen(), layout() {
|
Preferences() : screen(), layout() {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Preferences() {
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void load() {
|
||||||
auto path = std::filesystem::path("data/preferences.json");
|
auto path = std::filesystem::path("data/preferences.json");
|
||||||
if (std::filesystem::exists(path)) {
|
if (std::filesystem::exists(path)) {
|
||||||
std::ifstream prefs_file;
|
std::ifstream prefs_file;
|
||||||
prefs_file.open(path);
|
prefs_file.open(path);
|
||||||
try {
|
try {
|
||||||
cereal::JSONInputArchive archive{prefs_file};
|
cereal::JSONInputArchive archive{prefs_file};
|
||||||
this->serialize(archive);
|
serialize(archive);
|
||||||
} catch(const std::exception& e) {
|
} catch(const std::exception& e) {
|
||||||
std::cerr << "Error while loading data/preferences.json : " << e.what() << std::endl;
|
std::cerr << "Error while loading data/preferences.json : " << e.what() << std::endl;
|
||||||
std::cerr << "Using fallback preferences instead" << std::endl;
|
std::cerr << "Using fallback preferences instead" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
~Preferences() {
|
void save() {
|
||||||
auto data_folder = std::filesystem::path("data");
|
auto data_folder = std::filesystem::path("data");
|
||||||
if (not std::filesystem::exists(data_folder)) {
|
if (not std::filesystem::exists(data_folder)) {
|
||||||
std::filesystem::create_directory(data_folder);
|
std::filesystem::create_directory(data_folder);
|
||||||
}
|
}
|
||||||
if (not std::filesystem::is_directory(data_folder)) {
|
if (not std::filesystem::is_directory(data_folder)) {
|
||||||
std::cerr << "Could not save preferences : can't create data folder, a file named 'data' exists" << std::endl;
|
std::cerr << "Can't create data folder to save preferences, a file named 'data' exists" << std::endl;
|
||||||
}
|
}
|
||||||
std::ofstream preferences_file;
|
std::ofstream preferences_file;
|
||||||
preferences_file.open(data_folder / "preferences.json", std::ofstream::trunc | std::ofstream::out);
|
preferences_file.open(data_folder / "preferences.json", std::ofstream::trunc | std::ofstream::out);
|
||||||
@ -75,7 +84,7 @@ namespace Data {
|
|||||||
cereal::JSONOutputArchive archive{preferences_file};
|
cereal::JSONOutputArchive archive{preferences_file};
|
||||||
serialize(archive);
|
serialize(archive);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
void serialize(Archive & archive) {
|
void serialize(Archive & archive) {
|
||||||
|
@ -11,6 +11,22 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
bool cmp_dif_name::operator()(const std::string &a, const std::string &b) const {
|
||||||
|
if (dif_names.find(a) != dif_names.end()) {
|
||||||
|
if (dif_names.find(b) != dif_names.end()) {
|
||||||
|
return dif_names.find(a)->second < dif_names.find(b)->second;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dif_names.find(b) != dif_names.end()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return a < b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<fs::path> Song::full_cover_path() const {
|
std::optional<fs::path> Song::full_cover_path() const {
|
||||||
if (cover) {
|
if (cover) {
|
||||||
return folder/cover.value();
|
return folder/cover.value();
|
||||||
|
@ -3,15 +3,23 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <map>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Difficulty name ordering : BSC > ADV > EXT > anything else in lexicographical order
|
||||||
|
*/
|
||||||
|
struct cmp_dif_name {
|
||||||
|
std::map<std::string,int> dif_names = {{"BSC",1},{"ADV",2},{"EXT",3}};
|
||||||
|
bool operator()(const std::string& a, const std::string& b) const;
|
||||||
|
};
|
||||||
|
|
||||||
// Basic metadata about a song
|
// Basic metadata about a song
|
||||||
struct Song {
|
struct Song {
|
||||||
Song() = default;
|
Song() = default;
|
||||||
@ -26,7 +34,7 @@ namespace Data {
|
|||||||
// Mapping from chart difficulty (BSC, ADV, EXT ...) to the numeric level,
|
// Mapping from chart difficulty (BSC, ADV, EXT ...) to the numeric level,
|
||||||
// the level is stored multiplied by 10 and displayed divided by 10
|
// the level is stored multiplied by 10 and displayed divided by 10
|
||||||
// to allow for decimal levels (introduced in jubeat ... festo ?)
|
// to allow for decimal levels (introduced in jubeat ... festo ?)
|
||||||
std::unordered_map<std::string, unsigned int> chart_levels;
|
std::map<std::string, unsigned int, cmp_dif_name> chart_levels;
|
||||||
|
|
||||||
std::optional<fs::path> full_cover_path() const;
|
std::optional<fs::path> full_cover_path() const;
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ namespace Textures {
|
|||||||
|
|
||||||
// Hold time elapsed since loaded
|
// Hold time elapsed since loaded
|
||||||
struct AutoloadedTexture {
|
struct AutoloadedTexture {
|
||||||
AutoloadedTexture(std::shared_ptr<sf::Texture> t_texture) : texture(t_texture), clock() {};
|
AutoloadedTexture(std::shared_ptr<sf::Texture> t_texture) : texture(t_texture), loaded_since() {};
|
||||||
std::shared_ptr<sf::Texture> texture;
|
std::shared_ptr<sf::Texture> texture;
|
||||||
sf::Clock clock;
|
sf::Clock loaded_since;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Loads textures asynchronously (in the background) on demand and stores them in a map for easy path-based access
|
// Loads textures asynchronously (in the background) on demand and stores them in a map for easy path-based access
|
||||||
|
@ -11,6 +11,7 @@ MusicSelect::Screen::Screen(const Data::SongList& t_song_list) :
|
|||||||
song_list(t_song_list),
|
song_list(t_song_list),
|
||||||
resources(),
|
resources(),
|
||||||
ribbon(resources, m_panel_size, m_panel_spacing),
|
ribbon(resources, m_panel_size, m_panel_spacing),
|
||||||
|
song_info(resources, m_upper_part_width, m_upper_part_height),
|
||||||
selected_panel(),
|
selected_panel(),
|
||||||
button_highlight(m_panel_size, m_panel_spacing),
|
button_highlight(m_panel_size, m_panel_spacing),
|
||||||
key_mapping()
|
key_mapping()
|
||||||
@ -47,17 +48,20 @@ void MusicSelect::Screen::select_chart(sf::RenderWindow& window) {
|
|||||||
break;
|
break;
|
||||||
case sf::Event::MouseButtonPressed:
|
case sf::Event::MouseButtonPressed:
|
||||||
handle_mouse_click(event.mouseButton);
|
handle_mouse_click(event.mouseButton);
|
||||||
|
break;
|
||||||
case sf::Event::Closed:
|
case sf::Event::Closed:
|
||||||
window.close();
|
window.close();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::SFML::Update(window, imguiClock.restart());
|
ImGui::SFML::Update(window, imguiClock.restart());
|
||||||
window.clear(sf::Color(252, 201, 0, 255));
|
window.clear(sf::Color::Black);
|
||||||
ribbon.draw_debug();
|
ribbon.draw_debug();
|
||||||
window.draw(ribbon);
|
window.draw(ribbon);
|
||||||
window.draw(button_highlight);
|
window.draw(button_highlight);
|
||||||
|
window.draw(song_info);
|
||||||
ImGui::SFML::Render(window);
|
ImGui::SFML::Render(window);
|
||||||
window.display();
|
window.display();
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
#include "../../Data/KeyMapping.hpp"
|
#include "../../Data/KeyMapping.hpp"
|
||||||
#include "../../Toolkit/AffineTransform.hpp"
|
#include "../../Toolkit/AffineTransform.hpp"
|
||||||
#include "Ribbon.hpp"
|
#include "Ribbon.hpp"
|
||||||
#include "Resources.hpp"
|
#include "SongInfo.hpp"
|
||||||
|
#include "SharedResources.hpp"
|
||||||
#include "ButtonHighlight.hpp"
|
#include "ButtonHighlight.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
@ -23,15 +24,18 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Data
|
// Data
|
||||||
const Data::SongList& song_list;
|
const Data::SongList song_list;
|
||||||
float m_panel_size = 160.0f;
|
float m_panel_size = 160.0f;
|
||||||
float m_panel_spacing = 112.0f / 3.0f;
|
float m_panel_spacing = 112.0f / 3.0f;
|
||||||
|
float m_upper_part_width = 768.0f;
|
||||||
|
float m_upper_part_height = 464.0f;
|
||||||
|
|
||||||
// Resources
|
// Resources
|
||||||
Resources resources;
|
SharedResources resources;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
Ribbon ribbon;
|
Ribbon ribbon;
|
||||||
|
SongInfo song_info;
|
||||||
std::optional<std::reference_wrapper<SongPanel>> selected_panel;
|
std::optional<std::reference_wrapper<SongPanel>> selected_panel;
|
||||||
ButtonHighlight button_highlight;
|
ButtonHighlight button_highlight;
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#include "Panel.hpp"
|
#include "Panel.hpp"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
#include "MusicSelect.hpp"
|
#include "MusicSelect.hpp"
|
||||||
|
#include "SharedResources.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
void ColorPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
void ColorPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
@ -64,7 +67,41 @@ namespace MusicSelect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SongPanel::click(Ribbon& ribbon, std::size_t from_button_index) {
|
void SongPanel::click(Ribbon& ribbon, std::size_t from_button_index) {
|
||||||
|
if (selected_chart.has_value()) {
|
||||||
|
// The song was already selected : look for the next chart in order
|
||||||
|
auto it = m_song.chart_levels.upper_bound(*selected_chart);
|
||||||
|
if (it != m_song.chart_levels.cend()) {
|
||||||
|
selected_chart = it->first;
|
||||||
|
} else {
|
||||||
|
selected_chart = m_song.chart_levels.cbegin()->first;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The song was not selected before : unselect the last one
|
||||||
|
if (m_resources.selected_panel.has_value()) {
|
||||||
|
m_resources.selected_panel->panel.unselect();
|
||||||
|
}
|
||||||
|
// Look for the first chart with dif greater or equal to the last select one
|
||||||
|
// or else select the first chart
|
||||||
|
auto it = m_song.chart_levels.lower_bound(ribbon.m_global_chart_dif);
|
||||||
|
if (it != m_song.chart_levels.cend()) {
|
||||||
|
selected_chart = it->first;
|
||||||
|
} else {
|
||||||
|
selected_chart = m_song.chart_levels.cbegin()->first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_resources.selected_panel.emplace(TimedSelectedPanel{*this});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SongPanel::unselect() {
|
||||||
|
selected_chart.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ChartSelection> SongPanel::get_selected_chart() const {
|
||||||
|
if (selected_chart) {
|
||||||
|
return ChartSelection{m_song, *selected_chart};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
void SongPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
@ -75,7 +112,7 @@ namespace MusicSelect {
|
|||||||
sf::Sprite cover{*(loaded_texture->texture)};
|
sf::Sprite cover{*(loaded_texture->texture)};
|
||||||
auto alpha = static_cast<std::uint8_t>(
|
auto alpha = static_cast<std::uint8_t>(
|
||||||
m_seconds_to_alpha.clampedTransform(
|
m_seconds_to_alpha.clampedTransform(
|
||||||
loaded_texture->clock.getElapsedTime().asSeconds()
|
loaded_texture->loaded_since.getElapsedTime().asSeconds()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
cover.setColor(sf::Color(255, 255, 255, alpha));
|
cover.setColor(sf::Color(255, 255, 255, alpha));
|
||||||
@ -89,7 +126,7 @@ namespace MusicSelect {
|
|||||||
song_title.setFont(m_resources.noto_sans_medium);
|
song_title.setFont(m_resources.noto_sans_medium);
|
||||||
song_title.setString(m_song.title);
|
song_title.setString(m_song.title);
|
||||||
song_title.setCharacterSize(static_cast<unsigned int>(0.06875f*m_size));
|
song_title.setCharacterSize(static_cast<unsigned int>(0.06875f*m_size));
|
||||||
song_title.setFillColor(sf::Color::Black);
|
song_title.setFillColor(sf::Color::White);
|
||||||
auto song_title_bounds = song_title.getLocalBounds();
|
auto song_title_bounds = song_title.getLocalBounds();
|
||||||
// text is too long : scale it
|
// text is too long : scale it
|
||||||
if (song_title_bounds.width > 0.88f * m_size) {
|
if (song_title_bounds.width > 0.88f * m_size) {
|
||||||
@ -97,7 +134,6 @@ namespace MusicSelect {
|
|||||||
}
|
}
|
||||||
song_title.setPosition(18.f/160.f,9.f/160.f);
|
song_title.setPosition(18.f/160.f,9.f/160.f);
|
||||||
target.draw(song_title, states);
|
target.draw(song_title, states);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_to_global_bounds(sf::RectangleShape& rect, const sf::Text& text) {
|
void set_to_global_bounds(sf::RectangleShape& rect, const sf::Text& text) {
|
||||||
|
@ -1,27 +1,31 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
#include <SFML/Window.hpp>
|
#include <SFML/Window.hpp>
|
||||||
|
|
||||||
#include "../../Data/SongList.hpp"
|
#include "../../Data/SongList.hpp"
|
||||||
#include "../../Toolkit/AffineTransform.hpp"
|
#include "../../Toolkit/AffineTransform.hpp"
|
||||||
#include "Resources.hpp"
|
#include "SharedResources.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
class Ribbon;
|
class Ribbon;
|
||||||
|
class SharedResources;
|
||||||
|
|
||||||
// A Panel holds anything that can go under a button on the moving part
|
// A Panel holds anything that can go under a button on the moving part
|
||||||
// of the music select screen, be it nothing, a category indicator, or a song
|
// of the music select screen, be it nothing, a category indicator, or a song
|
||||||
class Panel : public sf::Drawable, public sf::Transformable {
|
class Panel : public sf::Drawable, public sf::Transformable {
|
||||||
public:
|
public:
|
||||||
Panel(const float& size, Resources& resources) : m_size(size), m_resources(resources) {};
|
Panel(const float& size, SharedResources& resources) : m_size(size), m_resources(resources) {};
|
||||||
// What happens when you click on the panel
|
// What happens when you click on the panel
|
||||||
virtual void click(Ribbon& ribbon, std::size_t from_button_index) = 0;
|
virtual void click(Ribbon& ribbon, std::size_t from_button_index) = 0;
|
||||||
virtual ~Panel() = default;
|
virtual ~Panel() = default;
|
||||||
protected:
|
protected:
|
||||||
const float& m_size;
|
const float& m_size;
|
||||||
Resources& m_resources;
|
SharedResources& m_resources;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmptyPanel final : public Panel {
|
class EmptyPanel final : public Panel {
|
||||||
@ -34,7 +38,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
class ColoredMessagePanel final : public Panel {
|
class ColoredMessagePanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
ColoredMessagePanel(const float& size, Resources& resources, const sf::Color& color, const std::string& message) : Panel(size, resources), m_color(color), m_message(message) {};
|
ColoredMessagePanel(const float& size, SharedResources& resources, const sf::Color& color, const std::string& message) : Panel(size, resources), m_color(color), m_message(message) {};
|
||||||
void click(Ribbon& ribbon, std::size_t from_button_index) override {return;};
|
void click(Ribbon& ribbon, std::size_t from_button_index) override {return;};
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
@ -44,7 +48,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
class ColorPanel final : public Panel {
|
class ColorPanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
ColorPanel(const float& size, Resources& resources, const sf::Color& t_color) : Panel(size, resources), m_color(t_color) {};
|
ColorPanel(const float& size, SharedResources& resources, const sf::Color& t_color) : Panel(size, resources), m_color(t_color) {};
|
||||||
void click(Ribbon& ribbon, std::size_t from_button_index) override {return;};
|
void click(Ribbon& ribbon, std::size_t from_button_index) override {return;};
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
@ -53,22 +57,37 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
class CategoryPanel final : public Panel {
|
class CategoryPanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
explicit CategoryPanel(const float& size, Resources& resources, const std::string& t_label) : Panel(size, resources), m_label(t_label) {};
|
explicit CategoryPanel(const float& size, SharedResources& resources, const std::string& t_label) : Panel(size, resources), m_label(t_label) {};
|
||||||
void click(Ribbon& ribbon, std::size_t from_button_index) override;
|
void click(Ribbon& ribbon, std::size_t from_button_index) override;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
std::string m_label;
|
std::string m_label;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SongPanel final : public Panel {
|
struct ChartSelection {
|
||||||
|
const Data::Song& song;
|
||||||
|
const std::string& chart;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SelectablePanel : public Panel {
|
||||||
public:
|
public:
|
||||||
explicit SongPanel(const float& size, Resources& resources, const Data::Song& t_song) : Panel(size, resources), m_song(t_song) {};
|
using Panel::Panel;
|
||||||
|
virtual ~SelectablePanel() = default;
|
||||||
|
virtual void unselect() = 0;
|
||||||
|
virtual std::optional<ChartSelection> get_selected_chart() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SongPanel final : public SelectablePanel {
|
||||||
|
public:
|
||||||
|
explicit SongPanel(const float& size, SharedResources& resources, const Data::Song& t_song) : SelectablePanel(size, resources), m_song(t_song) {};
|
||||||
void click(Ribbon& ribbon, std::size_t from_button_index) override;
|
void click(Ribbon& ribbon, std::size_t from_button_index) override;
|
||||||
|
void unselect() override;
|
||||||
|
std::optional<ChartSelection> get_selected_chart() const override;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
const Data::Song& m_song;
|
const Data::Song& m_song;
|
||||||
const Toolkit::AffineTransform<float> m_seconds_to_alpha{0.0f, 0.15f, 0.f, 255.f};
|
const Toolkit::AffineTransform<float> m_seconds_to_alpha{0.0f, 0.15f, 0.f, 255.f};
|
||||||
std::optional<std::reference_wrapper<std::string>> selected_chart;
|
std::optional<std::string> selected_chart;
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_to_global_bounds(sf::RectangleShape& rect, const sf::Text& text);
|
void set_to_global_bounds(sf::RectangleShape& rect, const sf::Text& text);
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
|
||||||
|
|
||||||
#include "../../Resources/Autoloader.hpp"
|
|
||||||
|
|
||||||
namespace MusicSelect {
|
|
||||||
struct Resources {
|
|
||||||
Resources();
|
|
||||||
Textures::Autoloader covers;
|
|
||||||
sf::Texture fallback_cover;
|
|
||||||
sf::Font noto_sans_medium;
|
|
||||||
};
|
|
||||||
}
|
|
@ -64,7 +64,7 @@ namespace MusicSelect {
|
|||||||
return clock.getElapsedTime() / m_time_factor > sf::milliseconds(300);
|
return clock.getElapsedTime() / m_time_factor > sf::milliseconds(300);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ribbon::Ribbon(Resources& t_resources, float& panel_size, float& panel_spacing) :
|
Ribbon::Ribbon(SharedResources& t_resources, float& panel_size, float& panel_spacing) :
|
||||||
m_layout(),
|
m_layout(),
|
||||||
m_move_animation(),
|
m_move_animation(),
|
||||||
m_resources(t_resources),
|
m_resources(t_resources),
|
||||||
|
@ -3,11 +3,12 @@
|
|||||||
#include <SFML/Graphics/Drawable.hpp>
|
#include <SFML/Graphics/Drawable.hpp>
|
||||||
#include <SFML/Graphics/Transformable.hpp>
|
#include <SFML/Graphics/Transformable.hpp>
|
||||||
|
|
||||||
#include "Panel.hpp"
|
|
||||||
#include "../../Data/SongList.hpp"
|
#include "../../Data/SongList.hpp"
|
||||||
#include "../../Toolkit/AffineTransform.hpp"
|
#include "../../Toolkit/AffineTransform.hpp"
|
||||||
#include "../../Toolkit/Debuggable.hpp"
|
#include "../../Toolkit/Debuggable.hpp"
|
||||||
#include "../../Toolkit/EasingFunctions.hpp"
|
#include "../../Toolkit/EasingFunctions.hpp"
|
||||||
|
#include "Panel.hpp"
|
||||||
|
#include "SharedResources.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ namespace MusicSelect {
|
|||||||
// It can be sorted in a number of ways
|
// It can be sorted in a number of ways
|
||||||
class Ribbon final : public sf::Drawable, public sf::Transformable, public Toolkit::Debuggable {
|
class Ribbon final : public sf::Drawable, public sf::Transformable, public Toolkit::Debuggable {
|
||||||
public:
|
public:
|
||||||
Ribbon(Resources& t_resources, float& panel_size, float& panel_spacing);
|
Ribbon(SharedResources& t_resources, float& panel_size, float& panel_spacing);
|
||||||
void title_sort(const Data::SongList& song_list);
|
void title_sort(const Data::SongList& song_list);
|
||||||
void test_sort();
|
void test_sort();
|
||||||
void test2_sort();
|
void test2_sort();
|
||||||
@ -44,6 +45,7 @@ namespace MusicSelect {
|
|||||||
void move_left();
|
void move_left();
|
||||||
void move_to_next_category(const std::size_t& from_button_index);
|
void move_to_next_category(const std::size_t& from_button_index);
|
||||||
void draw_debug() override;
|
void draw_debug() override;
|
||||||
|
std::string m_global_chart_dif;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
void draw_with_animation(sf::RenderTarget& target, sf::RenderStates states) const;
|
void draw_with_animation(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||||
@ -54,7 +56,7 @@ namespace MusicSelect {
|
|||||||
std::vector<std::array<std::shared_ptr<Panel>,3>> m_layout;
|
std::vector<std::array<std::shared_ptr<Panel>,3>> m_layout;
|
||||||
std::size_t m_position = 0;
|
std::size_t m_position = 0;
|
||||||
mutable std::optional<MoveAnimation> m_move_animation;
|
mutable std::optional<MoveAnimation> m_move_animation;
|
||||||
Resources& m_resources;
|
SharedResources& m_resources;
|
||||||
float m_time_factor = 1.f;
|
float m_time_factor = 1.f;
|
||||||
Data::Song empty_song;
|
Data::Song empty_song;
|
||||||
float& m_panel_size;
|
float& m_panel_size;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "Resources.hpp"
|
#include "SharedResources.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
MusicSelect::Resources::Resources() :
|
MusicSelect::SharedResources::SharedResources() :
|
||||||
covers(),
|
covers(),
|
||||||
fallback_cover(),
|
fallback_cover(),
|
||||||
noto_sans_medium()
|
noto_sans_medium()
|
31
src/Screens/MusicSelect/SharedResources.hpp
Normal file
31
src/Screens/MusicSelect/SharedResources.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <SFML/System.hpp>
|
||||||
|
|
||||||
|
#include "../../Resources/Autoloader.hpp"
|
||||||
|
#include "../../Data/SongList.hpp"
|
||||||
|
|
||||||
|
#include "Panel.hpp"
|
||||||
|
|
||||||
|
namespace MusicSelect {
|
||||||
|
|
||||||
|
class SelectablePanel;
|
||||||
|
|
||||||
|
struct TimedSelectedPanel {
|
||||||
|
TimedSelectedPanel(SelectablePanel& s) : panel(s), selected_since() {};
|
||||||
|
SelectablePanel& panel;
|
||||||
|
sf::Clock selected_since;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SharedResources {
|
||||||
|
SharedResources();
|
||||||
|
Textures::Autoloader covers;
|
||||||
|
sf::Texture fallback_cover;
|
||||||
|
sf::Font noto_sans_medium;
|
||||||
|
std::optional<TimedSelectedPanel> selected_panel;
|
||||||
|
};
|
||||||
|
}
|
54
src/Screens/MusicSelect/SongInfo.cpp
Normal file
54
src/Screens/MusicSelect/SongInfo.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "SongInfo.hpp"
|
||||||
|
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
namespace MusicSelect {
|
||||||
|
|
||||||
|
SongInfo::SongInfo(SharedResources& resources, const float& width, const float& height) :
|
||||||
|
m_resources(resources),
|
||||||
|
m_width(width),
|
||||||
|
m_height(height),
|
||||||
|
m_cover_fallback({height*0.8f, height*0.8f})
|
||||||
|
{
|
||||||
|
m_cover_fallback.setFillColor(sf::Color::Black);
|
||||||
|
m_cover_fallback.setOutlineThickness(1.f);
|
||||||
|
m_cover_fallback.setOutlineColor(sf::Color::White);
|
||||||
|
m_cover_fallback.setPosition(height*0.1f, height*0.1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SongInfo::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
|
draw_cover(target, states);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MusicSelect::SongInfo::draw_cover(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
|
states.transform *= getTransform();
|
||||||
|
target.draw(m_cover_fallback, states);
|
||||||
|
auto selected_panel = m_resources.selected_panel;
|
||||||
|
if (not selected_panel.has_value()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto selected_chart = selected_panel->panel.get_selected_chart();
|
||||||
|
if (not selected_chart.has_value()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto cover_path = selected_chart->song.full_cover_path();
|
||||||
|
if (not cover_path.has_value()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto cover_texture = m_resources.covers.async_get(*cover_path);
|
||||||
|
if (not cover_texture.has_value()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sf::Sprite cover{*(cover_texture->texture)};
|
||||||
|
auto bounds = cover.getGlobalBounds();
|
||||||
|
cover.setScale(m_height*0.8f/bounds.width, m_height*0.8f/bounds.height);
|
||||||
|
cover.setPosition(m_height*0.1f, m_height*0.1f);
|
||||||
|
auto alpha = static_cast<std::uint8_t>(
|
||||||
|
m_seconds_to_alpha.clampedTransform(
|
||||||
|
selected_panel->selected_since.getElapsedTime().asSeconds()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
cover.setColor(sf::Color(255, 255, 255, alpha));
|
||||||
|
target.draw(cover, states);
|
||||||
|
}
|
24
src/Screens/MusicSelect/SongInfo.hpp
Normal file
24
src/Screens/MusicSelect/SongInfo.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <SFML/System.hpp>
|
||||||
|
|
||||||
|
#include "../../Toolkit/AffineTransform.hpp"
|
||||||
|
|
||||||
|
#include "SharedResources.hpp"
|
||||||
|
|
||||||
|
namespace MusicSelect {
|
||||||
|
// SongInfo displays the song info on the top part of the screen
|
||||||
|
class SongInfo : public sf::Drawable, public sf::Transformable {
|
||||||
|
public:
|
||||||
|
SongInfo(SharedResources& resources, const float& width, const float& height);
|
||||||
|
private:
|
||||||
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
|
void draw_cover(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||||
|
SharedResources& m_resources;
|
||||||
|
const float& m_width;
|
||||||
|
const float& m_height;
|
||||||
|
sf::RectangleShape m_cover_fallback;
|
||||||
|
const Toolkit::AffineTransform<float> m_seconds_to_alpha{0.0f, 0.3f, 0.f, 255.f};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user