# HG changeset patch # User Mike Becker # Date 1745067984 -7200 # Node ID 943bf9d7c6d6a4719608882178bea6c3899b0af5 # Parent f51eec4e7ccbab615c4b9507c2295ea935df8bc3 make asset paths configurable diff -r f51eec4e7ccb -r 943bf9d7c6d6 Makefile --- 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: diff -r f51eec4e7ccb -r 943bf9d7c6d6 src/Makefile --- 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 $< diff -r f51eec4e7ccb -r 943bf9d7c6d6 src/ascension/context.h --- 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 +#include /** 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 */ diff -r f51eec4e7ccb -r 943bf9d7c6d6 src/ascension/filesystem.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 + +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 diff -r f51eec4e7ccb -r 943bf9d7c6d6 src/context.c --- 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)); +} diff -r f51eec4e7ccb -r 943bf9d7c6d6 src/filesystem.c --- /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); +} diff -r f51eec4e7ccb -r 943bf9d7c6d6 src/font.c --- 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 #include @@ -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; diff -r f51eec4e7ccb -r 943bf9d7c6d6 src/shader.c --- 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 #include @@ -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); diff -r f51eec4e7ccb -r 943bf9d7c6d6 src/texture.c --- 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) { diff -r f51eec4e7ccb -r 943bf9d7c6d6 test/snake/Makefile --- 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 $< diff -r f51eec4e7ccb -r 943bf9d7c6d6 test/snake/snake.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;