1
0
mirror of synced 2024-09-24 03:18:24 +02:00

Display more stuff

This commit is contained in:
Stepland 2020-02-15 20:50:47 +01:00
parent 80cdb869fd
commit 629a54172a
14 changed files with 427 additions and 76 deletions

View File

@ -56,6 +56,8 @@ sources = [
'src/Toolkit/Debuggable.hpp',
'src/Toolkit/EasingFunctions.hpp',
'src/Toolkit/EasingFunctions.cpp',
'src/Toolkit/HSL.hpp',
'src/Toolkit/HSL.cpp',
'src/Toolkit/QuickRNG.hpp',
'src/Toolkit/QuickRNG.cpp',
]

View File

@ -56,8 +56,8 @@ namespace Data {
}
void load() {
auto path = std::filesystem::path("data/preferences.json");
if (std::filesystem::exists(path)) {
auto path = ghc::filesystem::path("data/preferences.json");
if (ghc::filesystem::exists(path)) {
std::ifstream prefs_file;
prefs_file.open(path);
try {
@ -71,11 +71,11 @@ namespace Data {
};
void save() {
auto data_folder = std::filesystem::path("data");
if (not std::filesystem::exists(data_folder)) {
std::filesystem::create_directory(data_folder);
auto data_folder = ghc::filesystem::path("data");
if (not ghc::filesystem::exists(data_folder)) {
ghc::filesystem::create_directory(data_folder);
}
if (not std::filesystem::is_directory(data_folder)) {
if (not ghc::filesystem::is_directory(data_folder)) {
std::cerr << "Can't create data folder to save preferences, a file named 'data' exists" << std::endl;
}
std::ofstream preferences_file;

View File

@ -15,13 +15,16 @@
int main(int argc, char const *argv[]) {
Data::Preferences preferences;
sf::ContextSettings settings;
settings.antialiasingLevel = 8;
sf::RenderWindow window{
sf::VideoMode(
preferences.screen.width,
preferences.screen.height
),
"jujube",
preferences.screen.fullscreen ? sf::Style::Fullscreen : sf::Style::Default
preferences.screen.fullscreen ? sf::Style::Fullscreen : sf::Style::Default,
settings
};
Data::SongList song_list;
MusicSelect::Screen music_select{song_list};

View File

@ -26,7 +26,6 @@ namespace Textures {
m_mapping.emplace(path, texture);
m_is_loading.erase(path);
}
std::cout << "Loaded " << path << std::endl;
}
void Autoloader::async_load(const fs::path& path) {

View File

@ -16,17 +16,6 @@ MusicSelect::Screen::Screen(const Data::SongList& t_song_list) :
button_highlight(m_panel_size, m_panel_spacing),
key_mapping()
{
/*
for (const auto& song : song_list.songs) {
if (song.cover) {
try {
resources.covers.get(song.cover.value());
} catch(const std::exception& e) {
std::cerr << e.what() << '\n';
}
}
}
*/
ribbon.title_sort(song_list);
std::cout << "loaded MusicSelect::Screen" << std::endl;
}

View File

@ -4,6 +4,9 @@
#include <SFML/Graphics.hpp>
#include "../../Toolkit/HSL.hpp"
#include "../../Toolkit/NormalizedOrigin.hpp"
#include "MusicSelect.hpp"
#include "SharedResources.hpp"
@ -30,7 +33,7 @@ namespace MusicSelect {
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);
Toolkit::setNormOrigin(frame, 0.5f, 0.5f);
frame.setPosition(m_size/2.f, m_size/2.f);
target.draw(frame, states);
@ -53,7 +56,7 @@ namespace MusicSelect {
label_text.setCharacterSize(100U);
label_text.setFillColor(sf::Color::White);
auto text_bounds = label_text.getLocalBounds();
label_text.setOrigin(text_bounds.width / 2.f, text_bounds.height / 2.f);
Toolkit::setNormOrigin(label_text, 0.5f, 0.5f);
if (text_bounds.height > text_bounds.width) {
label_text.setScale(m_size*0.8f/text_bounds.height, m_size*0.8f/text_bounds.height);
} else {
@ -88,9 +91,9 @@ namespace MusicSelect {
} else {
selected_chart = m_song.chart_levels.cbegin()->first;
}
}
m_resources.selected_panel.emplace(TimedSelectedPanel{*this});
}
}
void SongPanel::unselect() {
selected_chart.reset();
@ -105,6 +108,9 @@ namespace MusicSelect {
}
void SongPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const {
// We should gray out the panel if the currently selected difficulty doesn't exist for this song
auto selected_chart = m_resources.get_last_selected_chart();
bool should_be_grayed_out = m_song.chart_levels.find(selected_chart) == m_song.chart_levels.end();
if (m_song.cover) {
auto loaded_texture = m_resources.covers.async_get(m_song.folder/m_song.cover.value());
if (loaded_texture) {
@ -115,13 +121,49 @@ namespace MusicSelect {
loaded_texture->loaded_since.getElapsedTime().asSeconds()
)
);
cover.setColor(sf::Color(255, 255, 255, alpha));
auto grey = should_be_grayed_out ? 2 : 1;
cover.setColor(sf::Color(255/grey, 255/grey, 255/grey, alpha));
auto bounds = cover.getGlobalBounds();
cover.setScale(m_size*0.8f/bounds.width, m_size*0.8f/bounds.height);
cover.setPosition(m_size*0.1f,m_size*0.1563f);
target.draw(cover, states);
}
}
sf::CircleShape chart_dif_badge{m_size*0.1f, 30};
Toolkit::setNormOrigin(chart_dif_badge, 0.5f, 0.5f);
chart_dif_badge.setPosition(m_size*0.1f, m_size*(0.1563f + 0.15f));
if (should_be_grayed_out) {
chart_dif_badge.setFillColor(sf::Color(128,128,128));
} else {
if (selected_chart == "BSC") {
chart_dif_badge.setFillColor(m_resources.BSC_color);
} else if (selected_chart == "ADV") {
chart_dif_badge.setFillColor(m_resources.ADV_color);
} else if (selected_chart == "EXT") {
chart_dif_badge.setFillColor(m_resources.EXT_color);
} else {
chart_dif_badge.setFillColor(
Toolkit::HSL(
static_cast<int>(std::hash<std::string>{}(selected_chart)),
83,
49
).TurnToRGB()
);
}
}
target.draw(chart_dif_badge, states);
if (not should_be_grayed_out) {
auto dif = m_song.chart_levels.at(selected_chart);
sf::Text dif_label{
std::to_string(dif),
m_resources.noto_sans_medium,
static_cast<unsigned int>(m_size*0.15f)
};
dif_label.setFillColor(sf::Color::White);
Toolkit::setNormOrigin(dif_label, 0.5f, 0.5f);
dif_label.setPosition(m_size*0.1f, m_size*(0.1563f + 0.15f));
target.draw(dif_label, states);
}
sf::Text song_title;
song_title.setFont(m_resources.noto_sans_medium);
song_title.setString(m_song.title);

View File

@ -2,7 +2,8 @@
#include <iostream>
MusicSelect::SharedResources::SharedResources() :
namespace MusicSelect {
SharedResources::SharedResources() :
covers(),
fallback_cover(),
noto_sans_medium()
@ -13,5 +14,32 @@ MusicSelect::SharedResources::SharedResources() :
if (not fallback_cover.loadFromFile("assets/textures/fallback_cover.png")) {
throw std::runtime_error("Unable to load assets/textures/fallback_cover.png");
}
std::cout << "Loaded MusicSelect::Resources" << std::endl;
std::cout << "Loaded MusicSelect::SharedResources" << std::endl;
}
std::string SharedResources::get_last_selected_chart() {
return get_selected_chart().value_or("BSC");
}
std::optional<std::string> SharedResources::get_selected_chart() {
if (not selected_panel.has_value()) {
return {};
}
auto chart_selection = selected_panel->panel.get_selected_chart();
if (not chart_selection.has_value()) {
return {};
}
return chart_selection->chart;
}
std::optional<std::reference_wrapper<const Data::Song>> MusicSelect::SharedResources::get_selected_song() {
if (not selected_panel.has_value()) {
return {};
}
auto chart_selection = selected_panel->panel.get_selected_chart();
if (not chart_selection.has_value()) {
return {};
}
return chart_selection->song;
}
}

View File

@ -23,9 +23,19 @@ namespace MusicSelect {
struct SharedResources {
SharedResources();
Textures::Autoloader covers;
sf::Texture fallback_cover;
sf::Font noto_sans_medium;
std::optional<TimedSelectedPanel> selected_panel;
std::string get_last_selected_chart();
std::optional<std::string> get_selected_chart();
std::optional<std::reference_wrapper<const Data::Song>> get_selected_song();
sf::Color BSC_color = sf::Color{34,216,92};
sf::Color ADV_color = sf::Color{252,212,32};
sf::Color EXT_color = sf::Color{234,46,32};
};
}

View File

@ -4,24 +4,17 @@
namespace MusicSelect {
SongInfo::SongInfo(SharedResources& resources, const float& width, const float& height) :
BigCover::BigCover(SharedResources& resources, const float& size) :
m_resources(resources),
m_width(width),
m_height(height),
m_cover_fallback({height*0.8f, height*0.8f})
m_size(size),
m_cover_fallback({size,size})
{
m_cover_fallback.setFillColor(sf::Color::Black);
m_cover_fallback.setFillColor(sf::Color::Transparent);
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 {
void BigCover::draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform *= getTransform();
target.draw(m_cover_fallback, states);
auto selected_panel = m_resources.selected_panel;
@ -42,8 +35,7 @@ void MusicSelect::SongInfo::draw_cover(sf::RenderTarget& target, sf::RenderState
}
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);
cover.setScale(m_size/bounds.width, m_size/bounds.height);
auto alpha = static_cast<std::uint8_t>(
m_seconds_to_alpha.clampedTransform(
selected_panel->selected_since.getElapsedTime().asSeconds()
@ -52,3 +44,76 @@ void MusicSelect::SongInfo::draw_cover(sf::RenderTarget& target, sf::RenderState
cover.setColor(sf::Color(255, 255, 255, alpha));
target.draw(cover, states);
}
SongInfo::SongInfo(SharedResources& resources, const float& width, const float& height) :
m_resources(resources),
m_width(width),
m_height(height),
m_big_cover(resources, width*0.42f)
{
m_big_cover.setOrigin(width*0.42f*0.5f, 0.f);
m_big_cover.setPosition(width*0.5f, width*0.017f);
}
void SongInfo::draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform *= getTransform();
target.draw(m_big_cover, states);
draw_song_title(target);
}
void SongInfo::draw_song_title(sf::RenderTarget& target) const {
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 song_title = selected_chart->song.title;
if (not song_title.empty()) {
sf::Text song_title_label{
song_title,
m_resources.noto_sans_medium,
static_cast<unsigned int>(
0.026315789f*m_width
)
};
auto song_title_bounds = song_title_label.getLocalBounds();
if (song_title_bounds.width > 0.42f * m_width) {
song_title_label.setScale(0.42f * m_width / song_title_bounds.width, 1.0f);
}
song_title_label.setFillColor(sf::Color::White);
auto cover_pos = m_big_cover.getPosition();
song_title_label.setPosition(
m_width*(0.5f - (0.42f/2.f)),
m_width*(0.017f + 0.42f + 0.01f)
);
target.draw(song_title_label);
}
auto song_artist = selected_chart->song.artist;
if (not song_artist.empty()) {
sf::Text song_artist_label{
song_artist,
m_resources.noto_sans_medium,
static_cast<unsigned int>(
0.02f*m_width
)
};
song_artist_label.setStyle(sf::Text::Italic);
auto song_artist_bounds = song_artist_label.getLocalBounds();
if (song_artist_bounds.width > 0.42f * m_width) {
song_artist_label.setScale(0.42f * m_width / song_artist_bounds.width, 1.0f);
}
song_artist_label.setFillColor(sf::Color::White);
song_artist_label.setFillColor(sf::Color::White);
auto cover_pos = m_big_cover.getPosition();
song_artist_label.setPosition(
m_width*(0.5f - (0.42f/2.f)),
m_width*(0.017f + 0.42f + 0.01f + 0.04f)
);
target.draw(song_artist_label);
}
};
}

View File

@ -8,17 +8,28 @@
#include "SharedResources.hpp"
namespace MusicSelect {
// SongInfo displays the song info on the top part of the screen
class BigCover : public sf::Drawable, public sf::Transformable {
public:
BigCover(SharedResources& resources, const float& size);
private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
SharedResources& m_resources;
float m_size;
sf::RectangleShape m_cover_fallback;
const Toolkit::AffineTransform<float> m_seconds_to_alpha{0.0f, 0.3f, 0.f, 255.f};
};
// 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;
void draw_song_title(sf::RenderTarget& target) 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};
BigCover m_big_cover;
};
}

155
src/Toolkit/HSL.cpp Normal file
View File

@ -0,0 +1,155 @@
#include "HSL.hpp"
const double D_EPSILON = 0.00000000000001;
///Feel free to move this to your constants .h file or use it as a static constant if you don't like it here.
namespace Toolkit {
HSL::HSL() :Hue(0) ,Saturation(0) ,Luminance(0) {}
HSL::HSL(int H, int S, int L)
{
///Range control for Hue.
if (H <= 360 && H >= 0) {Hue = H;}
else
{
if(H > 360) { Hue = H%360; }
else if(H < 0 && H > -360) { Hue = -H; }
else if(H < 0 && H < -360) { Hue = -(H%360); }
}
///Range control for Saturation.
if (S <= 100 && S >= 0) {Saturation = S;}
else
{
if(S > 100) { Saturation = S%100;}
else if(S < 0 && S > -100) { Saturation = -S; }
else if(S < 0 && S < -100) { Saturation = -(S%100); }
}
///Range control for Luminance
if (L <= 100 && L >= 0) {Luminance = L;}
else
{
if(L > 100) { Luminance = L%100;}
if(L < 0 && L > -100) { Luminance = -L; }
if(L < 0 && L < -100) { Luminance = -(L%100); }
}
}
double HSL::HueToRGB(double arg1, double arg2, double H)
{
if ( H < 0 ) H += 1;
if ( H > 1 ) H -= 1;
if ( ( 6 * H ) < 1 ) { return (arg1 + ( arg2 - arg1 ) * 6 * H); }
if ( ( 2 * H ) < 1 ) { return arg2; }
if ( ( 3 * H ) < 2 ) { return ( arg1 + ( arg2 - arg1 ) * ( ( 2.0 / 3.0 ) - H ) * 6 ); }
return arg1;
}
sf::Color HSL::TurnToRGB()
{
///Reconvert to range [0,1]
double H = Hue/360.0;
double S = Saturation/100.0;
double L = Luminance/100.0;
float arg1, arg2;
if (S <= D_EPSILON)
{
sf::Color C(L*255, L*255, L*255);
return C;
}
else
{
if ( L < 0.5 ) { arg2 = L * ( 1 + S ); }
else { arg2 = ( L + S ) - ( S * L ); }
arg1 = 2 * L - arg2;
sf::Uint8 r =( 255 * HueToRGB( arg1, arg2, (H + 1.0/3.0 ) ) );
sf::Uint8 g =( 255 * HueToRGB( arg1, arg2, H ) );
sf::Uint8 b =( 255 * HueToRGB( arg1, arg2, (H - 1.0/3.0 ) ) );
sf::Color C(r,g,b);
return C;
}
}
HSL TurnToHSL(const sf::Color& C)
{
///Trivial cases.
if(C == sf::Color::White)
{ return HSL(0, 0, 100); }
if(C == sf::Color::Black)
{ return HSL(0, 0, 0); }
if(C == sf::Color::Red)
{ return HSL(0, 100, 50); }
if(C == sf::Color::Yellow)
{ return HSL(60, 100, 50); }
if(C == sf::Color::Green)
{ return HSL(120, 100, 50); }
if(C == sf::Color::Cyan)
{ return HSL(180, 100, 50); }
if(C == sf::Color::Blue)
{ return HSL(240, 100, 50); }
if(C == sf::Color::Cyan)
{ return HSL(300, 100, 50); }
double R, G, B;
R = C.r/255.0;
G = C.g/255.0;
B = C.b/255.0;
///Casos no triviales.
double max, min, l, s;
///Maximos
max = std::max(std::max(R,G),B);
///Minimos
min = std::min(std::min(R,G),B);
HSL A;
l = ((max + min)/2.0);
if (max - min <= D_EPSILON )
{
A.Hue = 0;
A.Saturation = 0;
}
else
{
double diff = max - min;
if(A.Luminance < 0.5)
{ s = diff/(max + min); }
else
{ s = diff/(2 - max - min); }
double diffR = ( (( max - R ) * 60) + (diff/2.0) ) / diff;
double diffG = ( (( max - G ) * 60) + (diff/2.0) ) / diff;
double diffB = ( (( max - B ) * 60) + (diff/2.0) ) / diff;
if (max - R <= D_EPSILON) { A.Hue = diffB - diffG; }
else if ( max - G <= D_EPSILON ) { A.Hue = (1*360)/3.0 + (diffR - diffB); }
else if ( max - B <= D_EPSILON ) { A.Hue = (2*360)/3.0 + (diffG - diffR); }
if (A.Hue <= 0 || A.Hue >= 360) { fmod(A.Hue, 360); }
s *= 100;
}
l *= 100;
A.Saturation = s;
A.Luminance = l;
return A;
}
}

28
src/Toolkit/HSL.hpp Normal file
View File

@ -0,0 +1,28 @@
// Taken from https://github.com/SFML/SFML/wiki/Source%3A-HSL-Color
#ifndef HSL_COLOR
#define HSL_COLOR
#include <SFML/Graphics/Color.hpp>
#include <algorithm>
#include <cmath>
namespace Toolkit {
struct HSL {
public:
double Hue;
double Saturation;
double Luminance;
HSL();
HSL(int H, int S, int L);
sf::Color TurnToRGB();
private:
double HueToRGB(double arg1, double arg2, double H);
};
HSL TurnToHSL(const sf::Color& C);
}
#endif // HSL_COLOR

View File

@ -0,0 +1,18 @@
#pragma once
#include <SFML/Graphics.hpp>
namespace Toolkit {
void setNormOrigin(sf::Shape& s, float x, float y) {
auto bounds = s.getGlobalBounds();
s.setOrigin(bounds.left+x*bounds.width, bounds.top+y*bounds.height);
};
void setNormOrigin(sf::Sprite& s, float x, float y) {
auto bounds = s.getGlobalBounds();
s.setOrigin(bounds.left+x*bounds.width, bounds.top+y*bounds.height);
}
void setNormOrigin(sf::Text& t, float x, float y) {
auto bounds = t.getGlobalBounds();
t.setOrigin(bounds.left+x*bounds.width, bounds.top+y*bounds.height);
}
}

View File

@ -16,6 +16,7 @@ args = parser.parse_args()
def create_song_folder_from_image(image: Path):
song_name = fake.sentence().strip(".") if args.random_name else image.stem
song_artist = fake.name()
song_folder = args.output_folder / song_name
song_folder.mkdir()
output_image = song_folder / f"{song_name}.jpg"
@ -24,7 +25,7 @@ def create_song_folder_from_image(image: Path):
"version": "0.1.0",
"metadata": {
"song title": song_name,
"artist": "",
"artist": song_artist,
"music path": "",
"album cover path": output_image.name,
"BPM": 120,