make asset paths configurable

Sat, 19 Apr 2025 15:06:24 +0200

author
Mike Becker <universe@uap-core.de>
date
Sat, 19 Apr 2025 15:06:24 +0200
changeset 86
943bf9d7c6d6
parent 85
f51eec4e7ccb
child 87
874a02a683c5

make asset paths configurable

Makefile file | annotate | diff | comparison | revisions
src/Makefile file | annotate | diff | comparison | revisions
src/ascension/context.h file | annotate | diff | comparison | revisions
src/ascension/filesystem.h file | annotate | diff | comparison | revisions
src/context.c file | annotate | diff | comparison | revisions
src/filesystem.c file | annotate | diff | comparison | revisions
src/font.c file | annotate | diff | comparison | revisions
src/shader.c file | annotate | diff | comparison | revisions
src/texture.c file | annotate | diff | comparison | revisions
test/snake/Makefile file | annotate | diff | comparison | revisions
test/snake/snake.c file | annotate | diff | comparison | revisions
--- a/Makefile	Sat Apr 19 13:00:32 2025 +0200
+++ b/Makefile	Sat Apr 19 15:06:24 2025 +0200
@@ -23,11 +23,12 @@
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
-all: config.mk build/lib/libascension.a
+all: build/lib/libascension.a \
+	test-snake
 
 test-snake: build/test/snake FORCE
 
-build/test/snake: all
+build/test/snake: build/lib/libascension.a FORCE
 	@cd test/snake && $(MAKE)
 
 build/lib/libascension.a: build/lib config.mk FORCE
@@ -48,7 +49,7 @@
 
 update-rules:
 	make/update-rules.sh src
-	CFLAGS=-I`pwd`/src make/update-rules.sh test/snake
+	CFLAGS=-I../../src make/update-rules.sh test/snake
 
 FORCE:
 
--- a/src/Makefile	Sat Apr 19 13:00:32 2025 +0200
+++ b/src/Makefile	Sat Apr 19 15:06:24 2025 +0200
@@ -27,7 +27,8 @@
 
 BUILD_DIR=../build/lib
 
-SRC = context.c glcontext.c error.c window.c shader.c \
+SRC = context.c glcontext.c error.c filesystem.c window.c \
+	  shader.c \
 	  mesh.c primitives.c texture.c \
 	  sprite.c \
 	  camera.c scene.c \
@@ -66,12 +67,16 @@
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
-$(BUILD_DIR)/font.o: font.c ascension/ui/font.h ascension/context.h \
- ascension/datatypes.h ascension/window.h ascension/glcontext.h \
- ascension/primitives.h ascension/mesh.h ascension/shader.h \
- ascension/scene.h ascension/scene_node.h ascension/transform.h \
- ascension/camera.h ascension/input.h ascension/ui/font.h \
- ascension/error.h
+$(BUILD_DIR)/filesystem.o: filesystem.c ascension/filesystem.h
+	@echo "Compiling $<"
+	$(CC) -o $@ $(CFLAGS) -c $<
+
+$(BUILD_DIR)/font.o: font.c ascension/context.h ascension/datatypes.h \
+ ascension/window.h ascension/glcontext.h ascension/primitives.h \
+ ascension/mesh.h ascension/shader.h ascension/scene.h \
+ ascension/scene_node.h ascension/transform.h ascension/camera.h \
+ ascension/input.h ascension/ui/font.h ascension/error.h \
+ ascension/filesystem.h ascension/ui/font.h
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
@@ -104,7 +109,12 @@
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
-$(BUILD_DIR)/shader.o: shader.c ascension/shader.h ascension/error.h
+$(BUILD_DIR)/shader.o: shader.c ascension/context.h ascension/datatypes.h \
+ ascension/window.h ascension/glcontext.h ascension/primitives.h \
+ ascension/mesh.h ascension/shader.h ascension/scene.h \
+ ascension/scene_node.h ascension/transform.h ascension/camera.h \
+ ascension/input.h ascension/ui/font.h ascension/shader.h \
+ ascension/error.h ascension/filesystem.h
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
--- a/src/ascension/context.h	Sat Apr 19 13:00:32 2025 +0200
+++ b/src/ascension/context.h	Sat Apr 19 15:06:24 2025 +0200
@@ -34,6 +34,7 @@
 #include "ui/font.h"
 
 #include <cx/buffer.h>
