#include "asset_manager.h" #include #include #include #include #include "linked_list.h" #include "memory_alloc.h" #include "display.h" asset_t *create_asset(asset_type_t asset_type) { asset_t *asset = malloc(sizeof(asset_t)); asset->type = asset_type; asset->nb_refs = 1; return asset; } void destroy_asset(asset_t *asset) { free(asset->name); switch(asset->type) { case ASSET_TEXTURE: SDL_DestroyTexture(asset->data.texture); default: break; } free(asset); } void destroy_asset_header_def(asset_header_def_t *asset_header_def) { free(asset_header_def->name); free(asset_header_def); } void asset_manager_init(asset_manager_t *asset_manager) { linked_list_init(&asset_manager->assets, sizeof(asset_t), (deleter_t)destroy_asset); linked_list_init(&asset_manager->assets_header_defs, sizeof(asset_header_def_t), (deleter_t)destroy_asset_header_def); asset_manager->asset_file = fopen(ASSET_FILE_NAME, "rb"); if(!asset_manager->asset_file) { printf("can't open asset file : %s.\n", ASSET_FILE_NAME); return; } size_t nb_assets; size_t ret = fread(&nb_assets, sizeof(nb_assets), 1, asset_manager->asset_file); if(ret != 1) { printf("can't read asset file."); return; } for(size_t i = 0; i < nb_assets; i++) { elem_t *elem = elem_create(&asset_manager->assets_header_defs); size_t cap = 0; ret = getdelim(&((asset_header_def_t *)elem->data)->name, &cap, '\0', asset_manager->asset_file); if(ret == SIZE_MAX) { printf("can't read asset file."); return; } ret = fread(&((asset_header_def_t *)elem->data)->start, sizeof(((asset_header_def_t *)elem->data)->start), 1, asset_manager->asset_file); if(ret != 1) { printf("can't read asset file."); return; } linked_list_push_back_elem(&asset_manager->assets_header_defs, elem); } } void asset_manager_exit(asset_manager_t *asset_manager) { linked_list_clear(&asset_manager->assets_header_defs); linked_list_clear(&asset_manager->assets); fclose(asset_manager->asset_file); } // Only for this file // No args static inline bool condition_is_asset_unused(elem_t *elem, va_list args __attribute__((unused))) { return !((asset_t *)elem->data)->nb_refs; } inline void asset_manager_collect_garbage(asset_manager_t *asset_manager) { linked_list_remove_if(&asset_manager->assets, condition_is_asset_unused); } // Only for this file // Arg : const char *asset_name static inline bool condition_is_asset_name(elem_t *elem, va_list args) { return !strcmp(((asset_t *)elem->data)->name, va_arg(args, const char *)); } //Only for this file // Arg : const char *asset_name static inline bool condition_is_asset_header_def_name(elem_t *elem, va_list args) { return !strcmp(((asset_header_def_t *)elem->data)->name, va_arg(args, const char *)); } static inline void load_texture(asset_manager_t *asset_manager, asset_t *asset, asset_header_def_t *asset_header_def) { if(fseek(asset_manager->asset_file, asset_header_def->start, SEEK_SET)) { printf("Couldn't seek in asset file."); return; } size_t width, height; if(fread(&width, sizeof(width), 1, asset_manager->asset_file) != 1) { printf("Failed to read in asset file."); return; } if(fread(&height, sizeof(height), 1, asset_manager->asset_file) != 1) { printf("Failed to read in asset file."); return; } SDL_Surface *tmp_surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 16, SDL_PIXELFORMAT_RGB565); if(SDL_LockSurface(tmp_surface)) { printf("Couldn't lock surface : %s\n", SDL_GetError()); return; } if(fread(tmp_surface->pixels, sizeof(uint16_t), width * height, asset_manager->asset_file) != width * height) { printf("Failed to read asset file."); return; } SDL_SetColorKey(tmp_surface, SDL_TRUE, SDL_MapRGB(tmp_surface->format, 0xFF, 0x00, 0xFF)); asset->data.texture = SDL_CreateTextureFromSurface(renderer, tmp_surface); SDL_FreeSurface(tmp_surface); } void asset_manager_load_asset(asset_manager_t *asset_manager, const char *asset_name, asset_type_t asset_type) { asset_t *asset = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name); if(asset) { asset->nb_refs++; return; } asset_header_def_t *asset_header_def = linked_list_get_if(&asset_manager->assets_header_defs, condition_is_asset_header_def_name, asset_name); if(!asset_header_def) { printf("Asset doesn't exist in asset file : %s\n", asset_name); return; } asset = create_asset(asset_type); asset->name = malloc(strlen(asset_name) + 1); strcpy(asset->name, asset_name); asset->type = asset_type; switch(asset_type) { case ASSET_TEXTURE: load_texture(asset_manager, asset, asset_header_def); break; default: return; } linked_list_push_back(&asset_manager->assets, asset); } void asset_manager_let_go_asset(asset_manager_t *asset_manager, const char *asset_name) { asset_t *asset = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name); if(asset) { asset->nb_refs--; } } texture_t *asset_manager_get_texture(asset_manager_t *asset_manager, const char *asset_name) { asset_t *asset = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name); if(!asset) return NULL; if(asset->type != ASSET_TEXTURE) return NULL; return asset->data.texture; } void asset_manager_draw_texture(texture_t *texture, rect_t *src_rect, rect_t *dst_rect, bool flip __attribute__((unused))) { SDL_RenderCopy(renderer, texture, src_rect, dst_rect); }