assets now integrate Asset trait
This commit is contained in:
parent
6e61a7666a
commit
63713a59e7
115
src/assets.c
115
src/assets.c
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
19
src/level.c
19
src/level.c
|
@ -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);
|
||||
}
|
||||
|
|
15
src/level.h
15
src/level.h
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue