Files
punchie-engine/src/AssetManager.c
T
abdelrahman 3f71cf0f3f Connected the AssetManager to the GameEngine and added function in the
GameEngine API to allow for loading and removing assets as well as rendering
textures using their AssetID
2022-09-23 04:39:17 +01:00

204 lines
4.1 KiB
C

#include "AssetManager.h"
#include "Renderer.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
#include "SDL_render.h"
#include "constants.h"
#include "reusable_ids.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef struct asset {
AssetType type;
char *path;
union {
SDL_Texture *texture;
Mix_Chunk *chunk;
Mix_Music *music;
} data;
} Asset;
struct asset_manager {
size_t count;
size_t deleted_count;
AssetID reusable_ids[MAX_ASSET_COUNT];
Asset assets[MAX_ASSET_COUNT];
};
AssetManager *create_asset_manager() {
AssetManager *am = (AssetManager *)malloc(sizeof(AssetManager));
if (!am) {
return NULL;
}
am->count = 0;
am->deleted_count = 0;
memset(am->reusable_ids, 0, sizeof(am->reusable_ids));
memset(am->assets, 0, sizeof(am->assets));
return am;
}
AssetID load_asset_to_manager(AssetManager *am, const char *path,
AssetType type, Renderer *renderer) {
if (!am || type == ASSET_TYPE_COUNT) {
return -1;
}
Asset asset = {};
bool loaded = true;
// TODO (Abdelrahman): Implement a way to make sure that an asset with the
// same path is not already loaded. If the user attempts to load an asset
// that already exists, the function should return -1 to indicate an error
switch (type) {
case ASSET_TYPE_IMAGE:
if (!renderer) {
loaded = false;
break;
}
asset.data.texture = load_texture(renderer, path);
if (!(asset.data.texture)) {
loaded = false;
}
break;
case ASSET_TYPE_AUDIO_FX:
// TODO (Abdelrahman): Implement loading audio chunks
break;
case ASSET_TYPE_MUSIC:
// TODO (Abdelrahman): Implement loading music
break;
default:
loaded = false;
break;
}
if (!loaded) {
return -1;
}
AssetID id;
if (am->deleted_count > 0) {
id = (AssetID)reuse_id((int32_t *)am->reusable_ids, am->deleted_count);
am->deleted_count -= 1;
am->count += 1;
} else {
id = (am->count)++;
}
am->assets[id].type = type;
am->assets[id].path = (char *)malloc(strlen(path) + 1);
strcpy(am->assets[id].path, path);
am->assets[id].data = asset.data;
switch (type) {
case ASSET_TYPE_IMAGE:
asset.data.texture = NULL;
break;
case ASSET_TYPE_AUDIO_FX:
asset.data.chunk = NULL;
break;
case ASSET_TYPE_MUSIC:
asset.data.music = NULL;
break;
default:
break;
}
return id;
}
void remove_asset_from_manager(AssetManager *am, AssetID id) {
if (!am || am->count == 0) {
return;
}
free(am->assets[id].path);
am->assets[id].path = 0;
switch (am->assets[id].type) {
case ASSET_TYPE_IMAGE:
SDL_DestroyTexture(am->assets[id].data.texture);
am->assets[id].data.texture = NULL;
break;
case ASSET_TYPE_AUDIO_FX:
// TODO (Abdelrahman): Implement closing audio chunk
break;
case ASSET_TYPE_MUSIC:
// TODO (Abdelrahman): Implement closing music
break;
default:
break;
}
am->reusable_ids[(am->deleted_count)++] = id;
am->count -= 1;
}
SDL_Texture *get_texture(AssetManager *am, AssetID id) {
if (am->assets[id].type != ASSET_TYPE_IMAGE) {
return NULL;
}
return am->assets[id].data.texture;
}
Mix_Chunk *get_audio_chunk(AssetManager *am, AssetID id) {
if (am->assets[id].type != ASSET_TYPE_AUDIO_FX) {
return NULL;
}
return am->assets[id].data.chunk;
}
Mix_Music *get_music(AssetManager *am, AssetID id) {
if (am->assets[id].type != ASSET_TYPE_MUSIC) {
return NULL;
}
return am->assets[id].data.music;
}
void destroy_asset_manager(AssetManager *am) {
if (!am) {
return;
}
for (size_t i = 0; i < am->count; ++i) {
free(am->assets[i].path);
am->assets[i].path = NULL;
switch (am->assets[i].type) {
case ASSET_TYPE_IMAGE:
SDL_DestroyTexture(am->assets[i].data.texture);
am->assets[i].data.texture = NULL;
break;
case ASSET_TYPE_AUDIO_FX:
// TODO (Abdelrahman): Implement closing audio chunk
break;
case ASSET_TYPE_MUSIC:
// TODO (Abdelrahman): Implement closing music
break;
default:
break;
}
}
am->count = 0;
am->deleted_count = 0;
free(am);
am = NULL;
}