Save before fixing
This commit is contained in:
parent
a111820c9d
commit
97d5f1493a
BIN
assets/fonts/NotoSans-Medium.ttf
Normal file
BIN
assets/fonts/NotoSans-Medium.ttf
Normal file
Binary file not shown.
14
meson.build
14
meson.build
@ -16,15 +16,23 @@ filesystem = cpp.find_library('stdc++fs')
|
||||
sources = [
|
||||
'src/Main.cpp',
|
||||
'src/Data/Chart.hpp',
|
||||
'src/Data/KeyMapping.hpp',
|
||||
'src/Data/KeyMapping.cpp',
|
||||
'src/Data/Note.hpp',
|
||||
'src/Data/Note.cpp',
|
||||
'srx/Data/Score.hpp',
|
||||
'src/Data/Score.hpp',
|
||||
'src/Data/SongList.hpp',
|
||||
'src/Data/SongList.cpp',
|
||||
'src/Screens/Gameplay.hpp',
|
||||
# 'src/Screens/Gameplay.hpp',
|
||||
'src/Screens/MusicSelect/MusicSelect.hpp',
|
||||
'src/Screens/MusicSelect/MusicSelect.cpp',
|
||||
'src/Screens/Result.hpp',
|
||||
'src/Screens/MusicSelect/Panel.hpp',
|
||||
'src/Screens/MusicSelect/Panel.cpp',
|
||||
'src/Screens/MusicSelect/Resources.hpp',
|
||||
'src/Screens/MusicSelect/Resources.cpp',
|
||||
'src/Screens/MusicSelect/Ribbon.hpp',
|
||||
'src/Screens/MusicSelect/Ribbon.cpp',
|
||||
# 'src/Screens/Result.hpp',
|
||||
'src/Resources/CoverAtlas.hpp',
|
||||
'src/Resources/CoverAtlas.cpp',
|
||||
]
|
||||
|
@ -1,54 +0,0 @@
|
||||
#include "KeyMaping.hpp"
|
||||
|
||||
PanelCoords toCoord(PanelEnum panel) {
|
||||
auto num = static_cast<int>(panel);
|
||||
return {num % 4, num / 4};
|
||||
}
|
||||
|
||||
KeyMaping::KeyMaping() {
|
||||
m_key_to_panel[sf::Keyboard::Num1] = PanelEnum::P1;
|
||||
m_key_to_panel[sf::Keyboard::Num2] = PanelEnum::P2;
|
||||
m_key_to_panel[sf::Keyboard::Num3] = PanelEnum::P3;
|
||||
m_key_to_panel[sf::Keyboard::Num4] = PanelEnum::P4;
|
||||
m_key_to_panel[sf::Keyboard::A] = PanelEnum::P5;
|
||||
m_key_to_panel[sf::Keyboard::Z] = PanelEnum::P6;
|
||||
m_key_to_panel[sf::Keyboard::E] = PanelEnum::P7;
|
||||
m_key_to_panel[sf::Keyboard::R] = PanelEnum::P8;
|
||||
m_key_to_panel[sf::Keyboard::Q] = PanelEnum::P9;
|
||||
m_key_to_panel[sf::Keyboard::S] = PanelEnum::P10;
|
||||
m_key_to_panel[sf::Keyboard::D] = PanelEnum::P11;
|
||||
m_key_to_panel[sf::Keyboard::F] = PanelEnum::P12;
|
||||
m_key_to_panel[sf::Keyboard::W] = PanelEnum::P13;
|
||||
m_key_to_panel[sf::Keyboard::X] = PanelEnum::P14;
|
||||
m_key_to_panel[sf::Keyboard::C] = PanelEnum::P15;
|
||||
m_key_to_panel[sf::Keyboard::V] = PanelEnum::P16;
|
||||
|
||||
for (const auto& [key, panel] : m_key_to_panel) {
|
||||
m_panel_to_key[panel] = key;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyMaping::setPanelToKey(const PanelEnum& panel, const sf::Keyboard::Key& key) {
|
||||
if (m_key_to_panel.find(key) != m_key_to_panel.end()) {
|
||||
m_panel_to_key.erase(m_key_to_panel[key]);
|
||||
m_key_to_panel.erase(key);
|
||||
}
|
||||
m_panel_to_key[panel] = key;
|
||||
m_key_to_panel[key] = panel;
|
||||
}
|
||||
|
||||
std::optional<PanelEnum> KeyMaping::key_to_panel(const sf::Keyboard::Key& key) {
|
||||
try {
|
||||
return m_key_to_panel.at(key);
|
||||
} catch(const std::exception& e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<sf::Keyboard::Key> KeyMaping::panel_to_key(const PanelEnum& panel) {
|
||||
try {
|
||||
return m_panel_to_key.at(panel);
|
||||
} catch(const std::exception& e) {
|
||||
return {};
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <SFML/Window.hpp>
|
||||
|
||||
enum class PanelEnum {
|
||||
P1,
|
||||
P2,
|
||||
P3,
|
||||
P4,
|
||||
P5,
|
||||
P6,
|
||||
P7,
|
||||
P8,
|
||||
P9,
|
||||
P10,
|
||||
P11,
|
||||
P12,
|
||||
P13,
|
||||
P14,
|
||||
P15,
|
||||
P16,
|
||||
};
|
||||
|
||||
struct PanelCoords {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
};
|
||||
|
||||
PanelCoords toCoord(PanelEnum panel);
|
||||
|
||||
class KeyMaping {
|
||||
public:
|
||||
KeyMaping();
|
||||
void setPanelToKey(const PanelEnum& panel, const sf::Keyboard::Key& key);
|
||||
std::optional<PanelEnum> key_to_panel(const sf::Keyboard::Key& key);
|
||||
std::optional<sf::Keyboard::Key> panel_to_key(const PanelEnum& panel);
|
||||
private:
|
||||
std::unordered_map<sf::Keyboard::Key, PanelEnum> m_key_to_panel;
|
||||
std::unordered_map<PanelEnum, sf::Keyboard::Key> m_panel_to_key;
|
||||
};
|
54
src/Data/KeyMapping.cpp
Normal file
54
src/Data/KeyMapping.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "KeyMapping.hpp"
|
||||
|
||||
ButtonCoords toCoord(Button panel) {
|
||||
auto num = static_cast<int>(panel);
|
||||
return {num % 4, num / 4};
|
||||
}
|
||||
|
||||
KeyMapping::KeyMapping() {
|
||||
m_key_to_button[sf::Keyboard::Num1] = Button::B1;
|
||||
m_key_to_button[sf::Keyboard::Num2] = Button::B2;
|
||||
m_key_to_button[sf::Keyboard::Num3] = Button::B3;
|
||||
m_key_to_button[sf::Keyboard::Num4] = Button::B4;
|
||||
m_key_to_button[sf::Keyboard::A] = Button::B5;
|
||||
m_key_to_button[sf::Keyboard::Z] = Button::B6;
|
||||
m_key_to_button[sf::Keyboard::E] = Button::B7;
|
||||
m_key_to_button[sf::Keyboard::R] = Button::B8;
|
||||
m_key_to_button[sf::Keyboard::Q] = Button::B9;
|
||||
m_key_to_button[sf::Keyboard::S] = Button::B10;
|
||||
m_key_to_button[sf::Keyboard::D] = Button::B11;
|
||||
m_key_to_button[sf::Keyboard::F] = Button::B12;
|
||||
m_key_to_button[sf::Keyboard::W] = Button::B13;
|
||||
m_key_to_button[sf::Keyboard::X] = Button::B14;
|
||||
m_key_to_button[sf::Keyboard::C] = Button::B15;
|
||||
m_key_to_button[sf::Keyboard::V] = Button::B16;
|
||||
|
||||
for (const auto& [key, panel] : m_key_to_button) {
|
||||
m_button_to_key[panel] = key;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyMapping::setPanelToKey(const Button& panel, const sf::Keyboard::Key& key) {
|
||||
if (m_key_to_button.find(key) != m_key_to_button.end()) {
|
||||
m_button_to_key.erase(m_key_to_button[key]);
|
||||
m_key_to_button.erase(key);
|
||||
}
|
||||
m_button_to_key[panel] = key;
|
||||
m_key_to_button[key] = panel;
|
||||
}
|
||||
|
||||
std::optional<Button> KeyMapping::key_to_button(const sf::Keyboard::Key& key) {
|
||||
try {
|
||||
return m_key_to_button.at(key);
|
||||
} catch(const std::exception& e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<sf::Keyboard::Key> KeyMapping::button_to_key(const Button& panel) {
|
||||
try {
|
||||
return m_button_to_key.at(panel);
|
||||
} catch(const std::exception& e) {
|
||||
return {};
|
||||
}
|
||||
}
|
43
src/Data/KeyMapping.hpp
Normal file
43
src/Data/KeyMapping.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <SFML/Window.hpp>
|
||||
|
||||
enum class Button {
|
||||
B1,
|
||||
B2,
|
||||
B3,
|
||||
B4,
|
||||
B5,
|
||||
B6,
|
||||
B7,
|
||||
B8,
|
||||
B9,
|
||||
B10,
|
||||
B11,
|
||||
B12,
|
||||
B13,
|
||||
B14,
|
||||
B15,
|
||||
B16,
|
||||
};
|
||||
|
||||
struct ButtonCoords {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
};
|
||||
|
||||
ButtonCoords toCoord(Button button);
|
||||
|
||||
class KeyMapping {
|
||||
public:
|
||||
KeyMapping();
|
||||
void setPanelToKey(const Button& button, const sf::Keyboard::Key& key);
|
||||
std::optional<Button> key_to_button(const sf::Keyboard::Key& key);
|
||||
std::optional<sf::Keyboard::Key> button_to_key(const Button& button);
|
||||
private:
|
||||
std::unordered_map<sf::Keyboard::Key, Button> m_key_to_button;
|
||||
std::unordered_map<Button, sf::Keyboard::Key> m_button_to_key;
|
||||
};
|
@ -16,11 +16,11 @@ Data::Note::Note(
|
||||
throw std::out_of_range("Tried creating a note with invalid position : "+std::to_string(t_position));
|
||||
}
|
||||
|
||||
if (t_length.asMicroseconds < 0) {
|
||||
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_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));
|
||||
}
|
||||
|
@ -9,111 +9,115 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
Data::SongList::SongList::SongList() {
|
||||
namespace Data {
|
||||
|
||||
// Loading all song metadata
|
||||
for (const auto& folder : getSongFolders()) {
|
||||
try {
|
||||
songs.emplace_back(folder);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Exception while parsing song folder "
|
||||
<< folder.string() << " : " << e.what() << '\n';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
SongList::SongList::SongList() {
|
||||
|
||||
|
||||
const std::vector<fs::path> Data::getSongFolders() {
|
||||
|
||||
std::vector<fs::path> song_folders;
|
||||
|
||||
for (const auto& dir_item : fs::directory_iterator("songs/")) {
|
||||
if (dir_item.is_directory()) {
|
||||
for (auto& path : recursiveSongSearch(dir_item.path())) {
|
||||
song_folders.push_back(path);
|
||||
// Loading all song metadata
|
||||
for (const auto& folder : getSongFolders()) {
|
||||
try {
|
||||
songs.emplace_back(folder);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Exception while parsing song folder "
|
||||
<< folder.string() << " : " << e.what() << '\n';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return song_folders;
|
||||
}
|
||||
|
||||
std::list<fs::path> Data::recursiveSongSearch(fs::path song_or_pack) {
|
||||
std::list<fs::path> res;
|
||||
fs::directory_iterator folder{song_or_pack};
|
||||
if (
|
||||
std::any_of(
|
||||
fs::begin(folder),
|
||||
fs::end(folder),
|
||||
[](const fs::directory_entry& de) {
|
||||
de.path().extension() == ".memo" or
|
||||
de.path().extension() == ".memon";
|
||||
const std::vector<fs::path> getSongFolders() {
|
||||
|
||||
std::vector<fs::path> song_folders;
|
||||
|
||||
for (const auto& dir_item : fs::directory_iterator("songs/")) {
|
||||
if (dir_item.is_directory()) {
|
||||
for (auto& path : recursiveSongSearch(dir_item.path())) {
|
||||
song_folders.push_back(path);
|
||||
}
|
||||
}
|
||||
)
|
||||
) {
|
||||
res.push_back(song_or_pack);
|
||||
return res;
|
||||
} else {
|
||||
for (auto& p : fs::directory_iterator(song_or_pack)) {
|
||||
if (p.is_directory()) {
|
||||
res.splice(res.end(), recursiveSongSearch(p));
|
||||
}
|
||||
|
||||
return song_folders;
|
||||
}
|
||||
|
||||
std::list<fs::path> recursiveSongSearch(fs::path song_or_pack) {
|
||||
std::list<fs::path> res;
|
||||
fs::directory_iterator folder{song_or_pack};
|
||||
if (
|
||||
std::any_of(
|
||||
fs::begin(folder),
|
||||
fs::end(folder),
|
||||
[](const fs::directory_entry& de) {
|
||||
de.path().extension() == ".memo" or
|
||||
de.path().extension() == ".memon";
|
||||
}
|
||||
)
|
||||
) {
|
||||
res.push_back(song_or_pack);
|
||||
return res;
|
||||
} else {
|
||||
for (auto& p : fs::directory_iterator(song_or_pack)) {
|
||||
if (p.is_directory()) {
|
||||
res.splice(res.end(), recursiveSongSearch(p));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
Song::Song(fs::path song_folder) {
|
||||
|
||||
// .memon ?
|
||||
auto memon_files = getMemonFiles(song_folder);
|
||||
if (not memon_files.empty()) {
|
||||
if (memon_files.size() > 1) {
|
||||
throw std::invalid_argument("Multiple .memon files");
|
||||
} else {
|
||||
stepland::memon m;
|
||||
std::ifstream file(memon_files.back());
|
||||
file >> m;
|
||||
this->title = m.song_title;
|
||||
this->artist = m.artist;
|
||||
if (not m.album_cover_path.empty()) {
|
||||
this->cover.emplace(m.album_cover_path);
|
||||
}
|
||||
if (not m.music_path.empty()) {
|
||||
this->audio.emplace(m.music_path);
|
||||
}
|
||||
for (const auto& [difficulty, chart] : m.charts) {
|
||||
this->chart_levels[difficulty] = chart.level;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// .memo ?
|
||||
auto memo_files = getMemoFiles(song_folder);
|
||||
if (not memo_files.empty()) {
|
||||
throw std::exception("jujube does not support .memo files for now ...");
|
||||
} else {
|
||||
throw std::invalid_argument("No valid file found in song folder");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<fs::path>& getMemoFiles(fs::path song_folder) {
|
||||
std::vector<fs::path> res;
|
||||
for (const auto& p : fs::directory_iterator(song_folder)) {
|
||||
if (p.path().extension() == ".memo") {
|
||||
res.push_back(p.path());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
Data::Song::Song(fs::path song_folder) {
|
||||
|
||||
// .memon ?
|
||||
auto memon_files = getMemonFiles(song_folder);
|
||||
if (not memon_files.empty()) {
|
||||
if (memon_files.size() > 1) {
|
||||
throw std::invalid_argument("Multiple .memon files");
|
||||
} else {
|
||||
stepland::memon m;
|
||||
std::ifstream file(memon_files.back());
|
||||
file >> m;
|
||||
this->title = m.song_title;
|
||||
this->artist = m.artist;
|
||||
if (not m.album_cover_path.empty()) {
|
||||
this->cover.emplace(m.album_cover_path);
|
||||
}
|
||||
if (not m.music_path.empty()) {
|
||||
this->audio.emplace(m.music_path);
|
||||
}
|
||||
for (const auto& [difficulty, chart] : m.charts) {
|
||||
this->chart_levels[difficulty] = chart.level;
|
||||
const std::vector<fs::path>& getMemonFiles(fs::path song_folder) {
|
||||
std::vector<fs::path> res;
|
||||
for (const auto& p : fs::directory_iterator(song_folder)) {
|
||||
if (p.path().extension() == ".memon") {
|
||||
res.push_back(p.path());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// .memo ?
|
||||
auto memo_files = getMemoFiles(song_folder);
|
||||
if (not memo_files.empty()) {
|
||||
throw std::exception("jujube does not support .memo files for now ...");
|
||||
} else {
|
||||
throw std::invalid_argument("No valid file found in song folder");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<fs::path>& Data::getMemoFiles(fs::path song_folder) {
|
||||
std::vector<fs::path> res;
|
||||
for (const auto& p : fs::directory_iterator(song_folder)) {
|
||||
if (p.path().extension() == ".memo") {
|
||||
res.push_back(p.path());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const std::vector<fs::path>& Data::getMemonFiles(fs::path song_folder) {
|
||||
std::vector<fs::path> res;
|
||||
for (const auto& p : fs::directory_iterator(song_folder)) {
|
||||
if (p.path().extension() == ".memon") {
|
||||
res.push_back(p.path());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <filesystem>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
15
src/Main.cpp
15
src/Main.cpp
@ -1,19 +1,23 @@
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include "Data/Chart.hpp"
|
||||
#include "Data/Score.hpp"
|
||||
#include "Data/SongList.hpp"
|
||||
// #include "Data/Chart.hpp"
|
||||
// #include "Data/Score.hpp"
|
||||
|
||||
#include "Screens/MusicSelect/MusicSelect.hpp"
|
||||
#include "Screens/Gameplay.hpp"
|
||||
#include "Screens/Result.hpp"
|
||||
// #include "Screens/Gameplay.hpp"
|
||||
// #include "Screens/Result.hpp"
|
||||
|
||||
int main(int argc, char const *argv[]) {
|
||||
|
||||
sf::RenderWindow window(sf::VideoMode(800,600), "jujube");
|
||||
window.setVerticalSyncEnabled(true);
|
||||
|
||||
MusicSelect::Screen music_select;
|
||||
Data::SongList song_list;
|
||||
MusicSelect::Screen music_select{song_list};
|
||||
|
||||
music_select.select_chart(window);
|
||||
/*
|
||||
while (true) {
|
||||
|
||||
Chart& selected_chart = music_select.select_chart(window);
|
||||
@ -25,6 +29,7 @@ int main(int argc, char const *argv[]) {
|
||||
result_screen.display(window);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -2,12 +2,11 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../../Data/KeyMaping.hpp"
|
||||
#include "../../Data/KeyMapping.hpp"
|
||||
|
||||
MusicSelect::Screen::Screen(const Data::SongList& t_song_list) :
|
||||
song_list(t_song_list),
|
||||
resources(),
|
||||
state(t_song_list)
|
||||
ribbon(MusicSelect::Ribbon::test_sort())
|
||||
{
|
||||
for (const auto& song : song_list.songs) {
|
||||
if (song.cover) {
|
||||
@ -20,7 +19,9 @@ MusicSelect::Screen::Screen(const Data::SongList& t_song_list) :
|
||||
}
|
||||
}
|
||||
|
||||
Chart& MusicSelect::Screen::select_chart(sf::Window& window) {
|
||||
void MusicSelect::Screen::select_chart(sf::RenderWindow& window) {
|
||||
|
||||
window.create(sf::VideoMode(600,600), "jujube", sf::Style::None);
|
||||
bool chart_selected = false;
|
||||
while (not chart_selected) {
|
||||
sf::Event event;
|
||||
@ -33,21 +34,23 @@ Chart& MusicSelect::Screen::select_chart(sf::Window& window) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// drawing the ribbon
|
||||
for (size_t panel = 0; panel < 12; panel++) {
|
||||
ribbon.at(panel)->draw(
|
||||
*this,
|
||||
window,
|
||||
sf::FloatRect((panel%4)*150.f, (panel/4)*150.f, 150.f, 150.f)
|
||||
);
|
||||
}
|
||||
window.display();
|
||||
}
|
||||
}
|
||||
|
||||
void MusicSelect::Screen::handle_key(const sf::Event::KeyEvent& key_event) {
|
||||
auto panel = key_mapping.key_to_panel(key_event.code);
|
||||
auto panel = key_mapping.key_to_button(key_event.code);
|
||||
if (panel) {
|
||||
if (PanelEnum::P2 <= *panel and *panel <= PanelEnum::P12) {
|
||||
auto coord = toCoord(*panel);
|
||||
auto ribbon_size = state.ribbon.get_layout().size();
|
||||
state
|
||||
.ribbon
|
||||
.get_layout()
|
||||
.at((state.ribbon_position + coord.x) % ribbon_size)
|
||||
.at(coord.y)
|
||||
->click(state);
|
||||
if (Button::B2 <= *panel and *panel <= Button::B12) {
|
||||
ribbon.at()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
#include "../../Data/SongList.hpp"
|
||||
#include "../../Data/Chart.hpp"
|
||||
#include "../../Data/KeyMaping.hpp"
|
||||
#include "State.hpp"
|
||||
#include "../../Data/KeyMapping.hpp"
|
||||
#include "Ribbon.hpp"
|
||||
#include "Resources.hpp"
|
||||
|
||||
namespace MusicSelect {
|
||||
@ -17,12 +17,20 @@ namespace MusicSelect {
|
||||
class Screen {
|
||||
public:
|
||||
Screen(const Data::SongList& t_song_list);
|
||||
Chart& select_chart(sf::Window& window);
|
||||
void select_chart(sf::RenderWindow& window);
|
||||
|
||||
private:
|
||||
// Data
|
||||
const Data::SongList& song_list;
|
||||
|
||||
// Resources
|
||||
Resources resources;
|
||||
State state;
|
||||
KeyMaping key_mapping;
|
||||
|
||||
// State
|
||||
Ribbon ribbon;
|
||||
std::optional<std::reference_wrapper<SongPanel>> selected_panel;
|
||||
|
||||
KeyMapping key_mapping;
|
||||
void handle_key(const sf::Event::KeyEvent& key_event);
|
||||
};
|
||||
};
|
||||
|
@ -1,6 +1,38 @@
|
||||
#include "Panel.hpp"
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
void MusicSelect::CategoryPanel::display(State& state, sf::Window& window, sf::FloatRect area) {
|
||||
|
||||
#include "MusicSelect.hpp"
|
||||
|
||||
void MusicSelect::CategoryPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
|
||||
sf::RectangleShape frame{{area.width*0.9f, area.height*0.9f}};
|
||||
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);
|
||||
frame.setPosition(area.left+area.width/2.f, area.top+area.height/2.f);
|
||||
target.draw(frame);
|
||||
|
||||
sf::Text top_text;
|
||||
top_text.setFont(resources.noto_sans_medium);
|
||||
top_text.setString("category");
|
||||
top_text.setCharacterSize(12U);
|
||||
top_text.setFillColor(sf::Color::White);
|
||||
auto bounds = top_text.getLocalBounds();
|
||||
top_text.setScale(area.width*0.45f / bounds.width, area.width*0.45f / bounds.width);
|
||||
top_text.setPosition(area.left + area.width*0.15f, area.top + area.height*0.15f);
|
||||
|
||||
sf::Text label_text;
|
||||
label_text.setFont(resources.noto_sans_medium);
|
||||
label_text.setString(this->label);
|
||||
label_text.setCharacterSize(24U);
|
||||
label_text.setFillColor(sf::Color::White);
|
||||
auto bounds = label_text.getLocalBounds();
|
||||
label_text.setOrigin(bounds.width / 2.f, bounds.height / 2.f);
|
||||
if (bounds.height > bounds.width) {
|
||||
label_text.setScale(area.height*0.8f / bounds.height, area.height*0.8f / bounds.height);
|
||||
} else {
|
||||
label_text.setScale(area.width*0.8f / bounds.width, area.width*0.8f / bounds.width);
|
||||
}
|
||||
label_text.setPosition(area.left + area.width / 2.f, area.top + area.height / 2.f);
|
||||
}
|
||||
|
@ -2,31 +2,35 @@
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/Window.hpp>
|
||||
#include "State.hpp"
|
||||
|
||||
#include "Resources.hpp"
|
||||
|
||||
namespace MusicSelect {
|
||||
// A Panel holds anything that can go under a panel on the moving part
|
||||
|
||||
class Screen;
|
||||
|
||||
// A Panel holds anything that can go under a button on the moving part
|
||||
// of the music select screen, be it nothing, a sort indicator, or a song
|
||||
class Panel {
|
||||
public:
|
||||
// What happens when you click on the panel
|
||||
virtual void click(State& state) = 0;
|
||||
virtual void click(Screen& screen) = 0;
|
||||
// How the panel should be displayed
|
||||
virtual void display(State& state, sf::Window& window, sf::FloatRect area) = 0;
|
||||
virtual void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) = 0;
|
||||
virtual ~Panel() = default;
|
||||
};
|
||||
|
||||
class EmptyPanel final : public Panel {
|
||||
public:
|
||||
void click(State& state) override {return;};
|
||||
void display(State& state, sf::Window& window, sf::FloatRect area) override {return;};
|
||||
void click(Screen& screen) override {return;};
|
||||
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override {return;};
|
||||
};
|
||||
|
||||
class CategoryPanel final : public Panel {
|
||||
public:
|
||||
CategoryPanel(const std::string& t_label) : label(t_label) {};
|
||||
void click(State& state) override;
|
||||
void display(State& state, sf::Window& window, sf::FloatRect area) override;
|
||||
void click(Screen& screen) override;
|
||||
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
|
||||
private:
|
||||
std::string label;
|
||||
};
|
||||
@ -34,8 +38,8 @@ namespace MusicSelect {
|
||||
class SongPanel final : public Panel {
|
||||
public:
|
||||
SongPanel(const Data::Song& t_song) : song(t_song) {};
|
||||
void click(State& state) override;
|
||||
void display(State& state, sf::Window& window, sf::FloatRect area) override;
|
||||
void click(Screen& screen) override;
|
||||
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
|
||||
private:
|
||||
const Data::Song& song;
|
||||
};
|
||||
|
8
src/Screens/MusicSelect/Resources.cpp
Normal file
8
src/Screens/MusicSelect/Resources.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "Resources.hpp"
|
||||
|
||||
|
||||
MusicSelect::Resources::Resources() {
|
||||
if (not noto_sans_medium.loadFromFile("assets/fonts/NotoSans-Medium.ttf")) {
|
||||
throw std::runtime_error("Unable to load assets/fonts/NotoSans-Medium.ttf");
|
||||
}
|
||||
}
|
@ -1,15 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
#include "../../Resources/CoverAtlas.hpp"
|
||||
|
||||
namespace MusicSelect {
|
||||
// Holds the fonts, graphics and sounds needed by all of the MusicSelect Screen
|
||||
struct Resources {
|
||||
Resources();
|
||||
Textures::CoverAltas cover_previews;
|
||||
std::unordered_map<std::string, sf::Font> fonts;
|
||||
sf::Font noto_sans_medium;
|
||||
};
|
||||
}
|
||||
}
|
@ -41,4 +41,33 @@ MusicSelect::Ribbon MusicSelect::Ribbon::title_sort(const Data::SongList& song_l
|
||||
}
|
||||
}
|
||||
return ribbon;
|
||||
}
|
||||
}
|
||||
|
||||
MusicSelect::Ribbon MusicSelect::Ribbon::test_sort() {
|
||||
Ribbon ribbon;
|
||||
ribbon.layout.push_back(
|
||||
{
|
||||
std::make_unique<EmptyPanel>(),
|
||||
std::make_unique<CategoryPanel>("A"),
|
||||
std::make_unique<CategoryPanel>("truc")
|
||||
}
|
||||
);
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
ribbon.layout.push_back(
|
||||
{
|
||||
std::make_unique<EmptyPanel>(),
|
||||
std::make_unique<EmptyPanel>(),
|
||||
std::make_unique<EmptyPanel>()
|
||||
}
|
||||
);
|
||||
}
|
||||
return ribbon;
|
||||
}
|
||||
|
||||
const std::unique_ptr<MusicSelect::Panel>& MusicSelect::Ribbon::at(unsigned int button_index) const {
|
||||
return (
|
||||
layout
|
||||
.at((position + (button_index % 4)) % layout.size())
|
||||
.at(button_index / 4)
|
||||
);
|
||||
}
|
||||
|
@ -10,8 +10,11 @@ namespace MusicSelect {
|
||||
public:
|
||||
Ribbon();
|
||||
static Ribbon title_sort(const Data::SongList& song_list);
|
||||
static Ribbon test_sort();
|
||||
const auto& get_layout() {return layout;};
|
||||
const std::unique_ptr<MusicSelect::Panel>& at(unsigned int button_index) const;
|
||||
private:
|
||||
std::vector<std::array<std::unique_ptr<Panel>,3>> layout;
|
||||
unsigned int position = 0;
|
||||
};
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#include "State.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
MusicSelect::State::State(const Data::SongList& song_list) {
|
||||
ribbon = MusicSelect::Ribbon::title_sort(song_list);
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "../Data/SongList.hpp"
|
||||
#include "Panel.hpp"
|
||||
#include "Ribbon.hpp"
|
||||
|
||||
|
||||
namespace MusicSelect {
|
||||
// Holds everything related to the displaying state of the MusicSelect screen
|
||||
struct State {
|
||||
State(const Data::SongList& song_list);
|
||||
// The ribbon is the moving part or the music select screen
|
||||
Ribbon ribbon;
|
||||
unsigned int ribbon_position;
|
||||
std::optional<std::reference_wrapper<SongPanel>> selected_panel;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user