1
0
mirror of synced 2025-02-08 22:59:41 +01:00

Make density Graphs visible

This commit is contained in:
Stepland 2020-02-18 10:09:07 +01:00
parent 4f0b11e4b3
commit 677cc62073
8 changed files with 80 additions and 33 deletions

View File

@ -2,7 +2,7 @@ project(
'jujube', 'jujube',
'cpp', 'cpp',
default_options : ['cpp_std=c++17'], default_options : ['cpp_std=c++17'],
version : '0.1.0-alpha', version : '0.1.0-alpha'
) )
cc = meson.get_compiler('cpp') cc = meson.get_compiler('cpp')
@ -16,7 +16,6 @@ thread_dep = dependency('threads')
m_dep = cc.find_library('m', required : false) m_dep = cc.find_library('m', required : false)
gl_dep = dependency('gl') gl_dep = dependency('gl')
add_project_link_arguments(['-lstdc++'], language : 'cpp') add_project_link_arguments(['-lstdc++'], language : 'cpp')
sources = [ sources = [

View File

@ -5,17 +5,53 @@
#include <SFML/Audio.hpp> #include <SFML/Audio.hpp>
namespace Data { namespace MusicSelect {
DensityGraph::DensityGraph(const std::array<unsigned int, 115>& t_densities) :
m_densities(t_densities),
m_vertex_array(sf::Quads, 0)
{
std::size_t column = 0;
for (auto &&density : m_densities) {
for (size_t row = 0; row < static_cast<std::size_t>(density); row++) {
m_vertex_array.append(sf::Vertex(
sf::Vector2f(column*5.0f, row*-5.0f),
sf::Color::White
));
m_vertex_array.append(sf::Vertex(
sf::Vector2f(column*5.0f, row*-5.0f),
sf::Color::White
));
m_vertex_array.append(sf::Vertex(
sf::Vector2f(column*5.0f, row*-5.0f),
sf::Color::White
));
m_vertex_array.append(sf::Vertex(
sf::Vector2f(column*5.0f, row*-5.0f),
sf::Color::White
));
}
column++;
}
}
void DensityGraph::draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform *= getTransform();
target.draw(m_vertex_array, states);
}
DensityGraph compute_density_graph_1(const SongDifficulty& sd) { DensityGraph compute_density_graph_1(const SongDifficulty& sd) {
return compute_density_graph_2(sd.song, sd.difficulty); return compute_density_graph_2(sd.song, sd.difficulty);
} }
DensityGraph compute_density_graph_2(const Song& song, const std::string& difficulty) { DensityGraph compute_density_graph_2(const Data::Song& song, const std::string& difficulty) {
auto c = song.get_chart(difficulty); auto c = song.get_chart(difficulty);
if (not c.has_value()) { if (not c.has_value()) {
throw std::invalid_argument("Song "+song.title+" has no "+difficulty+" chart"); throw std::invalid_argument("Song "+song.title+" has no "+difficulty+" chart");
} }
if (c->notes.empty()) {
return compute_density_graph_3(*c, 0, 0);
}
if (not song.audio.has_value()) { if (not song.audio.has_value()) {
return compute_density_graph_3(*c, c->notes.begin()->timing, c->notes.rbegin()->timing); return compute_density_graph_3(*c, c->notes.begin()->timing, c->notes.rbegin()->timing);
} }
@ -30,8 +66,8 @@ namespace Data {
); );
} }
DensityGraph compute_density_graph_3(const Chart& chart, long start, long end) { DensityGraph compute_density_graph_3(const Data::Chart& chart, long start, long end) {
DensityGraph d{}; std::array<unsigned int, 115> d{};
if (start != end) { if (start != end) {
for (auto &&note : chart.notes) { for (auto &&note : chart.notes) {
auto index = (note.timing-start)*115/(end-start); auto index = (note.timing-start)*115/(end-start);
@ -40,10 +76,10 @@ namespace Data {
std::replace_if( std::replace_if(
d.begin(), d.begin(),
d.end(), d.end(),
std::bind(std::greater<unsigned int>(), std::placeholders::_1, 8), std::bind(std::greater<unsigned int>(), std::placeholders::_1, 8U),
8 8
); );
} }
return d; return DensityGraph{d};
} }
} }

View File

@ -3,15 +3,24 @@
#include <array> #include <array>
#include <tuple> #include <tuple>
#include <SFML/Graphics.hpp>
#include "../../Data/Chart.hpp" #include "../../Data/Chart.hpp"
#include "../../Data/Song.hpp" #include "../../Data/Song.hpp"
#include "../../Toolkit/Cache.hpp" #include "../../Toolkit/Cache.hpp"
namespace Data { namespace MusicSelect {
using DensityGraph = std::array<unsigned int, 115>; class DensityGraph : public sf::Drawable, public sf::Transformable {
public:
explicit DensityGraph(const std::array<unsigned int, 115>& t_densities);
private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
std::array<unsigned int, 115> m_densities;
sf::VertexArray m_vertex_array;
};
struct SongDifficulty { struct SongDifficulty {
const Song& song; const Data::Song& song;
const std::string& difficulty; const std::string& difficulty;
bool operator==(const SongDifficulty &other) const { bool operator==(const SongDifficulty &other) const {
@ -23,16 +32,16 @@ namespace Data {
}; };
DensityGraph compute_density_graph_1(const SongDifficulty& sd); DensityGraph compute_density_graph_1(const SongDifficulty& sd);
DensityGraph compute_density_graph_2(const Song& song, const std::string& difficulty); DensityGraph compute_density_graph_2(const Data::Song& song, const std::string& difficulty);
DensityGraph compute_density_graph_3(const Chart& chart, long start, long end); DensityGraph compute_density_graph_3(const Data::Chart& chart, long start, long end);
using DensityGraphCache = Toolkit::Cache<SongDifficulty, DensityGraph, &compute_density_graph_1>; using DensityGraphCache = Toolkit::Cache<SongDifficulty, DensityGraph, &compute_density_graph_1>;
} }
namespace std { namespace std {
template <> template <>
struct hash<Data::SongDifficulty> { struct hash<MusicSelect::SongDifficulty> {
std::size_t operator()(const Data::SongDifficulty& sd) const { std::size_t operator()(const MusicSelect::SongDifficulty& sd) const {
auto song_hash = std::hash<std::string>()(sd.song.folder.string()); auto song_hash = std::hash<std::string>()(sd.song.folder.string());
song_hash ^= std::hash<std::string>()(sd.difficulty) + 0x9e3779b9 + (song_hash<<6) + (song_hash>>2); song_hash ^= std::hash<std::string>()(sd.difficulty) + 0x9e3779b9 + (song_hash<<6) + (song_hash>>2);
return song_hash; return song_hash;

View File

@ -98,9 +98,9 @@ namespace MusicSelect {
selected_chart.reset(); selected_chart.reset();
} }
std::optional<ChartSelection> SongPanel::get_selected_chart() const { std::optional<SongDifficulty> SongPanel::get_selected_difficulty() const {
if (selected_chart) { if (selected_chart) {
return ChartSelection{*m_song, *selected_chart}; return SongDifficulty{*m_song, *selected_chart};
} else { } else {
return {}; return {};
} }

View File

@ -8,6 +8,7 @@
#include "../../Data/Song.hpp" #include "../../Data/Song.hpp"
#include "../../Toolkit/AffineTransform.hpp" #include "../../Toolkit/AffineTransform.hpp"
#include "DensityGraph.hpp"
#include "SharedResources.hpp" #include "SharedResources.hpp"
namespace MusicSelect { namespace MusicSelect {
@ -62,17 +63,12 @@ namespace MusicSelect {
std::string m_label; std::string m_label;
}; };
struct ChartSelection {
const Data::Song& song;
const std::string& difficulty;
};
class SelectablePanel : public Panel { class SelectablePanel : public Panel {
public: public:
using Panel::Panel; using Panel::Panel;
virtual ~SelectablePanel() = default; virtual ~SelectablePanel() = default;
virtual void unselect() = 0; virtual void unselect() = 0;
virtual std::optional<ChartSelection> get_selected_chart() const = 0; virtual std::optional<SongDifficulty> get_selected_difficulty() const = 0;
}; };
class SongPanel final : public SelectablePanel { class SongPanel final : public SelectablePanel {
@ -80,7 +76,7 @@ namespace MusicSelect {
explicit SongPanel(SharedResources& resources, const std::shared_ptr<const Data::Song>& t_song) : SelectablePanel(resources), m_song(t_song) {}; explicit SongPanel(SharedResources& resources, const std::shared_ptr<const Data::Song>& t_song) : SelectablePanel(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; void unselect() override;
std::optional<ChartSelection> get_selected_chart() const override; std::optional<SongDifficulty> get_selected_difficulty() const override;
private: private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
std::shared_ptr<const Data::Song> m_song; std::shared_ptr<const Data::Song> m_song;

View File

@ -30,7 +30,7 @@ namespace MusicSelect {
if (not selected_panel.has_value()) { if (not selected_panel.has_value()) {
return {}; return {};
} }
auto chart_selection = selected_panel->panel.get_selected_chart(); auto chart_selection = selected_panel->panel.get_selected_difficulty();
if (not chart_selection.has_value()) { if (not chart_selection.has_value()) {
return {}; return {};
} }
@ -41,7 +41,7 @@ namespace MusicSelect {
if (not selected_panel.has_value()) { if (not selected_panel.has_value()) {
return {}; return {};
} }
auto chart_selection = selected_panel->panel.get_selected_chart(); auto chart_selection = selected_panel->panel.get_selected_difficulty();
if (not chart_selection.has_value()) { if (not chart_selection.has_value()) {
return {}; return {};
} }

View File

@ -34,7 +34,7 @@ namespace MusicSelect {
sf::Font noto_sans_medium; sf::Font noto_sans_medium;
Data::DensityGraphCache density_graphs; MusicSelect::DensityGraphCache density_graphs;
std::optional<TimedSelectedPanel> selected_panel; std::optional<TimedSelectedPanel> selected_panel;
std::string get_last_selected_difficulty(); std::string get_last_selected_difficulty();

View File

@ -28,7 +28,7 @@ namespace MusicSelect {
if (not selected_panel.has_value()) { if (not selected_panel.has_value()) {
return; return;
} }
auto selected_chart = selected_panel->panel.get_selected_chart(); auto selected_chart = selected_panel->panel.get_selected_difficulty();
if (not selected_chart.has_value()) { if (not selected_chart.has_value()) {
return; return;
} }
@ -73,7 +73,7 @@ namespace MusicSelect {
if (not selected_panel.has_value()) { if (not selected_panel.has_value()) {
return; return;
} }
auto selected_chart = selected_panel->panel.get_selected_chart(); auto selected_chart = selected_panel->panel.get_selected_difficulty();
if (not selected_chart.has_value()) { if (not selected_chart.has_value()) {
return; return;
} }
@ -128,7 +128,7 @@ namespace MusicSelect {
if (not selected_panel.has_value()) { if (not selected_panel.has_value()) {
return; return;
} }
auto selected_chart = selected_panel->panel.get_selected_chart(); auto selected_chart = selected_panel->panel.get_selected_difficulty();
if (not selected_chart.has_value()) { if (not selected_chart.has_value()) {
return; return;
} }
@ -177,7 +177,7 @@ namespace MusicSelect {
if (not selected_panel.has_value()) { if (not selected_panel.has_value()) {
return; return;
} }
auto selected_chart = selected_panel->panel.get_selected_chart(); auto selected_chart = selected_panel->panel.get_selected_difficulty();
if (not selected_chart.has_value()) { if (not selected_chart.has_value()) {
return; return;
} }
@ -227,9 +227,16 @@ namespace MusicSelect {
if (not selected_panel.has_value()) { if (not selected_panel.has_value()) {
return; return;
} }
auto selected_chart = selected_panel->panel.get_selected_chart(); auto selected_difficulty = selected_panel->panel.get_selected_difficulty();
if (not selected_chart.has_value()) { if (not selected_difficulty.has_value()) {
return; return;
} }
m_resources.density_graphs.load(*selected_difficulty);
auto densities = m_resources.density_graphs.get(*selected_difficulty);
if (not densities.has_value()) {
return;
}
densities->setScale(get_screen_width()/768.f, get_screen_width()/768.f);
target.draw(*densities, states);
} }
} }