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

IT BUILDS

This commit is contained in:
Stepland 2019-11-03 02:14:47 +01:00
parent 97d5f1493a
commit 73a02bf924
14 changed files with 147 additions and 109 deletions

View File

@ -1,4 +1,5 @@
#pragma once #ifndef MEMON_HPP_
#define MEMON_HPP_
#include <cassert> #include <cassert>
#include <set> #include <set>
@ -168,6 +169,7 @@ namespace stepland {
} else { } else {
m.load_from_memon_fallback(j); m.load_from_memon_fallback(j);
} }
return file;
} }
/* /*
@ -176,9 +178,9 @@ namespace stepland {
* this way the difficulty names are guaranteed to be unique * this way the difficulty names are guaranteed to be unique
* - "jacket path" is now "album cover path" because engrish much ? * - "jacket path" is now "album cover path" because engrish much ?
*/ */
void load_from_memon_v0_1_0(nlohmann::json memon) { void load_from_memon_v0_1_0(nlohmann::json memon_json) {
auto metadata = memon.at("metadata"); auto metadata = memon_json.at("metadata");
if (not metadata.is_object()) { if (not metadata.is_object()) {
throw std::invalid_argument("metadata fields is not an object"); throw std::invalid_argument("metadata fields is not an object");
} }
@ -190,11 +192,11 @@ namespace stepland {
this->BPM = metadata.value("BPM",120.0f); this->BPM = metadata.value("BPM",120.0f);
this->offset = metadata.value("offset",0.0f); this->offset = metadata.value("offset",0.0f);
if (not memon.at("data").is_object()) { if (not memon_json.at("data").is_object()) {
throw std::invalid_argument("data field is not an object"); throw std::invalid_argument("data field is not an object");
} }
for (auto& [dif_name, chart_json] : memon.at("data").items()) { for (auto& [dif_name, chart_json] : memon_json.at("data").items()) {
chart new_chart; chart new_chart;
new_chart.level = chart_json.value("level", 0); new_chart.level = chart_json.value("level", 0);
@ -234,9 +236,9 @@ namespace stepland {
* - "data" is an array of charts, each with a difficulty name * - "data" is an array of charts, each with a difficulty name
* - the album cover path field is named "jacket path" * - the album cover path field is named "jacket path"
*/ */
void load_from_memon_fallback(nlohmann::json memon) { void load_from_memon_fallback(nlohmann::json memon_json) {
auto metadata = memon.at("metadata"); auto metadata = memon_json.at("metadata");
if (not metadata.is_object()) { if (not metadata.is_object()) {
throw std::invalid_argument("metadata fields is not an object"); throw std::invalid_argument("metadata fields is not an object");
} }
@ -248,11 +250,11 @@ namespace stepland {
this->BPM = metadata.value("BPM",120.f); this->BPM = metadata.value("BPM",120.f);
this->offset = metadata.value("offset",0.f); this->offset = metadata.value("offset",0.f);
if (not memon.at("data").is_array()) { if (not memon_json.at("data").is_array()) {
throw std::invalid_argument("data field is not an array"); throw std::invalid_argument("data field is not an array");
} }
for (auto& chart_json : memon.at("data")) { for (auto& chart_json : memon_json.at("data")) {
chart new_chart; chart new_chart;
new_chart.level = chart_json.value("level", 0); new_chart.level = chart_json.value("level", 0);
new_chart.resolution = chart_json.at("resolution").get<int>(); new_chart.resolution = chart_json.at("resolution").get<int>();
@ -289,4 +291,6 @@ namespace stepland {
} }
} }
}; };
} }
#endif /* MEMON_HPP_ */

View File

@ -41,5 +41,12 @@ executable(
'jujube', 'jujube',
sources, sources,
dependencies: [sfml, filesystem], dependencies: [sfml, filesystem],
include_directories : include_directories('include') include_directories : include_directories('include'),
cpp_args : [
'-Wall',
'-Wextra',
'-Wshadow',
'-Wnon-virtual-dtor',
'-pedantic'
]
) )

View File

@ -1,73 +1,83 @@
#include "Note.hpp" #include "Note.hpp"
namespace Data {
Note::Note(
unsigned int t_position,
sf::Time t_timing,
sf::Time t_length,
unsigned int t_tail_position
) :
position(t_position),
timing(t_timing),
length(t_length),
tail_position(t_tail_position)
{
if (t_position > 15) {
throw std::out_of_range(
"Tried creating a note with invalid position : "
+std::to_string(t_position)
);
}
Data::Note::Note( if (t_length.asMicroseconds() < 0) {
unsigned int t_position, throw std::out_of_range(
sf::Time t_timing, "Tried creating a long note with negative length : "
sf::Time t_length, +std::to_string(t_length.asSeconds())+"s"
unsigned int t_tail_position );
) : }
position(t_position), if (t_length.asMicroseconds() > 0) {
timing(t_timing), if (t_tail_position > 5) {
length(t_length), throw std::out_of_range(
tail_position(t_tail_position) "Tried creating a long note with invalid tail position : "
{ +std::to_string(t_tail_position)
if (t_position > 15) { );
throw std::out_of_range("Tried creating a note with invalid position : "+std::to_string(t_position)); }
}
if (t_length.asMicroseconds() < 0) {
throw std::out_of_range("Tried creating a long note with negative length : "+std::to_string(t_length.asSeconds)+ "s");
}
if (t_length.asMicroseconds() > 0) {
if (t_tail_position > 5) {
throw std::out_of_range("Tried creating a long note with invalid tail position : "+std::to_string(t_tail_position));
} }
} }
}
bool Data::Note::operator==(const Data::Note &rhs) const { bool Note::operator==(const Note &rhs) const {
return timing == rhs.timing && position == rhs.position; return timing == rhs.timing && position == rhs.position;
}
bool Data::Note::operator!=(const Data::Note &rhs) const {
return !(rhs == *this);
}
bool Data::Note::operator<(const Data::Note &rhs) const {
if (timing < rhs.timing) {
return true;
} }
if (rhs.timing < timing) {
return false; bool Note::operator!=(const Note &rhs) const {
return !(rhs == *this);
} }
return position < rhs.position;
}
bool Data::Note::operator>(const Data::Note &rhs) const { bool Note::operator<(const Note &rhs) const {
return rhs < *this; if (timing < rhs.timing) {
} return true;
}
if (rhs.timing < timing) {
return false;
}
return position < rhs.position;
}
bool Data::Note::operator<=(const Data::Note &rhs) const { bool Note::operator>(const Note &rhs) const {
return !(rhs < *this); return rhs < *this;
} }
bool Data::Note::operator>=(const Data::Note &rhs) const { bool Note::operator<=(const Note &rhs) const {
return !(*this < rhs); return !(rhs < *this);
} }
const unsigned int Data::Note::getPosition() const {
return position;
}
const sf::Time& Data::Note::getTiming() const { bool Note::operator>=(const Note &rhs) const {
return timing; return !(*this < rhs);
} }
unsigned int Note::getPosition() const {
return position;
}
const sf::Time& Data::Note::getLength() const { const sf::Time& Note::getTiming() const {
return length; return timing;
} }
const unsigned int Data::Note::getTailPosition() const { const sf::Time& Note::getLength() const {
return tail_position; return length;
}
unsigned int Note::getTailPosition() const {
return tail_position;
}
} }

View File

@ -14,10 +14,10 @@ namespace Data {
bool operator<=(const Note &rhs) const; bool operator<=(const Note &rhs) const;
bool operator>=(const Note &rhs) const; bool operator>=(const Note &rhs) const;
const unsigned int getPosition() const; unsigned int getPosition() const;
const sf::Time& getTiming() const; const sf::Time& getTiming() const;
const sf::Time& getLength() const; const sf::Time& getLength() const;
const unsigned int getTailPosition() const; unsigned int getTailPosition() const;
private: private:
@ -27,4 +27,4 @@ namespace Data {
const unsigned int tail_position = 0; const unsigned int tail_position = 0;
}; };
}; }

View File

@ -49,7 +49,7 @@ namespace Data {
fs::begin(folder), fs::begin(folder),
fs::end(folder), fs::end(folder),
[](const fs::directory_entry& de) { [](const fs::directory_entry& de) {
de.path().extension() == ".memo" or return de.path().extension() == ".memo" or
de.path().extension() == ".memon"; de.path().extension() == ".memon";
} }
) )
@ -93,14 +93,14 @@ namespace Data {
// .memo ? // .memo ?
auto memo_files = getMemoFiles(song_folder); auto memo_files = getMemoFiles(song_folder);
if (not memo_files.empty()) { if (not memo_files.empty()) {
throw std::exception("jujube does not support .memo files for now ..."); throw std::invalid_argument("jujube does not support .memo files for now ...");
} else { } else {
throw std::invalid_argument("No valid file found in song folder"); throw std::invalid_argument("No valid file found in song folder");
} }
} }
} }
const std::vector<fs::path>& getMemoFiles(fs::path song_folder) { const std::vector<fs::path> getMemoFiles(fs::path song_folder) {
std::vector<fs::path> res; std::vector<fs::path> res;
for (const auto& p : fs::directory_iterator(song_folder)) { for (const auto& p : fs::directory_iterator(song_folder)) {
if (p.path().extension() == ".memo") { if (p.path().extension() == ".memo") {
@ -110,7 +110,7 @@ namespace Data {
return res; return res;
} }
const std::vector<fs::path>& getMemonFiles(fs::path song_folder) { const std::vector<fs::path> getMemonFiles(fs::path song_folder) {
std::vector<fs::path> res; std::vector<fs::path> res;
for (const auto& p : fs::directory_iterator(song_folder)) { for (const auto& p : fs::directory_iterator(song_folder)) {
if (p.path().extension() == ".memon") { if (p.path().extension() == ".memon") {

View File

@ -46,6 +46,6 @@ namespace Data {
// .memon files also accepted // .memon files also accepted
const std::vector<fs::path> getSongFolders(); const std::vector<fs::path> getSongFolders();
std::list<fs::path> recursiveSongSearch(fs::path song_or_pack); std::list<fs::path> recursiveSongSearch(fs::path song_or_pack);
const std::vector<fs::path>& getMemoFiles(fs::path song_folder); const std::vector<fs::path> getMemoFiles(fs::path song_folder);
const std::vector<fs::path>& getMemonFiles(fs::path song_folder); const std::vector<fs::path> getMemonFiles(fs::path song_folder);
} }

View File

@ -23,7 +23,7 @@ sf::Sprite Textures::CoverAltas::at(const fs::path& path) const {
index = 0; index = 0;
} }
auto location = get_detailed_location(path_to_index.at(path)); auto location = get_detailed_location(index);
sf::IntRect rect(location.column*256, location.row*256, 256, 256); sf::IntRect rect(location.column*256, location.row*256, 256, 256);
sf::Sprite cover; sf::Sprite cover;
cover.setTexture(textures.at(location.texture_index)->getTexture()); cover.setTexture(textures.at(location.texture_index)->getTexture());

View File

@ -18,7 +18,7 @@ namespace std {
return std::hash<std::string>()(p.string()); return std::hash<std::string>()(p.string());
} }
}; };
}; }
namespace Textures { namespace Textures {
@ -50,4 +50,4 @@ namespace Textures {
}; };
DetailedLocation get_detailed_location(unsigned int location); DetailedLocation get_detailed_location(unsigned int location);
}; }

View File

@ -37,9 +37,14 @@ void MusicSelect::Screen::select_chart(sf::RenderWindow& window) {
// drawing the ribbon // drawing the ribbon
for (size_t panel = 0; panel < 12; panel++) { for (size_t panel = 0; panel < 12; panel++) {
ribbon.at(panel)->draw( ribbon.at(panel)->draw(
*this, resources,
window, window,
sf::FloatRect((panel%4)*150.f, (panel/4)*150.f, 150.f, 150.f) sf::FloatRect(
(panel%4)*150.f,
(panel/4)*150.f,
150.f,
150.f
)
); );
} }
window.display(); window.display();
@ -47,10 +52,4 @@ void MusicSelect::Screen::select_chart(sf::RenderWindow& window) {
} }
void MusicSelect::Screen::handle_key(const sf::Event::KeyEvent& key_event) { void MusicSelect::Screen::handle_key(const sf::Event::KeyEvent& key_event) {
auto panel = key_mapping.key_to_button(key_event.code);
if (panel) {
if (Button::B2 <= *panel and *panel <= Button::B12) {
ribbon.at()
}
}
} }

View File

@ -33,4 +33,4 @@ namespace MusicSelect {
KeyMapping key_mapping; KeyMapping key_mapping;
void handle_key(const sf::Event::KeyEvent& key_event); void handle_key(const sf::Event::KeyEvent& key_event);
}; };
}; }

