summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt18
-rw-r--r--src/core/include/engine/core/dltools.h16
-rw-r--r--src/core/include/engine/core/logging.h49
-rw-r--r--src/core/include/engine/core/memory.h25
-rw-r--r--src/core/include/engine/core/state.h31
-rw-r--r--src/core/include/engine/core/types.h34
-rw-r--r--src/core/include/engine/engine.h130
-rw-r--r--src/ctrl/CMakeLists.txt12
-rw-r--r--src/ctrl/include/engine/ctrl/input.h92
-rw-r--r--src/rendering/CMakeLists.txt15
-rw-r--r--src/rendering/include/engine/rendering/rendering.h101
-rw-r--r--src/resources/CMakeLists.txt8
-rw-r--r--src/resources/include/engine/resources/resources.h79
-rw-r--r--src/ui/CMakeLists.txt6
-rw-r--r--src/ui/include/engine/ui/ui.h264
-rw-r--r--src/utils/CMakeLists.txt14
-rw-r--r--src/utils/include/engine/utils/btree.h54
-rw-r--r--src/utils/include/engine/utils/fov.h21
-rw-r--r--src/utils/include/engine/utils/hashmap.h54
-rw-r--r--src/utils/include/engine/utils/list.h11
-rw-r--r--src/utils/include/engine/utils/stack.h50
-rw-r--r--src/utils/include/engine/utils/utils.h36
-rw-r--r--src/utils/include/engine/utils/vector.h31
23 files changed, 1123 insertions, 28 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f8c0315..c6adabf 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,10 +1,12 @@
add_library(daw_core
- cleanup.c
- dltools.c
- harness.c
- init.c
- logging.c
- loop.c
- memory.c
- state.c
+ src/cleanup.c
+ src/dltools.c
+ src/harness.c
+ src/init.c
+ src/logging.c
+ src/loop.c
+ src/memory.c
+ src/state.c
)
+
+target_include_directories(daw_core PRIVATE include)
diff --git a/src/core/include/engine/core/dltools.h b/src/core/include/engine/core/dltools.h
new file mode 100644
index 0000000..5a53f49
--- /dev/null
+++ b/src/core/include/engine/core/dltools.h
@@ -0,0 +1,16 @@
+#ifndef DLTOOLS_H
+#define DLTOOLS_H
+
+#include <stdbool.h>
+
+/* Utility functions for handling runtime linked shared libraries */
+bool dynamic_library_close(void* shared_library);
+void* dynamic_library_open(const char* library_path);
+void* dynamic_library_reload(void* shared_library, const char* library_path);
+
+/* Returns the address of symbol in the provided shared_library handle.
+ * NULL on error*/
+void* dynamic_library_get_symbol(void* shared_library, const char* symbol);
+char* dynamic_library_get_error(void);
+
+#endif
diff --git a/src/core/include/engine/core/logging.h b/src/core/include/engine/core/logging.h
new file mode 100644
index 0000000..d1c5890
--- /dev/null
+++ b/src/core/include/engine/core/logging.h
@@ -0,0 +1,49 @@
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "types.h"
+
+#if defined __linux__ || defined __APPLE__
+#define TERM_COLOR_RESET "\033[0m"
+#define TERM_COLOR_RED "\033[31m"
+#define TERM_COLOR_GREEN "\033[32m"
+#define TERM_COLOR_YELLOW "\033[33m"
+#define TERM_COLOR_BLUE "\033[34m"
+#define TERM_COLOR_PURPLE "\033[35m"
+#else
+#define TERM_COLOR_RESET
+#define TERM_COLOR_RED
+#define TERM_COLOR_GREEN
+#define TERM_COLOR_YELLOW
+#define TERM_COLOR_BLUE
+#define TERM_COLOR_PURPLE
+#endif
+
+#define STR(a) (#a)
+
+void _log(FILE* stream, const char* prefix, const char* fmt, va_list ap);
+
+void LOG(const char* fmt, ...);
+
+void INFO_(const char* fmt, ...);
+void INFO(const char* fmt, ...);
+
+#ifdef _DEBUG
+#define DEBUG(fmt, ...) __DEBUG(__FILE__, __LINE__, __func__, fmt, __VA_ARGS__)
+void __DEBUG(const char* file, const i32 line, const char* func,
+ const char* fmt, ...);
+#else
+#define DEBUG(...)
+#endif
+
+void WARN(const char* fmt, ...);
+
+void ERROR(const char* fmt, ...);
+
+#endif
diff --git a/src/core/include/engine/core/memory.h b/src/core/include/engine/core/memory.h
new file mode 100644
index 0000000..04c24d5
--- /dev/null
+++ b/src/core/include/engine/core/memory.h
@@ -0,0 +1,25 @@
+#ifndef MEMORY_H
+#define MEMORY_H
+
+#include "types.h"
+// #include <stdlib.h>
+
+typedef struct memory {
+ void* data;
+ usize size;
+ usize pos;
+ usize free;
+} memory;
+
+memory* memory_new(usize max_size);
+
+/* Returns a pointer to the allocated data */
+void* memory_allocate(memory* mem, usize size);
+
+memory memory_init(void* data, usize size);
+
+void memory_free(memory* mem, usize size);
+
+void memory_clear(memory* mem);
+
+#endif
diff --git a/src/core/include/engine/core/state.h b/src/core/include/engine/core/state.h
new file mode 100644
index 0000000..13593ed
--- /dev/null
+++ b/src/core/include/engine/core/state.h
@@ -0,0 +1,31 @@
+#ifndef STATE_H
+#define STATE_H
+
+#include <engine/memory.h>
+
+typedef enum StateType {
+ STATE_null,
+#define State(name) STATE_##name,
+#include <states/list_of_states.h>
+#undef State
+ STATE_quit,
+} StateType;
+
+extern const char* StateTypeStr[];
+
+StateType (*State_updateFunc(StateType type))(void*);
+
+void State_init(StateType type, memory* mem);
+void State_free(StateType type, memory* mem);
+StateType State_update(StateType type, memory* mem);
+
+/* Reloads shared object file associated with state */
+#ifdef DAW_BUILD_HOTRELOAD
+#include <engine/input.h>
+bool State_reload(StateType type, i_ctx** ctx, usize ctx_len);
+
+#else
+#define State_reload(_, _0, _1) true
+#endif
+
+#endif
diff --git a/src/core/include/engine/core/types.h b/src/core/include/engine/core/types.h
new file mode 100644
index 0000000..934cb63
--- /dev/null
+++ b/src/core/include/engine/core/types.h
@@ -0,0 +1,34 @@
+#ifndef ENGINE_TYPES_H
+#define ENGINE_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/* Signed */
+typedef int8_t i8;
+typedef int16_t i16;
+typedef int32_t i32;
+typedef int64_t i64;
+
+/* Unsigned */
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+/* floating points */
+typedef float f32;
+typedef double f64;
+
+/* sizes */
+#if __x86_64__ || __ppc64__ || _WIN64
+typedef u64 usize;
+typedef i64 isize;
+#else
+typedef u32 usize;
+typedef i32 isize;
+#endif
+
+typedef bool(predicate_t)(const void*);
+
+#endif
diff --git a/src/core/include/engine/engine.h b/src/core/include/engine/engine.h
new file mode 100644
index 0000000..e8a5ace
--- /dev/null
+++ b/src/core/include/engine/engine.h
@@ -0,0 +1,130 @@
+#ifndef ENGINE_H
+#define ENGINE_H
+
+#include <stdbool.h>
+
+#include <engine/input.h>
+#include <engine/logging.h>
+#include <engine/memory.h>
+#include <engine/resources.h>
+#include <engine/stack.h>
+#include <engine/state.h>
+#include <engine/types.h>
+#include <engine/vector.h>
+
+typedef struct {
+ u32 texture_id;
+ i32 x, y, w, h;
+} RenderUnit;
+
+typedef struct Window Window;
+
+#define NUM_GLOBAL_BINDINGS 1
+typedef struct {
+ void* data; /* Contains textures and such */
+ u64 data_len;
+
+ Window* window;
+ bool quit;
+
+ u64 frame;
+ f32 fps_target;
+
+ /* TODO: Move mouse data to input ctx */
+ v2_i32 mouse_pos;
+
+ v2_i32 mousedown;
+ v2_i32 mouseup;
+
+ bool mouse_lclick;
+ bool mouse_rclick;
+
+ i32 camera_x;
+ i32 camera_y;
+
+ /* Text input/editing is currently not used/implemented */
+ char* edit_text;
+ usize edit_pos;
+
+ memory* mem;
+
+ i_ctx** bindings;
+ usize bindings_sz;
+ usize bindings_len;
+
+ struct RenderObject *testobject;
+
+ binding_t bindings_global[NUM_GLOBAL_BINDINGS];
+} Platform;
+
+/* Essential functions */
+Platform* engine_init(const char* windowtitle, v2_i32 windowsize,
+ const f32 render_scale, const u32 flags,
+ const usize initial_memory, const Asset_FontSpec* fonts[],
+ const Asset_TextureSpec* textures[]);
+
+i32 engine_run(Platform* p, StateType initial_state);
+
+void engine_stop(Platform* p);
+
+/* Utility functions */
+void engine_fps_max(u64 cap);
+
+void render_set_zoom(f32 new_zoom);
+void render_adjust_zoom(f32 diff);
+void render_add_unit(RenderUnit* u);
+
+f64 get_time(void);
+v2_i32 get_windowsize(void);
+v2_i32* get_mousepos(void);
+
+/* Input handling */
+void engine_input_ctx_push(i_ctx* ctx);
+void engine_input_ctx_pop(void);
+void engine_input_ctx_reset(void);
+
+#include "rendering.h"
+
+#ifdef ENGINE_INTERNALS
+
+#include <glad/gl.h>
+#define GLFW_INCLUDE_NONE
+#include <GLFW/glfw3.h>
+
+/* Window */
+struct Window {
+ GLFWwindow* window;
+ GladGLContext* context;
+ f32 render_scale;
+
+ v2_i32 windowsize;
+
+ i32* game_w;
+ i32* game_h;
+};
+
+typedef struct {
+ const i32 tilesize;
+ const i32 width;
+ const i32 height;
+} Texture;
+
+struct Resources {
+ usize textures_len;
+ usize textures_size;
+ usize fonts_len;
+
+ usize texturepaths_len;
+ usize fontpaths_len;
+
+ /* Paths for our sources, kept in case the user wants to reload them */
+ Asset_TextureSpec** texture_paths;
+ Asset_FontSpec** font_paths;
+
+ /* Our actual sources */
+ Texture** textures;
+ //TTF_Font** fonts;
+};
+
+#endif
+#endif
diff --git a/src/ctrl/CMakeLists.txt b/src/ctrl/CMakeLists.txt
index e086f07..7a449d6 100644
--- a/src/ctrl/CMakeLists.txt
+++ b/src/ctrl/CMakeLists.txt
@@ -1,7 +1,9 @@
add_library(daw_ctrl
- controller.c
- ctx.c
- input.c
- keyboard.c
- mouse.c
+ src/controller.c
+ src/ctx.c
+ src/input.c
+ src/keyboard.c
+ src/mouse.c
)
+
+target_include_directories(daw_ctrl PRIVATE include)
diff --git a/src/ctrl/include/engine/ctrl/input.h b/src/ctrl/include/engine/ctrl/input.h
new file mode 100644
index 0000000..49b3a96
--- /dev/null
+++ b/src/ctrl/include/engine/ctrl/input.h
@@ -0,0 +1,92 @@
+#ifndef INPUT_H
+#define INPUT_H
+
+#include <engine/types.h>
+
+typedef void input_callback_t(void*);
+typedef i32 scancode_t;
+
+typedef enum InputType {
+ InputType_error = 0,
+ InputType_action,
+ InputType_state,
+ InputType_range, /* TBD */
+} InputType;
+
+typedef union action_t {
+ InputType type;
+
+ struct {
+ InputType type;
+ input_callback_t* callback;
+ char* callback_str;
+ } action;
+
+ struct {
+ InputType type;
+ input_callback_t* activate;
+ input_callback_t* deactivate;
+ char* activate_str;
+ char* deactivate_str;
+ } state;
+} action_t;
+
+typedef struct binding_t {
+ action_t action;
+
+ // Change type depending on input handling back-end. like u16 for GLFW_KEY
+ scancode_t scancode;
+ scancode_t scancode_alt;
+
+ u64 since_last_activation;
+} binding_t;
+
+typedef struct i_ctx {
+ binding_t* bindings;
+ isize len;
+} i_ctx;
+
+void i_ctx_t_free(i_ctx* c);
+/* Executes all callbacks that has been pushed onto the callstack and resets the
+ * callstack */
+void i_flush_bindings(usize numcalls, void* state_mem, input_callback_t* c[]);
+action_t i_get_action(const i_ctx* restrict ctx, u32 time, scancode_t scancode);
+
+void i_ctx_push(i_ctx* ctx);
+void i_ctx_pop(void);
+void i_ctx_reset(void);
+
+/* Finds and updates the scancode of a binding with the given action in ctx */
+void i_bind_ctx(i_ctx* c, scancode_t s, action_t* a);
+void i_bind_ctx_alt(i_ctx* c, scancode_t s, action_t* a);
+
+/* Update the scancode of a binding */
+void i_bind(binding_t* b, scancode_t s);
+void i_bind_alt(binding_t* b, scancode_t s);
+
+#define BindAction(key, altkey, f_action) \
+ (binding_t) { \
+ .action = (action_t){.action = \
+ { \
+ .type = InputType_action, \
+ .callback = (input_callback_t*)&f_action, \
+ .callback_str = strdup(#f_action), \
+ }}, \
+ .scancode = key, .scancode_alt = altkey, .since_last_activation = 0 \
+ }
+
+#define BindState(key, altkey, f_activate, f_deactivate) \
+ (binding_t) { \
+ .action = \
+ (action_t){.state = \
+ { \
+ .type = InputType_state, \
+ .activate = (input_callback_t*)&f_activate, \
+ .deactivate = (input_callback_t*)&f_deactivate, \
+ .activate_str = strdup(#f_activate), \
+ .deactivate_str = strdup(#f_deactivate), \
+ }}, \
+ .scancode = key, .scancode_alt = altkey, .since_last_activation = 0 \
+ }
+
+#endif
diff --git a/src/rendering/CMakeLists.txt b/src/rendering/CMakeLists.txt
index a7313e9..e04d858 100644
--- a/src/rendering/CMakeLists.txt
+++ b/src/rendering/CMakeLists.txt
@@ -1,6 +1,13 @@
add_library(daw_rendering
- gl.c
- rendering.c
- text.c
- window.c
+ src/gl.c
+ src/rendering.c
+ src/text.c
+ src/window.c
+ )
+
+target_include_directories(daw_rendering PRIVATE include)
+target_link_libraries(daw_rendering PRIVATE
+ OpenGL::GL
+ cglm
+ glfw
)
diff --git a/src/rendering/include/engine/rendering/rendering.h b/src/rendering/include/engine/rendering/rendering.h
new file mode 100644
index 0000000..ff24412
--- /dev/null
+++ b/src/rendering/include/engine/rendering/rendering.h
@@ -0,0 +1,101 @@
+#ifndef RENDERING_H
+#define RENDERING_H
+
+#include "types.h"
+#include "vector.h"
+
+#define GLFW_INCLUDE_NONE
+#include <GLFW/glfw3.h>
+
+/* Definitions */
+#define RGBA(_r, _g, _b, _a) \
+ ((Engine_color){.r = _r, .g = _g, .b = _b, .a = _a})
+#define RGB(_r, _g, _b) RGBA(_r, _g, _b, 0xFF)
+
+/* Types */
+typedef struct {
+ u8 r;
+ u8 g;
+ u8 b;
+ u8 a;
+} Engine_color;
+
+typedef struct {
+ u32 texture_id;
+ v2_i32 coord;
+} Sprite;
+
+
+#include "engine.h"
+#include "ui.h"
+
+/* Rendering functions */
+void render_begin(Window* w);
+void render_present(Window* w);
+void drawcall_reset(void);
+void render(Window* w);
+
+/* Misc */
+void window_size_callback(GLFWwindow* window, i32 width, i32 height);
+void engine_window_resize_pointers(i32* w, i32* h);
+void engine_window_resize_pointers_reset(void);
+
+/* UI rendering */
+/* See rendering_ui.c for implementation */
+i64 engine_render_text(i32 font_id, Engine_color fg, char* text,
+ v2_i32* size_out, bool wrapped);
+void engine_draw_uitree(UITree* t);
+void engine_draw_sprite(Sprite* s, v2_i32* pos, f32 scale);
+void engine_draw_sprite_ex(Sprite* s, v2_i32* pos, f32 scale,
+ Engine_color colormod);
+
+Sprite sprite_new(u64 tid, u8 coord);
+
+#ifdef ENGINE_INTERNALS
+#include "engine.h"
+
+//#include <glad/gl.h>
+//#define GLFW_INCLUDE_NONE
+//#include <GLFW/glfw3.h>
+
+#define TEXTURES_INCREMENT 512
+
+typedef enum {
+ RenderDrawCallType_UITree,
+ /*RenderDrawCallType_UIButton,*/
+ RenderDrawCallType_Text,
+ RenderDrawCallType_Sprite,
+} RenderDrawCallType;
+
+typedef struct {
+ RenderDrawCallType type;
+ union {
+ void* data;
+ struct {
+ Sprite* sprite;
+ i32 x;
+ i32 y;
+ f32 scale;
+ } sprite;
+ } data;
+} RenderDrawCall;
+
+struct RenderObject {
+ u32 vao;
+ u32 vbo;
+ u32 col;
+ u32 shaderprogram;
+ f32 g_vertex_buffer_data[9];
+};
+
+void render_uitree(Window* w, UITree* t);
+
+void render_container(Window* w, UITree_container* t);
+void render_button(Window* w, UITree_button* t);
+void render_title(Window* w, UITree_title* t);
+void render_text(Window* w, UITree_text* t);
+v2_i32 elem_size(UITree* root);
+
+#endif
+
+#endif
diff --git a/src/resources/CMakeLists.txt b/src/resources/CMakeLists.txt
index 7fe5cac..02ab1ca 100644
--- a/src/resources/CMakeLists.txt
+++ b/src/resources/CMakeLists.txt
@@ -1,5 +1,7 @@
add_library(daw_resources
- fonts.c
- scripts.c
- textures.c
+ src/fonts.c
+ src/scripts.c
+ src/textures.c
)
+
+target_include_directories(daw_resources PRIVATE include)
diff --git a/src/resources/include/engine/resources/resources.h b/src/resources/include/engine/resources/resources.h
new file mode 100644
index 0000000..1689544
--- /dev/null
+++ b/src/resources/include/engine/resources/resources.h
@@ -0,0 +1,79 @@
+#ifndef RESOURCES_H
+#define RESOURCES_H
+
+#include <engine/types.h>
+
+/* We need some "global resources", available to all states.
+ * These are resources such as common fonts, GUI frames, button background
+ * images.
+ *
+ * We need to define state-specific resources as well.
+ * - Can both be defined alike?
+ * If we lazy-load all resources we can get away with a lot.
+ * Maybe use fall-back resources? like the missing source texture, and an ugly
+ * font?
+ * - Then declare to the engine, in the main function for the game, that these
+ * resources are to be made available throughout?
+ * - Make all resource specifications A UNION?! 🤯
+ * */
+
+enum Asset {
+ Asset_error,
+ Asset_font,
+ Asset_texture,
+ Asset_audio,
+};
+
+typedef struct {
+ enum Asset type;
+ const char* font_path;
+ i32 ptsize;
+} Asset_FontSpec;
+
+typedef struct {
+ enum Asset type;
+ const char* path;
+ i32 width;
+ i32 height;
+} Asset_TextureSpec;
+
+typedef struct {
+ enum Asset type;
+ const char* path;
+} Asset_AudioSpec;
+
+typedef union {
+ enum Asset type;
+ Asset_FontSpec font;
+ Asset_TextureSpec texture;
+ Asset_AudioSpec audio;
+} asset_t;
+
+#define Resource_FontDefinition(_path, _fontsize) \
+ (const Asset_FontSpec) { \
+ .type = Asset_font, .font_path = _path, .ptsize = _fontsize \
+ }
+
+#define Resource_TextureAtlasDefinition(_path, _subtexture_width, \
+ _subtexture_height) \
+ (const Asset_TextureSpec) { \
+ .type = Asset_texture, .width = _subtexture_width, \
+ .height = _subtexture_height, .path = _path \
+ }
+
+#define TextureDefinition(_path, ...) unimplemented
+
+#define Resource_AudioDefinition(_path, ...) unimplemented
+
+/* Each of resource_load_font, resource_load_texture, and resource_load_audio
+ * loads a given resource into the engines memory and returns an identifier.
+ */
+isize resource_load_font(Asset_FontSpec font_def);
+isize resource_load_texture(Asset_TextureSpec texture_def);
+isize resource_load_audio(Asset_AudioSpec audio_def);
+
+/* Makes a resource globally available. This must be called **BEFORE** any call
+ * to `engine_run` */
+isize resource_make_global(isize resource_id);
+
+#endif
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 05b2648..23dcae6 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -1,4 +1,6 @@
add_library(daw_ui
- positioning.c
- rendering.c
+ src/positioning.c
+ src/rendering.c
)
+
+target_include_directories(daw_ui PRIVATE include)
diff --git a/src/ui/include/engine/ui/ui.h b/src/ui/include/engine/ui/ui.h
new file mode 100644
index 0000000..4a3cd3e
--- /dev/null
+++ b/src/ui/include/engine/ui/ui.h
@@ -0,0 +1,264 @@
+#ifndef ENGINE_UI_H
+#define ENGINE_UI_H
+
+#include "list.h"
+#include "types.h"
+#include "vector.h"
+
+#define DIRECTION_HORIZONTAL true
+#define DIRECTION_VERTICAL false
+
+/* Ui positioning constraints */
+typedef enum {
+ ui_size_pixel,
+ ui_size_percent,
+} ui_size_t;
+
+typedef union {
+ ui_size_t type;
+ struct {
+ ui_size_t type;
+ i32 value;
+ } pixel;
+ struct {
+ ui_size_t type;
+ f32 value;
+ } percent;
+} ui_size;
+
+typedef enum {
+ ui_constraint_width,
+ ui_constraint_height,
+
+ ui_constraint_horizontal_align,
+ ui_constraint_vertical_align,
+
+ ui_constraint_left,
+ ui_constraint_right,
+ ui_constraint_top,
+ ui_constraint_bottom,
+} ui_constraint_t;
+
+typedef enum {
+ ui_constraint_vertical_align_top,
+ ui_constraint_vertical_align_center,
+ ui_constraint_vertical_align_bottom,
+} ui_constraint_vertical_align_t;
+
+typedef enum {
+ ui_constraint_horizontal_align_left,
+ ui_constraint_horizontal_align_center,
+ ui_constraint_horizontal_align_right,
+} ui_constraint_horizontal_align_t;
+
+typedef union {
+ struct {
+ ui_size size;
+ } width;
+ struct {
+ ui_size size;
+ } height;
+
+ /* spacing is the padding between the aligned edge and the container itself */
+ struct {
+ ui_constraint_horizontal_align_t align;
+ ui_size spacing;
+ } horizontal_align;
+ struct {
+ ui_constraint_vertical_align_t align;
+ ui_size spacing;
+ } vertical_align;
+
+ struct {
+ ui_size pos;
+ } left;
+ struct {
+ ui_size pos;
+ } top;
+ struct {
+ ui_size pos;
+ } right;
+ struct {
+ ui_size pos;
+ } bottom;
+} constraintval_t;
+
+#define CONSTRAINT_POSITION(axis, alignment_sub, margin, cnext) \
+ { \
+ .value = \
+ { \
+ .type = ui_constraint_##axis##_align, \
+ .constraint.axis##_align = \
+ { \
+ .align = ui_constraint_##axis##_align_##alignment_sub, \
+ .spacing = margin, \
+ }, \
+ }, \
+ .next = cnext, \
+ }
+
+#define CONSTRAINT_SIZE(c_type, csize, cnext) \
+ { \
+ .value = \
+ { \
+ .type = ui_constraint_##c_type, \
+ .constraint.c_type = \
+ { \
+ .size = csize, \
+ }, \
+ }, \
+ .next = cnext, \
+ }
+
+typedef struct {
+ ui_constraint_t type;
+ constraintval_t constraint;
+} ui_constraint;
+
+typedef DEFINE_LLIST(ui_constraint);
+
+enum uitype {
+ uitype_container,
+ uitype_button,
+ uitype_title,
+ uitype_text,
+
+ uitype_MAX,
+};
+
+typedef struct UITree_container {
+ enum uitype type;
+ bool visible;
+ bool direction;
+ i32 x, y, w, h;
+ i32 padding;
+ i32 margin;
+
+ Engine_color fg;
+ Engine_color bg;
+ Engine_color bordercolor;
+
+ usize children_len; /* Number of children */
+ usize children_size; /* Memory size */
+ union UITree** children;
+ struct List_ui_constraint* constraints;
+} UITree_container;
+
+typedef struct UITree_button {
+ enum uitype type;
+
+ bool enabled;
+ u64 id;
+
+ i32 x, y, w, h;
+ i32 padding;
+ i32 margin;
+
+ Engine_color fg;
+ Engine_color bg;
+
+ i32 font_id;
+ const char* text_original;
+ u64 text_texture_index;
+ v2_i32 texture_size;
+ struct List_ui_constraint* constraints;
+} UITree_button;
+
+typedef struct UITree_title {
+ enum uitype type;
+ i32 x, y, w, h;
+
+ i32 padding;
+ i32 margin;
+
+ Engine_color fg;
+
+ i32 font_id;
+ const char* text_original;
+ u64 text_texture_index;
+ v2_i32 texture_size;
+ struct List_ui_constraint* constraints;
+} UITree_title;
+
+typedef struct UITree_text {
+ enum uitype type;
+ i32 x, y, w, h;
+
+ i32 padding;
+ i32 margin;
+
+ Engine_color fg;
+
+ i32 font_id;
+ const char* text_original;
+ u64 text_texture_index;
+ v2_i32 texture_size;
+ struct List_ui_constraint* constraints;
+} UITree_text;
+
+typedef union UITree {
+ enum uitype type;
+
+ UITree_container container;
+ UITree_button button;
+ UITree_title title;
+ UITree_text text;
+ struct List_ui_constraint constraints;
+} UITree;
+
+/* Sizes */
+f32 ui_size_pixel_to_percent_width(i32 pixels);
+f32 ui_size_pixel_to_percent_height(i32 pixels);
+f32 ui_size_pixel_to_percent(i32 pixels);
+i32 ui_size_percent_width_to_pixel(f32 percent);
+i32 ui_size_percent_height_to_pixel(f32 percent);
+i32 ui_size_percent_to_pixel(f32 percent);
+i32 ui_size_to_pixel(ui_size s);
+
+#define ui_size_percent_new(p) \
+ { \
+ .percent = {.type = ui_size_percent, .value = p } \
+ }
+#define ui_size_pixel_new(p) \
+ { \
+ .pixel = {.type = ui_size_pixel, .value = p } \
+ }
+
+/* Constructors */
+UITree* ui_container(bool direction, struct List_ui_constraint* constraints);
+UITree* ui_button(u64 id, i32 font_id, char* text,
+ struct List_ui_constraint* constraints);
+UITree* ui_title(i32 font_id, const char* text,
+ struct List_ui_constraint* constraints);
+UITree* ui_text(i32 font_id, const char* text,
+ struct List_ui_constraint* constraints);
+
+/* Extended Constructors */
+UITree* ui_container_new_ex(Engine_color fg, Engine_color bg,
+ Engine_color border, bool direction,
+ struct List_ui_constraint* constraints);
+
+/* Destructors */
+void clear_ui(void);
+void uitree_free(UITree* t);
+
+/* Manipulation */
+void ui_container_attach(UITree* container, UITree* child);
+
+void ui_resolve_constraints(void);
+
+void ui_button_enable(UITree_button* b);
+void ui_button_disable(UITree_button* b);
+
+/* Tweaking default colors */
+void ui_set_default_colors(Engine_color fg, Engine_color bg);
+void ui_set_default_padding(i32 padding);
+Engine_color ui_get_default_fg(void);
+Engine_color ui_get_default_bg(void);
+
+#define ELEM_NOT_FOUND (-1)
+#define NO_CLICK (-2)
+/* Returns -1 if not found */
+u64 ui_check_click(UITree* root);
+
+#endif
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
index 3274f55..7508d26 100644
--- a/src/utils/CMakeLists.txt
+++ b/src/utils/CMakeLists.txt
@@ -1,8 +1,10 @@
add_library(daw_utils
- btree.c
- fov.c
- hashmap.c
- misc.c
- stack.c
- vector.c
+ src/btree.c
+ src/fov.c
+ src/hashmap.c
+ src/misc.c
+ src/stack.c
+ src/vector.c
)
+
+target_include_directories(daw_utils PRIVATE include)
diff --git a/src/utils/include/engine/utils/btree.h b/src/utils/include/engine/utils/btree.h
new file mode 100644
index 0000000..04f9ff8
--- /dev/null
+++ b/src/utils/include/engine/utils/btree.h
@@ -0,0 +1,54 @@
+#ifndef BTREE_H
+#define BTREE_H
+
+#include <stddef.h>
+
+#define BTREE_DEGREE_DEFAULT 4
+
+#define BTREE_SIZE_MIN 8
+#define BTREE_SIZE_MAX 4096
+
+#define BTREE_CMP_LT (-1)
+#define BTREE_CMP_EQ (0)
+#define BTREE_CMP_GT (1)
+
+struct btree;
+struct btree_iter_t;
+
+/* elem_size: the size of the elements, typically `sizeof(struct <your struct>)`
+ * t: degree of the btree, if you're in doubt, use `BTREE_SIZE_DEFAULT`
+ * cmp: comparison function, in order to support any operations on the tree.
+ *
+ * This function just calls `btree_new_with_allocator` with `free` and `malloc`
+ * as initializers.
+ */
+struct btree* btree_new(size_t elem_size, size_t t,
+ int (*cmp)(const void* a, const void* b));
+
+/* Same as `btree_new`, except that it actually initializes a btree, but with
+ * the given allocators.
+ */
+struct btree* btree_new_with_allocator(size_t elem_size, size_t t,
+ int (*cmp)(const void* a, const void* b),
+ void* (*alloc)(size_t),
+ void (*dealloc)(void*));
+
+void btree_free(struct btree** btree);
+
+void* btree_search(struct btree* btree, void* elem);
+void btree_insert(struct btree* btree, void* elem);
+int btree_delete(struct btree* btree, void* elem);
+
+void btree_print(struct btree* btree, void (*print_elem)(const void*));
+
+void* btree_first(struct btree* btree);
+void* btree_last(struct btree* btree);
+
+size_t btree_size(struct btree* btree);
+
+struct btree_iter_t* btree_iter_t_new(struct btree* tree);
+void btree_iter_t_reset(struct btree* tree, struct btree_iter_t** it);
+
+void* btree_iter(struct btree* tree, struct btree_iter_t* iter);
+
+#endif
diff --git a/src/utils/include/engine/utils/fov.h b/src/utils/include/engine/utils/fov.h
new file mode 100644
index 0000000..15ef38b
--- /dev/null
+++ b/src/utils/include/engine/utils/fov.h
@@ -0,0 +1,21 @@
+#ifndef ENGINE_FOV_H
+#define ENGINE_FOV_H
+
+#include "types.h"
+#include "vector.h"
+#include <stdbool.h>
+
+/* `fov_shadowcast`: */
+/* map: your 2D enum tile grid
+ * mapsize: x: width, y: height of the map
+ * visblocking: pointer to a function that returns `true` when receiving a
+ * pointer to a LOS blocking tile
+ * lightmap: [out] 2D lightmap, this is simply overwritten with the
+ * distance to the source. range: visibility range/radius. src: 2D
+ * point to calculate FOV from
+ * */
+void fov_shadowcast(const void* map, const v2_i32 mapsize,
+ bool (*visblocking)(const void*), i32* lightmap,
+ const i32 range, v2_i32 src);
+
+#endif
diff --git a/src/utils/include/engine/utils/hashmap.h b/src/utils/include/engine/utils/hashmap.h
new file mode 100644
index 0000000..bf1d87c
--- /dev/null
+++ b/src/utils/include/engine/utils/hashmap.h
@@ -0,0 +1,54 @@
+#ifndef ENGINE_HASHMAP_H
+#define ENGINE_HASHMAP_H
+
+#include "types.h"
+
+#include "list.h"
+#include "memory.h"
+#include <stdlib.h>
+
+i32 lolhash(const usize s, i32 v);
+
+/* Define a linked list before using this */
+/* Example: DEFINE_LLIST(i32) */
+#define DEFINE_HASHMAP(type, lsize, cmp, type_to_int) \
+ typedef DEFINE_LLIST(type); \
+ typedef struct hashmap_##type { \
+ usize size; \
+ List_##type elems[64]; \
+ } hashmap_##type; \
+ \
+ type* hashmap_##type##_lookup(hashmap_##type* hmap, const type* val) { \
+ const i32 idx = lolhash(64, type_to_int(val)); \
+ List_##type* head = &hmap->elems[idx]; \
+ while (head != NULL) { \
+ if (!cmp(&(head->value), val)) return &(head->value); \
+ head = head->next; \
+ } \
+ return NULL; \
+ } \
+ \
+ void hashmap_##type##_insert(memory* m, hashmap_##type* hmap, \
+ const type* val) { \
+ const i32 idx = lolhash(64, type_to_int(val)); \
+ List_##type* head = &(hmap->elems[idx]); \
+ \
+ /* This is highly dependant on whether the memory is zero-initialized */ \
+ if (!type_to_int(&(head->value))) { \
+ memcpy(&(head->value), val, sizeof(type)); \
+ return; \
+ } \
+ \
+ while (head->next != NULL && cmp(&head->value, val)) { \
+ head = head->next; \
+ } \
+ \
+ if (!cmp(&head->value, val)) \
+ memcpy(&(head->value), val, sizeof(type)); \
+ else { \
+ head->next = memory_allocate(m, sizeof(List_##type)); \
+ memcpy(&(head->next->value), val, sizeof(type)); \
+ } \
+ }
+
+#endif
diff --git a/src/utils/include/engine/utils/list.h b/src/utils/include/engine/utils/list.h
new file mode 100644
index 0000000..37857f0
--- /dev/null
+++ b/src/utils/include/engine/utils/list.h
@@ -0,0 +1,11 @@
+#ifndef ENGINE_LIST_H
+#define ENGINE_LIST_H
+
+#define DEFINE_LLIST(type) \
+ struct List_##type { \
+ type value; \
+ struct List_##type* next; \
+ /* Force the user to add `;` for style consistency */ \
+ } List_##type
+
+#endif
diff --git a/src/utils/include/engine/utils/stack.h b/src/utils/include/engine/utils/stack.h
new file mode 100644
index 0000000..69975df
--- /dev/null
+++ b/src/utils/include/engine/utils/stack.h
@@ -0,0 +1,50 @@
+/* Copyright © 2021 Upqwerk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the “Software”), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ * */
+
+/* Stack implementation
+ * Author: Upqwerk
+ */
+#ifndef STACK_H
+#define STACK_H
+
+#include "types.h"
+
+typedef struct {
+ isize head; /* current number of elements */
+ const usize elem_size; /* size in bytes of each element */
+ usize size; /* current memory size used by the stack */
+ const usize chunk_size; /* size of which the stack increases when running out
+ of mem */
+ void* data; /* memory buffer */
+} Stack;
+
+Stack stack_new_ex(const usize element_size, const usize size);
+
+Stack stack_new(const usize element_size);
+
+void stack_free(Stack* s);
+void* stack_pop(Stack* s);
+void stack_push(Stack* s, void* elem);
+void* stack_peek(Stack* s);
+isize stack_size(const Stack* s);
+void stack_swap(Stack* s, Stack* t);
+
+#endif
diff --git a/src/utils/include/engine/utils/utils.h b/src/utils/include/engine/utils/utils.h
new file mode 100644
index 0000000..e537f52
--- /dev/null
+++ b/src/utils/include/engine/utils/utils.h
@@ -0,0 +1,36 @@
+#ifndef ENGINE_UTILS_H
+#define ENGINE_UTILS_H
+
+#include "types.h"
+#include "vector.h"
+
+#define MIN(a, b) ((a < b) ? (a) : (b))
+#define MAX(a, b) ((a > b) ? (a) : (b))
+
+#define MASK_TL (1 << 0)
+#define MASK_T (1 << 1)
+#define MASK_TR (1 << 2)
+#define MASK_L (1 << 3)
+#define MASK_C (1 << 4)
+#define MASK_R (1 << 5)
+#define MASK_BL (1 << 6)
+#define MASK_B (1 << 7)
+#define MASK_BR (1 << 8)
+
+/* Linear interpolate */
+f32 lerp(f32 dt, f32 a, f32 b);
+i32 int_lerp(f32 dt, i32 a, i32 b);
+
+/* Hashes */
+u32 hash(char* str);
+
+/* Masks surrounding tiles of a kernel size of 3x3 */
+/* In reality we only need 9 bits for this, but I think I had a reason for using
+ * i32 */
+i32* kernmap(const void* map, i32* dstmap, const v2_i32 mapsize,
+ predicate_t* predicate);
+
+/* Returns an index from the given weights. */
+i32 pick_from_sample(const i32* weights, i32 len);
+
+#endif
diff --git a/src/utils/include/engine/utils/vector.h b/src/utils/include/engine/utils/vector.h
new file mode 100644
index 0000000..58bb0a2
--- /dev/null
+++ b/src/utils/include/engine/utils/vector.h
@@ -0,0 +1,31 @@
+#ifndef VECTOR_H
+#define VECTOR_H
+
+#include "types.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+
+typedef struct {
+ i32 x;
+ i32 y;
+} v2_i32;
+
+bool v2_i32_eq(const v2_i32 a, const v2_i32 b);
+
+v2_i32 v2_i32_add(v2_i32 a, v2_i32 b);
+v2_i32 v2_i32_add_i(v2_i32 a, i32 b);
+v2_i32 v2_i32_sub(v2_i32 a, v2_i32 b);
+v2_i32 v2_i32_sub_i(v2_i32 a, i32 b);
+v2_i32 v2_i32_div(v2_i32 a, v2_i32 b);
+v2_i32 v2_i32_div_i(v2_i32 a, i32 b);
+v2_i32 v2_i32_mul(v2_i32 a, v2_i32 b);
+v2_i32 v2_i32_mul_i(v2_i32 a, i32 b);
+v2_i32 v2_i32_mod(v2_i32 a, v2_i32 b);
+v2_i32 v2_i32_mod_i(v2_i32 a, i32 b);
+v2_i32 v2_i32_max(v2_i32 a, v2_i32 b);
+v2_i32 v2_i32_min(v2_i32 a, v2_i32 b);
+v2_i32 v2_i32_lerp(f32 dt, v2_i32 a, v2_i32 b);
+
+void v2_i32_fprintf(FILE* stream, v2_i32 a);
+#endif