+#include <cx/string.h>
 
 /** The flag for the overall initialized state. */
 #define ASC_FLAG_INITILIZED  0x01u
@@ -50,6 +51,9 @@
 typedef struct AscContext {
     unsigned int flags;
     CxBuffer error_buffer;
+    cxmutstr font_path;
+    cxmutstr shader_path;
+    cxmutstr texture_path;
     AscInput input;
     AscWindow windows[ASC_MAX_WINDOWS];
     AscFont active_font;
@@ -107,5 +111,10 @@
 #define asc_ink_rgba(r,g,b,a) asc_context.ink = (asc_col4i){(r),(g),(b),(a)}
 #define asc_ink_rgb(r,g,b) asc_context.ink = (asc_col4i){(r),(g),(b),255u}
 
+
+void asc_set_font_path(const char *path);
+void asc_set_shader_path(const char *path);
+void asc_set_texture_path(const char *path);
+
 #endif /* ASCENSION_CONTEXT_H */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ascension/filesystem.h	Sat Apr 19 15:06:24 2025 +0200
@@ -0,0 +1,46 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ * Copyright 2025 Mike Becker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ASCENSION_FILESYSTEM_H
+#define ASCENSION_FILESYSTEM_H
+
+#include <cx/string.h>
+
+bool asc_filesystem_is_absolute(cxstring path);
+
+/**
+ * Combines a path with a base path if it is relative.
+ *
+ * The resulting string must be freed with cx_strfree().
+ *
+ * @param base the base path
+ * @param path an absolute or relative path
+ * @return if @p path is relative, the combination of @p base and @p path, or just @p path otherwise
+ */
+cxmutstr asc_filesystem_combine_paths(cxstring base, cxstring path);
+
+#endif
--- a/src/context.c	Sat Apr 19 13:00:32 2025 +0200
+++ b/src/context.c	Sat Apr 19 15:06:24 2025 +0200
@@ -51,6 +51,11 @@
         return;
     memset(&asc_context, 0, sizeof(AscContext));
 
+    // initialize default paths
+    asc_context.font_path = cx_strdup(CX_STR("./fonts"));
+    asc_context.shader_path = cx_strdup(CX_STR("./shader"));
+    asc_context.texture_path = cx_strdup(CX_STR("./textures"));
+
     // initialize the font cache
     asc_font_cache_init();
 
@@ -102,6 +107,11 @@
     cxBufferDestroy(&asc_context.error_buffer);
     asc_context.flags = 0;
     asc_dprintf("Ascension context destroyed.");
+
+    // destroy the path information
+    cx_strfree(&asc_context.font_path);
+    cx_strfree(&asc_context.shader_path);
+    cx_strfree(&asc_context.texture_path);
 }
 
 void asc_context_quit(void) {
@@ -191,3 +201,15 @@
 
     return !asc_test_flag(asc_context.flags, ASC_FLAG_QUIT);
 }
