AssetManager.cxx 3.2 KB

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