1
0
mirror of synced 2025-02-15 09:52:36 +01:00

Variable panel size and spacing

This commit is contained in:
Stepland 2020-02-09 17:19:19 +01:00
parent df4f88934e
commit d6e7ec89a8
6 changed files with 94 additions and 86 deletions

View File

@ -10,9 +10,9 @@
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),
resources(), resources(),
ribbon(resources), ribbon(resources, m_panel_size, m_panel_spacing),
selected_panel(), selected_panel(),
button_highlight(panel_size), button_highlight(m_panel_size),
key_mapping() key_mapping()
{ {
/* /*
@ -31,7 +31,7 @@ MusicSelect::Screen::Screen(const Data::SongList& t_song_list) :
} }
void MusicSelect::Screen::select_chart(sf::RenderWindow& window) { void MusicSelect::Screen::select_chart(sf::RenderWindow& window) {
window.create(sf::VideoMode(panel_size*4, panel_size*4), "jujube", sf::Style::Titlebar); window.create(sf::VideoMode(m_panel_size*4, m_panel_size*4), "jujube", sf::Style::Titlebar);
window.setFramerateLimit(60); window.setFramerateLimit(60);
ImGui::SFML::Init(window); ImGui::SFML::Init(window);
bool chart_selected = false; bool chart_selected = false;
@ -78,7 +78,7 @@ void MusicSelect::Screen::handle_key_press(const sf::Event::KeyEvent& key_event)
void MusicSelect::Screen::handle_mouse_click(const sf::Event::MouseButtonEvent& mouse_button_event) { void MusicSelect::Screen::handle_mouse_click(const sf::Event::MouseButtonEvent& mouse_button_event) {
if (mouse_button_event.button == sf::Mouse::Left) { if (mouse_button_event.button == sf::Mouse::Left) {
int clicked_panel_index = (mouse_button_event.x / panel_size) + 4 * (mouse_button_event.y / panel_size); int clicked_panel_index = (mouse_button_event.x / m_panel_size) + 4 * (mouse_button_event.y / m_panel_size);
auto button = fromIndex(clicked_panel_index); auto button = fromIndex(clicked_panel_index);
if (button) { if (button) {
press_button(*button); press_button(*button);

View File

@ -24,7 +24,8 @@ namespace MusicSelect {
private: private:
// Data // Data
const Data::SongList& song_list; const Data::SongList& song_list;
std::size_t panel_size = 150; std::size_t m_panel_size = 150;
std::size_t m_panel_spacing = 0;
// Resources // Resources
Resources resources; Resources resources;

View File

@ -5,72 +5,73 @@
#include "MusicSelect.hpp" #include "MusicSelect.hpp"
namespace MusicSelect { namespace MusicSelect {
void ColorPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) { void ColorPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const {
sf::RectangleShape panel{{area.width*0.9f, area.height*0.9f}}; sf::RectangleShape panel{{m_size*0.9f, m_size*0.9f}};
panel.setFillColor(this->color); panel.setFillColor(m_color);
panel.setOrigin(panel.getSize().x / 2.f, panel.getSize().y / 2.f); states.transform *= getTransform();
panel.setPosition(area.left+area.width/2.f, area.top+area.height/2.f); target.draw(panel, states);
target.draw(panel);
} }
void CategoryPanel::click(Ribbon& ribbon, std::size_t from_button_index) { void CategoryPanel::click(Ribbon& ribbon, std::size_t from_button_index) {
ribbon.move_to_next_category(from_button_index); ribbon.move_to_next_category(from_button_index);
} }
void CategoryPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) { void CategoryPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform *= getTransform();
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);
red_rectangle.setOutlineThickness(1.f); red_rectangle.setOutlineThickness(1.f);
sf::RectangleShape frame{{area.width*0.9f, area.height*0.9f}}; sf::RectangleShape frame{{m_size*0.9f, m_size*0.9f}};
frame.setFillColor(sf::Color::Black); frame.setFillColor(sf::Color::Black);
frame.setOutlineThickness(1.f); frame.setOutlineThickness(1.f);
frame.setOutlineColor(sf::Color::White); frame.setOutlineColor(sf::Color::White);
frame.setOrigin(frame.getSize().x / 2.f, frame.getSize().y / 2.f); 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); frame.setPosition(m_size/2.f, m_size/2.f);
target.draw(frame); target.draw(frame, states);
sf::Text top_text; sf::Text top_text;
top_text.setFont(resources.noto_sans_medium); top_text.setFont(m_resources.noto_sans_medium);
top_text.setString("category"); top_text.setString("category");
top_text.setCharacterSize(50U); top_text.setCharacterSize(50U);
top_text.setFillColor(sf::Color::White); top_text.setFillColor(sf::Color::White);
auto bounds = top_text.getLocalBounds(); auto bounds = top_text.getLocalBounds();
top_text.setScale(area.width*0.45f / bounds.width, area.width*0.45f / bounds.width); top_text.setScale(m_size*0.45f / bounds.width, m_size*0.45f / bounds.width);
top_text.setPosition(area.left + area.width*0.07f, area.top + area.height*0.07f); top_text.setPosition(m_size*0.07f, m_size*0.07f);
target.draw(top_text); target.draw(top_text, states);
set_to_global_bounds(red_rectangle, top_text); set_to_global_bounds(red_rectangle, top_text);
target.draw(red_rectangle); target.draw(red_rectangle, states);
sf::Text label_text; sf::Text label_text;
label_text.setFont(resources.noto_sans_medium); label_text.setFont(m_resources.noto_sans_medium);
label_text.setString(this->label); label_text.setString(m_label);
label_text.setCharacterSize(100U); label_text.setCharacterSize(100U);
label_text.setFillColor(sf::Color::White); label_text.setFillColor(sf::Color::White);
auto text_bounds = label_text.getLocalBounds(); auto text_bounds = label_text.getLocalBounds();
label_text.setOrigin(text_bounds.width / 2.f, text_bounds.height / 2.f); label_text.setOrigin(text_bounds.width / 2.f, text_bounds.height / 2.f);
if (text_bounds.height > text_bounds.width) { if (text_bounds.height > text_bounds.width) {
label_text.setScale(area.height*0.8f / text_bounds.height, area.height*0.8f / text_bounds.height); label_text.setScale(m_size*0.8f/text_bounds.height, m_size*0.8f/text_bounds.height);
} else { } else {
label_text.setScale(area.width*0.8f / text_bounds.width, area.width*0.8f / text_bounds.width); label_text.setScale(m_size*0.8f/text_bounds.width, m_size*0.8f/text_bounds.width);
} }
label_text.setPosition(area.left + area.width / 2.f, area.top + area.height / 2.f); label_text.setPosition(m_size / 2.f, m_size / 2.f);
target.draw(label_text); target.draw(label_text, states);
set_to_global_bounds(red_rectangle, label_text); set_to_global_bounds(red_rectangle, label_text);
target.draw(red_rectangle); target.draw(red_rectangle, states);
} }
void SongPanel::click(Ribbon& ribbon, std::size_t from_button_index) { void SongPanel::click(Ribbon& ribbon, std::size_t from_button_index) {
} }
void SongPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) { void SongPanel::draw(sf::RenderTarget& target, sf::RenderStates states) const {
if (m_song.cover) { if (m_song.cover) {
auto loaded_texture = resources.covers.async_get(m_song.folder/m_song.cover.value()); auto loaded_texture = m_resources.covers.async_get(m_song.folder/m_song.cover.value());
if (loaded_texture) { if (loaded_texture) {
states.transform *= getTransform();
sf::Sprite cover{*(loaded_texture->texture)}; sf::Sprite cover{*(loaded_texture->texture)};
auto alpha = static_cast<std::uint8_t>( auto alpha = static_cast<std::uint8_t>(
m_seconds_to_alpha.clampedTransform( m_seconds_to_alpha.clampedTransform(
@ -79,9 +80,8 @@ namespace MusicSelect {
); );
cover.setColor(sf::Color(255, 255, 255, alpha)); cover.setColor(sf::Color(255, 255, 255, alpha));
auto bounds = cover.getGlobalBounds(); auto bounds = cover.getGlobalBounds();
cover.setPosition(area.left, area.top); cover.setScale(m_size / bounds.width, m_size / bounds.height);
cover.setScale(area.width / bounds.width, area.width / bounds.width); target.draw(cover, states);
target.draw(cover);
} }
} }
} }

View File

@ -13,46 +13,49 @@ namespace MusicSelect {
// A Panel holds anything that can go under a button on the moving part // A Panel holds anything that can go under a button on the moving part
// of the music select screen, be it nothing, a category indicator, or a song // of the music select screen, be it nothing, a category indicator, or a song
class Panel { class Panel : public sf::Drawable, public sf::Transformable {
public: public:
Panel(const std::size_t& size, Resources& resources) : m_size(size), m_resources(resources) {};
// What happens when you click on the panel // What happens when you click on the panel
virtual void click(Ribbon& ribbon, std::size_t from_button_index) = 0; virtual void click(Ribbon& ribbon, std::size_t from_button_index) = 0;
// How the panel should be displayed
virtual void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) = 0;
virtual ~Panel() = default; virtual ~Panel() = default;
protected:
const std::size_t& m_size;
Resources& m_resources;
}; };
class EmptyPanel final : public Panel { class EmptyPanel final : public Panel {
public: public:
using Panel::Panel;
void click(Ribbon& ribbon, std::size_t from_button_index) override {return;}; void click(Ribbon& ribbon, std::size_t from_button_index) override {return;};
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override {return;}; private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const override {return;};
}; };
class ColorPanel final : public Panel { class ColorPanel final : public Panel {
public: public:
explicit ColorPanel(const sf::Color& t_color) : color(t_color) {}; ColorPanel(const std::size_t& size, Resources& resources, const sf::Color& t_color) : Panel(size, resources), m_color(t_color) {};
void click(Ribbon& ribbon, std::size_t from_button_index) override {return;}; void click(Ribbon& ribbon, std::size_t from_button_index) override {return;};
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
private: private:
const sf::Color color; void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
const sf::Color m_color;
}; };
class CategoryPanel final : public Panel { class CategoryPanel final : public Panel {
public: public:
explicit CategoryPanel(const std::string& t_label) : label(t_label) {}; explicit CategoryPanel(const std::size_t& size, Resources& resources, const std::string& t_label) : Panel(size, resources), m_label(t_label) {};
void click(Ribbon& ribbon, std::size_t from_button_index) override; void click(Ribbon& ribbon, std::size_t from_button_index) override;
void draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
private: private:
std::string label; void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
std::string m_label;
}; };
class SongPanel final : public Panel { class SongPanel final : public Panel {
public: public:
explicit SongPanel(const Data::Song& t_song) : m_song(t_song) {}; explicit SongPanel(const std::size_t& size, Resources& resources, const Data::Song& t_song) : Panel(size, 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 draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) override;
private: private:
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
const Data::Song& m_song; const Data::Song& m_song;
const Toolkit::AffineTransform<float> m_seconds_to_alpha{0.0f, 0.15f, 0.f, 255.f}; const Toolkit::AffineTransform<float> m_seconds_to_alpha{0.0f, 0.15f, 0.f, 255.f};
}; };

View File

@ -62,10 +62,12 @@ bool MusicSelect::MoveAnimation::ended() {
return clock.getElapsedTime() / m_time_factor > sf::milliseconds(300); return clock.getElapsedTime() / m_time_factor > sf::milliseconds(300);
} }
MusicSelect::Ribbon::Ribbon(Resources& t_resources) : MusicSelect::Ribbon::Ribbon(Resources& t_resources, unsigned int panel_size, unsigned int panel_spacing) :
m_resources(t_resources), m_resources(t_resources),
m_layout(), m_layout(),
empty_song() empty_song(),
m_panel_size(panel_size),
m_panel_spacing(panel_spacing)
{ {
std::cout << "Loaded MusicSelect::Ribbon" << std::endl; std::cout << "Loaded MusicSelect::Ribbon" << std::endl;
} }
@ -84,19 +86,19 @@ void MusicSelect::Ribbon::title_sort(const Data::SongList &song_list) {
categories categories
[std::string(1, letter)] [std::string(1, letter)]
.push_back( .push_back(
std::make_shared<SongPanel>(song) std::make_shared<SongPanel>(m_panel_size, m_resources, song)
); );
} else if ('a' <= letter and letter <= 'z') { } else if ('a' <= letter and letter <= 'z') {
categories categories
[std::string(1, 'A' + (letter - 'a'))] [std::string(1, 'A' + (letter - 'a'))]
.push_back( .push_back(
std::make_shared<SongPanel>(song) std::make_shared<SongPanel>(m_panel_size, m_resources, song)
); );
} else { } else {
categories["?"].push_back(std::make_shared<SongPanel>(song)); categories["?"].push_back(std::make_shared<SongPanel>(m_panel_size, m_resources, song));
} }
} else { } else {
categories["?"].push_back(std::make_shared<SongPanel>(song)); categories["?"].push_back(std::make_shared<SongPanel>(m_panel_size, m_resources, song));
} }
} }
layout_from_category_map(categories); layout_from_category_map(categories);
@ -105,15 +107,15 @@ void MusicSelect::Ribbon::title_sort(const Data::SongList &song_list) {
void MusicSelect::Ribbon::test_sort() { void MusicSelect::Ribbon::test_sort() {
m_layout.clear(); m_layout.clear();
m_layout.push_back({ m_layout.push_back({
std::make_shared<EmptyPanel>(), std::make_shared<EmptyPanel>(m_panel_size, m_resources),
std::make_shared<CategoryPanel>("A"), std::make_shared<CategoryPanel>(m_panel_size, m_resources, "A"),
std::make_shared<CategoryPanel>("truc") std::make_shared<CategoryPanel>(m_panel_size, m_resources, "truc")
}); });
for (size_t i = 0; i < 3; i++) { for (size_t i = 0; i < 3; i++) {
m_layout.push_back({ m_layout.push_back({
std::make_shared<EmptyPanel>(), std::make_shared<EmptyPanel>(m_panel_size, m_resources),
std::make_shared<EmptyPanel>(), std::make_shared<EmptyPanel>(m_panel_size, m_resources),
std::make_shared<EmptyPanel>() std::make_shared<EmptyPanel>(m_panel_size, m_resources)
}); });
} }
} }
@ -128,6 +130,7 @@ void MusicSelect::Ribbon::test2_sort() {
for (int i = 0; i < category_size; i++) { for (int i = 0; i < category_size; i++) {
categories[std::string(1, letter)].push_back( categories[std::string(1, letter)].push_back(
std::make_shared<MusicSelect::ColorPanel>( std::make_shared<MusicSelect::ColorPanel>(
m_panel_size, m_resources,
sf::Color( sf::Color(
panel_hue_generator.generate(), panel_hue_generator.generate(),
panel_hue_generator.generate(), panel_hue_generator.generate(),
@ -148,7 +151,7 @@ void MusicSelect::Ribbon::test_song_cover_sort() {
auto category_size = category_size_generator.generate(); auto category_size = category_size_generator.generate();
for (int i = 0; i < category_size; i++) { for (int i = 0; i < category_size; i++) {
categories[std::string(1, letter)].push_back( categories[std::string(1, letter)].push_back(
std::make_shared<MusicSelect::SongPanel>(this->empty_song) std::make_shared<MusicSelect::SongPanel>(m_panel_size, m_resources, this->empty_song)
); );
} }
} }
@ -177,7 +180,7 @@ void MusicSelect::Ribbon::layout_from_category_map(const std::map<std::string, s
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>(m_panel_size, m_resources, category));
for (auto &&panel : panels) { for (auto &&panel : panels) {
if (current_column.size() == 3) { if (current_column.size() == 3) {
m_layout.push_back({current_column[0], current_column[1], current_column[2]}); m_layout.push_back({current_column[0], current_column[1], current_column[2]});
@ -188,7 +191,7 @@ void MusicSelect::Ribbon::layout_from_category_map(const std::map<std::string, s
} }
if (not current_column.empty()) { if (not current_column.empty()) {
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>(m_panel_size, m_resources));
} }
m_layout.push_back({current_column[0], current_column[1], current_column[2]}); m_layout.push_back({current_column[0], current_column[1], current_column[2]});
} }
@ -270,19 +273,12 @@ void MusicSelect::Ribbon::draw_with_animation(sf::RenderTarget &target, sf::Rend
for (int column_offset = -1; column_offset <= 4; column_offset++) { for (int column_offset = -1; column_offset <= 4; column_offset++) {
std::size_t actual_column = (column_zero + column_offset + m_layout.size()) % m_layout.size(); std::size_t actual_column = (column_zero + column_offset + m_layout.size()) % m_layout.size();
for (int row = 0; row < 3; row++) { for (int row = 0; row < 3; row++) {
m_layout auto panel = m_layout.at(actual_column).at(row);
.at(actual_column) panel->setPosition(
.at(row) (static_cast<float>(relative_column_zero + column_offset) - float_position) * (m_panel_size+m_panel_spacing),
->draw( row * (m_panel_size+m_panel_spacing)
m_resources,
target,
sf::FloatRect(
(static_cast<float>(relative_column_zero + column_offset) - float_position) * 150.f,
row * 150.f,
150.f,
150.f
)
); );
target.draw(*panel);
} }
} }
} }
@ -291,19 +287,9 @@ void MusicSelect::Ribbon::draw_without_animation(sf::RenderTarget &target, sf::R
for (int column = -1; column <= 4; column++) { for (int column = -1; column <= 4; column++) {
int actual_column_index = (column + m_position + m_layout.size()) % m_layout.size(); int actual_column_index = (column + m_position + m_layout.size()) % m_layout.size();
for (int row = 0; row < 3; row++) { for (int row = 0; row < 3; row++) {
m_layout auto panel = m_layout.at(actual_column_index).at(row);
.at(actual_column_index) panel->setPosition(column * (m_panel_size+m_panel_spacing), row * (m_panel_size+m_panel_spacing));
.at(row) target.draw(*panel);
->draw(
m_resources,
target,
sf::FloatRect(
column * 150.f,
row * 150.f,
150.f,
150.f
)
);
} }
} }
} }
@ -312,6 +298,22 @@ void MusicSelect::Ribbon::draw_debug() {
if (debug) { if (debug) {
ImGui::Begin("Ribbon Debug", &debug); { ImGui::Begin("Ribbon Debug", &debug); {
ImGui::SliderFloat("Time Slowdown Factor", &m_time_factor, 1.f, 10.f); ImGui::SliderFloat("Time Slowdown Factor", &m_time_factor, 1.f, 10.f);
if (ImGui::CollapsingHeader("Panels")) {
auto panel_size = static_cast<int>(m_panel_size);
if(ImGui::InputInt("Size", &panel_size)) {
if (panel_size < 0) {
panel_size = 0;
}
m_panel_size = static_cast<std::size_t>(panel_size);
}
auto panel_spacing = static_cast<int>(m_panel_spacing);
if(ImGui::InputInt("Spacing", &panel_spacing)) {
if (panel_spacing < 0) {
panel_spacing = 0;
}
m_panel_spacing = static_cast<std::size_t>(panel_spacing);
}
}
} }
ImGui::End(); ImGui::End();
} }

View File

@ -32,7 +32,7 @@ namespace MusicSelect {
// It can be sorted in a number of ways // It can be sorted in a number of ways
class Ribbon final : public sf::Drawable, public Toolkit::Debuggable { class Ribbon final : public sf::Drawable, public Toolkit::Debuggable {
public: public:
Ribbon(Resources& t_resources); Ribbon(Resources& t_resources, unsigned int panel_size, unsigned int panel_spacing);
void title_sort(const Data::SongList& song_list); void title_sort(const Data::SongList& song_list);
void test_sort(); void test_sort();
void test2_sort(); void test2_sort();
@ -55,5 +55,7 @@ namespace MusicSelect {
Resources& m_resources; Resources& m_resources;
float m_time_factor = 1.f; float m_time_factor = 1.f;
Data::Song empty_song; Data::Song empty_song;
std::size_t m_panel_size;
std::size_t m_panel_spacing;
}; };
} }