WIP song select layout
This commit is contained in:
parent
12b5283a71
commit
ec5c4e270b
@ -10,7 +10,7 @@ foreach module : ['system', 'window', 'graphics', 'audio']
|
|||||||
sfml += [dependency('sfml-'+module, version : '>=2.5.1')]
|
sfml += [dependency('sfml-'+module, version : '>=2.5.1')]
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
add_project_link_arguments(['-lstdc++', '-lstdc++fs'], language : 'cpp')
|
add_project_link_arguments(['-lstdc++', '-lstdc++fs', '-lm'], language : 'cpp')
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
'src/Main.cpp',
|
'src/Main.cpp',
|
||||||
@ -36,9 +36,11 @@ sources = [
|
|||||||
# 'src/Screens/Result.hpp',
|
# 'src/Screens/Result.hpp',
|
||||||
'src/Resources/CoverAtlas.hpp',
|
'src/Resources/CoverAtlas.hpp',
|
||||||
'src/Resources/CoverAtlas.cpp',
|
'src/Resources/CoverAtlas.cpp',
|
||||||
|
'src/Toolkit/AffineTransform.hpp',
|
||||||
|
'src/Toolkit/EasingFunctions.hpp',
|
||||||
|
'src/Toolkit/EasingFunctions.cpp',
|
||||||
'src/Toolkit/QuickRNG.hpp',
|
'src/Toolkit/QuickRNG.hpp',
|
||||||
'src/Toolkit/QuickRNG.cpp',
|
'src/Toolkit/QuickRNG.cpp',
|
||||||
'src/Toolkit/AffineTransform.hpp',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
executable(
|
executable(
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
MusicSelect::Screen::Screen(const Data::SongList& t_song_list) :
|
MusicSelect::Screen::Screen(const Data::SongList& t_song_list) :
|
||||||
song_list(t_song_list),
|
song_list(t_song_list),
|
||||||
ribbon(MusicSelect::Ribbon::test2_sort()),
|
button_highlight(panel_size),
|
||||||
button_highlight(panel_size)
|
ribbon(resources)
|
||||||
{
|
{
|
||||||
for (const auto& song : song_list.songs) {
|
for (const auto& song : song_list.songs) {
|
||||||
if (song.cover) {
|
if (song.cover) {
|
||||||
@ -18,6 +18,7 @@ MusicSelect::Screen::Screen(const Data::SongList& t_song_list) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ribbon.test2_sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MusicSelect::Screen::select_chart(sf::RenderWindow& window) {
|
void MusicSelect::Screen::select_chart(sf::RenderWindow& window) {
|
||||||
@ -38,20 +39,7 @@ void MusicSelect::Screen::select_chart(sf::RenderWindow& window) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
window.draw(ribbon);
|
||||||
// draw the ribbon
|
|
||||||
for (size_t panel = 0; panel < 12; panel++) {
|
|
||||||
ribbon.at(panel)->draw(
|
|
||||||
resources,
|
|
||||||
window,
|
|
||||||
sf::FloatRect(
|
|
||||||
(panel%4)*150.f,
|
|
||||||
(panel/4)*150.f,
|
|
||||||
150.f,
|
|
||||||
150.f
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
window.draw(button_highlight);
|
window.draw(button_highlight);
|
||||||
window.display();
|
window.display();
|
||||||
window.clear(sf::Color::Black);
|
window.clear(sf::Color::Black);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "MusicSelect.hpp"
|
#include "MusicSelect.hpp"
|
||||||
|
|
||||||
void MusicSelect::ColorPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
|
void MusicSelect::ColorPanel::draw(const Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
|
||||||
sf::RectangleShape panel{{area.width*0.9f, area.height*0.9f}};
|
sf::RectangleShape panel{{area.width*0.9f, area.height*0.9f}};
|
||||||
panel.setFillColor(this->color);
|
panel.setFillColor(this->color);
|
||||||
panel.setOrigin(panel.getSize().x / 2.f, panel.getSize().y / 2.f);
|
panel.setOrigin(panel.getSize().x / 2.f, panel.getSize().y / 2.f);
|
||||||
@ -16,7 +16,7 @@ void MusicSelect::CategoryPanel::click(Screen& screen) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MusicSelect::CategoryPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
|
void MusicSelect::CategoryPanel::draw(const Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
|
||||||
sf::RectangleShape red_rectangle;
|
sf::RectangleShape red_rectangle;
|
||||||
red_rectangle.setFillColor(sf::Color::Transparent);
|
red_rectangle.setFillColor(sf::Color::Transparent);
|
||||||
red_rectangle.setOutlineColor(sf::Color::Red);
|
red_rectangle.setOutlineColor(sf::Color::Red);
|
||||||
@ -68,7 +68,7 @@ void MusicSelect::SongPanel::click(Screen& screen) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MusicSelect::SongPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
|
void MusicSelect::SongPanel::draw(const Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,21 +17,21 @@ namespace MusicSelect {
|
|||||||
// What happens when you click on the panel
|
// What happens when you click on the panel
|
||||||
virtual void click(Screen& screen) = 0;
|
virtual void click(Screen& screen) = 0;
|
||||||
// How the panel should be displayed
|
// How the panel should be displayed
|
||||||
virtual void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) = 0;
|
virtual void draw(const Resources& resources, sf::RenderTarget& target, sf::FloatRect area) = 0;
|
||||||
virtual ~Panel() = default;
|
virtual ~Panel() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmptyPanel final : public Panel {
|
class EmptyPanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
void click(Screen& screen) override {return;};
|
void click(Screen& screen) override {return;};
|
||||||
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override {return;};
|
void draw(const Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override {return;};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ColorPanel final : public Panel {
|
class ColorPanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
explicit ColorPanel(const sf::Color& t_color) : color(t_color) {};
|
explicit ColorPanel(const sf::Color& t_color) : color(t_color) {};
|
||||||
void click(Screen& screen) override {return;};
|
void click(Screen& screen) override {return;};
|
||||||
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
|
void draw(const Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
|
||||||
private:
|
private:
|
||||||
const sf::Color color;
|
const sf::Color color;
|
||||||
};
|
};
|
||||||
@ -40,7 +40,7 @@ namespace MusicSelect {
|
|||||||
public:
|
public:
|
||||||
explicit 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(const Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
|
||||||
private:
|
private:
|
||||||
std::string label;
|
std::string label;
|
||||||
};
|
};
|
||||||
@ -49,7 +49,7 @@ namespace MusicSelect {
|
|||||||
public:
|
public:
|
||||||
explicit 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(const Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
|
||||||
private:
|
private:
|
||||||
const Data::Song& song;
|
const Data::Song& song;
|
||||||
};
|
};
|
||||||
|
@ -7,50 +7,92 @@
|
|||||||
#include "Panel.hpp"
|
#include "Panel.hpp"
|
||||||
#include "../../Toolkit/QuickRNG.hpp"
|
#include "../../Toolkit/QuickRNG.hpp"
|
||||||
|
|
||||||
MusicSelect::Ribbon MusicSelect::Ribbon::title_sort(const Data::SongList& song_list) {
|
MusicSelect::MoveAnimation::MoveAnimation(unsigned int previous_pos, unsigned int next_pos, size_t ribbon_size, Direction direction) :
|
||||||
std::map<char,std::vector<Data::Song>> categories;
|
normalized_to_pos(create_transform(previous_pos, next_pos, ribbon_size, direction)),
|
||||||
for (const auto& song : song_list.songs) {
|
seconds_to_normalized(0.f, 0.3f, 0.f, 1.f),
|
||||||
if (song.title.size() > 0) {
|
clock(),
|
||||||
char letter = song.title[0];
|
ease_expo(-7.f)
|
||||||
if ('A' <= letter and letter <= 'Z') {
|
{
|
||||||
categories[letter].push_back(song);
|
|
||||||
} else if ('a' <= letter and letter <= 'z') {
|
|
||||||
categories['A' + (letter - 'a')].push_back(song);
|
|
||||||
} else {
|
|
||||||
categories['?'].push_back(song);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
categories['?'].push_back(song);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ribbon ribbon;
|
|
||||||
for (auto& [letter, songs] : categories) {
|
|
||||||
std::vector<std::shared_ptr<Panel>> panels;
|
|
||||||
panels.emplace_back(
|
|
||||||
std::make_shared<CategoryPanel>(
|
|
||||||
std::string(1, letter)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
std::sort(songs.begin(), songs.end(), Data::Song::sort_by_title);
|
|
||||||
for (const auto& song : songs) {
|
|
||||||
panels.push_back(std::make_shared<SongPanel>(song));
|
|
||||||
}
|
|
||||||
while (panels.size() % 3 != 0) {
|
|
||||||
panels.push_back(std::make_shared<EmptyPanel>());
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < panels.size(); i += 3) {
|
|
||||||
ribbon.layout.emplace_back();
|
|
||||||
for (size_t j = 0; j < 3; j++) {
|
|
||||||
ribbon.layout.back()[j] = std::move(panels[i+j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ribbon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicSelect::Ribbon MusicSelect::Ribbon::test_sort() {
|
Toolkit::AffineTransform<float> MusicSelect::MoveAnimation::create_transform(unsigned int previous_pos, unsigned int next_pos, size_t ribbon_size, Direction direction) {
|
||||||
Ribbon ribbon;
|
// We first deal with cases were we cross the end of the ribbon
|
||||||
ribbon.layout.push_back(
|
if (direction == Direction::Left and next_pos > previous_pos) {
|
||||||
|
return Toolkit::AffineTransform<float>(
|
||||||
|
0.f,
|
||||||
|
1.f,
|
||||||
|
static_cast<float>(previous_pos),
|
||||||
|
static_cast<float>(next_pos-ribbon_size)
|
||||||
|
);
|
||||||
|
} else if (direction == Direction::Right and next_pos < previous_pos) {
|
||||||
|
return Toolkit::AffineTransform<float>(
|
||||||
|
0.f,
|
||||||
|
1.f,
|
||||||
|
static_cast<float>(previous_pos),
|
||||||
|
static_cast<float>(next_pos+ribbon_size)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Toolkit::AffineTransform<float>(
|
||||||
|
0.f,
|
||||||
|
1.f,
|
||||||
|
static_cast<float>(previous_pos),
|
||||||
|
static_cast<float>(next_pos)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float MusicSelect::MoveAnimation::get_position() {
|
||||||
|
return normalized_to_pos.transform(
|
||||||
|
ease_expo.transform(
|
||||||
|
seconds_to_normalized.clampedTransform(
|
||||||
|
clock.getElapsedTime().asSeconds()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MusicSelect::MoveAnimation::ended() {
|
||||||
|
return clock.getElapsedTime() > sf::milliseconds(300);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MusicSelect::Ribbon::title_sort(const Data::SongList& song_list) {
|
||||||
|
std::vector<std::reference_wrapper<const Data::Song>> songs;
|
||||||
|
for (auto &&song : song_list.songs) {
|
||||||
|
songs.push_back(std::cref(song));
|
||||||
|
}
|
||||||
|
|
||||||
|
(song_list.songs.begin(), song_list.songs.end());
|
||||||
|
std::sort(songs.begin(), songs.end(), Data::Song::sort_by_title);
|
||||||
|
std::map<std::string,std::vector<std::shared_ptr<Panel>>> categories;
|
||||||
|
for (const auto& song : songs) {
|
||||||
|
if (song.get().title.size() > 0) {
|
||||||
|
char letter = song.get().title[0];
|
||||||
|
if ('A' <= letter and letter <= 'Z') {
|
||||||
|
categories
|
||||||
|
[std::string(1, letter)]
|
||||||
|
.push_back(
|
||||||
|
std::make_shared<SongPanel>(song)
|
||||||
|
);
|
||||||
|
} else if ('a' <= letter and letter <= 'z') {
|
||||||
|
categories
|
||||||
|
[std::string(1, 'A' + (letter - 'a'))]
|
||||||
|
.push_back(
|
||||||
|
std::make_shared<SongPanel>(song)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
categories["?"].push_back(std::make_shared<SongPanel>(song));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
categories["?"].push_back(std::make_shared<SongPanel>(song));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layout_from_category_map(categories);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MusicSelect::Ribbon::test_sort() {
|
||||||
|
layout.clear();
|
||||||
|
layout.push_back(
|
||||||
{
|
{
|
||||||
std::make_shared<EmptyPanel>(),
|
std::make_shared<EmptyPanel>(),
|
||||||
std::make_shared<CategoryPanel>("A"),
|
std::make_shared<CategoryPanel>("A"),
|
||||||
@ -58,7 +100,7 @@ MusicSelect::Ribbon MusicSelect::Ribbon::test_sort() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
for (size_t i = 0; i < 3; i++) {
|
for (size_t i = 0; i < 3; i++) {
|
||||||
ribbon.layout.push_back(
|
layout.push_back(
|
||||||
{
|
{
|
||||||
std::make_shared<EmptyPanel>(),
|
std::make_shared<EmptyPanel>(),
|
||||||
std::make_shared<EmptyPanel>(),
|
std::make_shared<EmptyPanel>(),
|
||||||
@ -66,12 +108,11 @@ MusicSelect::Ribbon MusicSelect::Ribbon::test_sort() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ribbon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicSelect::Ribbon MusicSelect::Ribbon::test2_sort() {
|
void MusicSelect::Ribbon::test2_sort() {
|
||||||
std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
std::map<std::string, std::list<std::shared_ptr<Panel>>> categories;
|
std::map<std::string, std::vector<std::shared_ptr<Panel>>> categories;
|
||||||
Toolkit::UniformIntRNG category_size_generator{1,10};
|
Toolkit::UniformIntRNG category_size_generator{1,10};
|
||||||
Toolkit::UniformIntRNG panel_hue_generator{0,255};
|
Toolkit::UniformIntRNG panel_hue_generator{0,255};
|
||||||
for (auto &&letter : alphabet) {
|
for (auto &&letter : alphabet) {
|
||||||
@ -88,7 +129,7 @@ MusicSelect::Ribbon MusicSelect::Ribbon::test2_sort() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ribbon::layout_from_map(categories);
|
layout_from_category_map(categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<MusicSelect::Panel>& MusicSelect::Ribbon::at(unsigned int button_index) const {
|
const std::shared_ptr<MusicSelect::Panel>& MusicSelect::Ribbon::at(unsigned int button_index) const {
|
||||||
@ -99,15 +140,15 @@ const std::shared_ptr<MusicSelect::Panel>& MusicSelect::Ribbon::at(unsigned int
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicSelect::Ribbon MusicSelect::Ribbon::layout_from_map(const std::map<std::string, std::list<std::shared_ptr<MusicSelect::Panel>>>& categories) {
|
void MusicSelect::Ribbon::layout_from_category_map(const std::map<std::string, std::vector<std::shared_ptr<MusicSelect::Panel>>>& categories) {
|
||||||
Ribbon ribbon;
|
layout.clear();
|
||||||
for (auto &&[category, panels] : categories) {
|
for (auto &&[category, panels] : categories) {
|
||||||
if (not panels.empty()) {
|
if (not panels.empty()) {
|
||||||
std::vector<std::shared_ptr<Panel>> current_column;
|
std::vector<std::shared_ptr<Panel>> current_column;
|
||||||
current_column.push_back(std::make_shared<CategoryPanel>(category));
|
current_column.push_back(std::make_shared<CategoryPanel>(category));
|
||||||
for (auto &&panel : panels) {
|
for (auto &&panel : panels) {
|
||||||
if (current_column.size() == 3) {
|
if (current_column.size() == 3) {
|
||||||
ribbon.layout.push_back({current_column[0], current_column[1], current_column[2]});
|
layout.push_back({current_column[0], current_column[1], current_column[2]});
|
||||||
current_column.clear();
|
current_column.clear();
|
||||||
} else {
|
} else {
|
||||||
current_column.push_back(std::move(panel));
|
current_column.push_back(std::move(panel));
|
||||||
@ -117,21 +158,71 @@ MusicSelect::Ribbon MusicSelect::Ribbon::layout_from_map(const std::map<std::str
|
|||||||
while (current_column.size() < 3) {
|
while (current_column.size() < 3) {
|
||||||
current_column.push_back(std::make_shared<EmptyPanel>());
|
current_column.push_back(std::make_shared<EmptyPanel>());
|
||||||
}
|
}
|
||||||
ribbon.layout.push_back({current_column[0], current_column[1], current_column[2]});
|
layout.push_back({current_column[0], current_column[1], current_column[2]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ribbon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MusicSelect::Ribbon::move_right() {
|
void MusicSelect::Ribbon::move_right() {
|
||||||
|
move_animation.emplace(position, position + 1, layout.size(), Direction::Right);
|
||||||
position = (position + 1) % layout.size();
|
position = (position + 1) % layout.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MusicSelect::Ribbon::move_left() {
|
void MusicSelect::Ribbon::move_left() {
|
||||||
|
move_animation.emplace(position, static_cast<int>(position)-1, layout.size(), Direction::Left);
|
||||||
if (position == 0) {
|
if (position == 0) {
|
||||||
position = layout.size() - 1;
|
position = layout.size() - 1;
|
||||||
} else {
|
} else {
|
||||||
position--;
|
position--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MusicSelect::Ribbon::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
|
if (move_animation) {
|
||||||
|
if (not move_animation->ended()) {
|
||||||
|
return draw_with_animation(target, states);
|
||||||
|
} else {
|
||||||
|
move_animation.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_without_animation(target, states);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MusicSelect::Ribbon::draw_with_animation(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
|
auto float_position = move_animation->get_position();
|
||||||
|
unsigned int column_zero = (static_cast<int>(float_position) + layout.size()) % layout.size();
|
||||||
|
for (int column_offset = -1; column_offset <= 4; column_offset++) {
|
||||||
|
unsigned int actual_column = (column_zero + column_offset + layout.size()) % layout.size();
|
||||||
|
for (int row = 0; row < 3; row++) {
|
||||||
|
layout.at(actual_column).at(row)->draw(
|
||||||
|
resources,
|
||||||
|
target,
|
||||||
|
sf::FloatRect(
|
||||||
|
(static_cast<float>(column_zero + column_offset)-float_position)*150.f,
|
||||||
|
row*150.f,
|
||||||
|
150.f,
|
||||||
|
150.f
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MusicSelect::Ribbon::draw_without_animation(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
|
for (int column = -1; column <= 4; column++) {
|
||||||
|
int actual_column_index = (column + position + layout.size()) % layout.size();
|
||||||
|
for (int row = 0; row < 3; row++) {
|
||||||
|
layout.at(actual_column_index).at(row)->draw(
|
||||||
|
resources,
|
||||||
|
target,
|
||||||
|
sf::FloatRect(
|
||||||
|
column*150.f,
|
||||||
|
row*150.f,
|
||||||
|
150.f,
|
||||||
|
150.f
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,24 +1,51 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <SFML/Graphics/Drawable.hpp>
|
||||||
|
|
||||||
#include "Panel.hpp"
|
#include "Panel.hpp"
|
||||||
#include "../../Data/SongList.hpp"
|
#include "../../Data/SongList.hpp"
|
||||||
|
#include "../../Toolkit/AffineTransform.hpp"
|
||||||
|
#include "../../Toolkit/EasingFunctions.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
|
enum class Direction {
|
||||||
|
Right,
|
||||||
|
Left,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MoveAnimation {
|
||||||
|
MoveAnimation(unsigned int previous_pos, unsigned int next_pos, size_t ribbon_size, Direction direction);
|
||||||
|
Toolkit::AffineTransform<float> normalized_to_pos;
|
||||||
|
Toolkit::AffineTransform<float> seconds_to_normalized;
|
||||||
|
sf::Clock clock;
|
||||||
|
Toolkit::EaseExponential ease_expo;
|
||||||
|
float get_position();
|
||||||
|
bool ended();
|
||||||
|
private:
|
||||||
|
Toolkit::AffineTransform<float> create_transform(unsigned int previous_pos, unsigned int next_pos, size_t ribbon_size, Direction direction);
|
||||||
|
};
|
||||||
|
|
||||||
// The Ribbon is the moving part of the Music Select Screen
|
// The Ribbon is the moving part of the Music Select Screen
|
||||||
// It can be sorted in a number of ways
|
// It can be sorted in a number of ways
|
||||||
class Ribbon {
|
class Ribbon final : public sf::Drawable {
|
||||||
public:
|
public:
|
||||||
Ribbon() = default;
|
Ribbon(const Resources& t_resources) : resources(t_resources) {};
|
||||||
static Ribbon title_sort(const Data::SongList& song_list);
|
void title_sort(const Data::SongList& song_list);
|
||||||
static Ribbon test_sort();
|
void test_sort();
|
||||||
static Ribbon test2_sort();
|
void test2_sort();
|
||||||
const auto& get_layout() {return layout;};
|
const auto& get_layout() {return layout;};
|
||||||
const std::shared_ptr<MusicSelect::Panel>& at(unsigned int button_index) const;
|
const std::shared_ptr<MusicSelect::Panel>& at(unsigned int button_index) const;
|
||||||
void move_right();
|
void move_right();
|
||||||
void move_left();
|
void move_left();
|
||||||
private:
|
private:
|
||||||
static Ribbon layout_from_map(const std::map<std::string,std::list<std::shared_ptr<Panel>>>& categories);
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
|
void draw_with_animation(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||||
|
void draw_without_animation(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||||
|
void layout_from_category_map(const std::map<std::string,std::vector<std::shared_ptr<Panel>>>& categories);
|
||||||
std::vector<std::array<std::shared_ptr<Panel>,3>> layout;
|
std::vector<std::array<std::shared_ptr<Panel>,3>> layout;
|
||||||
unsigned int position = 0;
|
unsigned int position = 0;
|
||||||
|
mutable std::optional<MoveAnimation> move_animation;
|
||||||
|
const Resources& resources;
|
||||||
};
|
};
|
||||||
}
|
}
|
10
src/Toolkit/EasingFunctions.cpp
Normal file
10
src/Toolkit/EasingFunctions.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "EasingFunctions.hpp"
|
||||||
|
|
||||||
|
float Toolkit::EaseExponential::transform(float in) {
|
||||||
|
// (1-2^(a*x))/(1-2^a)
|
||||||
|
return (
|
||||||
|
1.f - std::pow(2.f, easing_factor*in)
|
||||||
|
) / (
|
||||||
|
1.f - std::pow(2.f, easing_factor)
|
||||||
|
);
|
||||||
|
}
|
12
src/Toolkit/EasingFunctions.hpp
Normal file
12
src/Toolkit/EasingFunctions.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace Toolkit {
|
||||||
|
class EaseExponential {
|
||||||
|
public:
|
||||||
|
EaseExponential(float t_easing_factor) : easing_factor(t_easing_factor) {};
|
||||||
|
float transform(float in);
|
||||||
|
float easing_factor;
|
||||||
|
};
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user