From 2fce90f0f3f88e7c1d1be041d10426e077c0cbdd Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Mon, 8 Jan 2024 00:16:14 +0000 Subject: [PATCH] Abstract window and rendere initialisation code --- include/window.h | 52 ++++++++++++++++ src/window.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 include/window.h create mode 100644 src/window.c diff --git a/include/window.h b/include/window.h new file mode 100644 index 0000000..a85f1e9 --- /dev/null +++ b/include/window.h @@ -0,0 +1,52 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include "SDL_events.h" +#include "aliases/aliases.h" +#include "colour.h" +#include +#include +#include + +#ifndef MAX_HANDLERS_LENGTH +#define MAX_HANDLERS_LENGTH 128 +#endif // !MAX_HANDLERS_LENGTH + +typedef struct window window_t; + +typedef void (*event_listener_t)(const window_t *wnd, void *obj, + const SDL_Event *ev); +typedef void (*render_func_t)(const window_t *wnd, void *obj); + +typedef struct { + u64 x; + u64 y; + u64 width; + u64 height; +} render_rect_t; + +struct window { + u64 width; + u64 height; + SDL_Window *window; + SDL_Renderer *renderer; + colour_t bg_colour; + bool running; + SDL_Event event; + u64 count; + void *objects[MAX_HANDLERS_LENGTH]; + event_listener_t listeners[MAX_HANDLERS_LENGTH]; + render_func_t render_funcs[MAX_HANDLERS_LENGTH]; +}; + +bool open_window(window_t *wnd, const char *title, u64 w, u64 h, + colour_t bg_colour); +void run_window_loop(window_t *wnd); +void close_window(window_t *wnd); +bool add_event_listener(window_t *wnd, void *obj, event_listener_t listener); +bool add_renderer_func(window_t *wnd, void *obj, render_func_t func); +void fill_rect(const window_t *wnd, const render_rect_t *rect, colour_t colour); +void draw_rect(const window_t *wnd, const render_rect_t *rect, colour_t colour); +bool aabb(u64 x, u64 y, const render_rect_t *rect); + +#endif // !WINDOW_H diff --git a/src/window.c b/src/window.c new file mode 100644 index 0000000..dd3db67 --- /dev/null +++ b/src/window.c @@ -0,0 +1,159 @@ +#include "window.h" +#include "SDL_rect.h" +#include "SDL_render.h" +#include +#include + +void handle_quit(const window_t *wnd, void *obj, const SDL_Event *ev); +void clear_backgroud(const window_t *wnd, void *obj); + +bool open_window(window_t *wnd, const char *title, u64 w, u64 h, + colour_t bg_colour) { + SDL_Init(SDL_INIT_EVERYTHING); + + wnd->window = + SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, + h, SDL_WINDOW_SHOWN); + if (!wnd->window) { + close_window(wnd); + + return false; + } + + wnd->renderer = SDL_CreateRenderer( + wnd->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (!wnd->renderer) { + close_window(wnd); + + return false; + } + + wnd->width = w; + wnd->height = h; + wnd->running = true; + wnd->bg_colour = bg_colour; + wnd->event = (SDL_Event){0}; + wnd->count = 0; + + SDL_EventState(SDL_DROPFILE, SDL_ENABLE); + + add_event_listener(wnd, (void *)wnd, handle_quit); + add_renderer_func(wnd, (void *)wnd, clear_backgroud); + + return true; +} + +void run_window_loop(window_t *wnd) { + while (wnd->running) { + while (SDL_PollEvent(&wnd->event)) { + for (u64 i = 0; i < wnd->count; ++i) { + event_listener_t func = wnd->listeners[i]; + + if (!func) { + continue; + } + + func(wnd, wnd->objects[i], &wnd->event); + } + } + + for (u64 i = 0; i < wnd->count; ++i) { + render_func_t func = wnd->render_funcs[i]; + + if (!func) { + continue; + } + + func(wnd, wnd->objects[i]); + } + + SDL_RenderPresent(wnd->renderer); + } +} + +void close_window(window_t *wnd) { + wnd->width = 0; + wnd->height = 0; + wnd->running = false; + wnd->bg_colour.abgr = 0; + wnd->event = (SDL_Event){0}; + + if (wnd->renderer) { + SDL_DestroyRenderer(wnd->renderer); + } + + if (wnd->window) { + SDL_DestroyWindow(wnd->window); + } + + SDL_Quit(); +} + +bool add_event_listener(window_t *wnd, void *obj, event_listener_t listener) { + if (!wnd || wnd->count + 1 >= MAX_HANDLERS_LENGTH) { + return false; + } + + u64 index = (wnd->count)++; + + wnd->objects[index] = obj; + wnd->listeners[index] = listener; + + return true; +} + +bool add_renderer_func(window_t *wnd, void *obj, render_func_t func) { + if (!wnd || wnd->count + 1 >= MAX_HANDLERS_LENGTH) { + return false; + } + + u64 index = (wnd->count)++; + + wnd->objects[index] = obj; + wnd->render_funcs[index] = func; + + return true; +} + +void fill_rect(const window_t *wnd, const render_rect_t *rect, + colour_t colour) { + SDL_Rect dest = { + .x = rect->x, .y = rect->y, .w = rect->width, .h = rect->height}; + + SDL_SetRenderDrawColor(wnd->renderer, colour.colour.r, colour.colour.g, + colour.colour.b, colour.colour.a); + + SDL_RenderFillRect(wnd->renderer, &dest); +} + +void draw_rect(const window_t *wnd, const render_rect_t *rect, + colour_t colour) { + SDL_Rect dest = { + .x = rect->x, .y = rect->y, .w = rect->width, .h = rect->height}; + + SDL_SetRenderDrawColor(wnd->renderer, colour.colour.r, colour.colour.g, + colour.colour.b, colour.colour.a); + + SDL_RenderDrawRect(wnd->renderer, &dest); +} + +bool aabb(u64 x, u64 y, const render_rect_t *rect) { + return x >= rect->x && y >= rect->y && x < rect->x + rect->width && + y < rect->y + rect->height; +} + +void handle_quit(const window_t *wnd, void *obj, const SDL_Event *ev) { + if (ev->type == SDL_QUIT) { + window_t *wnd = obj; + + wnd->running = false; + } +} + +void clear_backgroud(const window_t *wnd, void *obj) { + SDL_SetRenderDrawColor(wnd->renderer, wnd->bg_colour.colour.r, + wnd->bg_colour.colour.g, wnd->bg_colour.colour.b, + wnd->bg_colour.colour.a); + + SDL_RenderClear(wnd->renderer); +}