Make density Graphs visible
This commit is contained in:
parent
4f0b11e4b3
commit
677cc62073
@ -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 = [
|
||||||
|
@ -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 &¬e : chart.notes) {
|
for (auto &¬e : 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};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user