less than bare minimum

rewrite2
Alessandro Mauri 11 months ago
parent 94837ed410
commit 156c3b3959
  1. 4
      Makefile
  2. 23
      cache.c
  3. 285
      ugui.c
  4. 32
      ugui.h
  5. 17
      vectree.c

@ -7,8 +7,10 @@ all: ugui
raylib/src/libraylib.a: raylib/src/Makefile raylib/src/libraylib.a: raylib/src/Makefile
cd raylib/src; $(MAKE) PLATFORM=PLATFORM_DESKTOP cd raylib/src; $(MAKE) PLATFORM=PLATFORM_DESKTOP
ugui: ugui.o vectree.o raylib/src/libraylib.a ugui: ugui.o vectree.o cache.o raylib/src/libraylib.a
ugui.o: ugui.c ugui.h ugui.o: ugui.c ugui.h
vectree.o: vectree.c ugui.h vectree.o: vectree.c ugui.h
cache.o: cache.c ugui.h

@ -24,13 +24,13 @@
#define HASH_MAXSIZE 4096 #define HASH_MAXSIZE 4096
// hash table (id -> index) // hash table (id -> cache index)
typedef struct { typedef struct {
uint32_t id; UgId id;
uint32_t index; uint32_t index;
} IdElem; } IdElem;
typedef struct { typedef struct _IdTable {
uint32_t items, size, exp; uint32_t items, size, exp;
IdElem bucket[]; IdElem bucket[];
} IdTable; } IdTable;
@ -62,7 +62,7 @@ void table_destroy(IdTable *ht)
} }
// Find and return the element by pointer // Find and return the element by pointer
IdElem *table_search(IdTable *ht, uint32_t id) IdElem *table_search(IdTable *ht, UgId id)
{ {
if (!ht) { if (!ht) {
return NULL; return NULL;
@ -93,7 +93,7 @@ IdElem *table_insert(IdTable *ht, IdElem entry)
return r; return r;
} }
IdElem *table_remove(IdTable *ht, uint32_t id) IdElem *table_remove(IdTable *ht, UgId id)
{ {
if (!ht) { if (!ht) {
return NULL; return NULL;
@ -119,13 +119,6 @@ IdElem *table_remove(IdTable *ht, uint32_t id)
} \ } \
} while (0) } while (0)
typedef struct {
IdTable *table;
UgElem *array;
uint64_t *present, *used;
int cycles;
} UgElemCache;
/* FIXME: check for allocation errors */ /* FIXME: check for allocation errors */
UgElemCache ug_cache_init(void) UgElemCache ug_cache_init(void)
{ {
@ -148,7 +141,7 @@ void ug_cache_free(UgElemCache *cache)
} }
} }
const UgElem *ug_cache_search(UgElemCache *cache, uint32_t id) UgElem *ug_cache_search(UgElemCache *cache, UgId id)
{ {
if (!cache) { if (!cache) {
return NULL; return NULL;
@ -190,7 +183,7 @@ int ug_cache_get_free_spot(UgElemCache *cache)
return 0; return 0;
} }
const UgElem *ug_cache_insert_at(UgElemCache *cache, const UgElem *g, uint32_t index) UgElem *ug_cache_insert_at(UgElemCache *cache, const UgElem *g, uint32_t index)
{ {
if (!cache) { if (!cache) {
return NULL; return NULL;
@ -211,7 +204,7 @@ const UgElem *ug_cache_insert_at(UgElemCache *cache, const UgElem *g, uint32_t i
} }
// Insert an element in the cache // Insert an element in the cache
const UgElem *ug_cache_insert(UgElemCache *cache, const UgElem *g, int32_t *index) UgElem *ug_cache_insert(UgElemCache *cache, const UgElem *g, uint32_t *index)
{ {
*index = ug_cache_get_free_spot(cache); *index = ug_cache_get_free_spot(cache);
return ug_cache_insert_at(cache, g, *index); return ug_cache_insert_at(cache, g, *index);

285
ugui.c

@ -1,3 +1,5 @@
#define _DEFAULT_SOURCE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
@ -6,30 +8,185 @@
#include "raylib.h" #include "raylib.h"
#include "ugui.h" #include "ugui.h"
typedef struct _UgCmd {
enum {
CMD_RECT = 0,
} type;
union {
struct {
int32_t x, y, w, h;
uint8_t color[4]; // rgba, [0] = r
} rect;
};
} UgCmd;
typedef struct _UgStack {
int size, count;
UgCmd *stack;
} UgStack;
int ug_stack_init(UgStack *stack, uint32_t size);
int ug_stack_free(UgStack *stack);
int ug_stack_push(UgStack *stack, UgCmd *cmd);
int ug_stack_pop(UgStack *stack, UgCmd *cmd);
int ug_stack_init(UgStack *stack, uint32_t size)
{
if (stack == NULL) {
return -1;
}
stack->size = size;
stack->count = 0;
stack->stack = calloc(size, sizeof(UgCmd));
if (stack->stack == NULL) {
return -1;
}
return 0;
}
int ug_stack_free(UgStack *stack)
{
if (stack != NULL && stack->stack != NULL) {
free(stack->stack);
stack->size = 0;
stack->count = 0;
}
return 0;
}
#define STACK_STEP 10
int ug_stack_push(UgStack *stack, UgCmd *cmd)
{
if (stack == NULL || cmd == NULL) {
return -1;
}
if (stack->count >= stack->size) {
// UgCmd *tmp = reallocarray(stack->stack, stack->size +
// STACK_STEP, sizeof(UgCmd)); if (tmp == NULL) { return -1;
// }
// stack->stack = tmp;
// stack->size += STACK_STEP;
return -1;
}
stack->stack[stack->count++] = *cmd;
return 0;
}
int ug_stack_pop(UgStack *stack, UgCmd *cmd)
{
if (stack == NULL || cmd == NULL) {
return -1;
}
if (stack->count <= 0) {
// UgCmd *tmp = reallocarray(stack->stack, stack->size +
// STACK_STEP, sizeof(UgCmd)); if (tmp == NULL) { return -1;
// }
// stack->stack = tmp;
// stack->size += STACK_STEP;
return -1;
}
*cmd = stack->stack[--stack->count];
return 0;
}
struct _UgCtx {
enum {
row = 0,
column,
floating,
} layout;
UgTree tree;
UgElemCache cache;
UgStack stack;
struct {
int width, height;
} size;
int div_using; // tree node indicating the current active div
};
int ug_div_begin(UgCtx *ctx, const char *name, UgRect div);
int ug_div_end(UgCtx *ctx);
int ug_input_window_size(UgCtx *ctx, int width, int height);
UgId djb2(const char *str);
int main(void) int main(void)
{ {
UgCtx ctx; UgCtx ctx;
ug_init(&ctx); ug_init(&ctx);
InitWindow(800, 450, "Ugui Test"); int width = 800, height = 450;
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(width, height, "Ugui Test");
ug_input_window_size(&ctx, width, height);
// Main loop // Main loop
while (!WindowShouldClose()) { while (!WindowShouldClose()) {
ug_begin_frame(&ctx);
// UI handling
ug_frame_begin(&ctx);
if (IsWindowResized()) {
width = GetScreenWidth();
height = GetScreenHeight();
ug_input_window_size(&ctx, width, height);
}
// main div, fill the whole window
#define DIV_FILL (UgRect) {.x = 0, .y = 0, .w = -1, .h = -1}
ug_div_begin(&ctx, "main", DIV_FILL);
ug_div_end(&ctx);
ug_frame_end(&ctx);
// drawing // drawing
BeginDrawing(); BeginDrawing();
ClearBackground(BLACK); ClearBackground(BLACK);
DrawText(
"Congrats! You created your first window!", Rectangle r;
190, Color c;
200, for (UgCmd cmd; ug_stack_pop(&ctx.stack, &cmd) >= 0;) {
20, switch (cmd.type) {
LIGHTGRAY case CMD_RECT:
printf(
"rect x=%d y=%d w=%d h=%d\n",
cmd.rect.x,
cmd.rect.y,
cmd.rect.w,
cmd.rect.h
);
c = (Color) {
.r = cmd.rect.color[0],
.g = cmd.rect.color[1],
.b = cmd.rect.color[2],
.a = cmd.rect.color[3],
};
DrawRectangle(
cmd.rect.x, cmd.rect.y, cmd.rect.w, cmd.rect.h, c
); );
break;
default:
printf("Unknown cmd type: %d\n", cmd.type);
break;
}
}
EndDrawing(); EndDrawing();
ug_end_frame(&ctx); WaitTime(0.2);
} }
CloseWindow(); CloseWindow();
@ -38,13 +195,21 @@ int main(void)
return 0; return 0;
} }
#define MAX_ELEMS 128
#define MAX_CMDS 256
int ug_init(UgCtx *ctx) int ug_init(UgCtx *ctx)
{ {
if (ctx == NULL) { if (ctx == NULL) {
return -1; return -1;
} }
ug_tree_init(&ctx->tree, 10); ug_tree_init(&ctx->tree, MAX_ELEMS);
ug_stack_init(&ctx->stack, MAX_CMDS);
ctx->cache = ug_cache_init();
ctx->layout = row;
ctx->div_using = 0;
return 0; return 0;
} }
@ -56,6 +221,106 @@ int ug_destroy(UgCtx *ctx)
} }
ug_tree_destroy(&ctx->tree); ug_tree_destroy(&ctx->tree);
ug_cache_free(&ctx->cache);
return 0; return 0;
} }
int ug_frame_begin(UgCtx *ctx) { return 0; }
int ug_frame_end(UgCtx *ctx) { return 0; }
int ug_input_window_size(UgCtx *ctx, int width, int height)
{
if (ctx == NULL) {
return -1;
}
if (width <= 0 || height <= 0) {
return -1;
}
if (width >= 0) {
ctx->size.width = width;
}
if (height >= 0) {
ctx->size.height = height;
}
return 0;
}
UgId djb2(const char *str)
{
uint64_t hash = 5381;
uint32_t c;
while ((c = (str++)[0]) != 0) {
hash = ((hash << 5) + hash) + c;
} /* hash * 33 + c */
return hash;
}
int ug_div_begin(UgCtx *ctx, const char *name, UgRect div)
{
if (ctx == NULL || name == NULL) {
return -1;
}
UgId id = djb2(name);
// add the element if it does not exist
UgElem *c_elem = ug_cache_search(&ctx->cache, id);
if (c_elem == NULL) {
UgElem elem = {
.id = id,
.type = ETYPE_DIV,
.rec = (UgRect) {
.x = div.x,
.y = div.y,
.w = div.w >= 0 ? div.w : ctx->size.width,
.h = div.h >= 0 ? div.h : ctx->size.height,
}};
uint32_t c_idx;
c_elem = ug_cache_insert(&ctx->cache, &elem, &c_idx);
}
// FIXME: why save the id in the tree and not something more direct like
// the element pointer or the index into the cache vector?
int div_node = ug_tree_add(&ctx->tree, c_elem->id, ctx->div_using);
if (div_node < 0) {
// do something
printf("Error adding to tree\n");
}
ctx->div_using = div_node;
// printf(
// "elem.rect: x=%d x=%d w=%d h=%d\n",
// c_elem->rec.x,
// c_elem->rec.y,
// c_elem->rec.w,
// c_elem->rec.h
// );
UgCmd cmd = {
.type = CMD_RECT,
.rect =
{
.x = c_elem->rec.x,
.y = c_elem->rec.y,
.w = c_elem->rec.w,
.h = c_elem->rec.h,
.color = {0xff, 0x00, 0x00, 0xff}, // red
},
};
ug_stack_push(&ctx->stack, &cmd);
return 0;
}
int ug_div_end(UgCtx *ctx)
{
// the div_using returns to the parent of the current one
ctx->div_using = ug_tree_parentof(&ctx->tree, ctx->div_using);
return 0;
}

@ -15,16 +15,15 @@ typedef struct {
uint8_t r, g, b, a; uint8_t r, g, b, a;
} UgColor; } UgColor;
typedef uint64_t UgId;
typedef enum { typedef enum {
ETYPE_NONE = 0, ETYPE_NONE = 0,
ETYPE_BUTTON, ETYPE_DIV,
ETYPE_TEXT,
ETYPE_SCROLL,
ETYPE_SLIDER,
} UgElemType; } UgElemType;
typedef struct { typedef struct {
uint64_t id; UgId id;
UgRect rec; UgRect rec;
union { union {
uint32_t type_int; uint32_t type_int;
@ -37,27 +36,42 @@ typedef struct {
typedef struct { typedef struct {
int size, elements; int size, elements;
uint32_t *vector; // vector of element ids UgId *vector; // vector of element ids
int *refs, *ordered_refs; int *refs, *ordered_refs;
} UgTree; } UgTree;
typedef struct { typedef struct {
UgTree tree; struct _IdTable *table;
} UgCtx; UgElem *array;
uint64_t *present, *used;
int cycles;
} UgElemCache;
typedef struct _UgCtx UgCtx;
// tree implementation // tree implementation
int ug_tree_init(UgTree *tree, unsigned int size); int ug_tree_init(UgTree *tree, unsigned int size);
int ug_tree_pack(UgTree *tree); int ug_tree_pack(UgTree *tree);
int ug_tree_resize(UgTree *tree, unsigned int newsize); int ug_tree_resize(UgTree *tree, unsigned int newsize);
int ug_tree_add(UgTree *tree, uint32_t elem, int parent); int ug_tree_add(UgTree *tree, UgId elem, int parent);
int ug_tree_prune(UgTree *tree, int ref); int ug_tree_prune(UgTree *tree, int ref);
int ug_tree_subtree_size(UgTree *tree, int ref); int ug_tree_subtree_size(UgTree *tree, int ref);
int ug_tree_children_it(UgTree *tree, int parent, int *cursor); int ug_tree_children_it(UgTree *tree, int parent, int *cursor);
int ug_tree_level_order_it(UgTree *tree, int ref, int *cursor); int ug_tree_level_order_it(UgTree *tree, int ref, int *cursor);
int ug_tree_parentof(UgTree *tree, int node);
int ug_tree_destroy(UgTree *tree); int ug_tree_destroy(UgTree *tree);
// cache implementation
UgElemCache ug_cache_init(void);
void ug_cache_free(UgElemCache *cache);
UgElem *ug_cache_search(UgElemCache *cache, UgId id);
UgElem *ug_cache_insert(UgElemCache *cache, const UgElem *g, uint32_t *index);
int ug_init(UgCtx *ctx); int ug_init(UgCtx *ctx);
int ug_destroy(UgCtx *ctx); int ug_destroy(UgCtx *ctx);
int ug_frame_begin(UgCtx *ctx);
int ug_frame_end(UgCtx *ctx);
#endif // _UGUI_H #endif // _UGUI_H

@ -12,7 +12,7 @@ int ug_tree_init(UgTree *tree, unsigned int size)
return -1; return -1;
} }
tree->vector = malloc(sizeof(UgElem) * size); tree->vector = malloc(sizeof(UgId) * size);
if (tree->vector == NULL) { if (tree->vector == NULL) {
return -1; return -1;
} }
@ -37,7 +37,7 @@ int ug_tree_init(UgTree *tree, unsigned int size)
} }
// fill vector with zeroes // fill vector with zeroes
memset(tree->vector, 0, size * sizeof(UgElem)); memset(tree->vector, 0, size * sizeof(UgId));
tree->size = size; tree->size = size;
tree->elements = 0; tree->elements = 0;
@ -118,7 +118,7 @@ int ug_tree_resize(UgTree *tree, unsigned int newsize)
return -1; return -1;
} }
uint32_t *newvec = realloc(tree->vector, newsize * sizeof(uint32_t)); UgId *newvec = realloc(tree->vector, newsize * sizeof(UgId));
if (newvec == NULL) { if (newvec == NULL) {
return -1; return -1;
} }
@ -149,7 +149,7 @@ int ug_tree_resize(UgTree *tree, unsigned int newsize)
} }
// add an element to the tree, return it's ref // add an element to the tree, return it's ref
int ug_tree_add(UgTree *tree, uint32_t elem, int parent) int ug_tree_add(UgTree *tree, UgId elem, int parent)
{ {
if (tree == NULL) { if (tree == NULL) {
return -1; return -1;
@ -333,3 +333,12 @@ int ug_tree_level_order_it(UgTree *tree, int ref, int *cursor)
return -1; return -1;
} }
int ug_tree_parentof(UgTree *tree, int node)
{
if (tree == NULL || !IS_VALID_REF(tree, node) ||
!REF_IS_PRESENT(tree, node)) {
return -1;
}
return tree->refs[node];
}

Loading…
Cancel
Save