View File

@ -4,6 +4,10 @@
#include "MusicSelect.hpp" #include "MusicSelect.hpp"
void MusicSelect::CategoryPanel::click(Screen& screen) {
}
void MusicSelect::CategoryPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) { void MusicSelect::CategoryPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
sf::RectangleShape frame{{area.width*0.9f, area.height*0.9f}}; sf::RectangleShape frame{{area.width*0.9f, area.height*0.9f}};
frame.setFillColor(sf::Color::Black); frame.setFillColor(sf::Color::Black);
@ -27,12 +31,22 @@ void MusicSelect::CategoryPanel::draw(Resources& resources, sf::RenderTarget& ta
label_text.setString(this->label); label_text.setString(this->label);
label_text.setCharacterSize(24U); label_text.setCharacterSize(24U);
label_text.setFillColor(sf::Color::White); label_text.setFillColor(sf::Color::White);
auto bounds = label_text.getLocalBounds(); auto text_bounds = label_text.getLocalBounds();
label_text.setOrigin(bounds.width / 2.f, bounds.height / 2.f); label_text.setOrigin(text_bounds.width / 2.f, text_bounds.height / 2.f);
if (bounds.height > bounds.width) { if (text_bounds.height > text_bounds.width) {
label_text.setScale(area.height*0.8f / bounds.height, area.height*0.8f / bounds.height); label_text.setScale(area.height*0.8f / text_bounds.height, area.height*0.8f / text_bounds.height);
} else { } else {
label_text.setScale(area.width*0.8f / bounds.width, area.width*0.8f / bounds.width); label_text.setScale(area.width*0.8f / text_bounds.width, area.width*0.8f / text_bounds.width);
} }
label_text.setPosition(area.left + area.width / 2.f, area.top + area.height / 2.f); label_text.setPosition(area.left + area.width / 2.f, area.top + area.height / 2.f);
} }
void MusicSelect::SongPanel::click(Screen& screen) {
}
void MusicSelect::SongPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
}

