techkaczynski.dev / code

summaryrefslogtreecommitdiff
path: root/res.c
diff options
context:
space:
mode:
authortech kaczynski <tk@techkaczynski.dev>2026-09-22 22:38:57 +1000
committertech kaczynski <tk@techkaczynski.dev>2026-09-22 22:38:57 +1000
commit08cb8d6a585dd552b69a488d9db1be123f01467a (patch)
tree77d50ce30bbc102b08486929ba654b5bef70af43 /res.c
initial commit.
Diffstat (limited to 'res.c')
-rw-r--r--res.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/res.c b/res.c
new file mode 100644
index 0000000..b1ed86f
--- /dev/null
+++ b/res.c
@@ -0,0 +1,251 @@
+#include "res.h"
+#include "raygui.h"
+
+typedef struct {
+ map_t(Asset) assets;
+ map_t(FunShader) sdr;
+} Resources;
+
+static Resources res = {0};
+
+static bool
+asset_load_data(cstr key) {
+ Asset *asset = map_get(&res.assets, key);
+ cstr ext = GetFileExtension(key);
+ bool success = false;
+
+ if (!strcmp(ext, ".glb")) {
+ Model mdl = LoadModel(key);
+
+ if (!IsModelValid(mdl)) {
+ UnloadModel(mdl);
+ return false;
+ }
+
+ for (int i = 0; i < mdl.materialCount; ++i) {
+ mdl.materials[i].shader = shader_get("model")->sdr;
+ }
+
+ asset->tag = ASSET_TAG_MODEL;
+ asset->mdl = mdl;
+ success = true;
+ }
+
+ if (!strcmp(ext, ".png")) {
+ Texture tex = LoadTexture(key);
+
+ if (!IsTextureValid(tex)) {
+ UnloadTexture(tex);
+ return false;
+ }
+
+ GenTextureMipmaps(&tex);
+ // SetTextureFilter(tex, TEXTURE_FILTER_ANISOTROPIC_16X);
+ SetTextureFilter(tex, TEXTURE_FILTER_TRILINEAR);
+ // SetTextureFilter(tex, TEXTURE_FILTER_BILINEAR);
+
+ asset->tag = ASSET_TAG_TEXTURE;
+ asset->tex = tex;
+ success = true;
+ }
+
+ if (!strcmp(ext, ".ttf") || !strcmp(ext, ".otf")) {
+ Font fnt = LoadFont(key);
+
+ if (!IsFontValid(fnt)) {
+ UnloadFont(fnt);
+ return false;
+ }
+
+ asset->tag = ASSET_TAG_FONT;
+ asset->fnt = fnt;
+ success = true;
+ }
+
+ if (!strcmp(ext, ".ogg")) {
+ Sound snd = LoadSound(key);
+
+ if (!IsSoundValid(snd)) {
+ UnloadSound(snd);
+ return false;
+ }
+
+ asset->tag = ASSET_TAG_SOUND;
+ asset->snd = snd;
+ success = true;
+ }
+
+ if (!success) {
+ TraceLog(LOG_WARNING, "'%s' no valid file ext found.", key);
+ return false;
+ }
+
+ asset->loaded = true;
+ return true;
+}
+
+static void
+asset_unload(cstr key) {
+ Asset *asset = map_get(&res.assets, key);
+ if (!asset) {
+ TraceLog(LOG_WARNING,
+ "asset_unload: invalid key '%s'\n", key);
+ return;
+ }
+
+ if (!asset->loaded) {
+ TraceLog(LOG_INFO,
+ "asset_unload: nothing to unload '%s'", key);
+ return;
+ }
+
+ free(asset->path);
+ asset->path_strlen = 0;
+
+ switch(asset->tag) {
+ case ASSET_TAG_MODEL:
+ UnloadModel(asset->mdl);
+ break;
+ case ASSET_TAG_TEXTURE:
+ UnloadTexture(asset->tex);
+ break;
+ case ASSET_TAG_SOUND:
+ UnloadSound(asset->snd);
+ break;
+ case ASSET_TAG_FONT:
+ UnloadFont(asset->fnt);
+ break;
+ case ASSET_TAG_INVALID:
+ TraceLog(LOG_WARNING,
+ "asset_unload: invalid tag '%s'\n", key);
+ break;
+ }
+}
+
+void
+res_init(void) {
+ map_init(&res.sdr);
+ map_init(&res.assets);
+
+ fun_shader_create("model",
+ "res/sdr/mdl_vtx_lit.vs",
+ "res/sdr/mdl_vtx_lit.fs");
+
+ fun_shader_create("sky", NULL, "res/sdr/sky.fs");
+
+ cstr filter = ".glb;.png;.ttf;.otf;.ogg";
+ FilePathList res_list = LoadDirectoryFilesEx("res", filter, true);
+
+ for (int i = 0; i < res_list.count; ++i) {
+ cstr path = res_list.paths[i];
+ Asset asset = {0};
+ asset.path_strlen = strlen(path);
+ asset.path = strdup(path); // freed in asset_unload
+ map_set(&res.assets, asset.path, asset);
+ }
+
+ UnloadDirectoryFiles(res_list);
+}
+
+void
+res_exit(void) {
+ cstr key;
+ map_iter_t iter;
+
+ iter = map_iter(&res.assets);
+ while ((key = map_next(&res.assets, &iter))) {
+ asset_unload(key);
+ }
+
+ iter = map_iter(&res.sdr);
+ while ((key = map_next(&res.sdr, &iter))) {
+ FunShader *sdr = map_get(&res.sdr, key);
+ if (!sdr) {
+ TraceLog(LOG_ERROR, "res_exit: '%s' invalid\n", key);
+ }
+ fun_shader_delete(sdr);
+ }
+
+ map_deinit(&res.assets);
+ map_deinit(&res.sdr);
+}
+
+void
+res_update(void) {
+}
+
+Asset*
+asset_get(cstr key) {
+ Asset *asset = map_get(&res.assets, key);
+ if (!asset) {
+ TraceLog(LOG_ERROR, "asset '%s' not found.\n", key);
+ return NULL;
+ }
+
+ if (!asset->loaded) {
+ if (!asset_load_data(key)) {
+ TraceLog(LOG_ERROR, "asset '%s' couldn't load.", key);
+ return NULL;
+ }
+ }
+
+ return asset;
+}
+
+FunShader*
+shader_get(cstr key) {
+ FunShader *sdr = map_get(&res.sdr, key);
+ if (!sdr) {
+ TraceLog(LOG_ERROR, "shader '%s' not found.", key);
+ return NULL;
+ }
+ return sdr;
+}
+
+void
+fun_shader_create(cstr key, cstr vpath, cstr fpath) {
+ FunShader shader = {0};
+ shader.sdr = LoadShader(vpath, fpath);
+ if (!IsShaderValid(shader.sdr)) {
+ printf("err: fun_shader_create('%s', '%s', '%s')\n",
+ key, vpath, fpath);
+ exit(1);
+ }
+ map_init(&shader.uniforms);
+ map_set(&res.sdr, key, shader);
+}
+
+void
+fun_shader_delete(FunShader *shader) {
+ UnloadShader(shader->sdr);
+ map_deinit(&shader->uniforms);
+}
+
+int
+fun_shader_uniform(cstr skey, cstr ukey) {
+ FunShader *sdr = shader_get(skey);
+
+ int *ret = map_get(&sdr->uniforms, ukey);
+ if (ret) {
+ return *ret;
+ }
+
+ BeginShaderMode(sdr->sdr);
+ int loc = rlGetLocationUniform(sdr->sdr.id, ukey);
+ if (loc < 0) {
+ TraceLog(LOG_ERROR,
+ "shader '%s' uniform '%s' not found.\n", skey, ukey);
+ exit(1);
+ }
+ EndShaderMode();
+
+ map_set(&sdr->uniforms, ukey, loc);
+ ret = map_get(&sdr->uniforms, ukey);
+ if (!ret) {
+ TraceLog(LOG_ERROR,
+ "shader '%s' uniform '%s' not found", skey, ukey);
+ return -1;
+ }
+
+ return *ret;
+}