From 7769f5fd5841f9bae82111d8204c4816c4b14889 Mon Sep 17 00:00:00 2001 From: Luka Jankovic Date: Tue, 17 Jun 2025 01:05:40 +0200 Subject: [PATCH] Add generic dynamic array type --- kubo_context.c | 42 +++++++++++------------------------------ kubo_context.h | 11 +++-------- kubo_dynarray.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ kubo_wall.c | 33 +++++++++----------------------- kubo_wall.h | 13 ++++++++----- kubo_window.c | 24 +++++++++++++----------- 6 files changed, 94 insertions(+), 79 deletions(-) create mode 100644 kubo_dynarray.h diff --git a/kubo_context.c b/kubo_context.c index a22596c..7eb41c8 100644 --- a/kubo_context.c +++ b/kubo_context.c @@ -2,49 +2,29 @@ struct kubo_context *kubo_context_init() { struct kubo_context *context = malloc(sizeof(struct kubo_context)); + if (!context) { + return NULL; + } - context->num_walls_alloc = KUBO_CONTEXT_NUM_WALLS_ALLOC; - context->walls = - malloc(sizeof(struct kubo_wall) * context->num_walls_alloc); + kubo_wall_arr_init(&context->walls); return context; } void kubo_context_cleanup(struct kubo_context *context) { - free(context->walls); + kubo_wall_arr_free(&context->walls); free(context); } -bool kubo_context_add_wall(struct kubo_context *context, - struct kubo_wall *wall) { - - struct kubo_wall **new_walls; - - if (context->num_walls == context->num_walls_alloc - 1) { - - context->num_walls_alloc *= 2; - - new_walls = realloc(context->walls, sizeof(struct kubo_wall *) * - context->num_walls_alloc); - - if (!new_walls) - return false; - - context->walls = new_walls; - } - - context->walls[context->num_walls++] = wall; - - return true; -} - struct kubo_wall *kubo_context_get_pending_wall(struct kubo_context *context) { - if (context->num_walls > 0) { - switch (context->walls[context->num_walls - 1]->state) { + if (context->walls.count > 0) { + struct kubo_wall *last_wall = + kubo_wall_arr_get(&context->walls, context->walls.count - 1); + switch (last_wall->state) { case KUBO_WALL_INIT: case KUBO_WALL_DRAWING: - return context->walls[context->num_walls - 1]; + return last_wall; break; default: break; @@ -52,7 +32,7 @@ struct kubo_wall *kubo_context_get_pending_wall(struct kubo_context *context) { } struct kubo_wall *wall = kubo_wall_init(); - kubo_context_add_wall(context, wall); + kubo_wall_arr_add(&context->walls, wall); return wall; } diff --git a/kubo_context.h b/kubo_context.h index f260c46..5e9be03 100644 --- a/kubo_context.h +++ b/kubo_context.h @@ -5,24 +5,19 @@ #include #include +#include "kubo_dynarray.h" #include "kubo_wall.h" -#define KUBO_CONTEXT_NUM_WALLS_ALLOC 4 +KUBO_DYNARRAY_REGISTER(kubo_wall_arr, struct kubo_wall *); struct kubo_context { bool exit_pending; - - struct kubo_wall **walls; - unsigned int num_walls; - unsigned int num_walls_alloc; + struct kubo_wall_arr walls; }; struct kubo_context *kubo_context_init(); void kubo_context_cleanup(struct kubo_context *context); -bool kubo_context_add_wall(struct kubo_context *context, - struct kubo_wall *wall); - struct kubo_wall *kubo_context_get_pending_wall(struct kubo_context *context); #endif diff --git a/kubo_dynarray.h b/kubo_dynarray.h new file mode 100644 index 0000000..e33d269 --- /dev/null +++ b/kubo_dynarray.h @@ -0,0 +1,50 @@ +#ifndef KUBO_DYNARRAY_H +#define KUBO_DYNARRAY_H + +#include +#include + +#define KUBO_DRYNARRAY_DEFAULT_CAP 4 + +#define KUBO_DYNARRAY_REGISTER(name, type) \ + struct name { \ + type *data; \ + size_t count; \ + size_t capacity; \ + }; \ + \ + static inline void name##_init(struct name *arr) { \ + arr->count = 0; \ + arr->capacity = KUBO_DRYNARRAY_DEFAULT_CAP; \ + arr->data = malloc(sizeof(type) * arr->capacity); \ + } \ + \ + static inline void name##_free(struct name *arr) { free(arr->data); } \ + \ + static inline bool name##_reserve(struct name *arr, size_t new_cap) { \ + if (arr->capacity >= new_cap) \ + return true; \ + type *new_data = realloc(arr->data, sizeof(type) * new_cap); \ + if (!new_data) \ + return false; \ + arr->data = new_data; \ + arr->capacity = new_cap; \ + return true; \ + } \ + \ + static inline bool name##_add(struct name *arr, type new_val) { \ + if (arr->count == arr->capacity - 1) { \ + if (!name##_reserve(arr, arr->capacity * 2)) { \ + return false; \ + } \ + } \ + arr->data[arr->count++] = new_val; \ + return true; \ + } \ + \ + static inline type name##_get(struct name *arr, size_t index) { \ + assert(index < arr->count); \ + return arr->data[index]; \ + } + +#endif diff --git a/kubo_wall.c b/kubo_wall.c index 5f4bbbd..bdb5307 100644 --- a/kubo_wall.c +++ b/kubo_wall.c @@ -6,37 +6,22 @@ struct kubo_wall *kubo_wall_init() { if (!wall) return NULL; - wall->num_vertices_alloc = KUBO_WALL_INIT_VERTICES; - wall->vertices = malloc(sizeof(Vector2) * wall->num_vertices_alloc); - wall->num_vertices = 0; wall->state = KUBO_WALL_INIT; + kubo_vector2_arr_init(&wall->vertices); + return wall; } void kubo_wall_cleanup(struct kubo_wall *wall) { - free(wall->vertices); + kubo_vector2_arr_free(&wall->vertices); free(wall); } -bool kubo_wall_append(struct kubo_wall *wall, Vector2 vertex) { - - Vector2 *new_vertices; - - if (wall->num_vertices == wall->num_vertices_alloc - 1) { - - wall->num_vertices_alloc *= 2; - - new_vertices = - realloc(wall->vertices, sizeof(Vector2) * wall->num_vertices_alloc); - - if (!new_vertices) - return false; - - wall->vertices = new_vertices; - } - - wall->vertices[wall->num_vertices++] = vertex; - - return true; +bool kubo_wall_add_vertex(struct kubo_wall *wall, Vector2 vec) { + return kubo_vector2_arr_add(&wall->vertices, vec); +} + +Vector2 kubo_wall_get_vertex(struct kubo_wall *wall, size_t index) { + return kubo_vector2_arr_get(&wall->vertices, index); } diff --git a/kubo_wall.h b/kubo_wall.h index 3e39e8a..fab0d1d 100644 --- a/kubo_wall.h +++ b/kubo_wall.h @@ -4,6 +4,8 @@ #include #include +#include "kubo_dynarray.h" + #define KUBO_WALL_INIT_VERTICES 4 enum kubo_wall_state { @@ -12,17 +14,18 @@ enum kubo_wall_state { KUBO_WALL_DONE }; -struct kubo_wall { - Vector2 *vertices; - unsigned int num_vertices; - unsigned int num_vertices_alloc; +KUBO_DYNARRAY_REGISTER(kubo_vector2_arr, Vector2) +struct kubo_wall { + struct kubo_vector2_arr vertices; enum kubo_wall_state state; }; struct kubo_wall *kubo_wall_init(); void kubo_wall_cleanup(struct kubo_wall *wall); -bool kubo_wall_append(struct kubo_wall *wall, Vector2 vertex); +bool kubo_wall_add_vertex(struct kubo_wall *wall, Vector2 vec); +Vector2 kubo_wall_get_vertex(struct kubo_wall *wall, size_t index); #endif + diff --git a/kubo_window.c b/kubo_window.c index 8d9b823..f9eadf5 100644 --- a/kubo_window.c +++ b/kubo_window.c @@ -34,15 +34,17 @@ void kubo_window_render(struct kubo_context *context) { DrawSplineLinear(points, 2, 10.f, BLACK); } - for (int i = 0; i < context->num_walls; i++) { - DrawSplineLinear(context->walls[i]->vertices, - context->walls[i]->num_vertices, 10.f, BLACK); - if (context->walls[i]->state == KUBO_WALL_STARTED) { - Vector2 mouse_pos = GetMousePosition(); - Vector2 points[] = { - context->walls[i] - ->vertices[context->walls[i]->num_vertices - 1], - mouse_pos}; + for (int i = 0; i < context->walls.count; i++) { + struct kubo_wall *wall = kubo_wall_arr_get(&context->walls, i); + assert(wall != NULL); + + DrawSplineLinear(wall->vertices.data, wall->vertices.count, 10.f, + BLACK); + + if (wall->state == KUBO_WALL_DRAWING) { + Vector2 mouse = GetMousePosition(); + Vector2 points[] = {wall->vertices.data[wall->vertices.count - 1], + mouse}; DrawSplineLinear(points, 2, 10.f, BLACK); } } @@ -59,8 +61,8 @@ void kubo_window_input(struct kubo_context *context) { if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { Vector2 new_pos = GetMousePosition(); - kubo_wall_append(current_wall, new_pos); - current_wall->state = KUBO_WALL_STARTED; + kubo_wall_add_vertex(current_wall, new_pos); + current_wall->state = KUBO_WALL_DRAWING; } else if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) { current_wall->state = KUBO_WALL_DONE; }