AssetManager.cxx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #include "AssetManager.hxx"
  2. #include <cassert>
  3. #include <filesystem>
  4. #include <SDL_image.h>
  5. AssetManager* AssetManager::instance_ = nullptr;
  6. AssetManager::AssetManager(SDLRenderer& renderer)
  7. :renderer_{renderer}
  8. {
  9. namespace fs = std::filesystem;
  10. assert(instance_==nullptr);
  11. auto const current_path = fs::current_path();
  12. auto const asset_directory =
  13. fs::exists(current_path/"assets")
  14. ? current_path/"assets"
  15. : fs::exists(current_path.parent_path()/"assets")
  16. ? current_path.parent_path()/"assets"
  17. : fs::path{};
  18. if (asset_directory.empty()) {
  19. throw std::runtime_error("Assets directory not found.");
  20. }
  21. total_assets_ = std::distance(fs::directory_iterator(asset_directory),
  22. fs::directory_iterator());
  23. loading_thread_ = std::thread{&AssetManager::load_assets, this, asset_directory};
  24. instance_ = this;
  25. }
  26. AssetManager::~AssetManager()
  27. {
  28. assert(instance_!=nullptr);
  29. if (loading_thread_.joinable()) {
  30. loading_thread_.join();
  31. }
  32. for (auto const& kv: surface_assets_) {
  33. SDL_FreeSurface(kv.second);
  34. }
  35. for (auto const& kv: texture_assets_) {
  36. SDL_DestroyTexture(kv.second);
  37. SDL_Log("Unloaded texture %s successfully.", kv.first.c_str());
  38. }
  39. for (auto const& kv: font_assets_) {
  40. TTF_CloseFont(kv.second);
  41. SDL_Log("Unloaded font %s successfully.", kv.first.c_str());
  42. }
  43. instance_ = nullptr;
  44. }
  45. void AssetManager::load_assets(std::filesystem::path const& asset_directory)
  46. {
  47. for (auto const& entry: std::filesystem::directory_iterator(asset_directory)) {
  48. auto const path = entry.path().string();
  49. auto const ext = entry.path().extension();
  50. auto const filename = entry.path().filename().string();
  51. if (ext==".png" || ext==".jpg") {
  52. auto const surface = IMG_Load(path.c_str());
  53. if (surface==nullptr) {
  54. throw SDLError{"Failed to load texture "+path+"."};
  55. }
  56. surface_assets_[filename] = surface;
  57. SDL_Log("Loaded texture %s successfully.", filename.c_str());
  58. }
  59. else if (ext==".ttf") {
  60. auto const font = TTF_OpenFont(path.c_str(), 42);
  61. if (font==nullptr) {
  62. throw SDLError{"Failed to load font "+path+"."};
  63. }
  64. font_assets_[filename] = font;
  65. SDL_Log("Loaded font %s successfully.", filename.c_str());
  66. }
  67. ++assets_loaded_;
  68. }
  69. }
  70. float AssetManager::get_progress() const
  71. {
  72. return static_cast<float>(assets_loaded_)/static_cast<float>(total_assets_);
  73. }
  74. SDL_Texture* AssetManager::get_texture_asset(std::string const& filepath)
  75. {
  76. auto const it = texture_assets_.find(filepath);
  77. if (it==std::end(texture_assets_)) {
  78. auto const surf_it = surface_assets_.find(filepath);
  79. if (surf_it==std::end(surface_assets_))
  80. return nullptr;
  81. auto const texture = SDL_CreateTextureFromSurface(renderer_, surf_it->second);
  82. texture_assets_[filepath] = texture;
  83. SDL_FreeSurface(surf_it->second);
  84. surface_assets_.erase(surf_it);
  85. return texture;
  86. }
  87. return it->second;
  88. }
  89. TTF_Font* AssetManager::get_font_asset(std::string const& filepath)
  90. {
  91. return font_assets_[filepath];
  92. }
  93. AssetManager& AssetManager::instance() noexcept
  94. {
  95. assert(instance_!=nullptr);
  96. return *instance_;
  97. }