View File

@ -3,6 +3,7 @@
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <SFML/Window.hpp> #include <SFML/Window.hpp>
#include "../../Data/SongList.hpp"
#include "Resources.hpp" #include "Resources.hpp"
namespace MusicSelect { namespace MusicSelect {
@ -28,7 +29,7 @@ namespace MusicSelect {
class CategoryPanel final : public Panel { class CategoryPanel final : public Panel {
public: public:
CategoryPanel(const std::string& t_label) : label(t_label) {}; explicit CategoryPanel(const std::string& t_label) : label(t_label) {};
void click(Screen& screen) override; void click(Screen& screen) override;
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override; void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
private: private:
@ -37,7 +38,7 @@ namespace MusicSelect {
class SongPanel final : public Panel { class SongPanel final : public Panel {
public: public:
SongPanel(const Data::Song& t_song) : song(t_song) {}; explicit SongPanel(const Data::Song& t_song) : song(t_song) {};
void click(Screen& screen) override; void click(Screen& screen) override;
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override; void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
private: private:

View File

@ -8,7 +8,7 @@
MusicSelect::Ribbon MusicSelect::Ribbon::title_sort(const Data::SongList& song_list) { MusicSelect::Ribbon MusicSelect::Ribbon::title_sort(const Data::SongList& song_list) {
std::map<char,std::vector<Data::Song>> categories; std::map<char,std::vector<Data::Song>> categories;
for (const auto& song : song_list.songs) { for (const auto& song : song_list.songs) {
if (song.title.size > 0) { if (song.title.size() > 0) {
char letter = song.title[0]; char letter = song.title[0];
if ('A' <= letter and letter <= 'Z') { if ('A' <= letter and letter <= 'Z') {
categories[letter].push_back(song); categories[letter].push_back(song);
@ -22,22 +22,25 @@ MusicSelect::Ribbon MusicSelect::Ribbon::title_sort(const Data::SongList& song_l
} }
} }
Ribbon ribbon; Ribbon ribbon;
for (const auto& [letter, songs] : categories) { for (auto& [letter, songs] : categories) {
std::vector<std::unique_ptr<Panel>> panels = {std::make_unique<CategoryPanel>(letter)}; std::vector<std::unique_ptr<Panel>> panels;
panels.emplace_back(
std::make_unique<CategoryPanel>(
std::string(1, letter)
)
);
std::sort(songs.begin(), songs.end(), Data::Song::sort_by_title); std::sort(songs.begin(), songs.end(), Data::Song::sort_by_title);
for (const auto& song : songs) { for (const auto& song : songs) {
panels.push_back(std::make_unique<SongPanel>(song)); panels.push_back(std::make_unique<SongPanel>(song));
} }
while (panels.size % 3 != 0) { while (panels.size() % 3 != 0) {
panels.push_back(std::make_unique<EmptyPanel>()); panels.push_back(std::make_unique<EmptyPanel>());
} }
for (size_t i = 0; i < panels.size; i += 3) { for (size_t i = 0; i < panels.size(); i += 3) {
std::array<std::unique_ptr<Panel>,3> column = { ribbon.layout.emplace_back();
std::move(panels[i]), for (size_t j = 0; j < 3; j++) {
std::move(panels[i+1]), ribbon.layout.back()[j] = std::move(panels[i+j]);
std::move(panels[i+2]) }
};
ribbon.layout.push_back(column);
} }
} }
return ribbon; return ribbon;

View File

@ -8,7 +8,7 @@ namespace MusicSelect {
// It can be sorted in a number of ways // It can be sorted in a number of ways
class Ribbon { class Ribbon {
public: public:
Ribbon(); Ribbon() = default;
static Ribbon title_sort(const Data::SongList& song_list); static Ribbon title_sort(const Data::SongList& song_list);
static Ribbon test_sort(); static Ribbon test_sort();
const auto& get_layout() {return layout;}; const auto& get_layout() {return layout;};