10 #include <ST_loaders/loaders.hpp>
11 #include <assets_manager.hpp>
13 static bool singleton_initialized =
false;
23 gTask_manager(gTask_manager) {
25 if (singleton_initialized) {
26 throw std::runtime_error(
"The assets manager cannot be initialized more than once!");
28 singleton_initialized =
true;
32 gMessage_bus.
subscribe(LOAD_LIST, &msg_sub);
33 gMessage_bus.
subscribe(UNLOAD_LIST, &msg_sub);
34 gMessage_bus.
subscribe(LOAD_ASSET, &msg_sub);
35 gMessage_bus.
subscribe(UNLOAD_ASSET, &msg_sub);
36 gMessage_bus.
subscribe(LOAD_BINARY, &msg_sub);
39 load_assets_from_list(
"assets_internal/assets_internal.list");
40 load_assets_from_list(
"game/levels/assets_global.list");
50 self->handle_messages();
57 void assets_manager::handle_messages() {
59 while (temp !=
nullptr) {
60 auto path = *
static_cast<std::string *
>(temp->
get_data());
61 switch (temp->msg_name) {
63 load_assets_from_list(path);
66 unload_assets_from_list(path);
69 if (load_asset(path) == 0) {
75 if (unload_asset(path) == 0) {
81 load_assets_from_binary(path);
94 int8_t assets_manager::load_assets_from_binary(
const std::string &path) {
95 ST::assets_named *assets1 = ST::unpack_binary(path);
96 if (assets1 !=
nullptr) {
97 for (
const auto &surface: assets1->surfaces) {
98 if (count[surface.first] == 0) {
99 gMessage_bus.
send_msg(
new message(LOG_SUCCESS, make_data<std::string>(
"Unpacking " + surface.first)));
100 uint16_t hashed = ST::hash_string(surface.first);
101 all_assets.surfaces[hashed] = surface.second;
103 ++count[surface.first];
105 for (
const auto &chunk: assets1->chunks) {
106 if (count[chunk.first] == 0) {
107 gMessage_bus.
send_msg(
new message(LOG_SUCCESS, make_data<std::string>(
"Unpacking " + chunk.first)));
108 uint16_t hashed = ST::hash_string(chunk.first);
109 all_assets.chunks[hashed] = chunk.second;
111 ++count[chunk.first];
113 for (
const auto &music: assets1->music) {
114 if (count[music.first] == 0) {
115 gMessage_bus.
send_msg(
new message(LOG_SUCCESS, make_data<std::string>(
"Unpacking " + music.first)));
116 count[music.first]++;
117 uint16_t hashed = ST::hash_string(music.first);
118 all_assets.music[hashed] = music.second;
120 ++count[music.first];
134 int8_t assets_manager::unload_assets_from_binary(
const std::string &path) {
135 ST::assets_named *assets1 = ST::unpack_binary(path);
136 if (assets1 !=
nullptr) {
137 for (
const auto &surface: assets1->surfaces) {
138 unload_asset(surface.first);
139 SDL_FreeSurface(surface.second);
141 for (
const auto &chunk: assets1->chunks) {
142 unload_asset(chunk.first);
143 Mix_FreeChunk(chunk.second);
145 for (
const auto &music: assets1->music) {
146 unload_asset(music.first);
147 Mix_FreeMusic(music.second);
156 void assets_manager::send_assets() {
157 gMessage_bus.
send_msg(
new message(SURFACES_ASSETS, make_data(&all_assets.surfaces)));
158 gMessage_bus.
send_msg(
new message(FONTS_ASSETS, make_data(&all_assets.fonts)));
159 gMessage_bus.
send_msg(
new message(CHUNKS_ASSETS, make_data(&all_assets.chunks)));
160 gMessage_bus.
send_msg(
new message(MUSIC_ASSETS, make_data(&all_assets.music)));
169 int8_t assets_manager::load_asset(std::string path) {
171 if (path.at(0) ==
'#') {
176 auto _asset_count = count.find(ST::trim_path(path));
177 if (_asset_count != count.end() && _asset_count->second > 0) {
178 ++_asset_count->second;
180 }
else if (_asset_count == count.end()) {
181 count.emplace(ST::trim_path(path), 0);
184 ST::asset_file_type extension = ST::get_file_extension(path);
187 if (extension == ST::asset_file_type::BIN) {
188 gMessage_bus.
send_msg(
new message(LOG_INFO, make_data<std::string>(
"Loading from binary " + path)));
190 gMessage_bus.
send_msg(
new message(LOG_INFO, make_data<std::string>(
"Loading " + path)));
193 if (extension == ST::asset_file_type::PNG || extension == ST::asset_file_type::WEBP) {
194 SDL_Surface *temp1 = IMG_Load(path.c_str());
195 if (temp1 !=
nullptr) {
196 path = ST::trim_path(path);
197 uint16_t string_hash = ST::hash_string(path);
198 all_assets.surfaces[string_hash] = temp1;
201 gMessage_bus.
send_msg(
new message(LOG_ERROR, make_data<std::string>(
"File " + path +
" not found")));
204 }
else if (extension == ST::asset_file_type::WAV) {
205 Mix_Chunk *temp1 = Mix_LoadWAV(path.c_str());
206 if (temp1 !=
nullptr) {
207 path = ST::trim_path(path);
208 uint16_t string_hash = ST::hash_string(path);
209 all_assets.chunks[string_hash] = temp1;
212 gMessage_bus.
send_msg(
new message(LOG_ERROR, make_data<std::string>(
"File " + path +
" not found")));
215 }
else if (extension == ST::asset_file_type::OGG) {
216 Mix_Music *temp1 = Mix_LoadMUS(path.c_str());
217 if (temp1 !=
nullptr) {
218 path = ST::trim_path(path);
219 uint16_t string_hash = ST::hash_string(path);
220 all_assets.music[string_hash] = temp1;
223 gMessage_bus.
send_msg(
new message(LOG_ERROR, make_data<std::string>(
"File " + path +
" not found")));
226 }
else if (extension == ST::asset_file_type::BIN) {
227 load_assets_from_binary(path);
229 std::vector<std::string> result;
230 std::istringstream iss(path);
231 for (std::string path_; iss >> path;) {
232 result.push_back(path);
236 std::stringstream convert(result.at(1));
238 }
catch (
const std::out_of_range &e) {
240 gMessage_bus.
send_msg(
new message(LOG_ERROR, make_data<std::string>(
"Font size not specified!")));
243 std::string font = result.at(0);
245 TTF_Font *tempFont = TTF_OpenFont(font.c_str(), size);
246 if (tempFont !=
nullptr) {
247 font = ST::trim_path(font);
248 std::string font_and_size = font +
" " + result.at(1);
249 all_assets.fonts[ST::hash_string(font_and_size)] = tempFont;
250 ++count.at(font_and_size);
252 gMessage_bus.
send_msg(
new message(LOG_ERROR, make_data<std::string>(
"File " + font +
" not found!")));
264 int8_t assets_manager::load_assets_from_list(
const std::string &path) {
266 file.open(path.c_str());
267 if (file.is_open()) {
269 while (!file.eof()) {
277 gMessage_bus.
send_msg(
new message(LOG_ERROR, make_data<std::string>(
"File " + path +
" not found")));
289 int8_t assets_manager::unload_assets_from_list(
const std::string &path) {
291 file.open(path.c_str());
292 if (file.is_open()) {
294 while (!file.eof()) {
298 if (path.at(0) !=
'#') {
305 gMessage_bus.
send_msg(
new message(LOG_ERROR, make_data<std::string>(
"File " + path +
" not found")));
317 int8_t assets_manager::unload_asset(std::string path) {
318 auto _asset_count = count.find(ST::trim_path(path));
319 if (_asset_count != count.end() && _asset_count->second > 1) {
320 --_asset_count->second;
322 }
else if ((_asset_count == count.end() || _asset_count->second == 0) &&
323 ST::get_file_extension(path) != ST::asset_file_type::BIN) {
327 ST::asset_file_type extension = ST::get_file_extension(path);
328 gMessage_bus.
send_msg(
new message(LOG_INFO, make_data<std::string>(
"Unloading " + path)));
330 if (extension == ST::asset_file_type::PNG || extension == ST::asset_file_type::WEBP) {
331 path = ST::trim_path(path);
332 uint16_t string_hash = ST::hash_string(path);
333 SDL_FreeSurface(all_assets.surfaces[string_hash]);
334 all_assets.surfaces[string_hash] =
nullptr;
336 }
else if (extension == ST::asset_file_type::WAV) {
337 path = ST::trim_path(path);
338 uint16_t string_hash = ST::hash_string(path);
339 Mix_FreeChunk(all_assets.chunks[string_hash]);
340 all_assets.chunks[string_hash] =
nullptr;
342 }
else if (extension == ST::asset_file_type::OGG) {
343 path = ST::trim_path(path);
344 uint16_t string_hash = ST::hash_string(path);
345 Mix_FreeMusic(all_assets.music[string_hash]);
346 all_assets.music[string_hash] =
nullptr;
348 }
else if (extension == ST::asset_file_type::BIN) {
349 return unload_assets_from_binary(path);
351 path = ST::trim_path(path);
352 TTF_CloseFont(all_assets.fonts[ST::hash_string(path)]);
353 all_assets.fonts[ST::hash_string(path)] =
nullptr;
364 for (
auto &i: count) {
367 unload_asset(i.first);
370 singleton_initialized =
false;
An object representing a task to be run by the task manager.
This object is responsible for loading/unloading assets.
assets_manager(message_bus &gMessageBus, task_manager &tsk_mngr)
static void update_task(void *arg)
The central messaging system of the engine. All subsystem make extensive use of it.
void subscribe(uint8_t msg, subscriber *sub)
void send_msg(message *msg)
A message object passed around in the message bus. Holds anything created with make_data<>().
message * get_next_message()
The Task Manager handles all things multi-threaded in the engine.
void start_task_lockfree(ST::task *arg)