AssetManager.cxx 3.8 KB

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