diff --git a/src/entry_linux.c b/src/entry_linux.c index f2c270a..d6b07ec 100644 --- a/src/entry_linux.c +++ b/src/entry_linux.c @@ -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)); diff --git a/src/game.c b/src/game.c index 92e3674..4e61f43 100644 --- a/src/game.c +++ b/src/game.c @@ -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; diff --git a/src/game.h b/src/game.h index a3d8164..df80eb7 100644 --- a/src/game.h +++ b/src/game.h @@ -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; + PushConst pc; + Arena *arena; + GUIWindow *windows; + u32 window_len; + GUIButton *buttons; + u32 btn_len; } GameContext; static void RunCycle(GameContext *ctx, GameInput *inputs, u32 i_count); diff --git a/src/platform/platform_linux.c b/src/platform/platform_linux.c index cb1b478..8ccb46b 100644 --- a/src/platform/platform_linux.c +++ b/src/platform/platform_linux.c @@ -323,7 +323,7 @@ u8 *OSOpenFile(const char *) return bytes; } -b32 _ShouldQuit() +b32 ShouldQuit() { return false; } diff --git a/src/platform/platform_windows.c b/src/platform/platform_windows.c index 31ed4c0..8853060 100644 --- a/src/platform/platform_windows.c +++ b/src/platform/platform_windows.c @@ -201,7 +201,7 @@ void WaitForWindowEvent() } } -b32 _ShouldQuit() +b32 ShouldQuit() { return global_quit; } diff --git a/src/shared_types.h b/src/shared_types.h index c7aa5ac..7f62ddb 100644 --- a/src/shared_types.h +++ b/src/shared_types.h @@ -255,4 +255,5 @@ typedef struct u32 *indices; u32 indices_len; u32 instance_count; + b8 has_grabbed; } GUIContext;