mirror of
https://gitlab.com/square-game-liberation-front/F.E.I.S.git
synced 2024-11-12 02:00:53 +01:00
async marker loading !
This commit is contained in:
parent
0446e717ec
commit
f190201582
@ -36,6 +36,7 @@
|
|||||||
- The editable time range of a chart now grows in a way that should interfere less with editing
|
- The editable time range of a chart now grows in a way that should interfere less with editing
|
||||||
- Support for the jujube marker format
|
- Support for the jujube marker format
|
||||||
- Sound parameters are saved
|
- Sound parameters are saved
|
||||||
|
- Markers and Marker previews are loaded in the background, which should avoid long boot up times + UI freezes
|
||||||
|
|
||||||
## 🚧 Changes 🚧
|
## 🚧 Changes 🚧
|
||||||
- Force using the asset folder next to the executable
|
- Force using the asset folder next to the executable
|
||||||
|
@ -24,8 +24,12 @@
|
|||||||
#include <SFML/System/Vector2.hpp>
|
#include <SFML/System/Vector2.hpp>
|
||||||
#include <tinyfiledialogs.h>
|
#include <tinyfiledialogs.h>
|
||||||
|
|
||||||
|
#include "custom_sfml_audio/synced_sound_streams.hpp"
|
||||||
|
#include "widgets/linear_view.hpp"
|
||||||
|
#include "better_metadata.hpp"
|
||||||
#include "better_note.hpp"
|
#include "better_note.hpp"
|
||||||
#include "better_song.hpp"
|
#include "better_song.hpp"
|
||||||
|
#include "better_timing.hpp"
|
||||||
#include "chart_state.hpp"
|
#include "chart_state.hpp"
|
||||||
#include "compile_time_info.hpp"
|
#include "compile_time_info.hpp"
|
||||||
#include "file_dialogs.hpp"
|
#include "file_dialogs.hpp"
|
||||||
@ -36,14 +40,10 @@
|
|||||||
#include "long_note_dummy.hpp"
|
#include "long_note_dummy.hpp"
|
||||||
#include "notifications_queue.hpp"
|
#include "notifications_queue.hpp"
|
||||||
#include "special_numeric_types.hpp"
|
#include "special_numeric_types.hpp"
|
||||||
#include "better_metadata.hpp"
|
|
||||||
#include "better_timing.hpp"
|
|
||||||
#include "custom_sfml_audio/synced_sound_streams.hpp"
|
|
||||||
#include "utf8_sfml_redefinitions.hpp"
|
#include "utf8_sfml_redefinitions.hpp"
|
||||||
#include "variant_visitor.hpp"
|
|
||||||
#include "utf8_strings.hpp"
|
#include "utf8_strings.hpp"
|
||||||
|
#include "variant_visitor.hpp"
|
||||||
#include "waveform.hpp"
|
#include "waveform.hpp"
|
||||||
#include "widgets/linear_view.hpp"
|
|
||||||
|
|
||||||
EditorState::EditorState(const std::filesystem::path& assets_, config::Config& config_) :
|
EditorState::EditorState(const std::filesystem::path& assets_, config::Config& config_) :
|
||||||
config(config_),
|
config(config_),
|
||||||
@ -434,7 +434,7 @@ Fraction EditorState::get_snap_step() const {
|
|||||||
return Fraction{1, snap};
|
return Fraction{1, snap};
|
||||||
};
|
};
|
||||||
|
|
||||||
void EditorState::display_playfield(const std::optional<std::shared_ptr<Marker>>& opt_marker, Judgement markerEndingState) {
|
void EditorState::display_playfield(const Markers::marker_type& opt_marker, Judgement markerEndingState) {
|
||||||
ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_Once);
|
ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_Once);
|
||||||
ImGui::SetNextWindowSizeConstraints(
|
ImGui::SetNextWindowSizeConstraints(
|
||||||
ImVec2(0, 0),
|
ImVec2(0, 0),
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "generic_interval.hpp"
|
#include "generic_interval.hpp"
|
||||||
#include "history.hpp"
|
#include "history.hpp"
|
||||||
#include "marker.hpp"
|
#include "marker.hpp"
|
||||||
|
#include "markers.hpp"
|
||||||
#include "clipboard.hpp"
|
#include "clipboard.hpp"
|
||||||
#include "notifications_queue.hpp"
|
#include "notifications_queue.hpp"
|
||||||
#include "playfield.hpp"
|
#include "playfield.hpp"
|
||||||
@ -142,7 +143,7 @@ public:
|
|||||||
Fraction get_snap_step() const;
|
Fraction get_snap_step() const;
|
||||||
|
|
||||||
bool show_playfield = true;
|
bool show_playfield = true;
|
||||||
void display_playfield(const std::optional<std::shared_ptr<Marker>>& marker, Judgement markerEndingState);
|
void display_playfield(const Markers::marker_type& marker, Judgement markerEndingState);
|
||||||
|
|
||||||
bool show_file_properties = false;
|
bool show_file_properties = false;
|
||||||
void display_file_properties();
|
void display_file_properties();
|
||||||
|
91
src/main.cpp
91
src/main.cpp
@ -4,6 +4,7 @@
|
|||||||
#include <SFML/Graphics/Texture.hpp>
|
#include <SFML/Graphics/Texture.hpp>
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
#include <SFML/Window/Keyboard.hpp>
|
#include <SFML/Window/Keyboard.hpp>
|
||||||
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@ -28,6 +29,7 @@
|
|||||||
#include "history_item.hpp"
|
#include "history_item.hpp"
|
||||||
#include "imgui_extras.hpp"
|
#include "imgui_extras.hpp"
|
||||||
#include "marker.hpp"
|
#include "marker.hpp"
|
||||||
|
#include "markers.hpp"
|
||||||
#include "mp3_reader.hpp"
|
#include "mp3_reader.hpp"
|
||||||
#include "notifications_queue.hpp"
|
#include "notifications_queue.hpp"
|
||||||
#include "src/custom_sfml_audio/synced_sound_streams.hpp"
|
#include "src/custom_sfml_audio/synced_sound_streams.hpp"
|
||||||
@ -36,8 +38,6 @@
|
|||||||
#include "widgets/blank_screen.hpp"
|
#include "widgets/blank_screen.hpp"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// TODO : Make the playfield not appear when there's no chart selected
|
|
||||||
|
|
||||||
// extend SFML to be able to read mp3's
|
// extend SFML to be able to read mp3's
|
||||||
sf::SoundFileFactory::registerReader<sf::priv::SoundFileReaderMp3>();
|
sf::SoundFileFactory::registerReader<sf::priv::SoundFileReaderMp3>();
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ int main() {
|
|||||||
const auto settings_folder = executable_folder / "settings";
|
const auto settings_folder = executable_folder / "settings";
|
||||||
const auto markers_folder = assets_folder / "textures" / "markers";
|
const auto markers_folder = assets_folder / "textures" / "markers";
|
||||||
|
|
||||||
config::Config config {settings_folder};
|
config::Config config{settings_folder};
|
||||||
|
|
||||||
sf::RenderWindow window(sf::VideoMode(800, 600), "FEIS");
|
sf::RenderWindow window(sf::VideoMode(800, 600), "FEIS");
|
||||||
window.setVerticalSyncEnabled(true);
|
window.setVerticalSyncEnabled(true);
|
||||||
@ -78,49 +78,7 @@ int main() {
|
|||||||
|
|
||||||
IO.ConfigWindowsMoveFromTitleBarOnly = true;
|
IO.ConfigWindowsMoveFromTitleBarOnly = true;
|
||||||
|
|
||||||
// Loading markers preview
|
Markers markers{markers_folder, config};
|
||||||
std::map<std::filesystem::path, std::future<std::optional<feis::Texture>>> marker_previews_loaders;
|
|
||||||
std::map<std::filesystem::path, std::optional<feis::Texture>> marker_previews;
|
|
||||||
for (const auto& dir_entry : std::filesystem::directory_iterator(markers_folder)) {
|
|
||||||
const auto folder = std::filesystem::relative(dir_entry, markers_folder);
|
|
||||||
marker_previews_loaders[folder] = std::async(
|
|
||||||
std::launch::async,
|
|
||||||
[](const std::filesystem::path& folder) -> std::optional<feis::Texture> {
|
|
||||||
for (const auto& file : {"preview.png", "ma15.png"}) {
|
|
||||||
const auto preview_path = folder / file;
|
|
||||||
if (std::filesystem::exists(preview_path)) {
|
|
||||||
feis::Texture preview;
|
|
||||||
if (preview.load_from_path(preview_path)) {
|
|
||||||
return preview;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
dir_entry.path()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
using MarkerTuple = std::tuple<std::filesystem::path, std::optional<std::shared_ptr<Marker>>>;
|
|
||||||
std::future<MarkerTuple> marker_loader;
|
|
||||||
const auto load_marker_async = [&](const std::filesystem::path& folder) -> MarkerTuple {
|
|
||||||
try {
|
|
||||||
return {folder, load_marker_from(markers_folder / folder)};
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
return {folder, {}};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::shared_ptr<Marker> marker = [&](const std::optional<std::filesystem::path>& folder){
|
|
||||||
if (folder and folder->is_relative()) {
|
|
||||||
try {
|
|
||||||
return load_marker_from(markers_folder / *folder);
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
fmt::print("Failed to load marker from preferences");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return first_available_marker_in(markers_folder);
|
|
||||||
}(config.marker.folder);
|
|
||||||
|
|
||||||
if (not config.marker.ending_state) {
|
if (not config.marker.ending_state) {
|
||||||
config.marker.ending_state = Judgement::Perfect;
|
config.marker.ending_state = Judgement::Perfect;
|
||||||
}
|
}
|
||||||
@ -490,7 +448,7 @@ int main() {
|
|||||||
editor_state->display_history();
|
editor_state->display_history();
|
||||||
}
|
}
|
||||||
if (editor_state->chart_state and editor_state->show_playfield) {
|
if (editor_state->chart_state and editor_state->show_playfield) {
|
||||||
editor_state->display_playfield(marker, markerEndingState);
|
editor_state->display_playfield(markers.get_chosen_marker(), markerEndingState);
|
||||||
}
|
}
|
||||||
if (editor_state->show_linear_view) {
|
if (editor_state->show_linear_view) {
|
||||||
editor_state->display_linear_view();
|
editor_state->display_linear_view();
|
||||||
@ -781,33 +739,44 @@ int main() {
|
|||||||
}
|
}
|
||||||
if (ImGui::BeginMenu("Marker")) {
|
if (ImGui::BeginMenu("Marker")) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto& [path, opt_preview] : marker_previews) {
|
std::for_each(
|
||||||
|
markers.cbegin(),
|
||||||
|
markers.cend(),
|
||||||
|
[&](const auto& it){
|
||||||
|
const auto& [path, opt_preview] = it;
|
||||||
ImGui::PushID(path.c_str());
|
ImGui::PushID(path.c_str());
|
||||||
|
bool clicked = false;
|
||||||
if (opt_preview) {
|
if (opt_preview) {
|
||||||
if (ImGui::ImageButton(*opt_preview, {100, 100})) {
|
clicked = ImGui::ImageButton(*opt_preview, {100, 100});
|
||||||
|
} else {
|
||||||
marker_loader = std::async
|
clicked = ImGui::Button(path_to_utf8_encoded_string(path).c_str(), {100, 100});
|
||||||
marker = marker_ptr;
|
|
||||||
config.marker.folder = path;
|
|
||||||
}
|
}
|
||||||
|
if (clicked) {
|
||||||
|
markers.load_marker(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
i++;
|
i++;
|
||||||
if (i % 4 != 0) {
|
if (i % 4 != 0) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
if (ImGui::BeginMenu("Marker Ending State")) {
|
if (ImGui::BeginMenu("Marker Ending State")) {
|
||||||
for (const auto& [judgement, name] : judgement_to_name) {
|
for (const auto& [judgement, name] : judgement_to_name) {
|
||||||
const auto preview = marker->judgement_preview(judgement);
|
if (const auto& marker = markers.get_chosen_marker()) {
|
||||||
|
const auto preview = (*marker)->judgement_preview(judgement);
|
||||||
if (ImGui::ImageButton(preview, {100, 100})) {
|
if (ImGui::ImageButton(preview, {100, 100})) {
|
||||||
markerEndingState = judgement;
|
markerEndingState = judgement;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::TextUnformatted(name.c_str());
|
ImGui::TextUnformatted(name.c_str());
|
||||||
|
} else {
|
||||||
|
if (ImGui::Button((name+"##Marker Ending State").c_str())) {
|
||||||
|
markerEndingState = judgement;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
@ -824,19 +793,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
|
|
||||||
ImGui::SFML::Render(window);
|
ImGui::SFML::Render(window);
|
||||||
window.display();
|
window.display();
|
||||||
|
markers.update();
|
||||||
for (auto& [path, future] : marker_previews_loaders) {
|
|
||||||
if (future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
|
||||||
marker_previews[path] = future.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto& future : )
|
|
||||||
if (marker_loader.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
|
||||||
marker = marker_loader.get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SFML::Shutdown();
|
ImGui::SFML::Shutdown();
|
||||||
|
@ -196,8 +196,8 @@ std::shared_ptr<Marker> load_marker_from(const std::filesystem::path& folder) {
|
|||||||
return std::make_shared<JujubeMarker>(std::move(JujubeMarker::load_from_folder(folder)));
|
return std::make_shared<JujubeMarker>(std::move(JujubeMarker::load_from_folder(folder)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Marker> first_available_marker_in(const std::filesystem::path& assets_folder) {
|
std::shared_ptr<Marker> first_available_marker_in(const std::filesystem::path& markers_folder) {
|
||||||
for (auto& folder : std::filesystem::directory_iterator(assets_folder / "textures" / "markers")) {
|
for (auto& folder : std::filesystem::directory_iterator(markers_folder)) {
|
||||||
try {
|
try {
|
||||||
return load_marker_from(folder);
|
return load_marker_from(folder);
|
||||||
} catch (const std::exception&) {}
|
} catch (const std::exception&) {}
|
||||||
|
164
src/markers.cpp
Normal file
164
src/markers.cpp
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
#include "markers.hpp"
|
||||||
|
|
||||||
|
#include <future>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
#include "fmt/core.h"
|
||||||
|
#include "imgui.h"
|
||||||
|
|
||||||
|
#include "marker.hpp"
|
||||||
|
#include "utf8_strings.hpp"
|
||||||
|
|
||||||
|
Markers::Markers(
|
||||||
|
const std::filesystem::path& markers_folder_,
|
||||||
|
config::Config& config_
|
||||||
|
) :
|
||||||
|
markers_folder(markers_folder_),
|
||||||
|
config(config_)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto contents = std::filesystem::directory_iterator(markers_folder);
|
||||||
|
auto subdirs = std::views::filter(contents, [](const auto& dir_it){return dir_it.is_directory();});
|
||||||
|
|
||||||
|
for (const auto& dir_it : subdirs) {
|
||||||
|
const auto folder = std::filesystem::relative(dir_it, markers_folder);
|
||||||
|
preview_loaders[folder] = std::async(std::launch::async, load_marker_preview, dir_it.path());
|
||||||
|
}
|
||||||
|
|
||||||
|
marker_loader = std::make_tuple(
|
||||||
|
std::filesystem::path{},
|
||||||
|
std::async(std::launch::async, load_default_marker, std::cref(config.marker.folder), std::cref(markers_folder))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Markers::load_marker(const std::filesystem::path& chosen) {
|
||||||
|
auto& [path, future] = marker_loader;
|
||||||
|
if (future.valid()) {
|
||||||
|
discarded_markers.emplace_back(std::async(std::launch::async, discard_marker, std::move(future)));
|
||||||
|
}
|
||||||
|
marker_loader = std::make_tuple(
|
||||||
|
chosen,
|
||||||
|
std::async(std::launch::async, load_marker_async, std::cref(chosen), std::cref(markers_folder))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Markers::marker_type& Markers::get_chosen_marker() const {
|
||||||
|
return chosen_marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
Markers::previews_type::const_iterator Markers::cbegin() const {
|
||||||
|
return previews.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
Markers::previews_type::const_iterator Markers::cend() const {
|
||||||
|
return previews.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Markers::update() {
|
||||||
|
std::erase_if(preview_loaders, [](const auto& it){
|
||||||
|
return not it.second.valid();
|
||||||
|
});
|
||||||
|
for (auto& [path, future] : preview_loaders) {
|
||||||
|
if (future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
||||||
|
previews[path] = future.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto& [path, future] = marker_loader;
|
||||||
|
if (future.valid()) {
|
||||||
|
if (future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
||||||
|
const auto loaded_marker = future.get();
|
||||||
|
if (loaded_marker) {
|
||||||
|
chosen_marker = loaded_marker;
|
||||||
|
config.marker.folder = path;
|
||||||
|
} else {
|
||||||
|
previews.erase(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::erase_if(discarded_markers, [](const std::future<void>& f){
|
||||||
|
return not f.valid() or f.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Markers::display_debug() {
|
||||||
|
if (ImGui::Begin("Markers Debug")) {
|
||||||
|
ImGui::TextUnformatted("chosen_marker :");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (not chosen_marker) {
|
||||||
|
ImGui::TextDisabled("(empty)");
|
||||||
|
} else {
|
||||||
|
ImGui::TextUnformatted(path_to_utf8_encoded_string((*chosen_marker)->get_folder()).c_str());
|
||||||
|
}
|
||||||
|
ImGui::TextUnformatted("marker_loader :");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (not std::get<1>(marker_loader).valid()) {
|
||||||
|
ImGui::TextDisabled("(empty)");
|
||||||
|
} else {
|
||||||
|
ImGui::TextUnformatted(path_to_utf8_encoded_string(std::get<0>(marker_loader)).c_str());
|
||||||
|
}
|
||||||
|
if (ImGui::TreeNodeEx("discarded_markers", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
for (const auto& future : discarded_markers) {
|
||||||
|
ImGui::BulletText("%s", fmt::format("{}", fmt::ptr(&future)).c_str());
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
if (ImGui::TreeNodeEx("previews", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
for (const auto& [path, _] : previews) {
|
||||||
|
ImGui::BulletText("%s", fmt::format("{}", path_to_utf8_encoded_string(path)).c_str());
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
if (ImGui::TreeNodeEx("preview_loaders", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
for (const auto& [path, _] : preview_loaders) {
|
||||||
|
ImGui::BulletText("%s", fmt::format("{}", path_to_utf8_encoded_string(path)).c_str());
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
Markers::marker_type Markers::load_default_marker(
|
||||||
|
const std::optional<std::filesystem::path>& chosen_from_config,
|
||||||
|
const std::filesystem::path& markers
|
||||||
|
) {
|
||||||
|
if (chosen_from_config and chosen_from_config->is_relative()) {
|
||||||
|
try {
|
||||||
|
return load_marker_from(markers / *chosen_from_config);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
fmt::print("Failed to load marker from preferences");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return first_available_marker_in(markers);
|
||||||
|
}
|
||||||
|
|
||||||
|
Markers::marker_type Markers::load_marker_async(const std::filesystem::path& chosen, const std::filesystem::path& markers) {
|
||||||
|
try {
|
||||||
|
return load_marker_from(markers / chosen);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Markers::discard_marker(std::future<marker_type>&& future) {
|
||||||
|
auto other_future = std::move(future);
|
||||||
|
if (other_future.valid()) {
|
||||||
|
other_future.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Markers::preview_type Markers::load_marker_preview(const std::filesystem::path& chosen) {
|
||||||
|
for (const auto& file : {"preview.png", "ma15.png"}) {
|
||||||
|
const auto preview_path = chosen / file;
|
||||||
|
if (std::filesystem::exists(preview_path)) {
|
||||||
|
feis::Texture preview;
|
||||||
|
if (preview.load_from_path(preview_path)) {
|
||||||
|
return preview;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
58
src/markers.hpp
Normal file
58
src/markers.hpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <future>
|
||||||
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "config.hpp"
|
||||||
|
#include "marker.hpp"
|
||||||
|
#include "utf8_sfml_redefinitions.hpp"
|
||||||
|
|
||||||
|
/* Deals with loading markers and marker previews asynchronously */
|
||||||
|
class Markers {
|
||||||
|
public:
|
||||||
|
|
||||||
|
using marker_type = std::optional<std::shared_ptr<Marker>>;
|
||||||
|
using marker_loader_type = std::future<marker_type>;
|
||||||
|
using preview_type = std::optional<feis::Texture>;
|
||||||
|
using previews_type = std::map<std::filesystem::path, preview_type>;
|
||||||
|
|
||||||
|
Markers(
|
||||||
|
const std::filesystem::path& markers_folder,
|
||||||
|
config::Config& config
|
||||||
|
);
|
||||||
|
|
||||||
|
void load_marker(const std::filesystem::path& chosen);
|
||||||
|
|
||||||
|
const marker_type& get_chosen_marker() const;
|
||||||
|
|
||||||
|
previews_type::const_iterator cbegin() const;
|
||||||
|
previews_type::const_iterator cend() const;
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
void display_debug();
|
||||||
|
private:
|
||||||
|
std::filesystem::path markers_folder;
|
||||||
|
config::Config& config;
|
||||||
|
|
||||||
|
// Markers
|
||||||
|
marker_type chosen_marker;
|
||||||
|
std::tuple<std::filesystem::path, std::future<marker_type>> marker_loader;
|
||||||
|
static marker_type load_default_marker(
|
||||||
|
const std::optional<std::filesystem::path>& marker_path_from_config,
|
||||||
|
const std::filesystem::path& markers_folder
|
||||||
|
);
|
||||||
|
static marker_type load_marker_async(
|
||||||
|
const std::filesystem::path& chosen,
|
||||||
|
const std::filesystem::path& markers
|
||||||
|
);
|
||||||
|
std::vector<std::future<void>> discarded_markers;
|
||||||
|
static void discard_marker(std::future<marker_type>&& future);
|
||||||
|
|
||||||
|
previews_type previews;
|
||||||
|
std::map<std::filesystem::path, std::future<preview_type>> preview_loaders;
|
||||||
|
|
||||||
|
static preview_type load_marker_preview(const std::filesystem::path& folder);
|
||||||
|
};
|
@ -27,6 +27,7 @@ sources += files(
|
|||||||
'long_note_dummy.cpp',
|
'long_note_dummy.cpp',
|
||||||
'main.cpp',
|
'main.cpp',
|
||||||
'marker.cpp',
|
'marker.cpp',
|
||||||
|
'markers.cpp',
|
||||||
'mp3_reader.cpp',
|
'mp3_reader.cpp',
|
||||||
'note.cpp',
|
'note.cpp',
|
||||||
'notification.cpp',
|
'notification.cpp',
|
||||||
|
Loading…
Reference in New Issue
Block a user