assets now integrate Asset trait

This commit is contained in:
Sara 2023-11-06 21:16:21 +01:00
parent 6e61a7666a
commit 63713a59e7
6 changed files with 94 additions and 91 deletions

View file

@ -1,21 +1,13 @@
#include "assets.h"
#include "debug.h"
#include "list.h"
#include <stdlib.h>
#include <memory.h>
#include <stdio.h>
typedef
struct AssetData {
void* asset;
asset_id id;
AssetDestructor destructor;
} AssetData;
cJSON* g_levels_json;
static AssetData* _assets = NULL;
static size_t _assets_len = 0;
static size_t _assets_cap = 0;
static List _assets;
static asset_id _next_id = 0;
static
@ -34,26 +26,9 @@ void read_file(FILE* fp, char* out_buffer, size_t out_size) {
fseek(fp, start, SEEK_SET);
}
static
void _resize_if_needed(size_t requested_len) {
if(requested_len < _assets_cap) {
return; // not needed.
}
size_t new_cap = _assets_cap ? _assets_cap : 8;
while(new_cap < requested_len) {
new_cap *= 2;
}
AssetData* new_assets = realloc(_assets, new_cap * sizeof(AssetData));
if(new_assets != NULL) {
_assets = new_assets;
_assets_cap = new_cap;
}
}
void assets_init() {
LOG_INFO("assets_init");
_assets = malloc(_assets_cap * sizeof(AssetData));
_assets = list_from_type(Asset);
_next_id = 1;
g_levels_json = load_json_from_file("assets/levels/levels.ldtk");
@ -62,59 +37,40 @@ void assets_init() {
// clear all assets without shrinking the assets array.
static
void _empty_assets() {
AssetData* start = _assets;
AssetData* end = _assets + _assets_len;
for(AssetData* asset = start; asset < end; ++asset) {
asset->destructor(asset->asset);
list_foreach(Asset*, asset, &_assets) {
asset->drop->drop(asset->data);
}
_assets_len = 0;
list_empty(&_assets);
}
void assets_clean() {
_empty_assets();
free(_assets);
_assets_len = 0;
_assets_cap = 0;
_assets = NULL;
cJSON_Delete(g_levels_json);
g_levels_json = NULL;
}
void assets_reset() {
_empty_assets();
size_t desired = 8;
AssetData* new = realloc(_assets, desired * sizeof(AssetData));
if(new == NULL)
return;
_assets_cap = desired;
_assets = new;
}
asset_id store_asset(void* asset, AssetDestructor destructor) {
_resize_if_needed(_assets_len + 1);
AssetData* data = _assets + _assets_len;
data->asset = asset;
data->destructor = destructor;
data->id = _next_id;
++_next_id;
++_assets_len;
return data->id;
asset_id store_asset(Asset asset) {
list_reserve(&_assets, _assets.len + 1);
size_t index = list_add(&_assets, &asset);
Asset* new_asset = list_at_as(Asset, &_assets, index);
asset_id id = _next_id++;
new_asset->tc->set_id(new_asset->data, id);
asset_id actual_id = new_asset->tc->get_id(new_asset->data);
ASSERT_RETURN(actual_id == id,actual_id, "ID stored in asset not the same as the expected id");
return actual_id;
}
static
AssetData* _internal_get_by_id(asset_id id) {
Asset* _internal_get_by_id(asset_id id) {
ASSERT_RETURN_WARN(id != 0, NULL, "Cannot get element with id 0");
for(size_t i = 0; i < _assets_len; ++i) {
if(_assets[i].id == id) {
return _assets + i;
list_foreach(Asset*, asset, &_assets) {
if(asset->tc->get_id(asset->data) == id) {
return asset;
}
}
@ -122,16 +78,15 @@ AssetData* _internal_get_by_id(asset_id id) {
}
void* get_asset(asset_id id) {
AssetData* found = _internal_get_by_id(id);
Asset* found = _internal_get_by_id(id);
ASSERT_RETURN(found != NULL, NULL, "Failed to find asset with id %zu.", id);
return found;
return found->data;
}
asset_id get_asset_id(void* asset) {
for(size_t i = 0; i < _assets_len; ++i) {
if(_assets[i].asset == asset) {
return _assets[i].id;
list_foreach(Asset*, asset, &_assets) {
if(asset->data == asset) {
return asset->tc->get_id(asset->data);
}
}
@ -139,16 +94,20 @@ asset_id get_asset_id(void* asset) {
}
void free_asset(asset_id id) {
AssetData* found = _internal_get_by_id(id);
Asset* found;
size_t found_index;
for(size_t i = 0; i < _assets.len; ++i) {
found = list_at_as(Asset, &_assets, i);
if(found->tc->get_id(found->data) == id) {
found_index = i;
break;
} else {
found = NULL;
}
}
ASSERT_RETURN(found != NULL,, "Attempt to free nonexistent asset.");
found->destructor(found->asset);
AssetData* next = found + 1;
size_t dif = next - (_assets + _assets_len);
memmove(found, next, dif);
--_assets_len;
found->drop->drop(found->data);
list_erase(&_assets, found_index);
}
cJSON* load_json_from_file(const char* filename) {

View file

@ -2,11 +2,12 @@
#define _fencer_assets_h
#include "vmath.h"
#include "drop.h"
#include "asset.h"
#include <cjson/cJSON.h>
#include <stdint.h>
typedef void(*AssetDestructor)(void*);
typedef uintptr_t asset_id;
extern cJSON* g_levels_json;
@ -19,7 +20,7 @@ void assets_clean();
void assets_reset();
// Submit an object to be managed as an asset. If the destructor is NULL, free will be used.
// Returns zero if asset could not be stored.
asset_id store_asset(void* asset, AssetDestructor destructor);
asset_id store_asset(Asset drop);
// Get an asset already submitted to the asset manager.
// Returns 0 if asset does not exist.
void* get_asset(asset_id id);

View file

@ -20,15 +20,11 @@ struct Level {
Vector player_start;
};
static
void _deallocate_level(void* self_void) {
Level* self = self_void;
void _internal_level_destroy(Level* self) {
for(size_t map_index = 0; map_index < self->tilemaps_len; ++map_index) {
physics_world_remove_map(self->tilemaps[map_index]);
tilemap_destroy(self->tilemaps[map_index]);
}
free(self);
}
@ -62,7 +58,7 @@ Level* level_from_json(cJSON* json) {
Level* self = malloc(sizeof(Level));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate level object.");
*self = (Level) {
.asset_id = store_asset(self, &_deallocate_level),
.asset_id = 0,
.transform = IdentityTransform
};
@ -98,6 +94,7 @@ Level* level_from_json(cJSON* json) {
}
}
store_asset(Level_as_Asset(self));
return self;
}
@ -139,3 +136,13 @@ Tilemap* level_get_tilemap_layer(Level* self, size_t layer) {
size_t level_get_tilemap_count(Level* self) {
return self->tilemaps_len;
}
asset_id level_get_asset_id(Level* self) {
LOG_INFO("(get) level asset id %zu", self->asset_id);
return self->asset_id;
}
void level_set_asset_id(Level* self, asset_id id) {
self->asset_id = id;
LOG_INFO("(set) level asset id %zu", self->asset_id);
}

View file

@ -1,6 +1,7 @@
#ifndef _fencer_level_h
#define _fencer_level_h
#include "asset.h"
#include "sprite.h"
#include <SDL2/SDL_render.h>
#include <cjson/cJSON.h>
@ -21,4 +22,18 @@ extern void level_draw(Level* self);
extern Tilemap* level_get_tilemap_layer(Level* self, size_t layer);
extern size_t level_get_tilemap_count(Level* self);
extern asset_id level_get_asset_id(Level* self);
extern void level_set_asset_id(Level* self, asset_id id);
extern void _internal_level_destroy(Level* self);
impl_Drop_for(Level,
_internal_level_destroy
)
impl_Asset_for(Level,
level_get_asset_id,
level_set_asset_id
)
#endif // !_fencer_level_h

View file

@ -24,11 +24,9 @@ struct Spritesheet {
float frame_interval;
};
static
void _spritesheet_destroy_asset(void* self_void) {
Spritesheet* self = self_void;
void _internal_spritesheet_destroy(Spritesheet* self) {
SDL_DestroyTexture(self->texture);
free(self_void);
free(self);
}
Spritesheet* spritesheet_load(const char* texture_name, IVector frame_resolution) {
@ -42,7 +40,7 @@ Spritesheet* spritesheet_from_texture(SDL_Texture* texture, IVector frame_resolu
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate spritesheet.");
self->asset_id = store_asset(self, _spritesheet_destroy_asset);
self->asset_id = store_asset(Spritesheet_as_Asset(self));
// Load the texture image and query it's size
self->texture = texture;
@ -78,3 +76,11 @@ SDL_Rect spritesheet_get_frame_rect(const Spritesheet* self, size_t index) {
IVector spritesheet_get_resolution(const Spritesheet* self) {
return self->resolution;
}
asset_id spritesheet_get_asset_id(Spritesheet* self) {
return self->asset_id;
}
void spritesheet_set_asset_id(Spritesheet* self, asset_id id) {
self->asset_id = id;
}

View file

@ -1,6 +1,7 @@
#ifndef _fencer_spritesheet_h
#define _fencer_spritesheet_h
#include "asset.h"
#include "vmath.h"
#include <SDL2/SDL_render.h>
@ -20,4 +21,18 @@ extern SDL_Texture* spritesheet_get_texture(const Spritesheet* self);
extern SDL_Rect spritesheet_get_frame_rect(const Spritesheet* self, size_t index);
extern IVector spritesheet_get_resolution(const Spritesheet* self);
extern asset_id spritesheet_get_asset_id(Spritesheet* self);
extern void spritesheet_set_asset_id(Spritesheet* self, asset_id id);
extern void _internal_spritesheet_destroy(Spritesheet* self_void);
impl_Drop_for(Spritesheet,
_internal_spritesheet_destroy
)
impl_Asset_for(Spritesheet,
spritesheet_get_asset_id,
spritesheet_set_asset_id
)
#endif // !_fencer_spritesheet_h