+
+void asc_set_font_path(const char *path) {
+    cx_strcpy(&asc_context.font_path, cx_str(path));
+}
+
+void asc_set_shader_path(const char *path) {
+    cx_strcpy(&asc_context.shader_path, cx_str(path));
+}
+
+void asc_set_texture_path(const char *path) {
+    cx_strcpy(&asc_context.texture_path, cx_str(path));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/filesystem.c	Sat Apr 19 15:06:24 2025 +0200
@@ -0,0 +1,54 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ * Copyright 2025 Mike Becker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ascension/filesystem.h"
+
+bool asc_filesystem_is_absolute(cxstring path) {
+#ifdef _WIN32
+#error "Windows currently not supported."
+#else
+    return path.length > 0 && path.ptr[0] == '/';
+#endif
+}
+
+
+cxmutstr asc_filesystem_combine_paths(cxstring base, cxstring path) {
+    if (asc_filesystem_is_absolute(path)) {
+        return cx_strdup(path);
+    }
+    if (base.length == 0) {
+        return cx_strdup(path);
+    }
+
+    if (base.ptr[base.length - 1] == '/') base.length--;
+
+    if (cx_strprefix(path, CX_STR("./"))) {
+        path = cx_strsubs(path, 2);
+    }
+
+    return cx_strcat(3, base, CX_STR("/"), path);
+}
--- a/src/font.c	Sat Apr 19 13:00:32 2025 +0200
+++ b/src/font.c	Sat Apr 19 15:06:24 2025 +0200
@@ -25,9 +25,10 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "ascension/ui/font.h"
 #include "ascension/context.h"
 #include "ascension/error.h"
+#include "ascension/filesystem.h"
+#include "ascension/ui/font.h"
 
 #include <assert.h>
 #include <cx/array_list.h>
@@ -40,13 +41,13 @@
 static char const *asc_font_filename(enum AscFontStyle style) {
     switch (style) {
         case ASC_FONT_REGULAR:
-            return "fonts/OpenSans-Regular.ttf";
+            return "OpenSans-Regular.ttf";
         case ASC_FONT_BOLD:
-            return "fonts/OpenSans-Bold.ttf";
+            return "OpenSans-Bold.ttf";
         case ASC_FONT_ITALIC:
-            return "fonts/OpenSans-Italic.ttf";
+            return "OpenSans-Italic.ttf";
         case ASC_FONT_BOLD_ITALIC:
-            return "fonts/OpenSans-BoldItalic.ttf";
+            return "OpenSans-BoldItalic.ttf";
         default:
             assert(false);
             return NULL;
@@ -78,7 +79,6 @@
     cxListFree(asc_font_cache);
 }
 
-
 TTF_Font *asc_font_load(AscFont font) {
     CxIterator iter = cxListIterator(asc_font_cache);
     cx_foreach(struct asc_font_cache_entry*, cache, iter) {
@@ -89,7 +89,9 @@
 
     struct asc_font_cache_entry entry;
     entry.font = font;
-    entry.ttf = TTF_OpenFont(asc_font_filename(font.style), font.size);
+    cxmutstr fpath = asc_filesystem_combine_paths(cx_strcast(asc_context.font_path), cx_str(asc_font_filename(font.style)));
+    entry.ttf = TTF_OpenFont(fpath.ptr, font.size);
+    cx_strfree(&fpath);
     if (entry.ttf == NULL) {
         asc_error(TTF_GetError());
         return NULL;
--- a/src/shader.c	Sat Apr 19 13:00:32 2025 +0200
+++ b/src/shader.c	Sat Apr 19 15:06:24 2025 +0200
@@ -25,8 +25,10 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "ascension/context.h"
 #include "ascension/shader.h"
 #include "ascension/error.h"
+#include "ascension/filesystem.h"
 
 #include <GL/glew.h>
 #include <string.h>
@@ -121,8 +123,8 @@
 int asc_shader_sprite_init(AscShaderSprite *sprite) {
     AscShaderCodes codes;
     if (asc_shader_load_code_files((AscShaderCodeFiles){
-        .vtx = "./shader/sprite_vtx.glsl",
-        .frag = "./shader/sprite_frag.glsl"
+        .vtx = "sprite_vtx.glsl",
+        .frag = "sprite_frag.glsl"
     }, &codes)) {
         asc_error("Loading sprite shader failed.");
         return 1;
@@ -159,7 +161,9 @@
         *code = NULL;
         return 0;
     }
-    FILE *f = fopen(filename, "r");
+    cxmutstr fpath = asc_filesystem_combine_paths(cx_strcast(asc_context.shader_path), cx_str(filename));
+    FILE *f = fopen(fpath.ptr, "r");
+    cx_strfree(&fpath);
     if (f == NULL) return -1;
     CxBuffer buffer;
     cxBufferInit(&buffer, NULL, 1024, NULL, CX_BUFFER_AUTO_EXTEND);
--- a/src/texture.c	Sat Apr 19 13:00:32 2025 +0200
+++ b/src/texture.c	Sat Apr 19 15:06:24 2025 +0200
@@ -39,9 +39,15 @@
     }
     glBindTexture(tex->target, tex->tex_id);
     glUniform1i(uniform_location, unit);
+    asc_error_catch_all_gl();
 }
 
 void asc_texture_from_surface(AscTexture *tex, SDL_Surface const *surface) {
+    if (asc_texture_uninitialized(tex)) {
+        asc_error("Tried to use uninitialized texture.");
+        asc_dprintf("Texture address: %"PRIxPTR, (uintptr_t) tex);
+        return;
+    }
     glBindTexture(tex->target,tex->tex_id);
     glPixelStorei(GL_UNPACK_ROW_LENGTH,
                   surface->pitch / surface->format->BytesPerPixel);
@@ -49,6 +55,7 @@
                  surface->w, surface->h,
                  0, GL_BGRA,
                  GL_UNSIGNED_BYTE, surface->pixels);
+    asc_error_catch_all_gl();
 }
 
 void asc_texture_init(
@@ -79,6 +86,7 @@
     glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER,
                     texture_filters[mag_filter]);
     asc_dprintf("Initialized texture: %u", tex->tex_id);
+    asc_error_catch_all_gl();
 }
 
 void asc_texture_destroy(AscTexture *tex) {
--- a/test/snake/Makefile	Sat Apr 19 13:00:32 2025 +0200
+++ b/test/snake/Makefile	Sat Apr 19 15:06:24 2025 +0200
@@ -27,7 +27,7 @@
 
 BUILD_DIR=$(srcdir)/build/test
 LIB_ASCENSION=$(srcdir)/build/lib/libascension.a
-CFLAGS += -I$(srcdir)/src
+CFLAGS += -I$(srcdir)/src -DTEST_BUILD
 
 all: $(BUILD_DIR) $(BUILD_DIR)/snake FORCE
 	@echo "Demo game 'snake' successfully built."
@@ -44,29 +44,19 @@
 
 FORCE:
 
-$(BUILD_DIR)/snake.o: snake.c \
- /home/mike/workspace/c/ascension/src/ascension/core.h \
- /home/mike/workspace/c/ascension/src/ascension/error.h \
- /home/mike/workspace/c/ascension/src/ascension/context.h \
- /home/mike/workspace/c/ascension/src/ascension/datatypes.h \
- /home/mike/workspace/c/ascension/src/ascension/window.h \
- /home/mike/workspace/c/ascension/src/ascension/glcontext.h \
- /home/mike/workspace/c/ascension/src/ascension/primitives.h \
- /home/mike/workspace/c/ascension/src/ascension/mesh.h \
- /home/mike/workspace/c/ascension/src/ascension/shader.h \
- /home/mike/workspace/c/ascension/src/ascension/scene.h \
- /home/mike/workspace/c/ascension/src/ascension/scene_node.h \
- /home/mike/workspace/c/ascension/src/ascension/transform.h \
- /home/mike/workspace/c/ascension/src/ascension/camera.h \
- /home/mike/workspace/c/ascension/src/ascension/input.h \
- /home/mike/workspace/c/ascension/src/ascension/ui/font.h \
- /home/mike/workspace/c/ascension/src/ascension/ui.h \
- /home/mike/workspace/c/ascension/src/ascension/ui/text.h \
- /home/mike/workspace/c/ascension/src/ascension/ui/font.h \
- /home/mike/workspace/c/ascension/src/ascension/ui/../2d/sprite.h \
- /home/mike/workspace/c/ascension/src/ascension/ui/../2d/../scene_node.h \
- /home/mike/workspace/c/ascension/src/ascension/ui/../2d/../texture.h \
- /home/mike/workspace/c/ascension/src/ascension/ui/../utils.h
+$(BUILD_DIR)/snake.o: snake.c ../../src/ascension/core.h \
+ ../../src/ascension/error.h ../../src/ascension/context.h \
+ ../../src/ascension/datatypes.h ../../src/ascension/window.h \
+ ../../src/ascension/glcontext.h ../../src/ascension/primitives.h \
+ ../../src/ascension/mesh.h ../../src/ascension/shader.h \
+ ../../src/ascension/scene.h ../../src/ascension/scene_node.h \
+ ../../src/ascension/transform.h ../../src/ascension/camera.h \
+ ../../src/ascension/input.h ../../src/ascension/ui/font.h \
+ ../../src/ascension/ui.h ../../src/ascension/ui/text.h \
+ ../../src/ascension/ui/font.h ../../src/ascension/ui/../2d/sprite.h \
+ ../../src/ascension/ui/../2d/../scene_node.h \
+ ../../src/ascension/ui/../2d/../texture.h \
+ ../../src/ascension/ui/../utils.h
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
--- a/test/snake/snake.c	Sat Apr 19 13:00:32 2025 +0200
+++ b/test/snake/snake.c	Sat Apr 19 15:06:24 2025 +0200
@@ -82,6 +82,13 @@
                 "Fatal Error",asc_get_error(),NULL);
         return 1;
     }
+#ifdef TEST_BUILD
+    asc_set_font_path("../../fonts");
+    asc_set_shader_path("../../shader");
+    asc_set_texture_path("../../test/snake/textures");
+#else
+#warning "Live build not yet supported"
+#endif
 
     // create window
     AscWindowSettings settings;

mercurial