180 lines
6.1 KiB
C
180 lines
6.1 KiB
C
/*
|
|
* This software is licensed under the terms of the MIT License.
|
|
* See COPYING for further information.
|
|
* ---
|
|
* Copyright (c) 2011-2024, Lukas Weber <laochailan@web.de>.
|
|
* Copyright (c) 2012-2024, Andrei Alexeyev <akari@taisei-project.org>.
|
|
*/
|
|
|
|
#pragma once
|
|
#include "taisei.h"
|
|
|
|
#include "dynarray.h"
|
|
#include "hashtable.h"
|
|
#include "vfs/public.h"
|
|
|
|
typedef enum ResourceType {
|
|
RES_TEXTURE,
|
|
RES_ANIM,
|
|
RES_SFX,
|
|
RES_BGM,
|
|
RES_SHADER_OBJECT,
|
|
RES_SHADER_PROGRAM,
|
|
RES_MODEL,
|
|
RES_POSTPROCESS,
|
|
RES_SPRITE,
|
|
RES_FONT,
|
|
RES_MATERIAL,
|
|
RES_NUMTYPES,
|
|
} ResourceType;
|
|
|
|
typedef enum ResourceFlags {
|
|
RESF_OPTIONAL = 1,
|
|
RESF_PRELOAD = 2,
|
|
RESF_RELOAD = 4,
|
|
|
|
RESF_DEFAULT = 0,
|
|
} ResourceFlags;
|
|
|
|
typedef struct ResourceLoadState ResourceLoadState;
|
|
|
|
struct ResourceLoadState {
|
|
const char *name;
|
|
const char *path;
|
|
void *opaque;
|
|
ResourceFlags flags;
|
|
};
|
|
|
|
// Converts an abstract resource name into a vfs path from which a resource with that name could be loaded.
|
|
// The path may not actually exist or be usable. The load function (see below) shall deal with such cases.
|
|
// The returned path must be free()'d.
|
|
// May return NULL on failure, but does not have to.
|
|
typedef char *(*ResourceFindProc)(const char *name);
|
|
|
|
// Tells whether the resource handler should attempt to load a file, specified by a vfs path.
|
|
typedef bool (*ResourceCheckProc)(const char *path);
|
|
|
|
// Begins loading a resource. Called on an unspecified thread.
|
|
// Must call one of the following res_load_* functions before returning to indicate status.
|
|
typedef void (*ResourceLoadProc)(ResourceLoadState *st);
|
|
|
|
// Makes `dst` refer to the resource represented by `src`.
|
|
// `src` may no longer be a valid reference to the resource after this operation.
|
|
// Resource previously represented by `dst` is destroyed in the process.
|
|
// Called on the main thread, after a resource reload successfully completes.
|
|
//
|
|
// Returns true if the operation succeeds.
|
|
// In case of failure, `dst` must not be modified, and `src` must be destroyed.
|
|
typedef bool (*ResourceTransferProc)(void *dst, void *src);
|
|
|
|
void res_load_failed(ResourceLoadState *st) attr_nonnull(1);
|
|
void res_load_finished(ResourceLoadState *st, void *res) attr_nonnull(1, 2);
|
|
|
|
// Indicates that loading must continue on the main thread.
|
|
// Schedules callback to be called on the main thread at some point in the future.
|
|
// The callback's load state parameter will contain the opaque pointer passed to this function.
|
|
// If the resource has dependencies, callback will not be called until they finish loading.
|
|
void res_load_continue_on_main(ResourceLoadState *st, ResourceLoadProc callback, void *opaque) attr_nonnull(1, 2);
|
|
|
|
// Like res_load_continue_on_main, but may be called from a worker thread.
|
|
// Use this to wait for dependencies if nothing needs to be done on the main thread.
|
|
void res_load_continue_after_dependencies(ResourceLoadState *st, ResourceLoadProc callback, void *opaque) attr_nonnull(1, 2);
|
|
|
|
// Registers another resource as a dependency and schedules it for asynchronous loading.
|
|
// Use with res_load_continue_after_dependencies/res_load_continue_on_main to wait for dependencies.
|
|
void res_load_dependency(ResourceLoadState *st, ResourceType type, const char *name);
|
|
|
|
// Like vfs_open(), but registers the path to monitor the file for changes.
|
|
// When a change is detected, the resource will be reloaded.
|
|
// This only works if the transfer proc is implemented; otherwise it's equivalent to vfs_open().
|
|
// Note that file monitoring support is not guaranteed.
|
|
SDL_RWops *res_open_file(ResourceLoadState *st, const char *path, VFSOpenMode mode);
|
|
|
|
// Unloads a resource, freeing all allocated to it memory.
|
|
typedef void (*ResourceUnloadProc)(void *res);
|
|
|
|
// Called during resource subsystem initialization
|
|
typedef void (*ResourceInitProc)(void);
|
|
|
|
// Called after the resources and rendering subsystems have been initialized
|
|
typedef void (*ResourcePostInitProc)(void);
|
|
|
|
// Called during resource subsystem shutdown
|
|
typedef void (*ResourceShutdownProc)(void);
|
|
|
|
typedef struct ResourceHandler {
|
|
ResourceType type;
|
|
|
|
char *typename;
|
|
char *subdir;
|
|
|
|
struct {
|
|
ResourceFindProc find;
|
|
ResourceCheckProc check;
|
|
ResourceLoadProc load;
|
|
ResourceUnloadProc unload;
|
|
ResourceTransferProc transfer;
|
|
ResourceInitProc init;
|
|
ResourcePostInitProc post_init;
|
|
ResourceShutdownProc shutdown;
|
|
} procs;
|
|
|
|
struct {
|
|
ht_str2ptr_ts_t mapping;
|
|
} private;
|
|
} ResourceHandler;
|
|
|
|
typedef struct Resource {
|
|
void *data;
|
|
ResourceType type;
|
|
ResourceFlags flags;
|
|
} Resource;
|
|
|
|
typedef struct ResourceGroup {
|
|
DYNAMIC_ARRAY(void*) refs;
|
|
} ResourceGroup;
|
|
|
|
void res_init(void);
|
|
void res_post_init(void);
|
|
void res_shutdown(void);
|
|
void res_reload_all(void);
|
|
void res_purge(void);
|
|
|
|
Resource *_res_get_prehashed(ResourceType type, const char *name, hash_t hash, ResourceFlags flags) attr_nonnull_all;
|
|
|
|
INLINE void *_res_get_data_prehashed(ResourceType type, const char *name, hash_t hash, ResourceFlags flags) {
|
|
Resource *res = _res_get_prehashed(type, name, hash, flags);
|
|
return res ? res->data : NULL;
|
|
}
|
|
|
|
attr_nonnull_all
|
|
INLINE Resource *res_get(ResourceType type, const char *name, ResourceFlags flags) {
|
|
return _res_get_prehashed(type, name, ht_str2ptr_hash(name), flags);
|
|
}
|
|
|
|
attr_nonnull_all
|
|
INLINE void *res_get_data(ResourceType type, const char *name, ResourceFlags flags) {
|
|
return _res_get_data_prehashed(type, name, ht_str2ptr_hash(name), flags);
|
|
}
|
|
|
|
void *res_for_each(ResourceType type, void *(*callback)(const char *name, Resource *res, void *arg), void *arg);
|
|
|
|
void res_group_init(ResourceGroup *rg) attr_nonnull_all;
|
|
void res_group_release(ResourceGroup *rg) attr_nonnull_all;
|
|
void res_group_preload(ResourceGroup *rg, ResourceType type, ResourceFlags flags, ...)
|
|
attr_sentinel;
|
|
|
|
void res_util_strip_ext(char *path);
|
|
char *res_util_basename(const char *prefix, const char *path);
|
|
|
|
#define DEFINE_RESOURCE_GETTER(_type, _name, _enum) \
|
|
attr_nonnull_all attr_returns_nonnull \
|
|
INLINE _type *_name(const char *resname) { \
|
|
return NOT_NULL(res_get_data(_enum, resname, RESF_DEFAULT)); \
|
|
}
|
|
|
|
#define DEFINE_OPTIONAL_RESOURCE_GETTER(_type, _name, _enum) \
|
|
attr_nonnull_all \
|
|
INLINE _type *_name(const char *resname) { \
|
|
return res_get_data(_enum, resname, RESF_OPTIONAL); \
|
|
}
|