async texture loading
This commit is contained in:
parent
2391ab7c13
commit
41c638c050
7
TODO.md
7
TODO.md
@ -2,7 +2,7 @@
|
||||
## Music Select Screen
|
||||
### TODO
|
||||
- Song Panel draw
|
||||
- async song cover loading
|
||||
|
||||
- Song Panel click
|
||||
- Chart Panel
|
||||
- Visible controls
|
||||
@ -12,6 +12,8 @@
|
||||
|
||||
### Done
|
||||
- Category Panel click
|
||||
- Song Panel draw
|
||||
- async song cover loading
|
||||
|
||||
## Gameplay Screen
|
||||
|
||||
@ -25,6 +27,9 @@
|
||||
# v1.1.0
|
||||
## FB9 Support
|
||||
|
||||
## Music Select Screen
|
||||
- bound memory usage of Textures::Autoloader
|
||||
|
||||
# v1.2.0
|
||||
|
||||
## P4IO Support
|
||||
|
@ -10,6 +10,8 @@ foreach module : ['system', 'window', 'graphics', 'audio']
|
||||
sfml += [dependency('sfml-'+module, version : '>=2.5.1')]
|
||||
endforeach
|
||||
|
||||
thread_dep = dependency('threads')
|
||||
|
||||
add_project_link_arguments(['-lstdc++', '-lstdc++fs', '-lm', '-lGL'], language : 'cpp')
|
||||
|
||||
sources = [
|
||||
@ -53,7 +55,7 @@ sources = [
|
||||
executable(
|
||||
'jujube',
|
||||
sources,
|
||||
dependencies: [sfml],
|
||||
dependencies: [sfml, thread_dep],
|
||||
include_directories : include_directories('include', 'include/imgui', 'include/imgui-sfml'),
|
||||
cpp_args : [
|
||||
'-Wall',
|
||||
|
@ -1,27 +1,66 @@
|
||||
#include "Autoloader.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
void Textures::Autoloader::load(const fs::path& t_path) {
|
||||
if (m_mapping.find(t_path) != m_mapping.end()) {
|
||||
void Textures::Autoloader::load(const fs::path& path) {
|
||||
if (has(path) or is_loading(path)) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::unique_lock lock{m_is_loading_mutex};
|
||||
m_is_loading.insert(path);
|
||||
}
|
||||
auto texture = std::make_shared<sf::Texture>();
|
||||
if (!texture->loadFromFile(t_path)) {
|
||||
throw std::invalid_argument("Unable to load cover image : "+t_path.string());
|
||||
if (!texture->loadFromFile(path)) {
|
||||
throw std::invalid_argument("Unable to load cover image : "+path.string());
|
||||
}
|
||||
texture->setSmooth(true);
|
||||
m_mapping[t_path] = texture;
|
||||
}
|
||||
|
||||
std::shared_ptr<sf::Texture> Textures::Autoloader::get(const fs::path& t_path) {
|
||||
if (m_mapping.find(t_path) == m_mapping.end()) {
|
||||
this->load(t_path);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock_mapping{m_mapping_mutex, std::defer_lock};
|
||||
std::unique_lock<std::shared_mutex> lock_is_loading{m_is_loading_mutex, std::defer_lock};
|
||||
std::lock(lock_mapping, lock_is_loading);
|
||||
m_mapping.emplace(path, texture);
|
||||
m_is_loading.erase(path);
|
||||
}
|
||||
return m_mapping.at(t_path);
|
||||
std::cout << "Loaded " << path << std::endl;
|
||||
}
|
||||
|
||||
bool Textures::Autoloader::has(const fs::path& t_path) {
|
||||
return m_mapping.find(t_path) != m_mapping.end();
|
||||
void Textures::Autoloader::async_load(const fs::path& path) {
|
||||
std::thread t(&Textures::Autoloader::load, this, path);
|
||||
t.detach();
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<sf::Texture>> Textures::Autoloader::async_get(const fs::path& path) {
|
||||
if (not has(path)) {
|
||||
if (not is_loading(path)) {
|
||||
async_load(path);
|
||||
}
|
||||
return {};
|
||||
} else {
|
||||
return get(path);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<sf::Texture>> Textures::Autoloader::get(const fs::path& path) {
|
||||
std::shared_lock lock{m_mapping_mutex};
|
||||
if (has(path)) {
|
||||
return m_mapping.at(path);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Textures::Autoloader::has(const fs::path& path) {
|
||||
std::shared_lock lock{m_mapping_mutex};
|
||||
return m_mapping.find(path) != m_mapping.end();
|
||||
}
|
||||
|
||||
bool Textures::Autoloader::is_loading(const fs::path& path) {
|
||||
std::shared_lock lock{m_is_loading_mutex};
|
||||
return m_is_loading.find(path) != m_is_loading.end();
|
||||
}
|
||||
|
@ -3,8 +3,10 @@
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
@ -21,14 +23,20 @@ namespace std {
|
||||
}
|
||||
|
||||
namespace Textures {
|
||||
// Loads textures on demand and stores them in a map for easy path-based access
|
||||
// Loads textures asynchronously (in the background) on demand and stores them in a map for easy path-based access
|
||||
class Autoloader {
|
||||
public:
|
||||
Autoloader() = default;
|
||||
std::shared_ptr<sf::Texture> get(const fs::path& t_path);
|
||||
void load(const fs::path& t_path);
|
||||
bool has(const fs::path& t_path);
|
||||
std::optional<std::shared_ptr<sf::Texture>> async_get(const fs::path& path);
|
||||
std::optional<std::shared_ptr<sf::Texture>> get(const fs::path& path);
|
||||
void load(const fs::path& path);
|
||||
void async_load(const fs::path& path);
|
||||
bool has(const fs::path& path);
|
||||
bool is_loading(const fs::path& path);
|
||||
private:
|
||||
std::unordered_map<fs::path, std::shared_ptr<sf::Texture>> m_mapping;
|
||||
std::shared_mutex m_mapping_mutex;
|
||||
std::unordered_set<fs::path> m_is_loading;
|
||||
std::shared_mutex m_is_loading_mutex;
|
||||
};
|
||||
}
|
@ -68,11 +68,13 @@ void MusicSelect::SongPanel::click(Ribbon& ribbon, std::size_t from_button_index
|
||||
|
||||
void MusicSelect::SongPanel::draw(Resources& resources, sf::RenderTarget& target, sf::FloatRect area) {
|
||||
sf::Sprite cover;
|
||||
sf::Texture& cover_texture = resources.fallback_cover;
|
||||
cover.setTexture(resources.fallback_cover);
|
||||
if (m_song.cover) {
|
||||
cover_texture = *resources.covers.get(m_song.folder/m_song.cover.value());
|
||||
auto loaded_texture = resources.covers.async_get(m_song.folder/m_song.cover.value());
|
||||
if (loaded_texture) {
|
||||
cover.setTexture(**loaded_texture, true);
|
||||
}
|
||||
}
|
||||
cover.setTexture(cover_texture);
|
||||
auto bounds = cover.getGlobalBounds();
|
||||
cover.setPosition(area.left, area.top);
|
||||
cover.setScale(area.width / bounds.width, area.width / bounds.width);
|
||||
|
Loading…
x
Reference in New Issue
Block a user