Asset refactor, phase one.
This commit is contained in:
@@ -8,8 +8,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
asset.c
|
||||
assetfile.c
|
||||
assetcache.c
|
||||
assetbatch.c
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
|
||||
+120
-15
@@ -21,7 +21,6 @@ errorret_t assetInit(void) {
|
||||
errorChain(assetInitPlatform());
|
||||
assertNotNull(ASSET.zip, "Asset zip null without error.");
|
||||
|
||||
assetCacheInit(&ASSET.cache);
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -33,26 +32,132 @@ bool_t assetFileExists(const char_t *filename) {
|
||||
return true;
|
||||
}
|
||||
|
||||
errorret_t assetLoad(
|
||||
const char_t *filename,
|
||||
assetfileloader_t loader,
|
||||
void *params,
|
||||
void *output
|
||||
assetentry_t * assetGetEntry(
|
||||
const char_t *name,
|
||||
const assetloadertype_t type,
|
||||
assetloaderinput_t *input
|
||||
) {
|
||||
assertStrLenMax(filename, ASSET_FILE_NAME_MAX, "Filename too long.");
|
||||
assertNotNull(output, "Output pointer cannot be NULL.");
|
||||
assertNotNull(loader, "Asset file loader cannot be NULL.");
|
||||
// Is there an existing asset?
|
||||
assetentry_t *entry = ASSET.entries;
|
||||
do {
|
||||
if(entry->type == ASSET_LOADER_TYPE_NULL) {
|
||||
entry++;
|
||||
continue;
|
||||
}
|
||||
if(stringEquals(entry->name, name)) {
|
||||
assertTrue(entry->type == type, "Asset entry type mismatch.");
|
||||
return entry;
|
||||
}
|
||||
entry++;
|
||||
} while(entry < ASSET.entries + ASSET_ENTRY_COUNT_MAX);
|
||||
|
||||
// We did not find one existing, Find first available slot.
|
||||
entry = ASSET.entries;
|
||||
do {
|
||||
if(entry->type != ASSET_LOADER_TYPE_NULL) {
|
||||
entry++;
|
||||
continue;
|
||||
}
|
||||
|
||||
assetfile_t file;
|
||||
errorChain(assetFileInit(&file, filename, params, output));
|
||||
errorChain(loader(&file));
|
||||
errorChain(assetFileDispose(&file));
|
||||
if(entry->state == ASSET_ENTRY_STATE_NOT_STARTED) {
|
||||
assetEntryInit(entry, name, type, input);
|
||||
return entry;
|
||||
}
|
||||
entry++;
|
||||
} while(entry < ASSET.entries + ASSET_ENTRY_COUNT_MAX);
|
||||
|
||||
assertUnreachable("No available asset entry slots.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
errorret_t assetRequireLoaded(assetentry_t *entry) {
|
||||
assertNotNull(entry, "Entry cannot be NULL.");
|
||||
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||
|
||||
// Already loaded?
|
||||
if(entry->state == ASSET_ENTRY_STATE_LOADED) {
|
||||
errorOk();
|
||||
}
|
||||
|
||||
// Not loaded, just spin the wheel
|
||||
while(entry->state != ASSET_ENTRY_STATE_LOADED) {
|
||||
errorChain(assetUpdate());
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t assetUpdate(void) {
|
||||
// Is there any pending entries?
|
||||
assetentry_t *entry = ASSET.entries;
|
||||
assetloading_t *loading;
|
||||
do {
|
||||
// Is this asset "ready to start loading" ?
|
||||
if(entry->type == ASSET_LOADER_TYPE_NULL) {
|
||||
entry++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(entry->state != ASSET_ENTRY_STATE_NOT_STARTED) {
|
||||
entry++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Yes, this is ready to load, but we need to see if we have a loading slot
|
||||
loading = ASSET.loading;
|
||||
bool_t found = false;
|
||||
do {
|
||||
if(loading->type != ASSET_LOADER_TYPE_NULL) {
|
||||
loading++;
|
||||
continue;
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
} while(loading < ASSET.loading + ASSET_LOADING_COUNT_MAX);
|
||||
|
||||
if(!found) {
|
||||
// No loading slot, try again next frame.
|
||||
entry++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start loading this asset.
|
||||
assetEntryStartLoading(entry, loading);
|
||||
entry++;
|
||||
} while(entry < ASSET.entries + ASSET_ENTRY_COUNT_MAX);
|
||||
|
||||
// At this point we have to see the state of all the loading assets.
|
||||
loading = ASSET.loading;
|
||||
do {
|
||||
if(loading->entry == NULL) {
|
||||
loading++;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(loading->entry->state) {
|
||||
case ASSET_ENTRY_STATE_PENDING_SYNC:
|
||||
// Begin sync loading
|
||||
loading->entry->state = ASSET_ENTRY_STATE_LOADING_SYNC;
|
||||
errorret_t ret = ASSET_LOADING_CALLBACKS[loading->type].loadSync(loading);
|
||||
if(ret.code != ERROR_OK) {
|
||||
loading->entry->state = ASSET_ENTRY_STATE_ERROR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
||||
loading++;
|
||||
break;
|
||||
|
||||
default:
|
||||
loading++;
|
||||
continue;
|
||||
}
|
||||
} while(loading < ASSET.loading + ASSET_LOADING_COUNT_MAX);
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t assetDispose(void) {
|
||||
assetCacheDispose(&ASSET.cache);
|
||||
|
||||
if(ASSET.zip != NULL) {
|
||||
if(zip_close(ASSET.zip) != 0) {
|
||||
errorThrow("Failed to close asset zip archive.");
|
||||
|
||||
+36
-13
@@ -9,7 +9,9 @@
|
||||
#include "error/error.h"
|
||||
#include "asset/assetplatform.h"
|
||||
#include "assetfile.h"
|
||||
#include "assetcache.h"
|
||||
|
||||
#include "asset/loader/assetentry.h"
|
||||
#include "asset/loader/assetloading.h"
|
||||
|
||||
#ifndef assetInitPlatform
|
||||
#error "Platform must define assetInitPlatform function."
|
||||
@@ -21,16 +23,24 @@
|
||||
#define ASSET_FILE_NAME "dusk.dsk"
|
||||
#define ASSET_HEADER_SIZE 3
|
||||
|
||||
#define ASSET_LOADING_COUNT_MAX 4
|
||||
#define ASSET_ENTRY_COUNT_MAX 128
|
||||
|
||||
typedef struct asset_s {
|
||||
zip_t *zip;
|
||||
assetplatform_t platform;
|
||||
assetcache_t cache;
|
||||
|
||||
// Assets that are mid loading.
|
||||
assetloading_t loading[ASSET_LOADING_COUNT_MAX];
|
||||
assetentry_t entries[ASSET_ENTRY_COUNT_MAX];
|
||||
} asset_t;
|
||||
|
||||
extern asset_t ASSET;
|
||||
|
||||
/**
|
||||
* Initializes the asset system.
|
||||
*
|
||||
* @return An error code if the asset system could not be initialized properly.
|
||||
*/
|
||||
errorret_t assetInit(void);
|
||||
|
||||
@@ -43,21 +53,34 @@ errorret_t assetInit(void);
|
||||
bool_t assetFileExists(const char_t *filename);
|
||||
|
||||
/**
|
||||
* Loads an asset by its filename,
|
||||
* Gets, or creates, a new asset entry. You will need to lock the asset soon
|
||||
* after creating or else it will be freed up on the next update cycle.
|
||||
*
|
||||
* @param filename The filename of the asset to retrieve.
|
||||
* @param loader Loader to use for loading the asset file.
|
||||
* @param params Parameters to pass to the loader.
|
||||
* @param output The output pointer to store the loaded asset data.
|
||||
* @return An error code if the asset could not be loaded.
|
||||
* @param name Filename of the asset.
|
||||
* @param type Type of the asset.
|
||||
*/
|
||||
errorret_t assetLoad(
|
||||
const char_t *filename,
|
||||
assetfileloader_t loader,
|
||||
void *params,
|
||||
void *output
|
||||
assetentry_t * assetGetEntry(
|
||||
const char_t *name,
|
||||
const assetloadertype_t type,
|
||||
assetloaderinput_t *input
|
||||
);
|
||||
|
||||
/**
|
||||
* Requires an asset entry to be loaded. This will block until the asset entry
|
||||
* is fully loaded.
|
||||
*
|
||||
* @param entry The asset entry to require.
|
||||
* @return An error code if the asset entry could not be loaded properly.
|
||||
*/
|
||||
errorret_t assetRequireLoaded(assetentry_t *entry);
|
||||
|
||||
/**
|
||||
* Updates the asset system.
|
||||
*
|
||||
* @return An error code if the asset system could not be updated properly.
|
||||
*/
|
||||
errorret_t assetUpdate(void);
|
||||
|
||||
/**
|
||||
* Disposes/cleans up the asset system.
|
||||
*
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "assetbatch.h"
|
||||
#include "asset.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
void assetBatchInit(
|
||||
assetbatch_t *batch,
|
||||
assetbatchcomplete_t onComplete,
|
||||
assetbatcherror_t onError,
|
||||
void *context
|
||||
) {
|
||||
memoryZero(batch, sizeof(assetbatch_t));
|
||||
batch->onComplete = onComplete;
|
||||
batch->onError = onError;
|
||||
batch->context = context;
|
||||
}
|
||||
|
||||
void assetBatchAdd(
|
||||
assetbatch_t *batch,
|
||||
const char_t *path,
|
||||
assetfileloader_t loader,
|
||||
const void *params,
|
||||
size_t paramsSize,
|
||||
size_t dataSize,
|
||||
assetcachedisposer_t disposer,
|
||||
void **outPtr
|
||||
) {
|
||||
assertTrue(batch->count < ASSET_BATCH_MAX, "Asset batch is full.");
|
||||
assertTrue(paramsSize <= ASSET_BATCH_PARAMS_SIZE, "Asset batch params too large.");
|
||||
assertNotNull(outPtr, "Batch output pointer cannot be NULL.");
|
||||
|
||||
assetbatchitem_t *item = &batch->items[batch->count++];
|
||||
stringCopy(item->path, path, ASSET_FILE_NAME_MAX);
|
||||
item->loader = loader;
|
||||
if (params != NULL && paramsSize > 0) {
|
||||
memoryCopy(item->params, params, paramsSize);
|
||||
}
|
||||
item->dataSize = dataSize;
|
||||
item->disposer = disposer;
|
||||
item->outPtr = outPtr;
|
||||
}
|
||||
|
||||
errorret_t assetBatchLoad(assetbatch_t *batch) {
|
||||
for (uint8_t i = 0; i < batch->count; i++) {
|
||||
assetbatchitem_t *item = &batch->items[i];
|
||||
|
||||
void *cached = assetCacheLookup(&ASSET.cache, item->path);
|
||||
if (cached != NULL) {
|
||||
assetCacheRetain(&ASSET.cache, item->path);
|
||||
*item->outPtr = cached;
|
||||
continue;
|
||||
}
|
||||
|
||||
void *data = memoryAllocate(item->dataSize);
|
||||
errorret_t err = assetLoad(item->path, item->loader, item->params, data);
|
||||
if (err.code != ERROR_OK) {
|
||||
memoryFree(data);
|
||||
if (batch->onError != NULL) {
|
||||
batch->onError(batch, batch->context, err);
|
||||
}
|
||||
return errorChainImpl(err, __FILE__, __func__, __LINE__);
|
||||
}
|
||||
|
||||
assetCacheInsert(&ASSET.cache, item->path, data, item->disposer);
|
||||
*item->outPtr = data;
|
||||
}
|
||||
|
||||
if (batch->onComplete != NULL) {
|
||||
batch->onComplete(batch, batch->context);
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "assetcache.h"
|
||||
#include "error/error.h"
|
||||
|
||||
#ifndef ASSET_BATCH_MAX
|
||||
#define ASSET_BATCH_MAX 16
|
||||
#endif
|
||||
|
||||
#define ASSET_BATCH_PARAMS_SIZE 16
|
||||
|
||||
typedef struct assetbatch_s assetbatch_t;
|
||||
|
||||
typedef void (*assetbatchcomplete_t)(assetbatch_t *batch, void *context);
|
||||
typedef void (*assetbatcherror_t)(
|
||||
assetbatch_t *batch,
|
||||
void *context,
|
||||
errorret_t error
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
char_t path[ASSET_FILE_NAME_MAX];
|
||||
assetfileloader_t loader;
|
||||
uint8_t params[ASSET_BATCH_PARAMS_SIZE];
|
||||
size_t dataSize;
|
||||
assetcachedisposer_t disposer;
|
||||
void **outPtr;
|
||||
} assetbatchitem_t;
|
||||
|
||||
struct assetbatch_s {
|
||||
assetbatchitem_t items[ASSET_BATCH_MAX];
|
||||
uint8_t count;
|
||||
assetbatchcomplete_t onComplete;
|
||||
assetbatcherror_t onError;
|
||||
void *context;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes a batch, optionally with completion and error callbacks.
|
||||
*
|
||||
* @param batch The batch to initialize.
|
||||
* @param onComplete Called when all items have loaded successfully. May be NULL.
|
||||
* @param onError Called if any item fails to load. May be NULL.
|
||||
* @param context Passed through to both callbacks.
|
||||
*/
|
||||
void assetBatchInit(
|
||||
assetbatch_t *batch,
|
||||
assetbatchcomplete_t onComplete,
|
||||
assetbatcherror_t onError,
|
||||
void *context
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds an item to the batch. Params are copied into inline storage.
|
||||
*
|
||||
* @param batch The batch to add to.
|
||||
* @param path Asset path, used as the cache key.
|
||||
* @param loader The loader function for this asset type.
|
||||
* @param params Loader-specific parameters. Copied — safe to pass stack address.
|
||||
* @param paramsSize Size of params in bytes. Must be <= ASSET_BATCH_PARAMS_SIZE.
|
||||
* @param dataSize Size in bytes to allocate for the output struct.
|
||||
* @param disposer Called on the data before freeing when released. May be NULL.
|
||||
* @param outPtr Caller's pointer variable. Set to the cache-owned data on load.
|
||||
*/
|
||||
void assetBatchAdd(
|
||||
assetbatch_t *batch,
|
||||
const char_t *path,
|
||||
assetfileloader_t loader,
|
||||
const void *params,
|
||||
size_t paramsSize,
|
||||
size_t dataSize,
|
||||
assetcachedisposer_t disposer,
|
||||
void **outPtr
|
||||
);
|
||||
|
||||
/**
|
||||
* Loads all items in the batch, checking the cache for each. Fires onComplete
|
||||
* on success or onError on the first failure. Also returns the error for
|
||||
* synchronous callers.
|
||||
*
|
||||
* @param batch The batch to execute.
|
||||
* @return Error if any item failed to load.
|
||||
*/
|
||||
errorret_t assetBatchLoad(assetbatch_t *batch);
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "assetcache.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
void assetCacheInit(assetcache_t *cache) {
|
||||
memoryZero(cache, sizeof(assetcache_t));
|
||||
}
|
||||
|
||||
void *assetCacheLookup(assetcache_t *cache, const char_t *path) {
|
||||
for(uint8_t i = 0; i < cache->count; i++) {
|
||||
if(stringCompare(cache->entries[i].path, path) == 0) {
|
||||
return cache->entries[i].data;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void assetCacheInsert(
|
||||
assetcache_t *cache,
|
||||
const char_t *path,
|
||||
void *data,
|
||||
assetcachedisposer_t disposer
|
||||
) {
|
||||
assertTrue(cache->count < ASSET_CACHE_MAX, "Asset cache is full.");
|
||||
|
||||
assetcacheentry_t *entry = &cache->entries[cache->count++];
|
||||
stringCopy(entry->path, path, ASSET_FILE_NAME_MAX);
|
||||
entry->data = data;
|
||||
entry->refcount = 1;
|
||||
entry->disposer = disposer;
|
||||
}
|
||||
|
||||
void assetCacheRetain(assetcache_t *cache, const char_t *path) {
|
||||
for (uint8_t i = 0; i < cache->count; i++) {
|
||||
if (stringCompare(cache->entries[i].path, path) == 0) {
|
||||
cache->entries[i].refcount++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
assertTrue(false, "Asset not found in cache for retain.");
|
||||
}
|
||||
|
||||
static void assetCacheEntryDispose(assetcacheentry_t *entry) {
|
||||
if (entry->disposer != NULL) {
|
||||
entry->disposer(entry->data);
|
||||
}
|
||||
memoryFree(entry->data);
|
||||
}
|
||||
|
||||
void assetCacheRelease(assetcache_t *cache, const char_t *path) {
|
||||
for (uint8_t i = 0; i < cache->count; i++) {
|
||||
if (stringCompare(cache->entries[i].path, path) == 0) {
|
||||
assetcacheentry_t *entry = &cache->entries[i];
|
||||
entry->refcount--;
|
||||
if (entry->refcount == 0) {
|
||||
assetCacheEntryDispose(entry);
|
||||
for (uint8_t j = i; j < cache->count - 1; j++) {
|
||||
cache->entries[j] = cache->entries[j + 1];
|
||||
}
|
||||
cache->count--;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
assertTrue(false, "Asset not found in cache for release.");
|
||||
}
|
||||
|
||||
void assetCacheDispose(assetcache_t *cache) {
|
||||
for (uint8_t i = 0; i < cache->count; i++) {
|
||||
assetCacheEntryDispose(&cache->entries[i]);
|
||||
}
|
||||
memoryZero(cache, sizeof(assetcache_t));
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "assetfile.h"
|
||||
|
||||
#ifndef ASSET_CACHE_MAX
|
||||
#define ASSET_CACHE_MAX 64
|
||||
#endif
|
||||
|
||||
typedef void (*assetcachedisposer_t)(void *data);
|
||||
|
||||
typedef struct {
|
||||
char_t path[ASSET_FILE_NAME_MAX];
|
||||
void *data;
|
||||
uint32_t refcount;
|
||||
assetcachedisposer_t disposer;
|
||||
} assetcacheentry_t;
|
||||
|
||||
typedef struct {
|
||||
assetcacheentry_t entries[ASSET_CACHE_MAX];
|
||||
uint8_t count;
|
||||
} assetcache_t;
|
||||
|
||||
/**
|
||||
* Initializes the asset cache.
|
||||
*
|
||||
* @param cache The cache to initialize.
|
||||
*/
|
||||
void assetCacheInit(assetcache_t *cache);
|
||||
|
||||
/**
|
||||
* Looks up a cached asset by path.
|
||||
*
|
||||
* @param cache The cache to search.
|
||||
* @param path The asset path to look up.
|
||||
* @return Pointer to the cached data, or NULL if not found.
|
||||
*/
|
||||
void *assetCacheLookup(assetcache_t *cache, const char_t *path);
|
||||
|
||||
/**
|
||||
* Inserts a newly loaded asset into the cache with refcount 1.
|
||||
*
|
||||
* @param cache The cache to insert into.
|
||||
* @param path The asset path key.
|
||||
* @param data Heap-allocated asset data. The cache takes ownership.
|
||||
* @param disposer Called with data before freeing when refcount reaches 0.
|
||||
*/
|
||||
void assetCacheInsert(
|
||||
assetcache_t *cache,
|
||||
const char_t *path,
|
||||
void *data,
|
||||
assetcachedisposer_t disposer
|
||||
);
|
||||
|
||||
/**
|
||||
* Increments the refcount for a cached asset.
|
||||
*
|
||||
* @param cache The cache containing the asset.
|
||||
* @param path The asset path.
|
||||
*/
|
||||
void assetCacheRetain(assetcache_t *cache, const char_t *path);
|
||||
|
||||
/**
|
||||
* Decrements the refcount. Disposes and frees the asset when it reaches 0.
|
||||
*
|
||||
* @param cache The cache containing the asset.
|
||||
* @param path The asset path.
|
||||
*/
|
||||
void assetCacheRelease(assetcache_t *cache, const char_t *path);
|
||||
|
||||
/**
|
||||
* Disposes all remaining cache entries and resets the cache.
|
||||
*
|
||||
* @param cache The cache to dispose.
|
||||
*/
|
||||
void assetCacheDispose(assetcache_t *cache);
|
||||
@@ -15,6 +15,7 @@ typedef struct assetfile_s assetfile_t;
|
||||
|
||||
typedef errorret_t (*assetfileloader_t)(assetfile_t *file);
|
||||
|
||||
// Describes a file not yet loaded.
|
||||
typedef struct assetfile_s {
|
||||
char_t filename[ASSET_FILE_NAME_MAX];
|
||||
void *params;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef enum assetloadertype_e {
|
||||
ASSET_LOADER_TYPE_NULL,
|
||||
|
||||
ASSET_LOADER_TYPE_MESH,
|
||||
ASSET_LOADER_TYPE_TEXTURE,
|
||||
ASSET_LOADER_TYPE_SHADER,
|
||||
|
||||
ASSET_LOADER_TYPE_COUNT
|
||||
} assetloadertype_t;
|
||||
|
||||
typedef union {
|
||||
void *nothing;
|
||||
} assetloaderloading_t;
|
||||
|
||||
typedef union {
|
||||
void *nothing;
|
||||
} assetloaderoutput_t;
|
||||
|
||||
typedef enum {
|
||||
ASSET_LOADER_LOADING_STATE_NOT_STARTED,
|
||||
ASSET_LOADER_LOADING_STATE_PENDING_ASYNC,
|
||||
ASSET_LOADER_LOADING_STATE_LOADING_ASYNC,
|
||||
ASSET_LOADER_LOADING_STATE_PENDING_SYNC,
|
||||
ASSET_LOADER_LOADING_STATE_LOADING_SYNC,
|
||||
ASSET_LOADER_LOADING_STATE_LOADED,
|
||||
ASSET_LOADER_LOADING_STATE_ERROR
|
||||
} assetloaderloadingstate_t;
|
||||
|
||||
typedef struct {
|
||||
assetloadertype_t type;
|
||||
assetloaderloadingstate_t state;
|
||||
assetloaderloading_t loading;
|
||||
} assetloadingentry_t;
|
||||
|
||||
typedef struct {
|
||||
assetloadertype_t type;
|
||||
assetloaderoutput_t output;
|
||||
} assetentry_t;
|
||||
@@ -4,6 +4,12 @@
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
assetentry.c
|
||||
assetloading.c
|
||||
)
|
||||
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(display)
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "assetentry.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
|
||||
assetentrycallbacks_t ASSET_ENTRY_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
|
||||
[ASSET_LOADER_TYPE_NULL] = { 0 },
|
||||
|
||||
[ASSET_LOADER_TYPE_TEXTURE] = {
|
||||
.dispose = &assetTextureDisposeNEW
|
||||
},
|
||||
|
||||
[ASSET_LOADER_TYPE_TILESET] = {
|
||||
.dispose = &assetTilesetDisposeNEW
|
||||
},
|
||||
};
|
||||
|
||||
void assetEntryInit(
|
||||
assetentry_t *entry,
|
||||
const char_t *name,
|
||||
const assetloadertype_t type,
|
||||
assetloaderinput_t *input
|
||||
) {
|
||||
assertNotNull(entry, "Entry cannot be NULL");
|
||||
assertStrLenMin(name, 1, "Name cannot be empty");
|
||||
assertStrLenMax(name, ASSET_FILE_NAME_MAX - 1, "Name too long");
|
||||
assertTrue(type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||
assertTrue(type < ASSET_LOADER_TYPE_COUNT, "Invalid loader type.");
|
||||
|
||||
memoryZero(entry, sizeof(assetentry_t));
|
||||
stringCopy(entry->name, name, ASSET_FILE_NAME_MAX);
|
||||
entry->type = type;
|
||||
entry->input = input;
|
||||
entry->state = ASSET_ENTRY_STATE_NOT_STARTED;
|
||||
refInit(&entry->refs, entry, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void assetEntryLock(assetentry_t *entry) {
|
||||
assertNotNull(entry, "Entry cannot be NULL");
|
||||
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||
refLock(&entry->refs);
|
||||
}
|
||||
|
||||
void assetEntryUnlock(assetentry_t *entry) {
|
||||
assertNotNull(entry, "Entry cannot be NULL");
|
||||
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||
refUnlock(&entry->refs);
|
||||
}
|
||||
|
||||
void assetEntryStartLoading(
|
||||
assetentry_t *entry,
|
||||
assetloading_t *loading
|
||||
) {
|
||||
assertNotNull(entry, "Entry cannot be NULL");
|
||||
assertNotNull(loading, "Loading cannot be NULL");
|
||||
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||
assertTrue(
|
||||
entry->state == ASSET_ENTRY_STATE_NOT_STARTED,
|
||||
"Can only start loading from NOT_STARTED state."
|
||||
);
|
||||
|
||||
entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
|
||||
memoryZero(loading, sizeof(assetloading_t));
|
||||
loading->type = entry->type;
|
||||
loading->entry = entry;
|
||||
// At this point the asset manager will manage this thing's loading
|
||||
}
|
||||
|
||||
errorret_t assetEntryDispose(assetentry_t *entry) {
|
||||
assertNotNull(entry, "Entry cannot be NULL");
|
||||
|
||||
assertTrue(entry->type != ASSET_LOADER_TYPE_NULL, "Invalid loader type.");
|
||||
assertTrue(entry->type < ASSET_LOADER_TYPE_COUNT, "Invalid loader type.");
|
||||
|
||||
errorChain(ASSET_ENTRY_CALLBACKS[entry->type].dispose(entry));
|
||||
memoryZero(entry, sizeof(assetentry_t));
|
||||
errorOk();
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "asset/loader/assetloading.h"
|
||||
#include "util/ref.h"
|
||||
|
||||
typedef enum {
|
||||
ASSET_ENTRY_STATE_NOT_STARTED,
|
||||
// ASSET_ENTRY_STATE_PENDING_ASYNC,
|
||||
// ASSET_ENTRY_STATE_LOADING_ASYNC,
|
||||
ASSET_ENTRY_STATE_PENDING_SYNC,
|
||||
ASSET_ENTRY_STATE_LOADING_SYNC,
|
||||
ASSET_ENTRY_STATE_LOADED,
|
||||
ASSET_ENTRY_STATE_ERROR
|
||||
} assetentrystate_t;
|
||||
|
||||
typedef struct assetentry_s {
|
||||
// Filename and cache key
|
||||
char_t name[ASSET_FILE_NAME_MAX];
|
||||
// What type of asset is this?
|
||||
assetloadertype_t type;
|
||||
// Data
|
||||
assetloaderoutput_t data;
|
||||
// What state is this asset entry in currently?
|
||||
assetentrystate_t state;
|
||||
// What is referencing this asset entry.
|
||||
ref_t refs;
|
||||
// Data that will be passed to the loader about how it should load.
|
||||
assetloaderinput_t *input;
|
||||
} assetentry_t;
|
||||
|
||||
typedef errorret_t (*assetentrydisposecallback_t)(assetentry_t *entry);
|
||||
|
||||
typedef struct {
|
||||
assetentrydisposecallback_t dispose;
|
||||
} assetentrycallbacks_t;
|
||||
|
||||
extern assetentrycallbacks_t ASSET_ENTRY_CALLBACKS[ASSET_LOADER_TYPE_COUNT];
|
||||
|
||||
/**
|
||||
* Initializes an asset entry with the given name and type. This does not load
|
||||
* the asset.
|
||||
*
|
||||
* @param entry The asset entry to initialize.
|
||||
* @param name The name of the asset, used as a key for loading and caching.
|
||||
* @param type The type of asset this entry represents.
|
||||
* @param input Data that will be passed to the loader about how it should load.
|
||||
*/
|
||||
void assetEntryInit(
|
||||
assetentry_t *entry,
|
||||
const char_t *name,
|
||||
const assetloadertype_t type,
|
||||
assetloaderinput_t *input
|
||||
);
|
||||
|
||||
/**
|
||||
* Locks an asset entry, preventing it from being freed until it is unlocked.
|
||||
*
|
||||
* @param entry The asset entry to lock.
|
||||
*/
|
||||
void assetEntryLock(assetentry_t *entry);
|
||||
|
||||
/**
|
||||
* Unlocks an asset entry, allowing it to be freed if there are no more locks.
|
||||
*
|
||||
* @param entry The asset entry to unlock.
|
||||
*/
|
||||
void assetEntryUnlock(assetentry_t *entry);
|
||||
|
||||
/**
|
||||
* Starts loading the given asset entry using an assetloading slot. This will
|
||||
* be called by the asset manager when it deems it's a good time to begin the
|
||||
* loading of this asset entry.
|
||||
*
|
||||
* Currently we return the error but in future this will not be returned.
|
||||
*
|
||||
* @param entry The asset entry to start loading.
|
||||
* @param loading The assetloading slot to use for loading this asset entry.
|
||||
* @return Any error that occurs during loading.
|
||||
*/
|
||||
void assetEntryStartLoading(assetentry_t *entry, assetloading_t *loading);
|
||||
|
||||
/**
|
||||
* Disposes an asset entry, freeing any resources it holds.
|
||||
*
|
||||
* @param entry The asset entry to dispose.
|
||||
* @return Any error that occurs during disposal.
|
||||
*/
|
||||
errorret_t assetEntryDispose(assetentry_t *entry);
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "asset/loader/display/assetmeshloader.h"
|
||||
#include "asset/loader/display/assettextureloader.h"
|
||||
#include "asset/loader/display/assettilesetloader.h"
|
||||
|
||||
typedef enum {
|
||||
ASSET_LOADER_TYPE_NULL,
|
||||
|
||||
// ASSET_LOADER_TYPE_MESH,
|
||||
ASSET_LOADER_TYPE_TEXTURE,
|
||||
ASSET_LOADER_TYPE_TILESET,
|
||||
|
||||
ASSET_LOADER_TYPE_COUNT
|
||||
} assetloadertype_t;
|
||||
|
||||
typedef union {
|
||||
assettextureloaderinput_t texture;
|
||||
assettilesetloaderinput_t tileset;
|
||||
} assetloaderinput_t;
|
||||
|
||||
typedef union {
|
||||
assettextureloaderloading_t texture;
|
||||
assettilesetloaderloading_t tileset;
|
||||
} assetloaderloading_t;
|
||||
|
||||
typedef union {
|
||||
assettextureoutput_t texture;
|
||||
assettilesetoutput_t tileset;
|
||||
} assetloaderoutput_t;
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "assetloading.h"
|
||||
#include "asset/loader/display/assetmeshloader.h"
|
||||
|
||||
assetloadingcallbacks_t ASSET_LOADING_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
|
||||
[ASSET_LOADER_TYPE_NULL] = { 0 },
|
||||
|
||||
// [ASSET_LOADER_TYPE_MESH] = {
|
||||
// .loadSync = assetMeshLoaderNEW,
|
||||
// },
|
||||
|
||||
[ASSET_LOADER_TYPE_TEXTURE] = {
|
||||
.loadSync = assetTextureLoaderNEW
|
||||
},
|
||||
|
||||
|
||||
[ASSET_LOADER_TYPE_TILESET] = {
|
||||
.loadSync = assetTilesetLoaderNEW
|
||||
},
|
||||
|
||||
// [ASSET_LOADER_TYPE_SHADER] = {
|
||||
|
||||
// }
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "assetloader.h"
|
||||
#include "asset/assetfile.h"
|
||||
|
||||
typedef struct assetentry_s assetentry_t;
|
||||
|
||||
typedef struct assetloading_s {
|
||||
// What type of asset is being loaded.
|
||||
assetloadertype_t type;
|
||||
// Referral back to the asset entry that will be kept alive after load done.
|
||||
assetentry_t *entry;
|
||||
// Information used during the load operation only.
|
||||
assetloaderloading_t loading;
|
||||
} assetloading_t;
|
||||
|
||||
typedef errorret_t (assetloadingcallback_t)(assetloading_t *loading);
|
||||
|
||||
typedef struct {
|
||||
assetloadingcallback_t *loadSync;
|
||||
} assetloadingcallbacks_t;
|
||||
|
||||
extern assetloadingcallbacks_t ASSET_LOADING_CALLBACKS[ASSET_LOADER_TYPE_COUNT];
|
||||
@@ -151,32 +151,32 @@ errorret_t assetMeshLoader(assetfile_t *file) {
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t assetMeshLoadToOutput(
|
||||
const char_t *path,
|
||||
assetmeshoutput_t *output
|
||||
) {
|
||||
assertNotNull(path, "Path cannot be null");
|
||||
assertNotNull(output, "Output cannot be null");
|
||||
assertNotNull(output->outMesh, "Output mesh cannot be null");
|
||||
assertNotNull(output->outVertices, "Output vertices cannot be null");
|
||||
// errorret_t assetMeshLoadToOutput(
|
||||
// const char_t *path,
|
||||
// assetmeshoutput_t *output
|
||||
// ) {
|
||||
// assertNotNull(path, "Path cannot be null");
|
||||
// assertNotNull(output, "Output cannot be null");
|
||||
// assertNotNull(output->outMesh, "Output mesh cannot be null");
|
||||
// assertNotNull(output->outVertices, "Output vertices cannot be null");
|
||||
|
||||
return assetLoad(path, &assetMeshLoader, NULL, output);
|
||||
}
|
||||
// return assetLoad(path, &assetMeshLoader, NULL, output);
|
||||
// }
|
||||
|
||||
errorret_t assetMeshLoad(
|
||||
const char_t *path,
|
||||
mesh_t *outMesh,
|
||||
meshvertex_t **outVertices,
|
||||
const assetmeshinputaxis_t inputAxis
|
||||
) {
|
||||
assertNotNull(path, "Path cannot be null");
|
||||
assertNotNull(outMesh, "Output mesh cannot be null");
|
||||
assertNotNull(outVertices, "Output vertices cannot be null");
|
||||
// errorret_t assetMeshLoad(
|
||||
// const char_t *path,
|
||||
// mesh_t *outMesh,
|
||||
// meshvertex_t **outVertices,
|
||||
// const assetmeshinputaxis_t inputAxis
|
||||
// ) {
|
||||
// assertNotNull(path, "Path cannot be null");
|
||||
// assertNotNull(outMesh, "Output mesh cannot be null");
|
||||
// assertNotNull(outVertices, "Output vertices cannot be null");
|
||||
|
||||
assetmeshoutput_t output = {
|
||||
outMesh,
|
||||
outVertices,
|
||||
inputAxis
|
||||
};
|
||||
return assetMeshLoadToOutput(path, &output);
|
||||
}
|
||||
// assetmeshoutput_t output = {
|
||||
// outMesh,
|
||||
// outVertices,
|
||||
// inputAxis
|
||||
// };
|
||||
// return assetMeshLoadToOutput(path, &output);
|
||||
// }
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "asset/asset.h"
|
||||
#include "asset/assetfile.h"
|
||||
#include "display/mesh/mesh.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
@@ -42,20 +42,4 @@ assertStructSize(assetmeshstltriangle_t, 50);
|
||||
* @param file Asset file to load the mesh from.
|
||||
* @return Any error that occurs during loading.
|
||||
*/
|
||||
errorret_t assetMeshLoader(assetfile_t *file);
|
||||
|
||||
/**
|
||||
* Handler for mesh assets.
|
||||
*
|
||||
* @param file Asset file to load the mesh from.
|
||||
* @param outMesh Output mesh to load the data into.
|
||||
* @param outVertices Output pointer to the vertex data, used for cleanup.
|
||||
* @param inputAxis The axis orientation of the input mesh data.
|
||||
* @return Any error that occurs during loading.
|
||||
*/
|
||||
errorret_t assetMeshLoad(
|
||||
const char_t *path,
|
||||
mesh_t *outMesh,
|
||||
meshvertex_t **outVertices,
|
||||
const assetmeshinputaxis_t inputAxis
|
||||
);
|
||||
errorret_t assetMeshLoader(assetfile_t *file);
|
||||
@@ -6,13 +6,41 @@
|
||||
*/
|
||||
|
||||
#include "assettextureloader.h"
|
||||
#include "asset/assetbatch.h"
|
||||
#include "assert/assert.h"
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
#include "log/log.h"
|
||||
#include "util/endian.h"
|
||||
|
||||
|
||||
#include "asset/loader/assetloading.h"
|
||||
#include "asset/loader/assetentry.h"
|
||||
|
||||
errorret_t assetTextureLoaderNEW(assetloading_t *loading) {
|
||||
assertNotNull(loading, "Loading cannot be NULL");
|
||||
|
||||
assettextureloaderparams_t params;
|
||||
params.format = loading->entry->input->texture;
|
||||
|
||||
assetfile_t *file = &loading->loading.texture.file;
|
||||
errorChain(assetFileInit(
|
||||
file,
|
||||
loading->entry->name,
|
||||
¶ms,
|
||||
&loading->entry->data.texture
|
||||
));
|
||||
errorChain(assetTextureLoader(file));
|
||||
assetFileDispose(file);
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t assetTextureDisposeNEW(assetentry_t *entry) {
|
||||
assertNotNull(entry, "Asset entry cannot be NULL");
|
||||
return textureDispose(&entry->data.texture);
|
||||
}
|
||||
|
||||
|
||||
|
||||
stbi_io_callbacks ASSET_TEXTURE_STB_CALLBACKS = {
|
||||
.read = assetTextureReader,
|
||||
.skip = assetTextureSkipper,
|
||||
@@ -102,37 +130,4 @@ errorret_t assetTextureLoader(assetfile_t *file) {
|
||||
|
||||
stbi_image_free(data);
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t assetTextureLoad(
|
||||
const char_t *path,
|
||||
texture_t *out,
|
||||
const textureformat_t format
|
||||
) {
|
||||
assettextureloaderparams_t params = {
|
||||
.format = format
|
||||
};
|
||||
return assetLoad(path, assetTextureLoader, ¶ms, out);
|
||||
}
|
||||
|
||||
static void assetTextureCacheDispose(void *data) {
|
||||
errorCatch(textureDispose((texture_t*)data));
|
||||
}
|
||||
|
||||
void assetBatchTexture(
|
||||
assetbatch_t *batch,
|
||||
const char_t *path,
|
||||
textureformat_t format,
|
||||
texture_t **out
|
||||
) {
|
||||
assettextureloaderparams_t params = { .format = format };
|
||||
assetBatchAdd(
|
||||
batch,
|
||||
path,
|
||||
assetTextureLoader,
|
||||
¶ms, sizeof(params),
|
||||
sizeof(texture_t),
|
||||
assetTextureCacheDispose,
|
||||
(void**)out
|
||||
);
|
||||
}
|
||||
@@ -6,14 +6,28 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "asset/asset.h"
|
||||
#include "asset/assetbatch.h"
|
||||
#include "asset/assetfile.h"
|
||||
#include "display/texture/texture.h"
|
||||
|
||||
typedef struct {
|
||||
textureformat_t format;
|
||||
} assettextureloaderparams_t;
|
||||
|
||||
// NEW STUFF
|
||||
typedef struct assetloading_s assetloading_t;
|
||||
typedef struct assetentry_s assetentry_t;
|
||||
|
||||
typedef textureformat_t assettextureloaderinput_t;
|
||||
typedef struct {
|
||||
assetfile_t file;
|
||||
} assettextureloaderloading_t;
|
||||
typedef texture_t assettextureoutput_t;
|
||||
|
||||
errorret_t assetTextureLoaderNEW(assetloading_t *loading);
|
||||
errorret_t assetTextureDisposeNEW(assetentry_t *entry);
|
||||
|
||||
// END NEW STUFF
|
||||
|
||||
/**
|
||||
* STB image read callback for asset files.
|
||||
*
|
||||
@@ -34,34 +48,4 @@ int assetTextureEOF(void *user);
|
||||
* @param file Asset file to load the texture from.
|
||||
* @return Any error that occurs during loading.
|
||||
*/
|
||||
errorret_t assetTextureLoader(assetfile_t *file);
|
||||
|
||||
/**
|
||||
* Loads a texture from the specified path.
|
||||
*
|
||||
* @param path Path to the texture asset.
|
||||
* @param out Output texture to load into.
|
||||
* @param format Format of the texture to load.
|
||||
* @return Any error that occurs during loading.
|
||||
*/
|
||||
errorret_t assetTextureLoad(
|
||||
const char_t *path,
|
||||
texture_t *out,
|
||||
const textureformat_t format
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds a texture load request to a batch. The cache-owned texture_t* is
|
||||
* written to *out when the batch completes.
|
||||
*
|
||||
* @param batch The batch to add to.
|
||||
* @param path Path to the texture asset.
|
||||
* @param format Format of the texture to load.
|
||||
* @param out Receives a pointer to the loaded texture on completion.
|
||||
*/
|
||||
void assetBatchTexture(
|
||||
assetbatch_t *batch,
|
||||
const char_t *path,
|
||||
textureformat_t format,
|
||||
texture_t **out
|
||||
);
|
||||
errorret_t assetTextureLoader(assetfile_t *file);
|
||||
@@ -6,11 +6,35 @@
|
||||
*/
|
||||
|
||||
#include "assettilesetloader.h"
|
||||
#include "asset/assetbatch.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/endian.h"
|
||||
|
||||
#include "asset/loader/assetloading.h"
|
||||
#include "asset/loader/assetentry.h"
|
||||
|
||||
errorret_t assetTilesetLoaderNEW(assetloading_t *loading) {
|
||||
assertNotNull(loading, "Loading cannot be NULL");
|
||||
assertTrue(loading->type == ASSET_LOADER_TYPE_TILESET, "Invalid type.");
|
||||
|
||||
assetfile_t *file = &loading->loading.tileset.file;
|
||||
tileset_t *out = &loading->entry->data.tileset;
|
||||
assertNotNull(file, "File cannot be NULL");
|
||||
assertNotNull(out, "Output cannot be NULL");
|
||||
|
||||
errorChain(assetFileInit(file, loading->entry->name, NULL, out));
|
||||
errorChain(assetTilesetLoader(file));
|
||||
errorChain(assetFileDispose(file));
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t assetTilesetDisposeNEW(assetentry_t *entry) {
|
||||
assertNotNull(entry, "Entry cannot be NULL");
|
||||
assertTrue(entry->type == ASSET_LOADER_TYPE_TILESET, "Invalid type.");
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t assetTilesetLoader(assetfile_t *file) {
|
||||
assertNotNull(file, "Asset file pointer for tileset loader is null.");
|
||||
|
||||
@@ -73,25 +97,9 @@ errorret_t assetTilesetLoader(assetfile_t *file) {
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t assetTilesetLoad(
|
||||
const char_t *path,
|
||||
tileset_t *out
|
||||
) {
|
||||
return assetLoad(path, assetTilesetLoader, NULL, out);
|
||||
}
|
||||
|
||||
void assetBatchTileset(
|
||||
assetbatch_t *batch,
|
||||
const char_t *path,
|
||||
tileset_t **out
|
||||
) {
|
||||
assetBatchAdd(
|
||||
batch,
|
||||
path,
|
||||
assetTilesetLoader,
|
||||
NULL, 0,
|
||||
sizeof(tileset_t),
|
||||
NULL,
|
||||
(void**)out
|
||||
);
|
||||
}
|
||||
// errorret_t assetTilesetLoad(
|
||||
// const char_t *path,
|
||||
// tileset_t *out
|
||||
// ) {
|
||||
// return assetLoad(path, assetTilesetLoader, NULL, out);
|
||||
// }
|
||||
@@ -6,40 +6,30 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "asset/asset.h"
|
||||
#include "asset/assetbatch.h"
|
||||
#include "asset/assetfile.h"
|
||||
#include "display/texture/tileset.h"
|
||||
|
||||
typedef struct {
|
||||
void *nothing;
|
||||
} assettilesetloaderinput_t;
|
||||
|
||||
// NEW STUFF
|
||||
typedef struct assetloading_s assetloading_t;
|
||||
typedef struct assetentry_s assetentry_t;
|
||||
|
||||
typedef struct {
|
||||
assetfile_t file;
|
||||
} assettilesetloaderloading_t;
|
||||
|
||||
typedef tileset_t assettilesetoutput_t;
|
||||
|
||||
errorret_t assetTilesetLoaderNEW(assetloading_t *loading);
|
||||
errorret_t assetTilesetDisposeNEW(assetentry_t *entry);
|
||||
|
||||
/**
|
||||
* Handler for tileset assets.
|
||||
*
|
||||
* @param file Asset file to load the tileset from.
|
||||
* @return Any error that occurs during loading.
|
||||
*/
|
||||
errorret_t assetTilesetLoader(assetfile_t *file);
|
||||
|
||||
/**
|
||||
* Loads a tileset from the specified path.
|
||||
*
|
||||
* @param path Path to the tileset asset.
|
||||
* @param out Output tileset to load into.
|
||||
* @return Any error that occurs during loading.
|
||||
*/
|
||||
errorret_t assetTilesetLoad(
|
||||
const char_t *path,
|
||||
tileset_t *out
|
||||
);
|
||||
|
||||
/**
|
||||
* Adds a tileset load request to a batch. The cache-owned tileset_t* is
|
||||
* written to *out when the batch completes.
|
||||
*
|
||||
* @param batch The batch to add to.
|
||||
* @param path Path to the tileset asset.
|
||||
* @param out Receives a pointer to the loaded tileset on completion.
|
||||
*/
|
||||
void assetBatchTileset(
|
||||
assetbatch_t *batch,
|
||||
const char_t *path,
|
||||
tileset_t **out
|
||||
);
|
||||
errorret_t assetTilesetLoader(assetfile_t *file);
|
||||
@@ -45,9 +45,9 @@ errorret_t assetJsonLoader(assetfile_t *file) {
|
||||
return assetJsonLoadFileToDoc(file, outDoc);
|
||||
}
|
||||
|
||||
errorret_t assetJsonLoad(
|
||||
const char_t *path,
|
||||
yyjson_doc **outDoc
|
||||
) {
|
||||
return assetLoad(path, assetJsonLoader, NULL, outDoc);
|
||||
}
|
||||
// errorret_t assetJsonLoad(
|
||||
// const char_t *path,
|
||||
// yyjson_doc **outDoc
|
||||
// ) {
|
||||
// return assetLoad(path, assetJsonLoader, NULL, outDoc);
|
||||
// }
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "asset/asset.h"
|
||||
#include "asset/assetfile.h"
|
||||
#include "yyjson.h"
|
||||
|
||||
#define ASSET_JSON_FILE_SIZE_MAX 1024*256
|
||||
@@ -30,16 +30,4 @@ errorret_t assetJsonLoadFileToDoc(assetfile_t *file, yyjson_doc **outDoc);
|
||||
* @param file Asset file to load the locale from.
|
||||
* @return Any error that occurs during loading.
|
||||
*/
|
||||
errorret_t assetJsonLoader(assetfile_t *file);
|
||||
|
||||
/**
|
||||
* Loads a locale from the specified path.
|
||||
*
|
||||
* @param path Path to the locale asset.
|
||||
* @param outDoc Pointer to store the loaded JSON document.
|
||||
* @return Any error that occurs during loading.
|
||||
*/
|
||||
errorret_t assetJsonLoad(
|
||||
const char_t *path,
|
||||
yyjson_doc **outDoc
|
||||
);
|
||||
errorret_t assetJsonLoader(assetfile_t *file);
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "asset/asset.h"
|
||||
#include "asset/assetfile.h"
|
||||
|
||||
#define ASSET_LOCALE_FILE_PLURAL_FORM_COUNT 6
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "util/memory.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "asset/asset.h"
|
||||
#include "asset/assetbatch.h"
|
||||
#include "asset/loader/display/assettextureloader.h"
|
||||
#include "asset/loader/display/assettilesetloader.h"
|
||||
#include "display/shader/shaderunlit.h"
|
||||
@@ -18,17 +17,35 @@
|
||||
font_t FONT_DEFAULT;
|
||||
|
||||
errorret_t textInit(void) {
|
||||
assetbatch_t batch;
|
||||
assetBatchInit(&batch, NULL, NULL, NULL);
|
||||
assetBatchTexture(&batch, "ui/minogram.png", TEXTURE_FORMAT_RGBA, &FONT_DEFAULT.texture);
|
||||
assetBatchTileset(&batch, "ui/minogram.dtf", &FONT_DEFAULT.tileset);
|
||||
errorChain(assetBatchLoad(&batch));
|
||||
assetloaderinput_t input = {
|
||||
.texture = TEXTURE_FORMAT_RGBA
|
||||
};
|
||||
assetentry_t *entryTexture = assetGetEntry(
|
||||
"ui/minogram.png", ASSET_LOADER_TYPE_TEXTURE, &input
|
||||
);
|
||||
assetentry_t *entryTileset = assetGetEntry(
|
||||
"ui/minogram.dtf", ASSET_LOADER_TYPE_TILESET, NULL
|
||||
);
|
||||
errorChain(assetRequireLoaded(entryTexture));
|
||||
errorChain(assetRequireLoaded(entryTileset));
|
||||
FONT_DEFAULT.texture = &entryTexture->data.texture;
|
||||
FONT_DEFAULT.tileset = &entryTileset->data.tileset;
|
||||
|
||||
// assetentry_t *entryTileset = assetGetEntry(
|
||||
// "ui/minogram.dtf", ASSET_LOADER_TYPE_TILESET
|
||||
// );
|
||||
|
||||
// assetbatch_t batch;
|
||||
// assetBatchInit(&batch, NULL, NULL, NULL);
|
||||
// assetBatchTexture(&batch, "ui/minogram.png", TEXTURE_FORMAT_RGBA, &FONT_DEFAULT.texture);
|
||||
// assetBatchTileset(&batch, "ui/minogram.dtf", &FONT_DEFAULT.tileset);
|
||||
// errorChain(assetBatchLoad(&batch));
|
||||
errorOk();
|
||||
}
|
||||
|
||||
errorret_t textDispose(void) {
|
||||
assetCacheRelease(&ASSET.cache, "ui/minogram.png");
|
||||
assetCacheRelease(&ASSET.cache, "ui/minogram.dtf");
|
||||
// assetCacheRelease(&ASSET.cache, "ui/minogram.png");
|
||||
// assetCacheRelease(&ASSET.cache, "ui/minogram.dtf");
|
||||
FONT_DEFAULT.texture = NULL;
|
||||
FONT_DEFAULT.tileset = NULL;
|
||||
errorOk();
|
||||
|
||||
@@ -74,6 +74,7 @@ errorret_t engineUpdate(void) {
|
||||
errorChain(displayUpdate());
|
||||
errorChain(cutsceneUpdate());
|
||||
errorChain(sceneUpdate());
|
||||
errorChain(assetUpdate());
|
||||
|
||||
if(inputPressed(INPUT_ACTION_RAGEQUIT)) ENGINE.running = false;
|
||||
errorOk();
|
||||
|
||||
@@ -13,4 +13,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
string.c
|
||||
math.c
|
||||
sort.c
|
||||
ref.c
|
||||
)
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "ref.h"
|
||||
#include "memory.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
void refInit(
|
||||
ref_t *ref,
|
||||
void *data,
|
||||
refcallback_t onLock,
|
||||
refcallback_t onUnlock,
|
||||
refcallback_t onAllUnlocked
|
||||
) {
|
||||
assertNotNull(ref, "Ref cannot be NULL.");
|
||||
memoryZero(ref, sizeof(ref_t));
|
||||
ref->count = 1;
|
||||
ref->data = data;
|
||||
ref->onLock = onLock;
|
||||
ref->onUnlock = onUnlock;
|
||||
ref->onAllUnlocked = onAllUnlocked;
|
||||
}
|
||||
|
||||
void refLock(ref_t *ref) {
|
||||
assertNotNull(ref, "Ref cannot be NULL.");
|
||||
assertTrue(ref->count > 0, "Cannot lock a ref with zero count.");
|
||||
ref->count++;
|
||||
if(ref->onLock != NULL) ref->onLock(ref);
|
||||
}
|
||||
|
||||
bool_t refUnlock(ref_t *ref) {
|
||||
assertNotNull(ref, "Ref cannot be NULL.");
|
||||
assertTrue(ref->count > 0, "Cannot unlock a ref with zero count.");
|
||||
|
||||
ref->count--;
|
||||
|
||||
if(ref->count > 0) {
|
||||
if(ref->onUnlock != NULL) ref->onUnlock(ref);
|
||||
return false;
|
||||
}
|
||||
|
||||
void *data = ref->data;
|
||||
refcallback_t onAllUnlocked = ref->onAllUnlocked;
|
||||
memoryZero(ref, sizeof(ref_t));
|
||||
ref->data = data;
|
||||
if(onAllUnlocked != NULL) onAllUnlocked(ref);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef struct ref_s ref_t;
|
||||
typedef void (*refcallback_t)(ref_t *ref);
|
||||
|
||||
typedef struct ref_s {
|
||||
uint32_t count;
|
||||
void *data;
|
||||
refcallback_t onLock;
|
||||
refcallback_t onUnlock;
|
||||
refcallback_t onAllUnlocked;
|
||||
} ref_t;
|
||||
|
||||
/**
|
||||
* Initializes a ref with a count of 1.
|
||||
*
|
||||
* @param ref The ref to initialize.
|
||||
* @param data Opaque context pointer accessible to all callbacks.
|
||||
* @param onLock Called each time the ref is locked. May be NULL.
|
||||
* @param onUnlock Called each time the ref is unlocked (count still > 0). May be NULL.
|
||||
* @param onAllUnlocked Called when the count reaches zero. Responsible for
|
||||
* any cleanup. May be NULL.
|
||||
*/
|
||||
void refInit(
|
||||
ref_t *ref,
|
||||
void *data,
|
||||
refcallback_t onLock,
|
||||
refcallback_t onUnlock,
|
||||
refcallback_t onAllUnlocked
|
||||
);
|
||||
|
||||
/**
|
||||
* Increments the lock count.
|
||||
*
|
||||
* @param ref The ref to lock.
|
||||
*/
|
||||
void refLock(ref_t *ref);
|
||||
|
||||
/**
|
||||
* Decrements the lock count. When it reaches zero onAllUnlocked is called
|
||||
* (if set) and the ref struct is zeroed.
|
||||
*
|
||||
* @param ref The ref to unlock.
|
||||
* @return true if the count reached zero.
|
||||
*/
|
||||
bool_t refUnlock(ref_t *ref);
|
||||
Reference in New Issue
Block a user