AssetManager.cxx 3.3 KB

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