added basic gui widgets

This commit is contained in:
Matthew 2025-03-30 20:50:33 +11:00
parent 8dd01f9dfc
commit ff07cbc572
6 changed files with 205 additions and 35 deletions

View File

@ -59,6 +59,13 @@ void RunThreadFunc(pthread_t *th, u32 *u, void *func)
pthread_create(th, NULL, func, u);
}
#define BIL 1000000000L
u64 GetDiff(struct timespec *start, struct timespec *end)
{
return BIL * (end->tv_sec - start->tv_sec) + end->tv_nsec - start->tv_nsec;
}
int main(int argc, char **argv)
{
u8 *mem = (u8 *)MemAllocZeroed(MB(64));

View File

@ -8,11 +8,11 @@ static void InitializeGame(Arena *arena, GameContext *ctx, Arena *ctx_arena)
ctx->gui.indices_len = 0;
ctx->gui.instance_count = 0;
ctx->window.p0.x = 0.0f;
ctx->window.p0.y = 0.0f;
ctx->windows = ArenaAlloc(ctx_arena, sizeof(GUIWindow) * 32);
ctx->window_len = 0;
ctx->window.p1.x = 100.0f;
ctx->window.p1.y = 100.0f;
ctx->buttons = ArenaAlloc(ctx_arena, sizeof(GUIButton) * 64);
ctx->btn_len = 0;
ctx->arena = arena;
}
@ -24,6 +24,7 @@ static void DestroyGame()
u32 selected_rect = 0;
b8 mouse_pressed = false;
b8 mouse_clicked = false;
i16 mouse_prev_pos_x = 0;
i16 mouse_prev_pos_y = 0;
i16 mouse_pos_x = 0;
@ -31,6 +32,8 @@ i16 mouse_pos_y = 0;
static void HandleInputs(GameInput *inputs, u32 count)
{
mouse_clicked = false;
for (u32 i = 0; i < count; i++)
{
if (inputs[i].type == GI_KEYBOARD)
@ -59,7 +62,11 @@ static void HandleInputs(GameInput *inputs, u32 count)
else if (inputs[i].type == GI_MOUSE)
{
if (inputs[i].m_code == M_LEFT_CLICK)
{
mouse_pressed = inputs[i].pressed;
if (!inputs[i].pressed)
mouse_clicked = true;
}
}
else if (inputs[i].type == GI_MOTION)
{
@ -71,46 +78,188 @@ static void HandleInputs(GameInput *inputs, u32 count)
}
}
static inline void PrepareGUICtx(GameContext *ctx)
{
ctx->gui.has_grabbed = false;
}
static inline u32 StrToU32(char *str)
{
u32 result = 0;
for (; *str != '\0'; str++)
{
result += (u32)(*str);
}
return result;
}
static b32 UIButton(GameContext *ctx, char *label, f32 x0, f32 y0, f32 x1, f32 y1)
{
GUIButton *btn = NULL;
u32 id = StrToU32(label) + (u32)(x0 + y0 + x1 + y1);
if (ctx->btn_len == 0)
{
ctx->buttons[0].p0.x = x0;
ctx->buttons[0].p0.y = y0;
ctx->buttons[0].p1.x = x1;
ctx->buttons[0].p1.y = y1;
ctx->buttons[0].id = id;
ctx->buttons[0].pressed = false;
ctx->buttons[0].pressed_prev = false;
btn = &ctx->buttons[0];
ctx->btn_len += 1;
}
else
{
for (u32 i = 0; i < ctx->btn_len; i++)
{
if (ctx->buttons[i].id == id)
{
btn = &ctx->buttons[i];
break;
}
}
if (btn == NULL)
{
ctx->btn_len += 1;
btn = &ctx->buttons[ctx->btn_len];
btn->p0.x = x0;
btn->p0.y = y0;
btn->p1.x = x1;
btn->p1.y = y1;
btn->id = id;
btn->pressed = false;
btn->pressed_prev = false;
}
}
Assert(btn != NULL, "button is null");
if (mouse_clicked
&& !ctx->gui.has_grabbed
&& mouse_pos_x > btn->p0.x
&& mouse_pos_x < btn->p1.x
&& mouse_pos_y > btn->p0.y
&& mouse_pos_y < btn->p1.y)
{
btn->pressed = !btn->pressed;
}
DrawRect(&ctx->gui, btn->p0, btn->p1, (Vec4){ .r = 0.1f, .g = 0.9f, .b = 0.4f, .a = 1.0f });
return btn->pressed;
}
static b32 UIWindow(GameContext *ctx, char *title, f32 x0, f32 y0, f32 x1, f32 y1)
{
GUIWindow *win = NULL;
u32 id = StrToU32(title) + (u32)(x0 + y0 + x1 + y1);
if (ctx->window_len == 0)
{
ctx->windows[0].p0.x = x0;
ctx->windows[0].p0.y = y0;
ctx->windows[0].p1.x = x1;
ctx->windows[0].p1.y = y1;
ctx->windows[0].id = id;
win = &ctx->windows[0];
ctx->window_len += 1;
}
else
{
for (u32 i = 0; i < ctx->window_len; i++)
{
if (ctx->windows[i].id == id)
{
win = &ctx->windows[i];
break;
}
}
if (win == NULL)
{
ctx->window_len += 1;
win = &ctx->windows[ctx->window_len];
win->p0.x = x0;
win->p0.y = y0;
win->p1.x = x1;
win->p1.y = y1;
win->id = id;
}
}
Assert(win != NULL, "window is null");
if (mouse_pressed && !win->grabbed
&& mouse_pos_x > win->p0.x
&& mouse_pos_x < win->p1.x
&& mouse_pos_y > win->p0.y
&& mouse_pos_y < win->p1.y
&& !ctx->gui.has_grabbed)
{
win->grabbed = true;
ctx->gui.has_grabbed = true;
win->grabbed_pos.x = (f32)mouse_pos_x - win->p0.x;
win->grabbed_pos.y = (f32)mouse_pos_y - win->p0.y;
}
else if (!mouse_pressed && win->grabbed)
{
win->grabbed = false;
win->grabbed_pos.x = 0.0f;
win->grabbed_pos.y = 0.0f;
}
if (win->grabbed)
{
f32 w = win->p1.x - win->p0.x;
f32 h = win->p1.y - win->p0.y;
win->p0.x = (f32)(mouse_pos_x) - win->grabbed_pos.x;
win->p0.y = (f32)(mouse_pos_y) - win->grabbed_pos.y;
win->p1.x = win->p0.x + w;
win->p1.y = win->p0.y + h;
ctx->gui.has_grabbed = true;
}
DrawRect(&ctx->gui, win->p0, win->p1, (Vec4){ .r = 0.1f, .g = 0.3f, .b = 0.8f, .a = 1.0f });
return true;
}
static void RunCycle(GameContext *ctx, GameInput *inputs, u32 i_count)
{
__atomic_store_n(&renderer.vk.imm.job_count, 0, __ATOMIC_RELEASE);
__atomic_store_n(&renderer.vk.imm.remaining_count, 0, __ATOMIC_RELEASE);
GetViewportSize(&ctx->pc.res);
PrepareGUICtx(ctx);
HandleInputs(inputs, i_count);
if (mouse_pressed && !ctx->window.grabbed
&& mouse_pos_x > ctx->window.p0.x
&& mouse_pos_x < ctx->window.p1.x
&& mouse_pos_y > ctx->window.p0.y
&& mouse_pos_y < ctx->window.p1.y)
if (UIButton(ctx, "Show 2", 150.0f, 150.0f, 200.0f, 200.0f))
{
ctx->window.grabbed = true;
ctx->window.grabbed_pos.x = (f32)mouse_pos_x - ctx->window.p0.x;
ctx->window.grabbed_pos.y = (f32)mouse_pos_y - ctx->window.p0.y;
}
else if (!mouse_pressed && ctx->window.grabbed)
{
ctx->window.grabbed = false;
ctx->window.grabbed_pos.x = 0.0f;
ctx->window.grabbed_pos.y = 0.0f;
UIWindow(ctx, "Window 2", 500.0f, 500.0f, 600.0f, 600.0f);
}
if (ctx->window.grabbed)
if (UIButton(ctx, "Show 1", 50.0f, 50.0f, 100.0f, 100.0f))
{
f32 w = ctx->window.p1.x - ctx->window.p0.x;
f32 h = ctx->window.p1.y - ctx->window.p0.y;
ctx->window.p0.x = (f32)(mouse_pos_x) - ctx->window.grabbed_pos.x;
ctx->window.p0.y = (f32)(mouse_pos_y) - ctx->window.grabbed_pos.y;
ctx->window.p1.x = ctx->window.p0.x + w;
ctx->window.p1.y = ctx->window.p0.y + h;
UIWindow(ctx, "Window 1", 200.0f, 200.0f, 400.0f, 400.0f);
}
DrawRect(&ctx->gui, ctx->window.p0, ctx->window.p1, (Vec4){ .r = 0.1f, .g = 0.3f, .b = 0.8f, .a = 1.0f });
if (UIButton(ctx, "Show 3", 150.0f, 300.0f, 200.0f, 350.0f))
{
UIWindow(ctx, "Window 3", 250.0f, 500.0f, 400.0f, 650.0f);
}
GetViewportSize(&ctx->pc.res);
RenderBuffer *vertex_buffer = ArenaAlloc(ctx->arena, sizeof(RenderBuffer));
vertex_buffer->type = RENDER_BUFFER_TYPE_VERTEX;

View File

@ -5,15 +5,28 @@ typedef struct GUIWindow_t
Vec2 p0;
Vec2 p1;
Vec2 grabbed_pos;
u32 id;
b8 grabbed;
} GUIWindow;
typedef struct GUIButton_t
{
Vec2 p0;
Vec2 p1;
u32 id;
b8 pressed;
b8 pressed_prev;
} GUIButton;
typedef struct GameContext_t
{
GUIContext gui;
PushConst pc;
Arena *arena;
GUIWindow window;
GUIWindow *windows;
u32 window_len;
GUIButton *buttons;
u32 btn_len;
} GameContext;
static void RunCycle(GameContext *ctx, GameInput *inputs, u32 i_count);

View File

@ -323,7 +323,7 @@ u8 *OSOpenFile(const char *)
return bytes;
}
b32 _ShouldQuit()
b32 ShouldQuit()
{
return false;
}

View File

@ -201,7 +201,7 @@ void WaitForWindowEvent()
}
}
b32 _ShouldQuit()
b32 ShouldQuit()
{
return global_quit;
}

View File

@ -255,4 +255,5 @@ typedef struct
u32 *indices;
u32 indices_len;
u32 instance_count;
b8 has_grabbed;
} GUIContext;