Refactor UI code into an immediate mode style (#1)

Co-authored-by: Abdelrahman <said.abdelrahman89@gmail.com>
Reviewed-on: #1
This commit is contained in:
2024-01-20 22:22:17 +00:00
parent 60d236c080
commit 63f119c1b2
9 changed files with 247 additions and 175 deletions

139
src/ui.c
View File

@@ -1,6 +1,139 @@
#include "ui.h"
#include "SDL_events.h"
#include "aliases/aliases.h"
#include "window.h"
bool aabb(const rect_t *rect, i32 x, i32 y) {
return x > rect->topleft.x && x <= rect->topleft.x + rect->w &&
y > rect->topleft.y && y <= rect->topleft.y + rect->h;
bool aabb(const ui_elem_t *elem, i32 x, i32 y) {
return x > elem->rect.topleft.x && x <= elem->rect.topleft.x + elem->rect.w &&
y > elem->rect.topleft.y && y <= elem->rect.topleft.y + elem->rect.h;
}
void init_ui_ctx(ui_ctx_t *ctx) {
*ctx = (ui_ctx_t){0};
ctx->hovered = -1;
ctx->active = -1;
}
void reset_ui_ctx(ui_ctx_t *ctx) {
ctx->count = 0;
ctx->mouse_down = false;
ctx->mouse_up = false;
}
void handle_ui_events(const window_t *wnd, ui_ctx_t *ctx,
const SDL_Event *event) {
switch (event->type) {
case SDL_MOUSEMOTION:
if (wnd->id == event->motion.windowID) {
ctx->mouse_x = event->motion.x;
ctx->mouse_y = event->motion.y;
ctx->wnd = wnd;
break;
}
case SDL_MOUSEBUTTONDOWN:
if (wnd->id == event->button.windowID) {
ctx->mouse_x = event->button.x;
ctx->mouse_y = event->button.y;
ctx->mouse_down = true;
ctx->wnd = wnd;
}
break;
case SDL_MOUSEBUTTONUP:
if (wnd->id == event->button.windowID) {
ctx->mouse_x = event->button.x;
ctx->mouse_y = event->button.y;
ctx->mouse_up = true;
ctx->wnd = wnd;
}
break;
}
}
bool button(const window_t *wnd, ui_ctx_t *ctx, rect_t rect,
ui_elem_colours_t colours) {
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
return false;
}
ui_elem_t elem = (ui_elem_t){
.id = (ctx->count)++,
.rect = rect,
.type = UI_ELEM_BUTTON,
};
fill_rect(wnd, rect, colours.fill);
draw_rect(wnd, rect, colours.border);
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != elem.id)) {
return false;
}
if (!aabb(&elem, ctx->mouse_x, ctx->mouse_y)) {
return false;
}
ctx->hovered = elem.id;
if (ctx->mouse_down) {
ctx->active = elem.id;
}
if (ctx->mouse_up && ctx->hovered == elem.id && ctx->active == elem.id) {
ctx->hovered = ctx->active = -1;
return true;
}
return false;
}
rect_t node(const window_t *wnd, ui_ctx_t *ctx, rect_t rect,
ui_elem_colours_t colours) {
if (ctx->count + 1 >= MAX_UI_ELEMENTS) {
return (rect_t){0};
}
ui_elem_t elem = (ui_elem_t){
.id = (ctx->count)++,
.rect = rect,
.type = UI_ELEM_NODE,
};
fill_rect(wnd, rect, colours.fill);
draw_rect(wnd, rect, colours.border);
if (wnd != ctx->wnd || (ctx->active >= 0 && ctx->active != elem.id)) {
return rect;
}
if (ctx->mouse_up) {
ctx->hovered = ctx->active = -1;
ctx->rel_x = ctx->rel_y = 0;
return rect;
}
if (ctx->hovered == elem.id && ctx->active == elem.id) {
return (rect_t){
.topleft.x = ctx->mouse_x + ctx->rel_x,
.topleft.y = ctx->mouse_y + ctx->rel_y,
.w = rect.w,
.h = rect.h,
};
}
if (!aabb(&elem, ctx->mouse_x, ctx->mouse_y)) {
return rect;
}
ctx->hovered = elem.id;
if (ctx->mouse_down) {
ctx->active = elem.id;
ctx->rel_x = rect.topleft.x - ctx->mouse_x;
ctx->rel_y = rect.topleft.y - ctx->mouse_y;
}
return rect;
}