Divide Resources into shared and screen-specific
This commit is contained in:
parent
917e44dac0
commit
3de0d50975
1
TODO.md
1
TODO.md
@ -2,6 +2,7 @@
|
|||||||
## Misc
|
## Misc
|
||||||
|
|
||||||
## Gameplay Screen
|
## Gameplay Screen
|
||||||
|
- Precise Input handling, the dirty way
|
||||||
|
|
||||||
## Results Screen
|
## Results Screen
|
||||||
|
|
||||||
|
21
meson.build
21
meson.build
@ -30,23 +30,26 @@ sources = [
|
|||||||
'src/Data/Note.hpp',
|
'src/Data/Note.hpp',
|
||||||
'src/Data/Preferences.hpp',
|
'src/Data/Preferences.hpp',
|
||||||
'src/Data/Preferences.cpp',
|
'src/Data/Preferences.cpp',
|
||||||
'src/Data/Score.hpp',
|
|
||||||
'src/Data/Song.hpp',
|
'src/Data/Song.hpp',
|
||||||
'src/Data/Song.cpp',
|
'src/Data/Song.cpp',
|
||||||
'src/Drawables/BlackFrame.hpp',
|
'src/Drawables/BlackFrame.hpp',
|
||||||
'src/Drawables/BlackFrame.cpp',
|
'src/Drawables/BlackFrame.cpp',
|
||||||
'src/Drawables/ButtonHighlight.hpp',
|
'src/Drawables/ButtonHighlight.hpp',
|
||||||
'src/Drawables/ButtonHighlight.cpp',
|
'src/Drawables/ButtonHighlight.cpp',
|
||||||
|
'src/Drawables/DensityGraph.hpp',
|
||||||
|
'src/Drawables/DensityGraph.cpp',
|
||||||
'src/Input/Buttons.hpp',
|
'src/Input/Buttons.hpp',
|
||||||
'src/Input/Buttons.cpp',
|
'src/Input/Buttons.cpp',
|
||||||
'src/Input/KeyMapping.hpp',
|
'src/Input/KeyMapping.hpp',
|
||||||
'src/Input/KeyMapping.cpp',
|
'src/Input/KeyMapping.cpp',
|
||||||
'src/Input/MappableKeys.hpp',
|
'src/Input/Events.hpp',
|
||||||
'src/Input/MappableKeys.cpp',
|
'src/Input/Events.cpp',
|
||||||
'src/Resources/TextureCache.cpp',
|
'src/Resources/TextureCache.cpp',
|
||||||
'src/Resources/TextureCache.hpp',
|
'src/Resources/TextureCache.hpp',
|
||||||
'src/Resources/Marker.cpp',
|
'src/Resources/Marker.cpp',
|
||||||
'src/Resources/Marker.hpp',
|
'src/Resources/Marker.hpp',
|
||||||
|
'src/Resources/SharedResources.hpp',
|
||||||
|
'src/Resources/SharedResources.cpp',
|
||||||
# 'src/Resources/CoverAtlas.hpp',
|
# 'src/Resources/CoverAtlas.hpp',
|
||||||
# 'src/Resources/CoverAtlas.cpp',
|
# 'src/Resources/CoverAtlas.cpp',
|
||||||
# 'src/Screens/Gameplay.hpp',
|
# 'src/Screens/Gameplay.hpp',
|
||||||
@ -62,8 +65,6 @@ sources = [
|
|||||||
'src/Screens/MusicSelect/Panels/Panel.cpp',
|
'src/Screens/MusicSelect/Panels/Panel.cpp',
|
||||||
'src/Screens/MusicSelect/Panels/SubpagePanel.hpp',
|
'src/Screens/MusicSelect/Panels/SubpagePanel.hpp',
|
||||||
'src/Screens/MusicSelect/Panels/SubpagePanel.cpp',
|
'src/Screens/MusicSelect/Panels/SubpagePanel.cpp',
|
||||||
'src/Screens/MusicSelect/DensityGraph.hpp',
|
|
||||||
'src/Screens/MusicSelect/DensityGraph.cpp',
|
|
||||||
'src/Screens/MusicSelect/MusicPreview.hpp',
|
'src/Screens/MusicSelect/MusicPreview.hpp',
|
||||||
'src/Screens/MusicSelect/MusicPreview.cpp',
|
'src/Screens/MusicSelect/MusicPreview.cpp',
|
||||||
'src/Screens/MusicSelect/MusicSelect.hpp',
|
'src/Screens/MusicSelect/MusicSelect.hpp',
|
||||||
@ -72,10 +73,16 @@ sources = [
|
|||||||
'src/Screens/MusicSelect/PanelLayout.cpp',
|
'src/Screens/MusicSelect/PanelLayout.cpp',
|
||||||
'src/Screens/MusicSelect/Ribbon.hpp',
|
'src/Screens/MusicSelect/Ribbon.hpp',
|
||||||
'src/Screens/MusicSelect/Ribbon.cpp',
|
'src/Screens/MusicSelect/Ribbon.cpp',
|
||||||
'src/Screens/MusicSelect/SharedResources.hpp',
|
'src/Screens/MusicSelect/Resources.hpp',
|
||||||
'src/Screens/MusicSelect/SharedResources.cpp',
|
'src/Screens/MusicSelect/Resources.cpp',
|
||||||
'src/Screens/MusicSelect/SongInfo.hpp',
|
'src/Screens/MusicSelect/SongInfo.hpp',
|
||||||
'src/Screens/MusicSelect/SongInfo.cpp',
|
'src/Screens/MusicSelect/SongInfo.cpp',
|
||||||
|
'src/Screens/Gameplay/Gameplay.hpp',
|
||||||
|
'src/Screens/Gameplay/Gameplay.cpp',
|
||||||
|
'src/Screens/Gameplay/PreciseMusic.hpp',
|
||||||
|
'src/Screens/Gameplay/PreciseMusic.cpp',
|
||||||
|
'src/Screens/Gameplay/Silence.hpp',
|
||||||
|
'src/Screens/Gameplay/Silence.cpp',
|
||||||
# 'src/Screens/Result.hpp',
|
# 'src/Screens/Result.hpp',
|
||||||
'src/Toolkit/AffineTransform.hpp',
|
'src/Toolkit/AffineTransform.hpp',
|
||||||
'src/Toolkit/Cache.hpp',
|
'src/Toolkit/Cache.hpp',
|
||||||
|
@ -11,21 +11,21 @@ namespace Data {
|
|||||||
auto [_, chart] = *it;
|
auto [_, chart] = *it;
|
||||||
level = chart.level;
|
level = chart.level;
|
||||||
resolution = static_cast<std::size_t>(chart.resolution);
|
resolution = static_cast<std::size_t>(chart.resolution);
|
||||||
Toolkit::AffineTransform<float> memon_timing_to_1000Hz(
|
Toolkit::AffineTransform<float> memon_timing_to_seconds(
|
||||||
0.f, static_cast<float>(chart.resolution),
|
0.f, static_cast<float>(chart.resolution),
|
||||||
-memon.offset*1000.f, (-memon.offset+60.f/memon.BPM)*1000.f
|
-memon.offset, (-memon.offset+60.f/memon.BPM)
|
||||||
);
|
);
|
||||||
Toolkit::AffineTransform<float> memon_timing_to_300Hz_proportional(
|
Toolkit::AffineTransform<float> memon_timing_to_seconds_proportional(
|
||||||
0.f, static_cast<float>(chart.resolution),
|
0.f, static_cast<float>(chart.resolution),
|
||||||
0.f, (60.f/memon.BPM)*300.f
|
0.f, (60.f/memon.BPM)*1000.f
|
||||||
);
|
);
|
||||||
for (auto &¬e : chart.notes) {
|
for (auto &¬e : chart.notes) {
|
||||||
auto timing = static_cast<long>(memon_timing_to_1000Hz.transform(note.get_timing()));
|
auto timing = sf::seconds(memon_timing_to_seconds.transform(note.get_timing()));
|
||||||
auto position = static_cast<Input::Button>(note.get_pos());
|
auto position = static_cast<Input::Button>(note.get_pos());
|
||||||
std::size_t length = 0;
|
sf::Time length = sf::Time::Zero;
|
||||||
auto tail = Input::Button::B1;
|
auto tail = Input::Button::B1;
|
||||||
if (note.get_length() != 0) {
|
if (note.get_length() != 0) {
|
||||||
length = static_cast<std::size_t>(memon_timing_to_300Hz_proportional.transform(note.get_length()));
|
length = sf::seconds(memon_timing_to_seconds_proportional.transform(note.get_length()));
|
||||||
tail = convert_memon_tail(position, note.get_tail_pos());
|
tail = convert_memon_tail(position, note.get_tail_pos());
|
||||||
}
|
}
|
||||||
notes.insert({timing, position, length, tail});
|
notes.insert({timing, position, length, tail});
|
||||||
@ -74,4 +74,12 @@ namespace Data {
|
|||||||
}
|
}
|
||||||
return *tail;
|
return *tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sf::Time Chart::get_duration_based_on_notes() const {
|
||||||
|
if (notes.rbegin() == notes.rend()) {
|
||||||
|
return sf::Time::Zero;
|
||||||
|
} else {
|
||||||
|
return notes.rbegin()->timing;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <memon/memon.hpp>
|
#include <memon/memon.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
#include "../Input/Buttons.hpp"
|
#include "../Input/Buttons.hpp"
|
||||||
#include "Note.hpp"
|
#include "Note.hpp"
|
||||||
@ -14,6 +15,7 @@ namespace Data {
|
|||||||
int level;
|
int level;
|
||||||
std::set<Note> notes;
|
std::set<Note> notes;
|
||||||
std::size_t resolution;
|
std::size_t resolution;
|
||||||
|
sf::Time get_duration_based_on_notes() const;
|
||||||
};
|
};
|
||||||
Input::Button convert_memon_tail(Input::Button note, unsigned int tail_position);
|
Input::Button convert_memon_tail(Input::Button note, unsigned int tail_position);
|
||||||
}
|
}
|
@ -1,14 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
#include "../Input/Buttons.hpp"
|
#include "../Input/Buttons.hpp"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
struct Note {
|
struct Note {
|
||||||
// Timing is stored as ticks on a 1000Hz clock starting at the begging of the audio
|
// offset since the begging of the audio
|
||||||
long int timing;
|
sf::Time timing;
|
||||||
Input::Button position;
|
Input::Button position;
|
||||||
// zero length means it's a standard note
|
// zero means it's a normal note
|
||||||
std::size_t length;
|
sf::Time duration;
|
||||||
Input::Button tail;
|
Input::Button tail;
|
||||||
|
|
||||||
bool operator==(const Note &rhs) const {
|
bool operator==(const Note &rhs) const {
|
||||||
|
@ -5,4 +5,4 @@ namespace Data {
|
|||||||
public:
|
public:
|
||||||
Score();
|
Score();
|
||||||
};
|
};
|
||||||
};
|
}
|
@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
#include <SFML/Audio.hpp>
|
#include <SFML/Audio.hpp>
|
||||||
|
|
||||||
#include "../../Toolkit/AffineTransform.hpp"
|
#include "../Toolkit/AffineTransform.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace Drawables {
|
||||||
|
|
||||||
DensityGraph::DensityGraph(const std::array<unsigned int, 115>& t_densities) :
|
DensityGraph::DensityGraph(const std::array<unsigned int, 115>& t_densities) :
|
||||||
m_densities(t_densities),
|
m_densities(t_densities),
|
||||||
@ -53,7 +53,7 @@ namespace MusicSelect {
|
|||||||
throw std::invalid_argument("Song "+song.title+" has no "+difficulty+" chart");
|
throw std::invalid_argument("Song "+song.title+" has no "+difficulty+" chart");
|
||||||
}
|
}
|
||||||
if (c->notes.empty()) {
|
if (c->notes.empty()) {
|
||||||
return compute_density_graph_from_chart(*c, 0, 0);
|
return compute_density_graph_from_chart(*c, sf::Time::Zero, sf::Time::Zero);
|
||||||
}
|
}
|
||||||
if (not song.audio.has_value()) {
|
if (not song.audio.has_value()) {
|
||||||
return compute_density_graph_from_chart(*c, c->notes.begin()->timing, c->notes.rbegin()->timing);
|
return compute_density_graph_from_chart(*c, c->notes.begin()->timing, c->notes.rbegin()->timing);
|
||||||
@ -64,22 +64,22 @@ namespace MusicSelect {
|
|||||||
}
|
}
|
||||||
return compute_density_graph_from_chart(
|
return compute_density_graph_from_chart(
|
||||||
*c,
|
*c,
|
||||||
std::min(0L, c->notes.begin()->timing),
|
sf::microseconds(std::min(0LL, c->notes.begin()->timing.asMicroseconds())),
|
||||||
std::max(c->notes.rbegin()->timing, static_cast<long>(m.getDuration().asMilliseconds()*3/10))
|
sf::microseconds(std::max(c->notes.rbegin()->timing.asMicroseconds(), m.getDuration().asMicroseconds()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DensityGraph compute_density_graph_from_chart(const Data::Chart& chart, long start, long end) {
|
DensityGraph compute_density_graph_from_chart(const Data::Chart& chart, sf::Time start, sf::Time end) {
|
||||||
std::array<unsigned int, 115> d{};
|
std::array<unsigned int, 115> d{};
|
||||||
if (start != end) {
|
if (start != end) {
|
||||||
Toolkit::AffineTransform<float> ticks_to_column{
|
Toolkit::AffineTransform<float> ticks_to_column{
|
||||||
static_cast<float>(start),
|
start.asSeconds(),
|
||||||
static_cast<float>(end),
|
end.asSeconds(),
|
||||||
0.f,
|
0.f,
|
||||||
115.f
|
115.f
|
||||||
};
|
};
|
||||||
for (auto &¬e : chart.notes) {
|
for (auto &¬e : chart.notes) {
|
||||||
auto index = static_cast<unsigned int>(ticks_to_column.transform(static_cast<float>(note.timing)));
|
auto index = static_cast<unsigned int>(ticks_to_column.transform(note.timing.asSeconds()));
|
||||||
d.at(index) += 1;
|
d.at(index) += 1;
|
||||||
}
|
}
|
||||||
std::replace_if(
|
std::replace_if(
|
||||||
@ -95,7 +95,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
namespace Toolkit {
|
namespace Toolkit {
|
||||||
template<>
|
template<>
|
||||||
void set_origin_normalized(MusicSelect::DensityGraph& s, float x, float y) {
|
void set_origin_normalized(Drawables::DensityGraph& s, float x, float y) {
|
||||||
s.setOrigin(x*574.f, y*39.f);
|
s.setOrigin(x*574.f, y*39.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
#include "../../Data/Chart.hpp"
|
#include "../Data/Chart.hpp"
|
||||||
#include "../../Data/Song.hpp"
|
#include "../Data/Song.hpp"
|
||||||
#include "../../Toolkit/Cache.hpp"
|
#include "../Toolkit/Cache.hpp"
|
||||||
#include "../../Toolkit/NormalizedOrigin.hpp"
|
#include "../Toolkit/NormalizedOrigin.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace Drawables {
|
||||||
class DensityGraph : public sf::Drawable, public sf::Transformable {
|
class DensityGraph : public sf::Drawable, public sf::Transformable {
|
||||||
public:
|
public:
|
||||||
explicit DensityGraph(const std::array<unsigned int, 115>& t_densities);
|
explicit DensityGraph(const std::array<unsigned int, 115>& t_densities);
|
||||||
@ -22,7 +22,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
DensityGraph compute_density_graph_from_struct(const Data::SongDifficulty& sd);
|
DensityGraph compute_density_graph_from_struct(const Data::SongDifficulty& sd);
|
||||||
DensityGraph compute_density_graph_from_song_difficulty(const Data::Song& song, const std::string& difficulty);
|
DensityGraph compute_density_graph_from_song_difficulty(const Data::Song& song, const std::string& difficulty);
|
||||||
DensityGraph compute_density_graph_from_chart(const Data::Chart& chart, long start, long end);
|
DensityGraph compute_density_graph_from_chart(const Data::Chart& chart, sf::Time start, sf::Time end);
|
||||||
|
|
||||||
using DensityGraphCache = Toolkit::Cache<Data::SongDifficulty, DensityGraph, &compute_density_graph_from_struct>;
|
using DensityGraphCache = Toolkit::Cache<Data::SongDifficulty, DensityGraph, &compute_density_graph_from_struct>;
|
||||||
}
|
}
|
||||||
@ -40,5 +40,5 @@ namespace std {
|
|||||||
|
|
||||||
namespace Toolkit {
|
namespace Toolkit {
|
||||||
template<>
|
template<>
|
||||||
void set_origin_normalized(MusicSelect::DensityGraph& s, float x, float y);
|
void set_origin_normalized(Drawables::DensityGraph& s, float x, float y);
|
||||||
}
|
}
|
@ -1,19 +1,19 @@
|
|||||||
#include "MappableKeys.hpp"
|
#include "Events.hpp"
|
||||||
|
|
||||||
namespace Input {
|
namespace Input {
|
||||||
MappableKeyToString mappable_button_to_string;
|
EventToString mappable_button_to_string;
|
||||||
|
|
||||||
std::string to_string(const MappableKey& mk) {
|
std::string to_string(const Event& mk) {
|
||||||
return std::visit(mappable_button_to_string, mk);
|
return std::visit(mappable_button_to_string, mk);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::regex mappable_button_regex("(.+?)::(.+)");
|
std::regex mappable_button_regex("(.+?)::(.+)");
|
||||||
std::regex joystick_button_regex("(\\d+)_(\\d+)");
|
std::regex joystick_button_regex("(\\d+)_(\\d+)");
|
||||||
|
|
||||||
MappableKey from_string(const std::string& s) {
|
Event from_string(const std::string& s) {
|
||||||
std::smatch matches;
|
std::smatch matches;
|
||||||
if (not std::regex_match(s, matches, mappable_button_regex)) {
|
if (not std::regex_match(s, matches, mappable_button_regex)) {
|
||||||
throw std::runtime_error("Unknown MappableKey : "+s);
|
throw std::runtime_error("Unknown Event : "+s);
|
||||||
}
|
}
|
||||||
auto device = matches[1].str();
|
auto device = matches[1].str();
|
||||||
auto button = matches[2].str();
|
auto button = matches[2].str();
|
@ -33,7 +33,7 @@ namespace std {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace Input {
|
namespace Input {
|
||||||
using MappableKey = std::variant<sf::Keyboard::Key, JoystickButton>;
|
using Event = std::variant<sf::Keyboard::Key, JoystickButton>;
|
||||||
|
|
||||||
const std::unordered_map<sf::Keyboard::Key, std::string> keyboard_to_string{
|
const std::unordered_map<sf::Keyboard::Key, std::string> keyboard_to_string{
|
||||||
{
|
{
|
||||||
@ -249,8 +249,7 @@ namespace Input {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MappableKeyToString {
|
struct EventToString {
|
||||||
public:
|
|
||||||
std::string operator() (const sf::Keyboard::Key& k) {
|
std::string operator() (const sf::Keyboard::Key& k) {
|
||||||
return "Keyboard::"+keyboard_to_string.at(k);
|
return "Keyboard::"+keyboard_to_string.at(k);
|
||||||
};
|
};
|
||||||
@ -259,6 +258,6 @@ namespace Input {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string to_string(const MappableKey& mk);
|
std::string to_string(const Event& mk);
|
||||||
MappableKey from_string(const std::string& s);
|
Event from_string(const std::string& s);
|
||||||
}
|
}
|
@ -24,21 +24,21 @@ namespace Input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyMapping::KeyMapping(std::unordered_map<Button, MappableKey> button_to_key) : m_button_to_key(button_to_key) {
|
KeyMapping::KeyMapping(std::unordered_map<Button, Event> button_to_key) : m_button_to_key(button_to_key) {
|
||||||
for (auto &&[button, key] : m_button_to_key) {
|
for (auto &&[button, key] : m_button_to_key) {
|
||||||
m_key_to_button[key] = button;
|
m_key_to_button[key] = button;
|
||||||
}
|
}
|
||||||
assert((m_button_to_key.size() == m_key_to_button.size()));
|
assert((m_button_to_key.size() == m_key_to_button.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyMapping::KeyMapping(std::unordered_map<MappableKey, Button> key_to_button) : m_key_to_button(key_to_button) {
|
KeyMapping::KeyMapping(std::unordered_map<Event, Button> key_to_button) : m_key_to_button(key_to_button) {
|
||||||
for (auto &&[key, button] : m_key_to_button) {
|
for (auto &&[key, button] : m_key_to_button) {
|
||||||
m_button_to_key[button] = key;
|
m_button_to_key[button] = key;
|
||||||
}
|
}
|
||||||
assert((m_button_to_key.size() == m_key_to_button.size()));
|
assert((m_button_to_key.size() == m_key_to_button.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyMapping::set_button_to_key(const Button& button, const MappableKey& key) {
|
void KeyMapping::set_button_to_key(const Button& button, const Event& key) {
|
||||||
if (m_key_to_button.find(key) != m_key_to_button.end()) {
|
if (m_key_to_button.find(key) != m_key_to_button.end()) {
|
||||||
m_button_to_key.erase(m_key_to_button[key]);
|
m_button_to_key.erase(m_key_to_button[key]);
|
||||||
m_key_to_button.erase(key);
|
m_key_to_button.erase(key);
|
||||||
@ -47,7 +47,7 @@ namespace Input {
|
|||||||
m_key_to_button[key] = button;
|
m_key_to_button[key] = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Button> KeyMapping::key_to_button(const MappableKey& key) {
|
std::optional<Button> KeyMapping::key_to_button(const Event& key) {
|
||||||
if (m_key_to_button.find(key) == m_key_to_button.end()) {
|
if (m_key_to_button.find(key) == m_key_to_button.end()) {
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
@ -55,7 +55,7 @@ namespace Input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<MappableKey> KeyMapping::button_to_key(const Button& button) {
|
std::optional<Event> KeyMapping::button_to_key(const Button& button) {
|
||||||
if (m_button_to_key.find(button) == m_button_to_key.end()) {
|
if (m_button_to_key.find(button) == m_button_to_key.end()) {
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
@ -70,7 +70,7 @@ namespace Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void from_json(const nlohmann::json& j, KeyMapping& km) {
|
void from_json(const nlohmann::json& j, KeyMapping& km) {
|
||||||
std::unordered_map<Button, MappableKey> map;
|
std::unordered_map<Button, Event> map;
|
||||||
for (std::size_t i = 0; i < 16; i++) {
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
map[*index_to_button(i)] = from_string(j.at("B"+std::to_string(i+1)));
|
map[*index_to_button(i)] = from_string(j.at("B"+std::to_string(i+1)));
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <SFML/Window.hpp>
|
#include <SFML/Window.hpp>
|
||||||
|
|
||||||
#include "Buttons.hpp"
|
#include "Buttons.hpp"
|
||||||
#include "MappableKeys.hpp"
|
#include "Events.hpp"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
struct Preferences;
|
struct Preferences;
|
||||||
@ -19,14 +19,14 @@ namespace Input {
|
|||||||
class KeyMapping {
|
class KeyMapping {
|
||||||
public:
|
public:
|
||||||
KeyMapping();
|
KeyMapping();
|
||||||
explicit KeyMapping(std::unordered_map<Button, MappableKey> button_to_key);
|
explicit KeyMapping(std::unordered_map<Button, Event> button_to_key);
|
||||||
explicit KeyMapping(std::unordered_map<MappableKey, Button> button_to_key);
|
explicit KeyMapping(std::unordered_map<Event, Button> button_to_key);
|
||||||
void set_button_to_key(const Button& button, const MappableKey& key);
|
void set_button_to_key(const Button& button, const Event& key);
|
||||||
std::optional<Button> key_to_button(const MappableKey& key);
|
std::optional<Button> key_to_button(const Event& key);
|
||||||
std::optional<MappableKey> button_to_key(const Button& button);
|
std::optional<Event> button_to_key(const Button& button);
|
||||||
private:
|
private:
|
||||||
std::unordered_map<MappableKey, Button> m_key_to_button;
|
std::unordered_map<Event, Button> m_key_to_button;
|
||||||
std::unordered_map<Button, MappableKey> m_button_to_key;
|
std::unordered_map<Button, Event> m_button_to_key;
|
||||||
|
|
||||||
friend struct Data::Preferences;
|
friend struct Data::Preferences;
|
||||||
friend void to_json(nlohmann::json& j, const KeyMapping& km);
|
friend void to_json(nlohmann::json& j, const KeyMapping& km);
|
||||||
|
@ -6,9 +6,11 @@
|
|||||||
#include "Data/Song.hpp"
|
#include "Data/Song.hpp"
|
||||||
#include "Data/Preferences.hpp"
|
#include "Data/Preferences.hpp"
|
||||||
#include "Resources/Marker.hpp"
|
#include "Resources/Marker.hpp"
|
||||||
|
#include "Resources/SharedResources.hpp"
|
||||||
// #include "Data/Chart.hpp"
|
// #include "Data/Chart.hpp"
|
||||||
// #include "Data/Score.hpp"
|
// #include "Data/Score.hpp"
|
||||||
|
|
||||||
|
#include "Screens/MusicSelect/Resources.hpp"
|
||||||
#include "Screens/MusicSelect/MusicSelect.hpp"
|
#include "Screens/MusicSelect/MusicSelect.hpp"
|
||||||
// #include "Screens/Gameplay.hpp"
|
// #include "Screens/Gameplay.hpp"
|
||||||
// #include "Screens/Result.hpp"
|
// #include "Screens/Result.hpp"
|
||||||
@ -19,9 +21,10 @@ int main(int, char const **) {
|
|||||||
const std::string jujube_path = whereami::executable_dir();
|
const std::string jujube_path = whereami::executable_dir();
|
||||||
Data::Preferences preferences{jujube_path};
|
Data::Preferences preferences{jujube_path};
|
||||||
Data::SongList song_list{jujube_path};
|
Data::SongList song_list{jujube_path};
|
||||||
MusicSelect::SharedResources music_select_resources{preferences};
|
Resources::SharedResources shared_resources{preferences};
|
||||||
if (music_select_resources.markers.find(preferences.options.marker) == music_select_resources.markers.end()) {
|
MusicSelect::ScreenResources music_select_resources{shared_resources};
|
||||||
preferences.options.marker = music_select_resources.markers.begin()->first;
|
if (shared_resources.markers.find(preferences.options.marker) == shared_resources.markers.end()) {
|
||||||
|
preferences.options.marker = shared_resources.markers.begin()->first;
|
||||||
}
|
}
|
||||||
MusicSelect::Screen music_select{song_list, music_select_resources};
|
MusicSelect::Screen music_select{song_list, music_select_resources};
|
||||||
|
|
||||||
|
@ -2,12 +2,9 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "../../Toolkit/HSL.hpp"
|
#include "../Toolkit/HSL.hpp"
|
||||||
|
|
||||||
#include "Options/OptionPage.hpp"
|
namespace Resources {
|
||||||
#include "Panels/Panel.hpp"
|
|
||||||
|
|
||||||
namespace MusicSelect {
|
|
||||||
|
|
||||||
FallbackFont::FallbackFont(const ghc::filesystem::path& jujube_path) :
|
FallbackFont::FallbackFont(const ghc::filesystem::path& jujube_path) :
|
||||||
light(),
|
light(),
|
||||||
@ -36,32 +33,6 @@ namespace MusicSelect {
|
|||||||
std::cout << "Loaded MusicSelect::SharedResources" << std::endl;
|
std::cout << "Loaded MusicSelect::SharedResources" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SharedResources::get_last_selected_difficulty() {
|
|
||||||
return get_selected_difficulty().value_or("BSC");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::string> SharedResources::get_selected_difficulty() {
|
|
||||||
if (not selected_panel.has_value()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
auto chart_selection = selected_panel->obj.get_selected_difficulty();
|
|
||||||
if (not chart_selection.has_value()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return chart_selection->difficulty;
|
|
||||||
}
|
|
||||||
|
|
||||||
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->obj.get_selected_difficulty();
|
|
||||||
if (not chart_selection.has_value()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return chart_selection->song;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Color SharedResources::get_chart_color(const std::string& chart) {
|
sf::Color SharedResources::get_chart_color(const std::string& chart) {
|
||||||
if (chart == "BSC") {
|
if (chart == "BSC") {
|
||||||
return BSC_color;
|
return BSC_color;
|
@ -9,20 +9,16 @@
|
|||||||
#include <SFML/Graphics/Font.hpp>
|
#include <SFML/Graphics/Font.hpp>
|
||||||
#include <SFML/System.hpp>
|
#include <SFML/System.hpp>
|
||||||
|
|
||||||
#include "../../Data/Preferences.hpp"
|
#include "../Data/Preferences.hpp"
|
||||||
#include "../../Data/Song.hpp"
|
#include "../Data/Song.hpp"
|
||||||
#include "../../Drawables/ButtonHighlight.hpp"
|
#include "../Drawables/ButtonHighlight.hpp"
|
||||||
#include "../../Resources/Marker.hpp"
|
#include "../Drawables/DensityGraph.hpp"
|
||||||
#include "../../Resources/TextureCache.hpp"
|
#include "../Resources/Marker.hpp"
|
||||||
|
#include "../Resources/TextureCache.hpp"
|
||||||
|
|
||||||
#include "DensityGraph.hpp"
|
namespace Resources {
|
||||||
#include "MusicPreview.hpp"
|
|
||||||
|
|
||||||
namespace MusicSelect {
|
|
||||||
|
|
||||||
class SelectablePanel;
|
|
||||||
class MarkerPanel;
|
class MarkerPanel;
|
||||||
class OptionPage;
|
|
||||||
|
|
||||||
template<class Object>
|
template<class Object>
|
||||||
struct Timed {
|
struct Timed {
|
||||||
@ -40,7 +36,7 @@ namespace MusicSelect {
|
|||||||
sf::Font black;
|
sf::Font black;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Holds everything that needs to be shared by all levels of the class hierarchy
|
// Holds everything that needs to be shared between screens and down the class hierarchy
|
||||||
struct SharedResources : public Data::HoldsPreferences {
|
struct SharedResources : public Data::HoldsPreferences {
|
||||||
SharedResources(Data::Preferences& p);
|
SharedResources(Data::Preferences& p);
|
||||||
|
|
||||||
@ -48,32 +44,21 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
FallbackFont fallback_font;
|
FallbackFont fallback_font;
|
||||||
|
|
||||||
MusicSelect::DensityGraphCache density_graphs;
|
Drawables::DensityGraphCache density_graphs;
|
||||||
|
|
||||||
std::optional<Timed<SelectablePanel>> selected_panel;
|
|
||||||
std::string get_last_selected_difficulty();
|
|
||||||
std::optional<std::string> get_selected_difficulty();
|
|
||||||
std::optional<std::reference_wrapper<const Data::Song>> get_selected_song();
|
|
||||||
|
|
||||||
sf::Color BSC_color = sf::Color{34,216,92};
|
sf::Color BSC_color = sf::Color{34,216,92};
|
||||||
sf::Color ADV_color = sf::Color{252,212,32};
|
sf::Color ADV_color = sf::Color{252,212,32};
|
||||||
sf::Color EXT_color = sf::Color{234,46,32};
|
sf::Color EXT_color = sf::Color{234,46,32};
|
||||||
sf::Color get_chart_color(const std::string& chart);
|
sf::Color get_chart_color(const std::string& chart);
|
||||||
|
|
||||||
MusicPreview music_preview;
|
|
||||||
|
|
||||||
std::vector<std::reference_wrapper<OptionPage>> options_state;
|
|
||||||
|
|
||||||
Resources::Markers markers;
|
Resources::Markers markers;
|
||||||
std::optional<Timed<MarkerPanel>> selected_marker;
|
|
||||||
|
|
||||||
Drawables::ButtonHighlight button_highlight;
|
Drawables::ButtonHighlight button_highlight;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Proxy for HoldsPreferences
|
// Proxy for HoldsPreferences
|
||||||
struct HoldsSharedResources : public Data::HoldsPreferences {
|
struct HoldsSharedResources : public Data::HoldsPreferences {
|
||||||
HoldsSharedResources(SharedResources& t_resources) : Data::HoldsPreferences(t_resources.preferences), resources(t_resources) {};
|
HoldsSharedResources(SharedResources& t_resources) : Data::HoldsPreferences(t_resources.preferences), shared(t_resources) {};
|
||||||
protected:
|
SharedResources& shared;
|
||||||
SharedResources& resources;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,5 +1,9 @@
|
|||||||
#include "Gameplay.hpp"
|
#include "Gameplay.hpp"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <optional>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <imgui/imgui.h>
|
#include <imgui/imgui.h>
|
||||||
#include <imgui-sfml/imgui-SFML.h>
|
#include <imgui-sfml/imgui-SFML.h>
|
||||||
|
|
||||||
@ -8,16 +12,22 @@ namespace Gameplay {
|
|||||||
song_selection(t_song_selection),
|
song_selection(t_song_selection),
|
||||||
chart(*t_song_selection.song.get_chart(t_song_selection.difficulty))
|
chart(*t_song_selection.song.get_chart(t_song_selection.difficulty))
|
||||||
{
|
{
|
||||||
|
notes_left = chart.notes;
|
||||||
|
std::variant<PreciseMusic, Silence> music;
|
||||||
|
auto music_path = song_selection.song.full_audio_path();
|
||||||
|
if (music_path) {
|
||||||
|
music.emplace<PreciseMusic>(music_path->string());
|
||||||
|
} else {
|
||||||
|
music.emplace<Silence>(chart.get_duration_based_on_notes());
|
||||||
|
}
|
||||||
|
getPlayingOffset = std::visit(GetPlayingOffsetVisitor{}, music);
|
||||||
|
getStatus = std::visit(GetStatusVisitor{}, music);
|
||||||
}
|
}
|
||||||
|
|
||||||
Data::Score Screen::play_chart(sf::RenderWindow& window) {
|
Data::Score Screen::play_chart(sf::RenderWindow& window) {
|
||||||
window.setFramerateLimit(60);
|
std::thread render_thread(&Screen::render, this, std::ref(window));
|
||||||
ImGui::SFML::Init(window);
|
|
||||||
sf::Clock imguiClock;
|
|
||||||
sf::Music song;
|
|
||||||
if (song_selection.song.full_audio_path())
|
|
||||||
while ((not song_finished) and window.isOpen()) {
|
while ((not song_finished) and window.isOpen()) {
|
||||||
|
auto playing_offset = getPlayingOffset();
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
while (window.pollEvent(event)) {
|
while (window.pollEvent(event)) {
|
||||||
ImGui::SFML::ProcessEvent(event);
|
ImGui::SFML::ProcessEvent(event);
|
||||||
@ -32,13 +42,20 @@ namespace Gameplay {
|
|||||||
case sf::Event::Resized:
|
case sf::Event::Resized:
|
||||||
// update the view to the new size of the window
|
// update the view to the new size of the window
|
||||||
window.setView(sf::View({0, 0, static_cast<float>(event.size.width), static_cast<float>(event.size.height)}));
|
window.setView(sf::View({0, 0, static_cast<float>(event.size.width), static_cast<float>(event.size.height)}));
|
||||||
// resources.preferences.screen.height = event.size.height;
|
|
||||||
// resources.preferences.screen.width = event.size.width;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::render(sf::RenderWindow& window) {
|
||||||
|
window.setFramerateLimit(60);
|
||||||
|
ImGui::SFML::Init(window);
|
||||||
|
sf::Clock imguiClock;
|
||||||
|
while ((not song_finished) and window.isOpen()) {
|
||||||
ImGui::SFML::Update(window, imguiClock.restart());
|
ImGui::SFML::Update(window, imguiClock.restart());
|
||||||
window.clear(sf::Color(7, 23, 53));
|
window.clear(sf::Color(7, 23, 53));
|
||||||
draw_debug();
|
draw_debug();
|
||||||
@ -47,4 +64,29 @@ namespace Gameplay {
|
|||||||
}
|
}
|
||||||
ImGui::SFML::Shutdown();
|
ImGui::SFML::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::handle_raw_event(const Input::Event& event, const sf::Time& playing_offset) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::handle_button(const Input::Button& button, const sf::Time& playing_offset) {
|
||||||
|
// TODO : Button Highlight
|
||||||
|
|
||||||
|
// Is the music even playing ?
|
||||||
|
if (getStatus() == sf::SoundSource::Playing) {
|
||||||
|
for (auto &¬e : notes_left) {
|
||||||
|
// is the note visible ?
|
||||||
|
if (note.timing > playing_offset + sf::seconds(16.f/30.f)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// is it even the right button ?
|
||||||
|
if (note.position != button) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
notes_passed.emplace(note, note.timing-playing_offset);
|
||||||
|
notes_left.erase(note);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,11 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
#include "../../Data/Chart.hpp"
|
#include "../../Data/Chart.hpp"
|
||||||
|
#include "../../Data/Note.hpp"
|
||||||
#include "../../Data/Song.hpp"
|
#include "../../Data/Song.hpp"
|
||||||
#include "../../Data/Score.hpp"
|
#include "../../Data/Score.hpp"
|
||||||
|
#include "../../Input/Buttons.hpp"
|
||||||
|
#include "../../Input/Events.hpp"
|
||||||
#include "../../Toolkit/Debuggable.hpp"
|
#include "../../Toolkit/Debuggable.hpp"
|
||||||
|
#include "PreciseMusic.hpp"
|
||||||
|
#include "Silence.hpp"
|
||||||
|
#include "GradedNote.hpp"
|
||||||
|
|
||||||
namespace Gameplay {
|
namespace Gameplay {
|
||||||
class Screen : public Toolkit::Debuggable {
|
class Screen : public Toolkit::Debuggable {
|
||||||
@ -13,10 +21,39 @@ namespace Gameplay {
|
|||||||
explicit Screen(const Data::SongDifficulty& song_selection);
|
explicit Screen(const Data::SongDifficulty& song_selection);
|
||||||
Data::Score play_chart(sf::RenderWindow& window);
|
Data::Score play_chart(sf::RenderWindow& window);
|
||||||
private:
|
private:
|
||||||
|
void render(sf::RenderWindow& window);
|
||||||
|
|
||||||
|
std::function<sf::Time(void)> getPlayingOffset;
|
||||||
|
std::function<sf::SoundSource::Status(void)> getStatus;
|
||||||
|
|
||||||
|
void handle_raw_event(const Input::Event& event, const sf::Time& playing_offset);
|
||||||
|
void handle_button(const Input::Button& button, const sf::Time& playing_offset);
|
||||||
|
|
||||||
const Data::SongDifficulty& song_selection;
|
const Data::SongDifficulty& song_selection;
|
||||||
const Data::Chart chart;
|
const Data::Chart chart;
|
||||||
Data::Score score;
|
|
||||||
bool song_finished = false;
|
std::set<GradedNote> notes_passed;
|
||||||
};
|
std::set<Data::Note> notes_left;
|
||||||
};
|
|
||||||
|
std::atomic<bool> song_finished = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GetPlayingOffsetVisitor {
|
||||||
|
std::function<sf::Time(void)> operator() (const PreciseMusic& pm) {
|
||||||
|
return [&pm](){return pm.getPrecisePlayingOffset();};
|
||||||
|
}
|
||||||
|
std::function<sf::Time(void)> operator() (const Silence& s) {
|
||||||
|
return [&s](){return s.getPlayingOffset();};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GetStatusVisitor {
|
||||||
|
std::function<sf::SoundSource::Status(void)> operator() (const PreciseMusic& pm) {
|
||||||
|
return [&pm](){return pm.getStatus();};
|
||||||
|
}
|
||||||
|
std::function<sf::SoundSource::Status(void)> operator() (const Silence& s) {
|
||||||
|
return [&s](){return s.getStatus();};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
25
src/Screens/Gameplay/GradedNote.cpp
Normal file
25
src/Screens/Gameplay/GradedNote.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include "GradedNote.hpp"
|
||||||
|
|
||||||
|
namespace Gameplay {
|
||||||
|
Judgement delta_to_judgement(const sf::Time& delta) {
|
||||||
|
auto delta_abs = delta;
|
||||||
|
if (delta_abs < sf::Time::Zero) {
|
||||||
|
delta_abs = -delta_abs;
|
||||||
|
}
|
||||||
|
// Numbers from http://544332133981.hatenablog.com/entry/bemani-rank_4
|
||||||
|
// which themselves are apparently from jubeat analyser's code.
|
||||||
|
// Here they are divided by 2 because we are checking against an absolute
|
||||||
|
// offset from the target time position
|
||||||
|
if (delta_abs < sf::milliseconds(21)) {
|
||||||
|
return Judgement::Perfect;
|
||||||
|
} else if (delta_abs < sf::milliseconds(46)) {
|
||||||
|
return Judgement::Great;
|
||||||
|
} else if (delta_abs < sf::milliseconds(83)) {
|
||||||
|
return Judgement::Good;
|
||||||
|
} else if (delta_abs < sf::milliseconds(250)) {
|
||||||
|
return Judgement::Poor;
|
||||||
|
} else {
|
||||||
|
return Judgement::Miss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
src/Screens/Gameplay/GradedNote.hpp
Normal file
23
src/Screens/Gameplay/GradedNote.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
|
#include "../../Data/Note.hpp"
|
||||||
|
|
||||||
|
namespace Gameplay {
|
||||||
|
enum class Judgement {
|
||||||
|
Perfect,
|
||||||
|
Great,
|
||||||
|
Good,
|
||||||
|
Poor,
|
||||||
|
Miss
|
||||||
|
};
|
||||||
|
|
||||||
|
Judgement delta_to_judgement(const sf::Time& delta);
|
||||||
|
|
||||||
|
struct GradedNote : Data::Note {
|
||||||
|
GradedNote(const Data::Note& n, const sf::Time& t) : Note::Note(n), delta(t), judgement(delta_to_judgement(t)) {};
|
||||||
|
sf::Time delta;
|
||||||
|
Judgement judgement;
|
||||||
|
};
|
||||||
|
}
|
57
src/Screens/Gameplay/PreciseMusic.cpp
Normal file
57
src/Screens/Gameplay/PreciseMusic.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "PreciseMusic.hpp"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace Gameplay {
|
||||||
|
PreciseMusic::PreciseMusic() : Music::Music() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PreciseMusic::PreciseMusic(std::string path) {
|
||||||
|
if (not this->openFromFile(path)) {
|
||||||
|
throw std::invalid_argument("Could not open "+path);
|
||||||
|
}
|
||||||
|
position_update_watchdog = std::thread{&PreciseMusic::position_update_watchdog_main, this};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreciseMusic::position_update_watchdog_main() {
|
||||||
|
sf::Time next_music_position = sf::Time::Zero;
|
||||||
|
while (not should_stop_watchdog) {
|
||||||
|
if (this->getStatus() == sf::Music::Playing) {
|
||||||
|
next_music_position = this->getPlayingOffset();
|
||||||
|
if (next_music_position != last_music_position) {
|
||||||
|
lag = lag_measurement.getElapsedTime()/2.f;
|
||||||
|
should_correct = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PreciseMusic::~PreciseMusic() {
|
||||||
|
should_stop_watchdog = true;
|
||||||
|
position_update_watchdog.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Time PreciseMusic::getPrecisePlayingOffset() const {
|
||||||
|
if (should_correct) {
|
||||||
|
return last_music_position+last_position_update.getElapsedTime()-lag;
|
||||||
|
} else {
|
||||||
|
return this->getPlayingOffset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PreciseMusic::onGetData(sf::SoundStream::Chunk& data) {
|
||||||
|
if (first_onGetData_call) {
|
||||||
|
first_onGetData_call = false;
|
||||||
|
lag_measurement.restart();
|
||||||
|
}
|
||||||
|
bool continue_playback = sf::Music::onGetData(data);
|
||||||
|
if (continue_playback) {
|
||||||
|
last_music_position = getPlayingOffset();
|
||||||
|
last_position_update.restart();
|
||||||
|
}
|
||||||
|
return continue_playback;
|
||||||
|
}
|
||||||
|
}
|
31
src/Screens/Gameplay/PreciseMusic.hpp
Normal file
31
src/Screens/Gameplay/PreciseMusic.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#include <SFML/Audio.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
|
||||||
|
namespace Gameplay {
|
||||||
|
struct PreciseMusic : sf::Music {
|
||||||
|
PreciseMusic();
|
||||||
|
explicit PreciseMusic(std::string path);
|
||||||
|
~PreciseMusic();
|
||||||
|
|
||||||
|
std::thread position_update_watchdog;
|
||||||
|
|
||||||
|
void position_update_watchdog_main();
|
||||||
|
std::atomic<bool> should_stop_watchdog = false;
|
||||||
|
|
||||||
|
sf::Time getPrecisePlayingOffset() const;
|
||||||
|
|
||||||
|
bool first_onGetData_call = true;
|
||||||
|
sf::Clock lag_measurement;
|
||||||
|
std::atomic<sf::Time> lag = sf::Time::Zero;
|
||||||
|
std::atomic<bool> should_correct = false;
|
||||||
|
std::atomic<sf::Time> last_music_position = sf::Time::Zero;
|
||||||
|
sf::Clock last_position_update;
|
||||||
|
protected:
|
||||||
|
bool onGetData(sf::SoundStream::Chunk& data) override;
|
||||||
|
};
|
||||||
|
}
|
67
src/Screens/Gameplay/Silence.cpp
Normal file
67
src/Screens/Gameplay/Silence.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include "Silence.hpp"
|
||||||
|
|
||||||
|
namespace Gameplay {
|
||||||
|
Silence::Silence(const sf::Time& duration) :
|
||||||
|
m_duration(duration),
|
||||||
|
m_status(sf::Music::Stopped)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Silence::play() {
|
||||||
|
if (m_status != sf::SoundSource::Paused) {
|
||||||
|
m_position = sf::Time::Zero;
|
||||||
|
}
|
||||||
|
m_clock.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Silence::pause() {
|
||||||
|
if (m_status == sf::SoundSource::Playing) {
|
||||||
|
m_position += m_clock.getElapsedTime();
|
||||||
|
if (m_position > m_duration) {
|
||||||
|
stop();
|
||||||
|
} else {
|
||||||
|
m_status = sf::Music::Paused;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Silence::stop() {
|
||||||
|
m_status = sf::Music::Stopped;
|
||||||
|
m_position = sf::Time::Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int getChannelCount() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int getSampleRate() {
|
||||||
|
return 48000;
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::SoundSource::Status Silence::getStatus() const {
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Silence::setPlayingOffset(sf::Time timeOffset) {
|
||||||
|
if (timeOffset > m_duration) {
|
||||||
|
stop();
|
||||||
|
} else {
|
||||||
|
m_position = timeOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Time Silence::getPlayingOffset() const {
|
||||||
|
if (m_status == sf::SoundSource::Playing) {
|
||||||
|
m_position += m_clock.restart();
|
||||||
|
if (m_position > m_duration) {
|
||||||
|
m_status = sf::Music::Stopped;
|
||||||
|
m_position = sf::Time::Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Time Silence::getDuration() const {
|
||||||
|
return m_duration;
|
||||||
|
}
|
||||||
|
}
|
34
src/Screens/Gameplay/Silence.hpp
Normal file
34
src/Screens/Gameplay/Silence.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SFML/Audio/Music.hpp>
|
||||||
|
#include <SFML/System/Time.hpp>
|
||||||
|
#include <SFML/System/Clock.hpp>
|
||||||
|
|
||||||
|
namespace Gameplay {
|
||||||
|
// noop class for use when the chart has no associated music file
|
||||||
|
class Silence : public sf::Music {
|
||||||
|
public:
|
||||||
|
Silence(const sf::Time& duration);
|
||||||
|
void play();
|
||||||
|
void pause();
|
||||||
|
void stop();
|
||||||
|
unsigned int getChannelCount() const;
|
||||||
|
unsigned int getSampleRate() const;
|
||||||
|
sf::SoundSource::Status getStatus() const;
|
||||||
|
void setPlayingOffset(sf::Time timeOffset);
|
||||||
|
sf::Time getPlayingOffset() const;
|
||||||
|
void setLoop(bool /*loop*/) {};
|
||||||
|
bool getLoop() const {return false;};
|
||||||
|
bool openFromFile(const std::string& /*filename*/) {return false;};
|
||||||
|
bool openFromMemory(const void* /*data*/, std::size_t /*sizeInBytes*/) {return false;};
|
||||||
|
bool openFromStream(sf::InputStream& /*stream*/) {return false;};
|
||||||
|
sf::Time getDuration() const;
|
||||||
|
TimeSpan getLoopPoints() const {return TimeSpan{};};
|
||||||
|
void setLoopPoints(TimeSpan /*timePoints*/) {};
|
||||||
|
private:
|
||||||
|
const sf::Time m_duration;
|
||||||
|
mutable sf::SoundSource::Status m_status;
|
||||||
|
mutable sf::Time m_position;
|
||||||
|
mutable sf::Clock m_clock;
|
||||||
|
};
|
||||||
|
}
|
@ -57,7 +57,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
sf::Text label{
|
sf::Text label{
|
||||||
"OPTIONS",
|
"OPTIONS",
|
||||||
resources.fallback_font.black,
|
shared.fallback_font.black,
|
||||||
static_cast<unsigned int>(0.2f*get_panel_size())
|
static_cast<unsigned int>(0.2f*get_panel_size())
|
||||||
};
|
};
|
||||||
label.setFillColor(sf::Color::White);
|
label.setFillColor(sf::Color::White);
|
||||||
@ -72,17 +72,17 @@ namespace MusicSelect {
|
|||||||
sf::CircleShape circle{get_panel_size()*0.4f};
|
sf::CircleShape circle{get_panel_size()*0.4f};
|
||||||
circle.setFillColor(sf::Color::Black);
|
circle.setFillColor(sf::Color::Black);
|
||||||
circle.setOutlineThickness(0.02f*get_panel_size());
|
circle.setOutlineThickness(0.02f*get_panel_size());
|
||||||
circle.setOutlineColor(resources.BSC_color);
|
circle.setOutlineColor(shared.BSC_color);
|
||||||
Toolkit::set_origin_normalized(circle, 0.5f, 0.5f);
|
Toolkit::set_origin_normalized(circle, 0.5f, 0.5f);
|
||||||
circle.setPosition(get_panel_size()*0.5f, get_panel_size()*0.5f);
|
circle.setPosition(get_panel_size()*0.5f, get_panel_size()*0.5f);
|
||||||
target.draw(circle, states);
|
target.draw(circle, states);
|
||||||
|
|
||||||
sf::Text label{
|
sf::Text label{
|
||||||
"START",
|
"START",
|
||||||
resources.fallback_font.black,
|
shared.fallback_font.black,
|
||||||
static_cast<unsigned int>(0.2f*get_panel_size())
|
static_cast<unsigned int>(0.2f*get_panel_size())
|
||||||
};
|
};
|
||||||
label.setFillColor(resources.BSC_color);
|
label.setFillColor(shared.BSC_color);
|
||||||
Toolkit::set_local_origin_normalized(label, 0.5f, 0.5f);
|
Toolkit::set_local_origin_normalized(label, 0.5f, 0.5f);
|
||||||
label.setPosition(get_panel_size()*0.5f, get_panel_size()*0.5f);
|
label.setPosition(get_panel_size()*0.5f, get_panel_size()*0.5f);
|
||||||
target.draw(label, states);
|
target.draw(label, states);
|
||||||
@ -93,17 +93,17 @@ namespace MusicSelect {
|
|||||||
sf::CircleShape circle{get_panel_size()*0.4f};
|
sf::CircleShape circle{get_panel_size()*0.4f};
|
||||||
circle.setFillColor(sf::Color::Black);
|
circle.setFillColor(sf::Color::Black);
|
||||||
circle.setOutlineThickness(0.02f*get_panel_size());
|
circle.setOutlineThickness(0.02f*get_panel_size());
|
||||||
circle.setOutlineColor(resources.EXT_color);
|
circle.setOutlineColor(shared.EXT_color);
|
||||||
Toolkit::set_origin_normalized(circle, 0.5f, 0.5f);
|
Toolkit::set_origin_normalized(circle, 0.5f, 0.5f);
|
||||||
circle.setPosition(get_panel_size()*0.5f, get_panel_size()*0.5f);
|
circle.setPosition(get_panel_size()*0.5f, get_panel_size()*0.5f);
|
||||||
target.draw(circle, states);
|
target.draw(circle, states);
|
||||||
|
|
||||||
sf::Text label{
|
sf::Text label{
|
||||||
"BACK",
|
"BACK",
|
||||||
resources.fallback_font.black,
|
shared.fallback_font.black,
|
||||||
static_cast<unsigned int>(0.2f*get_panel_size())
|
static_cast<unsigned int>(0.2f*get_panel_size())
|
||||||
};
|
};
|
||||||
label.setFillColor(resources.EXT_color);
|
label.setFillColor(shared.EXT_color);
|
||||||
Toolkit::set_local_origin_normalized(label, 0.5f, 0.5f);
|
Toolkit::set_local_origin_normalized(label, 0.5f, 0.5f);
|
||||||
label.setPosition(get_panel_size()*0.5f, get_panel_size()*0.5f);
|
label.setPosition(get_panel_size()*0.5f, get_panel_size()*0.5f);
|
||||||
target.draw(label, states);
|
target.draw(label, states);
|
||||||
|
@ -2,40 +2,40 @@
|
|||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
#include "../SharedResources.hpp"
|
#include "../Resources.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
class LeftButton final : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class LeftButton final : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
using HoldsSharedResources::HoldsSharedResources;
|
using HoldsResources::HoldsResources;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RightButton final : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class RightButton final : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
using HoldsSharedResources::HoldsSharedResources;
|
using HoldsResources::HoldsResources;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OptionsButton final : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class OptionsButton final : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
using HoldsSharedResources::HoldsSharedResources;
|
using HoldsResources::HoldsResources;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StartButton final : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class StartButton final : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
using HoldsSharedResources::HoldsSharedResources;
|
using HoldsResources::HoldsResources;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BackButton final : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class BackButton final : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
using HoldsSharedResources::HoldsSharedResources;
|
using HoldsResources::HoldsResources;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
};
|
};
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace fs = ghc::filesystem;
|
namespace fs = ghc::filesystem;
|
||||||
|
|
||||||
|
// In this file define stuff to try to handle creating sf::Music objects
|
||||||
|
// and starting their playback asynchronously while trying to keep some thread-safety
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
struct MusicLoop {
|
struct MusicLoop {
|
||||||
MusicLoop(fs::path music_path, std::optional<sf::Music::TimeSpan> t_loop);
|
MusicLoop(fs::path music_path, std::optional<sf::Music::TimeSpan> t_loop);
|
||||||
@ -18,7 +20,6 @@ namespace MusicSelect {
|
|||||||
sf::Music::TimeSpan loop;
|
sf::Music::TimeSpan loop;
|
||||||
Toolkit::AffineTransform<float> fade_out = {0.f, 1.f, 0.f, 1.f}; // placeholder value
|
Toolkit::AffineTransform<float> fade_out = {0.f, 1.f, 0.f, 1.f}; // placeholder value
|
||||||
};
|
};
|
||||||
|
|
||||||
class MusicPreview {
|
class MusicPreview {
|
||||||
public:
|
public:
|
||||||
MusicPreview() = default;
|
MusicPreview() = default;
|
||||||
|
@ -13,15 +13,15 @@
|
|||||||
#include "Panels/Panel.hpp"
|
#include "Panels/Panel.hpp"
|
||||||
#include "PanelLayout.hpp"
|
#include "PanelLayout.hpp"
|
||||||
|
|
||||||
MusicSelect::Screen::Screen(const Data::SongList& t_song_list, SharedResources& t_resources) :
|
MusicSelect::Screen::Screen(const Data::SongList& t_song_list, ScreenResources& t_resources) :
|
||||||
HoldsSharedResources(t_resources),
|
HoldsResources(t_resources),
|
||||||
song_list(t_song_list),
|
song_list(t_song_list),
|
||||||
ribbon(PanelLayout::title_sort(t_song_list, t_resources), t_resources),
|
ribbon(PanelLayout::title_sort(t_song_list, t_resources), t_resources),
|
||||||
song_info(t_resources),
|
song_info(t_resources),
|
||||||
main_option_page(t_resources),
|
main_option_page(t_resources),
|
||||||
options_button(t_resources),
|
options_button(t_resources),
|
||||||
start_button(t_resources),
|
start_button(t_resources),
|
||||||
black_frame(t_resources.preferences)
|
black_frame(t_resources.shared.preferences)
|
||||||
{
|
{
|
||||||
panel_filter.setFillColor(sf::Color(0,0,0,200));
|
panel_filter.setFillColor(sf::Color(0,0,0,200));
|
||||||
std::cout << "loaded MusicSelect::Screen" << std::endl;
|
std::cout << "loaded MusicSelect::Screen" << std::endl;
|
||||||
@ -32,7 +32,7 @@ std::optional<Data::SongDifficulty> MusicSelect::Screen::select_chart(sf::Render
|
|||||||
ImGui::SFML::Init(window);
|
ImGui::SFML::Init(window);
|
||||||
sf::Clock imguiClock;
|
sf::Clock imguiClock;
|
||||||
ribbon.setPosition(get_ribbon_x(), get_ribbon_y());
|
ribbon.setPosition(get_ribbon_x(), get_ribbon_y());
|
||||||
resources.button_highlight.setPosition(get_ribbon_x(), get_ribbon_y());
|
shared.button_highlight.setPosition(get_ribbon_x(), get_ribbon_y());
|
||||||
panel_filter.setSize(sf::Vector2f{window.getSize()});
|
panel_filter.setSize(sf::Vector2f{window.getSize()});
|
||||||
options_button.setPosition(get_ribbon_x()+2.f*get_panel_step(), get_ribbon_y()+3.f*get_panel_step());
|
options_button.setPosition(get_ribbon_x()+2.f*get_panel_step(), get_ribbon_y()+3.f*get_panel_step());
|
||||||
start_button.setPosition(get_ribbon_x()+3.f*get_panel_step(), get_ribbon_y()+3.f*get_panel_step());
|
start_button.setPosition(get_ribbon_x()+3.f*get_panel_step(), get_ribbon_y()+3.f*get_panel_step());
|
||||||
@ -53,10 +53,10 @@ std::optional<Data::SongDifficulty> MusicSelect::Screen::select_chart(sf::Render
|
|||||||
case sf::Event::Resized:
|
case sf::Event::Resized:
|
||||||
// update the view to the new size of the window
|
// update the view to the new size of the window
|
||||||
window.setView(sf::View({0, 0, static_cast<float>(event.size.width), static_cast<float>(event.size.height)}));
|
window.setView(sf::View({0, 0, static_cast<float>(event.size.width), static_cast<float>(event.size.height)}));
|
||||||
resources.preferences.screen.height = event.size.height;
|
shared.preferences.screen.height = event.size.height;
|
||||||
resources.preferences.screen.width = event.size.width;
|
shared.preferences.screen.width = event.size.width;
|
||||||
ribbon.setPosition(get_ribbon_x(), get_ribbon_y());
|
ribbon.setPosition(get_ribbon_x(), get_ribbon_y());
|
||||||
resources.button_highlight.setPosition(get_ribbon_x(), get_ribbon_y());
|
shared.button_highlight.setPosition(get_ribbon_x(), get_ribbon_y());
|
||||||
panel_filter.setSize(sf::Vector2f{window.getSize()});
|
panel_filter.setSize(sf::Vector2f{window.getSize()});
|
||||||
if (not resources.options_state.empty()) {
|
if (not resources.options_state.empty()) {
|
||||||
resources.options_state.back().get().update();
|
resources.options_state.back().get().update();
|
||||||
@ -77,15 +77,15 @@ std::optional<Data::SongDifficulty> MusicSelect::Screen::select_chart(sf::Render
|
|||||||
if (not resources.options_state.empty()) {
|
if (not resources.options_state.empty()) {
|
||||||
window.draw(panel_filter);
|
window.draw(panel_filter);
|
||||||
window.draw(resources.options_state.back());
|
window.draw(resources.options_state.back());
|
||||||
if (resources.options_state.back().get().should_exit()) {
|
|
||||||
resources.options_state.back().get().exit();
|
resources.options_state.back().get().exit();
|
||||||
|
if (resources.options_state.back().get().should_exit()) {
|
||||||
resources.options_state.pop_back();
|
resources.options_state.pop_back();
|
||||||
if (not resources.options_state.empty()) {
|
if (not resources.options_state.empty()) {
|
||||||
resources.options_state.back().get().update();
|
resources.options_state.back().get().update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.draw(resources.button_highlight);
|
window.draw(shared.button_highlight);
|
||||||
window.draw(black_frame);
|
window.draw(black_frame);
|
||||||
ribbon.draw_debug();
|
ribbon.draw_debug();
|
||||||
draw_debug();
|
draw_debug();
|
||||||
@ -107,20 +107,19 @@ void MusicSelect::Screen::draw_debug() {
|
|||||||
if (ImGui::CollapsingHeader("Preferences")) {
|
if (ImGui::CollapsingHeader("Preferences")) {
|
||||||
if (ImGui::TreeNode("screen")) {
|
if (ImGui::TreeNode("screen")) {
|
||||||
ImGui::TextUnformatted("width : "); ImGui::SameLine();
|
ImGui::TextUnformatted("width : "); ImGui::SameLine();
|
||||||
ImGui::Text("%s", std::to_string(resources.preferences.screen.width).c_str());
|
ImGui::Text("%s", std::to_string(preferences.screen.width).c_str());
|
||||||
ImGui::TextUnformatted("height : "); ImGui::SameLine();
|
ImGui::TextUnformatted("height : "); ImGui::SameLine();
|
||||||
ImGui::Text("%s", std::to_string(resources.preferences.screen.height).c_str());
|
ImGui::Text("%s", std::to_string(preferences.screen.height).c_str());
|
||||||
ImGui::TextUnformatted("fullscreen : "); ImGui::SameLine();
|
ImGui::TextUnformatted("fullscreen : "); ImGui::SameLine();
|
||||||
ImGui::Text("%s", resources.preferences.screen.fullscreen ? "true" : "false");
|
ImGui::Text("%s", preferences.screen.fullscreen ? "true" : "false");
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
if (ImGui::TreeNode("layout")) {
|
if (ImGui::TreeNode("layout")) {
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
if (ImGui::TreeNode("options")) {
|
if (ImGui::TreeNode("options")) {
|
||||||
ImGui::TextUnformatted("marker : "); ImGui::SameLine();
|
ImGui::TextUnformatted("marker : "); ImGui::SameLine();
|
||||||
ImGui::Text("%s", resources.preferences.options.marker.c_str());
|
ImGui::Text("%s", preferences.options.marker.c_str());
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +156,7 @@ void MusicSelect::Screen::handle_key_press(const sf::Event::KeyEvent& key_event)
|
|||||||
if (output_used) {
|
if (output_used) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto button = resources.preferences.key_mapping.key_to_button(key_event.code);
|
auto button = shared.preferences.key_mapping.key_to_button(key_event.code);
|
||||||
if (button) {
|
if (button) {
|
||||||
press_button(*button);
|
press_button(*button);
|
||||||
} else {
|
} else {
|
||||||
@ -203,7 +202,7 @@ void MusicSelect::Screen::handle_mouse_click(const sf::Event::MouseButtonEvent&
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MusicSelect::Screen::press_button(const Input::Button& button) {
|
void MusicSelect::Screen::press_button(const Input::Button& button) {
|
||||||
resources.button_highlight.button_pressed(button);
|
shared.button_highlight.button_pressed(button);
|
||||||
auto button_index = Input::button_to_index(button);
|
auto button_index = Input::button_to_index(button);
|
||||||
if (button_index < 14) {
|
if (button_index < 14) {
|
||||||
ribbon.click_on(button);
|
ribbon.click_on(button);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include "../../Toolkit/Debuggable.hpp"
|
#include "../../Toolkit/Debuggable.hpp"
|
||||||
#include "Ribbon.hpp"
|
#include "Ribbon.hpp"
|
||||||
#include "SongInfo.hpp"
|
#include "SongInfo.hpp"
|
||||||
#include "SharedResources.hpp"
|
#include "Resources.hpp"
|
||||||
#include "Options/OptionPage.hpp"
|
#include "Options/OptionPage.hpp"
|
||||||
#include "Drawables/ControlPanels.hpp"
|
#include "Drawables/ControlPanels.hpp"
|
||||||
|
|
||||||
@ -24,12 +24,9 @@ namespace MusicSelect {
|
|||||||
class SongPanel;
|
class SongPanel;
|
||||||
// The music select screen is created only once
|
// The music select screen is created only once
|
||||||
// it loads a cache of available songs in the song_list attribute
|
// it loads a cache of available songs in the song_list attribute
|
||||||
class Screen : public Toolkit::Debuggable, public HoldsSharedResources {
|
class Screen : public Toolkit::Debuggable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
Screen(
|
Screen(const Data::SongList& t_song_list, ScreenResources& t_resources);
|
||||||
const Data::SongList& t_song_list,
|
|
||||||
SharedResources& t_resources
|
|
||||||
);
|
|
||||||
std::optional<Data::SongDifficulty> select_chart(sf::RenderWindow& window);
|
std::optional<Data::SongDifficulty> select_chart(sf::RenderWindow& window);
|
||||||
void draw_debug() override;
|
void draw_debug() override;
|
||||||
private:
|
private:
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
PressHere::PressHere(SharedResources& t_resources) :
|
PressHere::PressHere(ScreenResources& t_resources) :
|
||||||
HoldsSharedResources(t_resources),
|
HoldsResources(t_resources),
|
||||||
color_anim(0.0f, 1.0f, 1.0f, 0.1f),
|
color_anim(0.0f, 1.0f, 1.0f, 0.1f),
|
||||||
size_anim(0.0f, 1.0f, 1.0f, 0.7f)
|
size_anim(0.0f, 1.0f, 1.0f, 0.7f)
|
||||||
{
|
{
|
||||||
message.setFont(resources.fallback_font.black);
|
message.setFont(shared.fallback_font.black);
|
||||||
message.setString("PRESS\nHERE!");
|
message.setString("PRESS\nHERE!");
|
||||||
message.setFillColor(sf::Color::White);
|
message.setFillColor(sf::Color::White);
|
||||||
message.setCharacterSize(static_cast<unsigned int>(0.2f*get_panel_size()));
|
message.setCharacterSize(static_cast<unsigned int>(0.2f*get_panel_size()));
|
||||||
@ -46,8 +46,8 @@ namespace MusicSelect {
|
|||||||
target.draw(message, states);
|
target.draw(message, states);
|
||||||
}
|
}
|
||||||
|
|
||||||
AlreadyMapped::AlreadyMapped(SharedResources& t_resources) : HoldsSharedResources(t_resources) {
|
AlreadyMapped::AlreadyMapped(ScreenResources& t_resources) : HoldsResources(t_resources) {
|
||||||
background.setFillColor(resources.BSC_color);
|
background.setFillColor(shared.BSC_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlreadyMapped::update() {
|
void AlreadyMapped::update() {
|
||||||
@ -60,17 +60,17 @@ namespace MusicSelect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MappingPreview::MappingPreview(
|
MappingPreview::MappingPreview(
|
||||||
SharedResources& t_resources,
|
ScreenResources& t_resources,
|
||||||
const std::unordered_map<Input::MappableKey, Input::Button>& t_key_to_button
|
const std::unordered_map<Input::Event, Input::Button>& t_key_to_button
|
||||||
) :
|
) :
|
||||||
HoldsSharedResources(t_resources),
|
HoldsResources(t_resources),
|
||||||
key_to_button(t_key_to_button)
|
key_to_button(t_key_to_button)
|
||||||
{
|
{
|
||||||
square.setFillColor(sf::Color::Transparent);
|
square.setFillColor(sf::Color::Transparent);
|
||||||
square.setOutlineThickness(1.f);
|
square.setOutlineThickness(1.f);
|
||||||
square.setOutlineColor(sf::Color::White);
|
square.setOutlineColor(sf::Color::White);
|
||||||
key_label.setFillColor(sf::Color::White);
|
key_label.setFillColor(sf::Color::White);
|
||||||
key_label.setFont(resources.fallback_font.medium);
|
key_label.setFont(shared.fallback_font.medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MappingPreview::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
void MappingPreview::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
@ -103,20 +103,20 @@ namespace MusicSelect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InputRemap::InputRemap(SharedResources& t_resources) :
|
InputRemap::InputRemap(ScreenResources& t_resources) :
|
||||||
OptionPage(t_resources),
|
OptionPage(t_resources),
|
||||||
press_here_panel(t_resources),
|
press_here_panel(t_resources),
|
||||||
already_mapped_panel(t_resources),
|
already_mapped_panel(t_resources),
|
||||||
mapping_preview(t_resources, m_key_to_button)
|
mapping_preview(t_resources, m_key_to_button)
|
||||||
{
|
{
|
||||||
confirm_text_top.setString("Are you sure about this setting ?");
|
confirm_text_top.setString("Are you sure about this setting ?");
|
||||||
confirm_text_top.setFillColor(resources.EXT_color);
|
confirm_text_top.setFillColor(shared.EXT_color);
|
||||||
confirm_text_top.setFont(resources.fallback_font.black);
|
confirm_text_top.setFont(shared.fallback_font.black);
|
||||||
confirm_text_bottom.setString("Press any key to cancel");
|
confirm_text_bottom.setString("Press any key to cancel");
|
||||||
confirm_text_bottom.setFillColor(resources.EXT_color);
|
confirm_text_bottom.setFillColor(shared.EXT_color);
|
||||||
confirm_text_bottom.setFont(resources.fallback_font.black);
|
confirm_text_bottom.setFont(shared.fallback_font.black);
|
||||||
big_number.setFillColor(sf::Color::Black);
|
big_number.setFillColor(sf::Color::Black);
|
||||||
big_number.setFont(resources.fallback_font.black);
|
big_number.setFont(shared.fallback_font.black);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputRemap::handle_raw_input(const sf::Event::KeyEvent& event) {
|
bool InputRemap::handle_raw_input(const sf::Event::KeyEvent& event) {
|
||||||
|
@ -6,16 +6,16 @@
|
|||||||
#include <SFML/System.hpp>
|
#include <SFML/System.hpp>
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
#include "../../../Input/MappableKeys.hpp"
|
#include "../../../Input/Events.hpp"
|
||||||
#include "../../../Toolkit/AffineTransform.hpp"
|
#include "../../../Toolkit/AffineTransform.hpp"
|
||||||
#include "../SharedResources.hpp"
|
#include "../Resources.hpp"
|
||||||
#include "OptionPage.hpp"
|
#include "OptionPage.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
class PressHere final : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class PressHere final : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
PressHere(SharedResources& t_resources);
|
PressHere(ScreenResources& t_resources);
|
||||||
void update();
|
void update();
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
@ -26,28 +26,28 @@ namespace MusicSelect {
|
|||||||
Toolkit::AffineTransform<float> size_anim;
|
Toolkit::AffineTransform<float> size_anim;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AlreadyMapped final : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class AlreadyMapped final : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
AlreadyMapped(SharedResources& t_resources);
|
AlreadyMapped(ScreenResources& t_resources);
|
||||||
void update();
|
void update();
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
sf::RectangleShape background;
|
sf::RectangleShape background;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MappingPreview final : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class MappingPreview final : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
MappingPreview(SharedResources& t_resources, const std::unordered_map<Input::MappableKey, Input::Button>& t_key_to_button);
|
MappingPreview(ScreenResources& t_resources, const std::unordered_map<Input::Event, Input::Button>& t_key_to_button);
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
const std::unordered_map<Input::MappableKey, Input::Button>& key_to_button;
|
const std::unordered_map<Input::Event, Input::Button>& key_to_button;
|
||||||
mutable sf::RectangleShape square;
|
mutable sf::RectangleShape square;
|
||||||
mutable sf::Text key_label;
|
mutable sf::Text key_label;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InputRemap final : public OptionPage {
|
class InputRemap final : public OptionPage {
|
||||||
public:
|
public:
|
||||||
InputRemap(SharedResources& t_resources);
|
InputRemap(ScreenResources& t_resources);
|
||||||
bool handle_raw_input(const sf::Event::KeyEvent& event) override;
|
bool handle_raw_input(const sf::Event::KeyEvent& event) override;
|
||||||
const std::string name = "Mapping";
|
const std::string name = "Mapping";
|
||||||
bool should_exit() override;
|
bool should_exit() override;
|
||||||
@ -61,7 +61,7 @@ namespace MusicSelect {
|
|||||||
mutable sf::Text confirm_text_top;
|
mutable sf::Text confirm_text_top;
|
||||||
mutable sf::Text confirm_text_bottom;
|
mutable sf::Text confirm_text_bottom;
|
||||||
mutable sf::Text big_number;
|
mutable sf::Text big_number;
|
||||||
std::unordered_map<Input::MappableKey, Input::Button> m_key_to_button;
|
std::unordered_map<Input::Event, Input::Button> m_key_to_button;
|
||||||
mutable PressHere press_here_panel;
|
mutable PressHere press_here_panel;
|
||||||
mutable AlreadyMapped already_mapped_panel;
|
mutable AlreadyMapped already_mapped_panel;
|
||||||
mutable MappingPreview mapping_preview;
|
mutable MappingPreview mapping_preview;
|
||||||
|
@ -15,7 +15,7 @@ namespace MusicSelect {
|
|||||||
this->setPosition(get_ribbon_x(), get_ribbon_y());
|
this->setPosition(get_ribbon_x(), get_ribbon_y());
|
||||||
}
|
}
|
||||||
|
|
||||||
RibbonPage::RibbonPage(const PanelLayout& layout, SharedResources& t_resources) :
|
RibbonPage::RibbonPage(const PanelLayout& layout, ScreenResources& t_resources) :
|
||||||
OptionPage(t_resources),
|
OptionPage(t_resources),
|
||||||
m_ribbon(layout, t_resources),
|
m_ribbon(layout, t_resources),
|
||||||
back_button(t_resources)
|
back_button(t_resources)
|
||||||
@ -36,7 +36,7 @@ namespace MusicSelect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RibbonPage::button_click(const Input::Button& button) {
|
void RibbonPage::button_click(const Input::Button& button) {
|
||||||
resources.button_highlight.button_pressed(button);
|
shared.button_highlight.button_pressed(button);
|
||||||
auto button_index = Input::button_to_index(button);
|
auto button_index = Input::button_to_index(button);
|
||||||
if (button_index < 12) {
|
if (button_index < 12) {
|
||||||
m_ribbon.click_on(button);
|
m_ribbon.click_on(button);
|
||||||
@ -61,12 +61,12 @@ namespace MusicSelect {
|
|||||||
target.draw(back_button, states);
|
target.draw(back_button, states);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainOptionPage::MainOptionPage(SharedResources& t_resources) :
|
MainOptionPage::MainOptionPage(ScreenResources& t_resources) :
|
||||||
RibbonPage(MainOptionPage::create_layout(t_resources), t_resources)
|
RibbonPage(MainOptionPage::create_layout(t_resources), t_resources)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelLayout MainOptionPage::create_layout(SharedResources& t_resources) {
|
PanelLayout MainOptionPage::create_layout(ScreenResources& t_resources) {
|
||||||
std::vector<std::shared_ptr<Panel>> subpages;
|
std::vector<std::shared_ptr<Panel>> subpages;
|
||||||
auto marker_select = std::make_shared<MarkerSelect>(t_resources);
|
auto marker_select = std::make_shared<MarkerSelect>(t_resources);
|
||||||
subpages.emplace_back(std::make_shared<SubpagePanel>(t_resources, std::move(marker_select), "markers"));
|
subpages.emplace_back(std::make_shared<SubpagePanel>(t_resources, std::move(marker_select), "markers"));
|
||||||
@ -75,19 +75,19 @@ namespace MusicSelect {
|
|||||||
return PanelLayout{subpages, t_resources};
|
return PanelLayout{subpages, t_resources};
|
||||||
}
|
}
|
||||||
|
|
||||||
InputOptionPage::InputOptionPage(SharedResources& t_resources) :
|
InputOptionPage::InputOptionPage(ScreenResources& t_resources) :
|
||||||
RibbonPage(InputOptionPage::create_layout(t_resources), t_resources)
|
RibbonPage(InputOptionPage::create_layout(t_resources), t_resources)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelLayout InputOptionPage::create_layout(SharedResources& t_resources) {
|
PanelLayout InputOptionPage::create_layout(ScreenResources& t_resources) {
|
||||||
std::vector<std::shared_ptr<Panel>> subpages;
|
std::vector<std::shared_ptr<Panel>> subpages;
|
||||||
auto input_remap = std::make_shared<InputRemap>(t_resources);
|
auto input_remap = std::make_shared<InputRemap>(t_resources);
|
||||||
subpages.emplace_back(std::make_shared<SubpagePanel>(t_resources, std::move(input_remap), "remap\nbuttons"));
|
subpages.emplace_back(std::make_shared<SubpagePanel>(t_resources, std::move(input_remap), "remap\nbuttons"));
|
||||||
return PanelLayout{subpages, t_resources};
|
return PanelLayout{subpages, t_resources};
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkerSelect::MarkerSelect(SharedResources& t_resources) :
|
MarkerSelect::MarkerSelect(ScreenResources& t_resources) :
|
||||||
RibbonPage(MarkerSelect::create_layout(t_resources), t_resources)
|
RibbonPage(MarkerSelect::create_layout(t_resources), t_resources)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -96,9 +96,9 @@ namespace MusicSelect {
|
|||||||
resources.selected_marker.reset();
|
resources.selected_marker.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelLayout MarkerSelect::create_layout(SharedResources& t_resources) {
|
PanelLayout MarkerSelect::create_layout(ScreenResources& t_resources) {
|
||||||
std::vector<std::shared_ptr<Panel>> markers;
|
std::vector<std::shared_ptr<Panel>> markers;
|
||||||
for (const auto &[name, marker] : t_resources.markers) {
|
for (const auto &[name, marker] : t_resources.shared.markers) {
|
||||||
markers.emplace_back(std::make_shared<MarkerPanel>(t_resources, marker));
|
markers.emplace_back(std::make_shared<MarkerPanel>(t_resources, marker));
|
||||||
}
|
}
|
||||||
return PanelLayout{markers, t_resources};
|
return PanelLayout{markers, t_resources};
|
||||||
|
@ -6,16 +6,16 @@
|
|||||||
#include "../../../Input/Buttons.hpp"
|
#include "../../../Input/Buttons.hpp"
|
||||||
#include "../Drawables/ControlPanels.hpp"
|
#include "../Drawables/ControlPanels.hpp"
|
||||||
#include "../Ribbon.hpp"
|
#include "../Ribbon.hpp"
|
||||||
#include "../SharedResources.hpp"
|
#include "../Resources.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
class PanelLayout;
|
class PanelLayout;
|
||||||
|
|
||||||
class OptionPage : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class OptionPage : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
OptionPage(SharedResources& t_resources) : HoldsSharedResources(t_resources) {update();};
|
OptionPage(ScreenResources& t_resources) : HoldsResources(t_resources) {update();};
|
||||||
// Returns true if input was used
|
// Returns true if input was used
|
||||||
virtual bool handle_raw_input(const sf::Event::KeyEvent& event) = 0;
|
virtual bool handle_raw_input(const sf::Event::KeyEvent& event) = 0;
|
||||||
virtual ~OptionPage() = default;
|
virtual ~OptionPage() = default;
|
||||||
@ -27,7 +27,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
class RibbonPage : public OptionPage {
|
class RibbonPage : public OptionPage {
|
||||||
public:
|
public:
|
||||||
RibbonPage(const PanelLayout& layout, SharedResources& t_resources);
|
RibbonPage(const PanelLayout& layout, ScreenResources& t_resources);
|
||||||
bool handle_raw_input(const sf::Event::KeyEvent& event) override;
|
bool handle_raw_input(const sf::Event::KeyEvent& event) override;
|
||||||
void button_click(const Input::Button& button);
|
void button_click(const Input::Button& button);
|
||||||
private:
|
private:
|
||||||
@ -38,26 +38,26 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
class MainOptionPage final : public RibbonPage {
|
class MainOptionPage final : public RibbonPage {
|
||||||
public:
|
public:
|
||||||
MainOptionPage(SharedResources& t_resources);
|
MainOptionPage(ScreenResources& t_resources);
|
||||||
const std::string name = "Options";
|
const std::string name = "Options";
|
||||||
private:
|
private:
|
||||||
static PanelLayout create_layout(SharedResources& t_resources);
|
static PanelLayout create_layout(ScreenResources& t_resources);
|
||||||
};
|
};
|
||||||
|
|
||||||
class InputOptionPage final : public RibbonPage {
|
class InputOptionPage final : public RibbonPage {
|
||||||
public:
|
public:
|
||||||
InputOptionPage(SharedResources& t_resources);
|
InputOptionPage(ScreenResources& t_resources);
|
||||||
const std::string name = "Input";
|
const std::string name = "Input";
|
||||||
private:
|
private:
|
||||||
static PanelLayout create_layout(SharedResources& t_resources);
|
static PanelLayout create_layout(ScreenResources& t_resources);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MarkerSelect final : public RibbonPage {
|
class MarkerSelect final : public RibbonPage {
|
||||||
public:
|
public:
|
||||||
MarkerSelect(SharedResources& t_resources);
|
MarkerSelect(ScreenResources& t_resources);
|
||||||
~MarkerSelect();
|
~MarkerSelect();
|
||||||
const std::string name = "Marker Select";
|
const std::string name = "Marker Select";
|
||||||
private:
|
private:
|
||||||
static PanelLayout create_layout(SharedResources& t_resources);
|
static PanelLayout create_layout(ScreenResources& t_resources);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
PanelLayout::PanelLayout(
|
PanelLayout::PanelLayout(
|
||||||
const std::map<std::string,std::vector<std::shared_ptr<Panel>>>& categories,
|
const std::map<std::string,std::vector<std::shared_ptr<Panel>>>& categories,
|
||||||
SharedResources& t_resources
|
ScreenResources& t_resources
|
||||||
) {
|
) {
|
||||||
for (auto &&[category, panels] : categories) {
|
for (auto &&[category, panels] : categories) {
|
||||||
if (not panels.empty()) {
|
if (not panels.empty()) {
|
||||||
@ -31,7 +31,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
PanelLayout::PanelLayout(
|
PanelLayout::PanelLayout(
|
||||||
const std::vector<std::shared_ptr<Panel>>& panels,
|
const std::vector<std::shared_ptr<Panel>>& panels,
|
||||||
SharedResources& t_resources
|
ScreenResources& t_resources
|
||||||
) {
|
) {
|
||||||
std::vector<std::shared_ptr<Panel>> current_column;
|
std::vector<std::shared_ptr<Panel>> current_column;
|
||||||
for (auto& panel : panels) {
|
for (auto& panel : panels) {
|
||||||
@ -50,7 +50,7 @@ namespace MusicSelect {
|
|||||||
fill_layout(t_resources);
|
fill_layout(t_resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelLayout PanelLayout::red_empty_layout(SharedResources& t_resources) {
|
PanelLayout PanelLayout::red_empty_layout(ScreenResources& t_resources) {
|
||||||
std::vector<std::shared_ptr<Panel>> panels;
|
std::vector<std::shared_ptr<Panel>> panels;
|
||||||
for (size_t i = 0; i < 3*4; i++) {
|
for (size_t i = 0; i < 3*4; i++) {
|
||||||
panels.emplace_back(std::make_shared<ColoredMessagePanel>(t_resources, sf::Color::Red, "- EMPTY -"));
|
panels.emplace_back(std::make_shared<ColoredMessagePanel>(t_resources, sf::Color::Red, "- EMPTY -"));
|
||||||
@ -58,7 +58,7 @@ namespace MusicSelect {
|
|||||||
return PanelLayout{panels, t_resources};
|
return PanelLayout{panels, t_resources};
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelLayout PanelLayout::title_sort(const Data::SongList& song_list, SharedResources& t_resources) {
|
PanelLayout PanelLayout::title_sort(const Data::SongList& song_list, ScreenResources& t_resources) {
|
||||||
std::vector<std::shared_ptr<const Data::Song>> songs;
|
std::vector<std::shared_ptr<const Data::Song>> songs;
|
||||||
for (auto &&song : song_list.songs) {
|
for (auto &&song : song_list.songs) {
|
||||||
songs.push_back(song);
|
songs.push_back(song);
|
||||||
@ -90,7 +90,7 @@ namespace MusicSelect {
|
|||||||
return PanelLayout{categories, t_resources};
|
return PanelLayout{categories, t_resources};
|
||||||
}
|
}
|
||||||
|
|
||||||
void PanelLayout::fill_layout(SharedResources& t_resources) {
|
void PanelLayout::fill_layout(ScreenResources& t_resources) {
|
||||||
while (size() < 4) {
|
while (size() < 4) {
|
||||||
push_back({
|
push_back({
|
||||||
std::make_shared<EmptyPanel>(t_resources),
|
std::make_shared<EmptyPanel>(t_resources),
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../../Data/Song.hpp"
|
#include "../../Data/Song.hpp"
|
||||||
#include "SharedResources.hpp"
|
#include "Resources.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
@ -14,14 +14,14 @@ namespace MusicSelect {
|
|||||||
class PanelLayout : public std::vector<std::array<std::shared_ptr<Panel>,3>> {
|
class PanelLayout : public std::vector<std::array<std::shared_ptr<Panel>,3>> {
|
||||||
public:
|
public:
|
||||||
// Takes of map of category name and associated Panels, useful for all the sorted layouts
|
// Takes of map of category name and associated Panels, useful for all the sorted layouts
|
||||||
explicit PanelLayout(const std::map<std::string,std::vector<std::shared_ptr<Panel>>>& categories, SharedResources& t_resources);
|
explicit PanelLayout(const std::map<std::string,std::vector<std::shared_ptr<Panel>>>& categories, ScreenResources& t_resources);
|
||||||
// Arranges all the panels in the vector in columns of three
|
// Arranges all the panels in the vector in columns of three
|
||||||
explicit PanelLayout(const std::vector<std::shared_ptr<Panel>>& panels, SharedResources& t_resources);
|
explicit PanelLayout(const std::vector<std::shared_ptr<Panel>>& panels, ScreenResources& t_resources);
|
||||||
// Stepmania-like empty layout with big red panels that say EMPTY
|
// Stepmania-like empty layout with big red panels that say EMPTY
|
||||||
static PanelLayout red_empty_layout(SharedResources& t_resources);
|
static PanelLayout red_empty_layout(ScreenResources& t_resources);
|
||||||
// Standard title sort with categories for each letter
|
// Standard title sort with categories for each letter
|
||||||
static PanelLayout title_sort(const Data::SongList& song_list, SharedResources& t_resources);
|
static PanelLayout title_sort(const Data::SongList& song_list, ScreenResources& t_resources);
|
||||||
private:
|
private:
|
||||||
void fill_layout(SharedResources& t_resources);
|
void fill_layout(ScreenResources& t_resources);
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -3,11 +3,11 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
MarkerPanel::MarkerPanel(SharedResources& t_resources, const Resources::Marker& marker) :
|
MarkerPanel::MarkerPanel(ScreenResources& t_resources, const Resources::Marker& marker) :
|
||||||
Panel(t_resources),
|
Panel(t_resources),
|
||||||
m_marker(marker)
|
m_marker(marker)
|
||||||
{
|
{
|
||||||
if (resources.preferences.options.marker == m_marker.m_metadata.name) {
|
if (shared.preferences.options.marker == m_marker.m_metadata.name) {
|
||||||
select();
|
select();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ namespace MusicSelect {
|
|||||||
resources.selected_marker->obj.unselect();
|
resources.selected_marker->obj.unselect();
|
||||||
}
|
}
|
||||||
resources.selected_marker.emplace(*this);
|
resources.selected_marker.emplace(*this);
|
||||||
resources.preferences.options.marker = m_marker.m_metadata.name;
|
preferences.options.marker = m_marker.m_metadata.name;
|
||||||
this->selected = true;
|
this->selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
class MarkerPanel final : public Panel {
|
class MarkerPanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
MarkerPanel(SharedResources& t_resources, const Resources::Marker& marker);
|
MarkerPanel(ScreenResources& t_resources, const Resources::Marker& marker);
|
||||||
void click(Ribbon&, const Input::Button&) override;
|
void click(Ribbon&, const Input::Button&) override;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include "../../../Toolkit/HSL.hpp"
|
#include "../../../Toolkit/HSL.hpp"
|
||||||
#include "../../../Toolkit/NormalizedOrigin.hpp"
|
#include "../../../Toolkit/NormalizedOrigin.hpp"
|
||||||
#include "../Ribbon.hpp"
|
#include "../Ribbon.hpp"
|
||||||
#include "../SharedResources.hpp"
|
#include "../Resources.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
Panel::Panel(SharedResources& t_resources) : HoldsSharedResources(t_resources) {
|
Panel::Panel(ScreenResources& t_resources) : HoldsResources(t_resources) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
sf::Text category_label{
|
sf::Text category_label{
|
||||||
"category",
|
"category",
|
||||||
resources.fallback_font.medium,
|
shared.fallback_font.medium,
|
||||||
static_cast<unsigned int>(get_size()*0.1f)
|
static_cast<unsigned int>(get_size()*0.1f)
|
||||||
};
|
};
|
||||||
category_label.setFillColor(sf::Color::White);
|
category_label.setFillColor(sf::Color::White);
|
||||||
@ -51,7 +51,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
sf::Text label_text{
|
sf::Text label_text{
|
||||||
m_label,
|
m_label,
|
||||||
resources.fallback_font.black,
|
shared.fallback_font.black,
|
||||||
static_cast<unsigned int>(get_size()*0.7f)
|
static_cast<unsigned int>(get_size()*0.7f)
|
||||||
};
|
};
|
||||||
label_text.setFillColor(sf::Color::White);
|
label_text.setFillColor(sf::Color::White);
|
||||||
@ -111,7 +111,7 @@ namespace MusicSelect {
|
|||||||
// We should gray out the panel if the currently selected difficulty doesn't exist for this song
|
// We should gray out the panel if the currently selected difficulty doesn't exist for this song
|
||||||
bool should_be_grayed_out = m_song->chart_levels.find(last_selected_chart) == m_song->chart_levels.end();
|
bool should_be_grayed_out = m_song->chart_levels.find(last_selected_chart) == m_song->chart_levels.end();
|
||||||
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 = shared.covers.async_get(m_song->folder/m_song->cover.value());
|
||||||
if (loaded_texture) {
|
if (loaded_texture) {
|
||||||
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>(
|
||||||
@ -134,7 +134,7 @@ namespace MusicSelect {
|
|||||||
chart_dif_badge.setFillColor(sf::Color(128,128,128));
|
chart_dif_badge.setFillColor(sf::Color(128,128,128));
|
||||||
} else {
|
} else {
|
||||||
chart_dif_badge.setFillColor(
|
chart_dif_badge.setFillColor(
|
||||||
resources.get_chart_color(last_selected_chart)
|
shared.get_chart_color(last_selected_chart)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
target.draw(chart_dif_badge, states);
|
target.draw(chart_dif_badge, states);
|
||||||
@ -142,7 +142,7 @@ namespace MusicSelect {
|
|||||||
auto dif = m_song->chart_levels.at(last_selected_chart);
|
auto dif = m_song->chart_levels.at(last_selected_chart);
|
||||||
sf::Text dif_label{
|
sf::Text dif_label{
|
||||||
std::to_string(dif),
|
std::to_string(dif),
|
||||||
resources.fallback_font.black,
|
shared.fallback_font.black,
|
||||||
static_cast<unsigned int>(get_size()*0.15f)
|
static_cast<unsigned int>(get_size()*0.15f)
|
||||||
};
|
};
|
||||||
dif_label.setFillColor(sf::Color::White);
|
dif_label.setFillColor(sf::Color::White);
|
||||||
@ -151,7 +151,7 @@ namespace MusicSelect {
|
|||||||
target.draw(dif_label, states);
|
target.draw(dif_label, states);
|
||||||
}
|
}
|
||||||
sf::Text song_title;
|
sf::Text song_title;
|
||||||
song_title.setFont(resources.fallback_font.medium);
|
song_title.setFont(shared.fallback_font.medium);
|
||||||
song_title.setString(sf::String::fromUtf8(m_song->title.begin(), m_song->title.end()));
|
song_title.setString(sf::String::fromUtf8(m_song->title.begin(), m_song->title.end()));
|
||||||
song_title.setCharacterSize(static_cast<unsigned int>(0.06875f*get_size()));
|
song_title.setCharacterSize(static_cast<unsigned int>(0.06875f*get_size()));
|
||||||
song_title.setFillColor(sf::Color::White);
|
song_title.setFillColor(sf::Color::White);
|
||||||
@ -181,7 +181,7 @@ namespace MusicSelect {
|
|||||||
target.draw(frame, states);
|
target.draw(frame, states);
|
||||||
|
|
||||||
sf::Text message;
|
sf::Text message;
|
||||||
message.setFont(resources.fallback_font.medium);
|
message.setFont(shared.fallback_font.medium);
|
||||||
message.setString(sf::String::fromUtf8(m_message.begin(), m_message.end()));
|
message.setString(sf::String::fromUtf8(m_message.begin(), m_message.end()));
|
||||||
message.setCharacterSize(static_cast<unsigned int>(0.1f*get_size()));
|
message.setCharacterSize(static_cast<unsigned int>(0.1f*get_size()));
|
||||||
message.setFillColor(m_color);
|
message.setFillColor(m_color);
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
#include "../../../Input/Buttons.hpp"
|
#include "../../../Input/Buttons.hpp"
|
||||||
#include "../../../Data/Song.hpp"
|
#include "../../../Data/Song.hpp"
|
||||||
#include "../../../Toolkit/AffineTransform.hpp"
|
#include "../../../Toolkit/AffineTransform.hpp"
|
||||||
#include "../DensityGraph.hpp"
|
#include "../Resources.hpp"
|
||||||
#include "../SharedResources.hpp"
|
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
@ -18,9 +17,9 @@ 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 : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class Panel : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
explicit Panel(SharedResources& t_resources);
|
explicit Panel(ScreenResources& t_resources);
|
||||||
// What happens when you click on the panel
|
// What happens when you click on the panel
|
||||||
virtual void click(Ribbon& ribbon, const Input::Button& button) = 0;
|
virtual void click(Ribbon& ribbon, const Input::Button& button) = 0;
|
||||||
virtual ~Panel() = default;
|
virtual ~Panel() = default;
|
||||||
@ -38,7 +37,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
class ColoredMessagePanel final : public Panel {
|
class ColoredMessagePanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
ColoredMessagePanel(SharedResources& t_resources, const sf::Color& color, const std::string& message) : Panel(t_resources), m_color(color), m_message(message) {};
|
ColoredMessagePanel(ScreenResources& t_resources, const sf::Color& color, const std::string& message) : Panel(t_resources), m_color(color), m_message(message) {};
|
||||||
void click(Ribbon&, const Input::Button&) override {return;};
|
void click(Ribbon&, const Input::Button&) override {return;};
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
@ -48,7 +47,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
class ColorPanel final : public Panel {
|
class ColorPanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
ColorPanel(SharedResources& t_resources, const sf::Color& t_color) : Panel(t_resources), m_color(t_color) {};
|
ColorPanel(ScreenResources& t_resources, const sf::Color& t_color) : Panel(t_resources), m_color(t_color) {};
|
||||||
void click(Ribbon&, const Input::Button&) override {return;};
|
void click(Ribbon&, const Input::Button&) override {return;};
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
@ -57,7 +56,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
class CategoryPanel final : public Panel {
|
class CategoryPanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
CategoryPanel(SharedResources& t_resources, const std::string& t_label) : Panel(t_resources), m_label(t_label) {};
|
CategoryPanel(ScreenResources& t_resources, const std::string& t_label) : Panel(t_resources), m_label(t_label) {};
|
||||||
void click(Ribbon& ribbon, const Input::Button& button) override;
|
void click(Ribbon& ribbon, const Input::Button& button) override;
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
@ -74,7 +73,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
class SongPanel final : public SelectablePanel {
|
class SongPanel final : public SelectablePanel {
|
||||||
public:
|
public:
|
||||||
explicit SongPanel(SharedResources& t_resources, const std::shared_ptr<const Data::Song>& t_song) : SelectablePanel(t_resources), m_song(t_song) {};
|
explicit SongPanel(ScreenResources& t_resources, const std::shared_ptr<const Data::Song>& t_song) : SelectablePanel(t_resources), m_song(t_song) {};
|
||||||
void click(Ribbon& ribbon, const Input::Button& button) override;
|
void click(Ribbon& ribbon, const Input::Button& button) override;
|
||||||
void unselect() override;
|
void unselect() override;
|
||||||
std::optional<Data::SongDifficulty> get_selected_difficulty() const override;
|
std::optional<Data::SongDifficulty> get_selected_difficulty() const override;
|
||||||
|
@ -19,7 +19,7 @@ namespace MusicSelect {
|
|||||||
target.draw(frame, states);
|
target.draw(frame, states);
|
||||||
|
|
||||||
sf::Text message;
|
sf::Text message;
|
||||||
message.setFont(resources.fallback_font.medium);
|
message.setFont(shared.fallback_font.medium);
|
||||||
message.setString(sf::String::fromUtf8(m_name.begin(), m_name.end()));
|
message.setString(sf::String::fromUtf8(m_name.begin(), m_name.end()));
|
||||||
message.setCharacterSize(static_cast<unsigned int>(0.1f*get_size()));
|
message.setCharacterSize(static_cast<unsigned int>(0.1f*get_size()));
|
||||||
message.setFillColor(sf::Color::White);
|
message.setFillColor(sf::Color::White);
|
||||||
|
@ -13,7 +13,7 @@ namespace MusicSelect {
|
|||||||
class SubpagePanel final : public Panel {
|
class SubpagePanel final : public Panel {
|
||||||
public:
|
public:
|
||||||
SubpagePanel(
|
SubpagePanel(
|
||||||
SharedResources& t_resources,
|
ScreenResources& t_resources,
|
||||||
std::shared_ptr<OptionPage> subpage,
|
std::shared_ptr<OptionPage> subpage,
|
||||||
const std::string& name
|
const std::string& name
|
||||||
) :
|
) :
|
||||||
|
31
src/Screens/MusicSelect/Resources.cpp
Normal file
31
src/Screens/MusicSelect/Resources.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "Resources.hpp"
|
||||||
|
|
||||||
|
#include "Panels/Panel.hpp"
|
||||||
|
|
||||||
|
namespace MusicSelect {
|
||||||
|
std::string ScreenResources::get_last_selected_difficulty() {
|
||||||
|
return get_selected_difficulty().value_or("BSC");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> ScreenResources::get_selected_difficulty() {
|
||||||
|
if (not selected_panel.has_value()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto chart_selection = selected_panel->obj.get_selected_difficulty();
|
||||||
|
if (not chart_selection.has_value()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return chart_selection->difficulty;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const Data::Song>> ScreenResources::get_selected_song() {
|
||||||
|
if (not selected_panel.has_value()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto chart_selection = selected_panel->obj.get_selected_difficulty();
|
||||||
|
if (not chart_selection.has_value()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return chart_selection->song;
|
||||||
|
}
|
||||||
|
}
|
32
src/Screens/MusicSelect/Resources.hpp
Normal file
32
src/Screens/MusicSelect/Resources.hpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../Resources/SharedResources.hpp"
|
||||||
|
#include "MusicPreview.hpp"
|
||||||
|
|
||||||
|
namespace MusicSelect {
|
||||||
|
|
||||||
|
class SelectablePanel;
|
||||||
|
class MarkerPanel;
|
||||||
|
class OptionPage;
|
||||||
|
|
||||||
|
struct ScreenResources : Resources::HoldsSharedResources {
|
||||||
|
ScreenResources(Resources::SharedResources& r) : Resources::HoldsSharedResources(r) {}
|
||||||
|
|
||||||
|
std::optional<Resources::Timed<SelectablePanel>> selected_panel;
|
||||||
|
std::string get_last_selected_difficulty();
|
||||||
|
std::optional<std::string> get_selected_difficulty();
|
||||||
|
std::optional<std::reference_wrapper<const Data::Song>> get_selected_song();
|
||||||
|
|
||||||
|
MusicPreview music_preview;
|
||||||
|
|
||||||
|
std::vector<std::reference_wrapper<OptionPage>> options_state;
|
||||||
|
|
||||||
|
std::optional<Resources::Timed<MarkerPanel>> selected_marker;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Proxy for HoldsPreferences
|
||||||
|
struct HoldsResources : Resources::HoldsSharedResources {
|
||||||
|
HoldsResources(ScreenResources& t_resources) : Resources::HoldsSharedResources(t_resources.shared), resources(t_resources) {};
|
||||||
|
ScreenResources& resources;
|
||||||
|
};
|
||||||
|
}
|
@ -65,8 +65,8 @@ namespace MusicSelect {
|
|||||||
return clock.getElapsedTime() / m_time_factor > sf::milliseconds(300);
|
return clock.getElapsedTime() / m_time_factor > sf::milliseconds(300);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ribbon::Ribbon(PanelLayout layout, SharedResources& t_resources) :
|
Ribbon::Ribbon(PanelLayout layout, ScreenResources& t_resources) :
|
||||||
HoldsSharedResources(t_resources),
|
HoldsResources(t_resources),
|
||||||
m_layout(layout),
|
m_layout(layout),
|
||||||
left_button(t_resources),
|
left_button(t_resources),
|
||||||
right_button(t_resources)
|
right_button(t_resources)
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "../../Toolkit/AffineTransform.hpp"
|
#include "../../Toolkit/AffineTransform.hpp"
|
||||||
#include "../../Toolkit/Debuggable.hpp"
|
#include "../../Toolkit/Debuggable.hpp"
|
||||||
#include "../../Toolkit/EasingFunctions.hpp"
|
#include "../../Toolkit/EasingFunctions.hpp"
|
||||||
#include "SharedResources.hpp"
|
#include "Resources.hpp"
|
||||||
#include "PanelLayout.hpp"
|
#include "PanelLayout.hpp"
|
||||||
#include "Drawables/ControlPanels.hpp"
|
#include "Drawables/ControlPanels.hpp"
|
||||||
|
|
||||||
@ -39,9 +39,9 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
// A Ribbon is a visual representation of a PanelLayout,
|
// A Ribbon is a visual representation of a PanelLayout,
|
||||||
// You can scroll it using the left and right buttons
|
// You can scroll it using the left and right buttons
|
||||||
class Ribbon : public sf::Drawable, public sf::Transformable, public HoldsSharedResources, public Toolkit::Debuggable {
|
class Ribbon : public sf::Drawable, public sf::Transformable, public HoldsResources, public Toolkit::Debuggable {
|
||||||
public:
|
public:
|
||||||
Ribbon(PanelLayout layout, SharedResources& t_resources);
|
Ribbon(PanelLayout layout, ScreenResources& t_resources);
|
||||||
std::shared_ptr<Panel>& get_panel_under_button(const Input::Button& button);
|
std::shared_ptr<Panel>& get_panel_under_button(const Input::Button& button);
|
||||||
void click_on(const Input::Button& button);
|
void click_on(const Input::Button& button);
|
||||||
void move_right();
|
void move_right();
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
BigCover::BigCover(SharedResources& t_resources) :
|
BigCover::BigCover(ScreenResources& t_resources) :
|
||||||
HoldsSharedResources(t_resources)
|
HoldsResources(t_resources)
|
||||||
{
|
{
|
||||||
m_cover_fallback.setFillColor(sf::Color::Transparent);
|
m_cover_fallback.setFillColor(sf::Color::Transparent);
|
||||||
m_cover_fallback.setOutlineThickness(1.f);
|
m_cover_fallback.setOutlineThickness(1.f);
|
||||||
@ -36,7 +36,7 @@ namespace MusicSelect {
|
|||||||
if (not cover_path.has_value()) {
|
if (not cover_path.has_value()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto cover_texture = resources.covers.async_get(*cover_path);
|
auto cover_texture = shared.covers.async_get(*cover_path);
|
||||||
if (not cover_texture.has_value()) {
|
if (not cover_texture.has_value()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -52,8 +52,8 @@ namespace MusicSelect {
|
|||||||
target.draw(cover, states);
|
target.draw(cover, states);
|
||||||
}
|
}
|
||||||
|
|
||||||
SongInfo::SongInfo(SharedResources& t_resources) :
|
SongInfo::SongInfo(ScreenResources& t_resources) :
|
||||||
HoldsSharedResources(t_resources),
|
HoldsResources(t_resources),
|
||||||
m_big_cover(resources)
|
m_big_cover(resources)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ namespace MusicSelect {
|
|||||||
if (not song_title.empty()) {
|
if (not song_title.empty()) {
|
||||||
sf::Text song_title_label{
|
sf::Text song_title_label{
|
||||||
sf::String::fromUtf8(song_title.begin(), song_title.end()),
|
sf::String::fromUtf8(song_title.begin(), song_title.end()),
|
||||||
resources.fallback_font.medium,
|
shared.fallback_font.medium,
|
||||||
static_cast<unsigned int>(
|
static_cast<unsigned int>(
|
||||||
0.026315789f*get_screen_width()
|
0.026315789f*get_screen_width()
|
||||||
)
|
)
|
||||||
@ -101,7 +101,7 @@ namespace MusicSelect {
|
|||||||
if (not song_artist.empty()) {
|
if (not song_artist.empty()) {
|
||||||
sf::Text song_artist_label{
|
sf::Text song_artist_label{
|
||||||
sf::String::fromUtf8(song_artist.begin(), song_artist.end()),
|
sf::String::fromUtf8(song_artist.begin(), song_artist.end()),
|
||||||
resources.fallback_font.medium,
|
shared.fallback_font.medium,
|
||||||
static_cast<unsigned int>(
|
static_cast<unsigned int>(
|
||||||
0.02f*get_screen_width()
|
0.02f*get_screen_width()
|
||||||
)
|
)
|
||||||
@ -132,7 +132,7 @@ namespace MusicSelect {
|
|||||||
}
|
}
|
||||||
sf::Text level_label{
|
sf::Text level_label{
|
||||||
"LEVEL",
|
"LEVEL",
|
||||||
resources.fallback_font.light,
|
shared.fallback_font.light,
|
||||||
static_cast<unsigned int>(12.f/768.f*get_screen_width())
|
static_cast<unsigned int>(12.f/768.f*get_screen_width())
|
||||||
};
|
};
|
||||||
Toolkit::set_origin_normalized(level_label, 0.5f, 0.f);
|
Toolkit::set_origin_normalized(level_label, 0.5f, 0.f);
|
||||||
@ -142,7 +142,7 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
sf::Text level_number_label{
|
sf::Text level_number_label{
|
||||||
std::to_string(selected_chart->song.chart_levels.at(selected_chart->difficulty)),
|
std::to_string(selected_chart->song.chart_levels.at(selected_chart->difficulty)),
|
||||||
resources.fallback_font.black,
|
shared.fallback_font.black,
|
||||||
static_cast<unsigned int>(130.f/768.f*get_screen_width())
|
static_cast<unsigned int>(130.f/768.f*get_screen_width())
|
||||||
};
|
};
|
||||||
Toolkit::set_origin_normalized(level_number_label, 0.5f, 0.f);
|
Toolkit::set_origin_normalized(level_number_label, 0.5f, 0.f);
|
||||||
@ -161,12 +161,12 @@ namespace MusicSelect {
|
|||||||
|
|
||||||
sf::Text chart_label{
|
sf::Text chart_label{
|
||||||
sf::String::fromUtf8(full_difficulty.begin(), full_difficulty.end()),
|
sf::String::fromUtf8(full_difficulty.begin(), full_difficulty.end()),
|
||||||
resources.fallback_font.medium,
|
shared.fallback_font.medium,
|
||||||
static_cast<unsigned int>(20.f/768.f*get_screen_width())
|
static_cast<unsigned int>(20.f/768.f*get_screen_width())
|
||||||
};
|
};
|
||||||
Toolkit::set_origin_normalized_no_position(chart_label, 0.5f, 0.f);
|
Toolkit::set_origin_normalized_no_position(chart_label, 0.5f, 0.f);
|
||||||
chart_label.setPosition(get_big_level_x(), get_big_level_y()+(145.f/768.f*get_screen_width()));
|
chart_label.setPosition(get_big_level_x(), get_big_level_y()+(145.f/768.f*get_screen_width()));
|
||||||
chart_label.setFillColor(resources.get_chart_color(selected_chart->difficulty));
|
chart_label.setFillColor(shared.get_chart_color(selected_chart->difficulty));
|
||||||
target.draw(chart_label, states);
|
target.draw(chart_label, states);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ namespace MusicSelect {
|
|||||||
for (auto &&[difficulty, level] : selected_chart->song.chart_levels) {
|
for (auto &&[difficulty, level] : selected_chart->song.chart_levels) {
|
||||||
sf::CircleShape dif_badge{dif_badge_radius};
|
sf::CircleShape dif_badge{dif_badge_radius};
|
||||||
Toolkit::set_origin_normalized(dif_badge, 0.5f, 0.5f);
|
Toolkit::set_origin_normalized(dif_badge, 0.5f, 0.5f);
|
||||||
dif_badge.setFillColor(resources.get_chart_color(difficulty));
|
dif_badge.setFillColor(shared.get_chart_color(difficulty));
|
||||||
dif_badge.setPosition(dif_badge_x+dif_index*dif_badge_step, dif_badge_y);
|
dif_badge.setPosition(dif_badge_x+dif_index*dif_badge_step, dif_badge_y);
|
||||||
target.draw(dif_badge, states);
|
target.draw(dif_badge, states);
|
||||||
if (difficulty == selected_chart->difficulty) {
|
if (difficulty == selected_chart->difficulty) {
|
||||||
@ -229,8 +229,8 @@ namespace MusicSelect {
|
|||||||
if (not selected_difficulty.has_value()) {
|
if (not selected_difficulty.has_value()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resources.density_graphs.load(*selected_difficulty);
|
shared.density_graphs.load(*selected_difficulty);
|
||||||
auto densities = resources.density_graphs.get(*selected_difficulty);
|
auto densities = shared.density_graphs.get(*selected_difficulty);
|
||||||
if (not densities.has_value()) {
|
if (not densities.has_value()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
#include "../../Toolkit/AffineTransform.hpp"
|
#include "../../Toolkit/AffineTransform.hpp"
|
||||||
|
|
||||||
#include "SharedResources.hpp"
|
#include "Resources.hpp"
|
||||||
|
|
||||||
namespace MusicSelect {
|
namespace MusicSelect {
|
||||||
|
|
||||||
class BigCover : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class BigCover : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
BigCover(SharedResources& t_resources);
|
BigCover(ScreenResources& t_resources);
|
||||||
float get_size() const {return preferences.layout.big_cover_size*get_screen_width();};
|
float get_size() const {return preferences.layout.big_cover_size*get_screen_width();};
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
@ -20,9 +20,9 @@ namespace MusicSelect {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Displays the song info on the top part of the screen
|
// Displays the song info on the top part of the screen
|
||||||
class SongInfo : public sf::Drawable, public sf::Transformable, public HoldsSharedResources {
|
class SongInfo : public sf::Drawable, public sf::Transformable, public HoldsResources {
|
||||||
public:
|
public:
|
||||||
SongInfo(SharedResources& t_resources);
|
SongInfo(ScreenResources& t_resources);
|
||||||
private:
|
private:
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||||
void draw_song_title(sf::RenderTarget& target, sf::RenderStates states) const;
|
void draw_song_title(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user