From c6825caa69f6b2f7e1fff1d5e127798951849e4f Mon Sep 17 00:00:00 2001 From: Piotr Krygier Date: Wed, 4 Mar 2026 11:04:53 +0100 Subject: [PATCH] Implement event handler Added event handler implementation. Moved enginge specific implementation outside graphics module Signed-off-by: Piotr Krygier --- events/meson.build | 3 +- events/rse_events_manager.h | 26 ++++++++++ events/src/events_context.h | 21 +++++--- events/src/events_manager.c | 66 ++++++++++++++++--------- events/src/events_manager.h | 20 -------- graphics/meson.build | 1 - graphics/rse_graphics.h | 6 ++- graphics/src/rse_graphics.c | 19 +++++-- graphics/src/vulkan_base.c | 7 +-- graphics/src/vulkan_base.h | 2 +- graphics/src/vulkan_commons.c | 24 --------- graphics/src/vulkan_commons.h | 4 -- graphics/src/window.c | 48 ------------------ graphics/src/window.h | 8 --- red_scarf_engine/meson.build | 1 + red_scarf_engine/red_scarf_engine.h | 1 - red_scarf_engine/src/main.c | 1 + red_scarf_engine/src/red_scarf_engine.c | 37 ++++++++++++-- 18 files changed, 143 insertions(+), 152 deletions(-) create mode 100644 events/rse_events_manager.h delete mode 100644 events/src/events_manager.h delete mode 100644 graphics/src/vulkan_commons.c diff --git a/events/meson.build b/events/meson.build index 20d78d2f..966a7057 100644 --- a/events/meson.build +++ b/events/meson.build @@ -1,4 +1,5 @@ rse_events_sources = [ + 'src/events_manager.c' ] sdl3_dep = dependency('sdl3', @@ -10,7 +11,7 @@ rse_events_lib = shared_library( include_directories : [ '../' ], - dependencies : [ + dependencies : [sdl3_dep, ], link_with: rse_utilities_lib, install : true diff --git a/events/rse_events_manager.h b/events/rse_events_manager.h new file mode 100644 index 00000000..a7b31c7a --- /dev/null +++ b/events/rse_events_manager.h @@ -0,0 +1,26 @@ +/** + * @file events_manager.h + * @author Piotr Krygier (piotrkrygier@everyonencancode.xyz) + * @brief Events manager for Red Scarf Engine + * @version 0.1 + * @date 2026-03-02 + * + * @copyright Copyright (c) 2026 + * + */ + +#ifndef RSE_EVENTS_MANAGER_H_ +#define RSE_EVENTS_MANAGER_H_ + +#include "src/events_context.h" +#include "utilities/commons.h" + +rse_err_t rse_events_init(struct events_context_t* events_context); + +rse_err_t rse_events_set_event_handler(struct events_context_t* events_context, + enum EVENT_HANDLER event_type, + rse_event_handler_t event_handler); + +rse_err_t rse_events_main_loop(struct events_context_t* context); + +#endif /* RSE_EVENTS_MANAGER_H_ */ diff --git a/events/src/events_context.h b/events/src/events_context.h index 016c35ca..d9929d30 100644 --- a/events/src/events_context.h +++ b/events/src/events_context.h @@ -15,6 +15,17 @@ #include "SDL3/SDL_mouse.h" #include "utilities/commons.h" +enum EVENT_HANDLER { + EVENT_HANDLER_QUIT, + EVENT_HANDLER_MOUSE, + EVENT_HANDLER_LAST +}; + +enum EVENT_SHOULD_STOP_ENGINE { + EVENT_SHOULD_STOP_ENGINE_FALSE, + EVENT_SHOULD_STOP_ENGINE_TRUE +}; + struct mouse_event_data_t { float x_pos; @@ -24,14 +35,10 @@ struct mouse_event_data_t typedef rse_err_t (*rse_event_handler_t)(void*); -struct event_handlers +struct events_context_t { - rse_event_handler_t mouse_event; -}; - -struct events_context -{ - struct event_handlers event_handlers; + enum EVENT_SHOULD_STOP_ENGINE should_stop; + rse_event_handler_t event_handlers[EVENT_HANDLER_LAST]; }; #endif /* EVENT_CONTEXT_H_ */ diff --git a/events/src/events_manager.c b/events/src/events_manager.c index d505482e..180cd506 100644 --- a/events/src/events_manager.c +++ b/events/src/events_manager.c @@ -9,11 +9,11 @@ * */ -#include "events_manager.h" - #include "SDL3/SDL_events.h" +#include "SDL3/SDL_log.h" #include "SDL3/SDL_mouse.h" #include "events_context.h" +#include "rse_events_manager.h" #include "utilities/commons.h" #include "utilities/errors_common.h" @@ -24,44 +24,62 @@ static rse_err_t default_event(void* args) return RSE_ERROR_NO_ERROR; } -static rse_err_t quit_event(void) +static rse_err_t run_custom_event_handler(struct events_context_t* context, + enum EVENT_HANDLER event_handler, + void* args) { - return RSE_ERROR_NO_ERROR; + return context->event_handlers[event_handler](args); } -static rse_err_t mouse_event(struct events_context* events_context) +static rse_err_t quit_event(struct events_context_t* context) +{ + context->should_stop = EVENT_SHOULD_STOP_ENGINE_TRUE; + + return run_custom_event_handler(context, EVENT_HANDLER_QUIT, NULL); +} + +static rse_err_t mouse_event(struct events_context_t* context) { struct mouse_event_data_t mouse_data = {0}; mouse_data.mouse_buttons = SDL_GetMouseState(&mouse_data.x_pos, &mouse_data.y_pos); - return events_context->event_handlers.mouse_event((void*)&mouse_data); + return run_custom_event_handler(context, EVENT_HANDLER_MOUSE, (void*)&mouse_data); } -rse_err_t events_init(struct events_context* events_context) +rse_err_t rse_events_init(struct events_context_t* events_context) { - events_context->event_handlers.mouse_event = default_event; + size_t i = 0U; - return RSE_ERROR_NO_ERROR; -} - -rse_err_t events_set_event_handler(struct events_context* events_context, - enum RSE_EVENT_TYPE event_type, - rse_event_handler_t event_handler) -{ - switch (event_type) { - case RSE_EVENT_TYPE_MOUSE: - events_context->event_handlers.mouse_event = event_handler; - break; - default: - SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Invalid event type provided"); - return RSE_ERROR_INVALID_PARAM; + for (i = 0U; i < EVENT_HANDLER_LAST; ++i) { + events_context->event_handlers[i] = default_event; } return RSE_ERROR_NO_ERROR; } -rse_err_t events_run(struct events_context* context) +rse_err_t rse_events_set_event_handler(struct events_context_t* events_context, + enum EVENT_HANDLER event_type, + rse_event_handler_t event_handler) +{ + if (event_type >= EVENT_HANDLER_LAST) { + SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Invalid event type selected"); + + return RSE_ERROR_INVALID_PARAM; + } + + if (event_handler == NULL) { + SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL event handler"); + + return RSE_ERROR_INVALID_PARAM; + } + + events_context->event_handlers[event_type] = event_handler; + + return RSE_ERROR_NO_ERROR; +} + +rse_err_t rse_events_main_loop(struct events_context_t* context) { SDL_Event event; rse_err_t status = RSE_ERROR_NO_ERROR; @@ -69,7 +87,7 @@ rse_err_t events_run(struct events_context* context) while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_EVENT_QUIT: - STATUS_CHECK(quit_event()); + STATUS_CHECK(quit_event(context)); break; case SDL_EVENT_MOUSE_BUTTON_DOWN: STATUS_CHECK(mouse_event(context)); diff --git a/events/src/events_manager.h b/events/src/events_manager.h deleted file mode 100644 index 9c668912..00000000 --- a/events/src/events_manager.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @file events_manager.h - * @author Piotr Krygier (piotrkrygier@everyonencancode.xyz) - * @brief Events manager for Red Scarf Engine - * @version 0.1 - * @date 2026-03-02 - * - * @copyright Copyright (c) 2026 - * - */ - -#ifndef EVENTS_MANAGER_H_ -#define EVENTS_MANAGER_H_ - -enum RSE_EVENT_TYPE { - RSE_EVENT_TYPE_MOUSE, -}; - - -#endif /* EVENTS_MANAGER_H_ */ diff --git a/graphics/meson.build b/graphics/meson.build index eec32728..56794ee8 100644 --- a/graphics/meson.build +++ b/graphics/meson.build @@ -9,7 +9,6 @@ rse_graphics_sources = [ 'src/vulkan_base.c', 'src/vulkan_buffers.c', 'src/vulkan_commands.c', - 'src/vulkan_commons.c', 'src/vulkan_image.c', 'src/vulkan_render_pass.c', 'src/vulkan_swapchain.c', diff --git a/graphics/rse_graphics.h b/graphics/rse_graphics.h index 5e23f4f6..b7a4ec36 100644 --- a/graphics/rse_graphics.h +++ b/graphics/rse_graphics.h @@ -18,13 +18,17 @@ rse_err_t rse_graphics_init(struct graphics_context_t* context); * * @return rse_err_t RSE_ERROR_NO_ERROR on success */ -rse_err_t rse_graphics_main_loop(struct graphics_context_t* context); +rse_err_t rse_graphics_run(struct graphics_context_t* context); +rse_err_t rse_graphics_main_loop(struct graphics_context_t* context); + /** * @brief Custom function for testing engine. TODO: Remove it whe releasing * */ rse_err_t rse_graphics_test_function(struct graphics_context_t* context); +void rse_graphics_deinit(struct graphics_context_t* context); + #endif /* RSE_GRAPHICS_H */ diff --git a/graphics/src/rse_graphics.c b/graphics/src/rse_graphics.c index 06d83c2d..153d2ce7 100644 --- a/graphics/src/rse_graphics.c +++ b/graphics/src/rse_graphics.c @@ -245,17 +245,28 @@ rse_err_t rse_graphics_test_function(struct graphics_context_t* context) return RSE_ERROR_NO_ERROR; } -rse_err_t rse_graphics_main_loop(struct graphics_context_t* context) +rse_err_t rse_graphics_run(struct graphics_context_t* context) { rse_err_t status = RSE_ERROR_NO_ERROR; STATUS_CHECK(vulkan_run(context)); - STATUS_CHECK(window_loop(context)); + return status; +} + +rse_err_t rse_graphics_main_loop(struct graphics_context_t* context) +{ + rse_err_t status = RSE_ERROR_NO_ERROR; + + STATUS_CHECK(vulkan_draw_frame(context)); + + return status; +} + +void rse_graphics_deinit(struct graphics_context_t* context) +{ vulkan_deinit(context); window_terminate(context->window_handle); rse_free(context->debug_overlay.pixels); - - return status; } diff --git a/graphics/src/vulkan_base.c b/graphics/src/vulkan_base.c index 2924b530..b03dd719 100644 --- a/graphics/src/vulkan_base.c +++ b/graphics/src/vulkan_base.c @@ -559,12 +559,10 @@ rse_err_t vulkan_run(struct graphics_context_t* context) STATUS_CHECK(create_sync_objects(context)); - init_time(); - return status; } -rse_err_t draw_frame(struct graphics_context_t* context) +rse_err_t vulkan_draw_frame(struct graphics_context_t* context) { rse_err_t status = RSE_ERROR_NO_ERROR; uint32_t image_index = 0U; @@ -580,8 +578,6 @@ rse_err_t draw_frame(struct graphics_context_t* context) STATUS_CHECK(buffers_update(context)); - update_time(); - result = vkAcquireNextImageKHR(context->vulkan_handles.device, context->swapchain_data.swapchain, UINT64_MAX, context->vulkan_handles.image_available_semaphores[context->current_frame], VK_NULL_HANDLE, &image_index); @@ -649,6 +645,7 @@ rse_err_t draw_frame(struct graphics_context_t* context) void vulkan_deinit(struct graphics_context_t* context) { + vkDeviceWaitIdle(context->vulkan_handles.device); destroy_buffers(context); for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) { vkDestroySemaphore(context->vulkan_handles.device, context->vulkan_handles.image_available_semaphores[i], NULL); diff --git a/graphics/src/vulkan_base.h b/graphics/src/vulkan_base.h index c2d97f82..120f9418 100644 --- a/graphics/src/vulkan_base.h +++ b/graphics/src/vulkan_base.h @@ -46,6 +46,6 @@ void vulkan_deinit(struct graphics_context_t* context); * @param context Graphics context * @return rse_err_t */ -rse_err_t draw_frame(struct graphics_context_t* context); +rse_err_t vulkan_draw_frame(struct graphics_context_t* context); #endif /* GRAPHICS_VULKANBASE_H */ diff --git a/graphics/src/vulkan_commons.c b/graphics/src/vulkan_commons.c deleted file mode 100644 index 69cc7e8f..00000000 --- a/graphics/src/vulkan_commons.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "vulkan_commons.h" - -#include - -time_t g_last_frame_time; -time_t g_this_frame_time; -float g_float_delta_time; - -void init_time(void) -{ - time(&g_last_frame_time); -} - -void update_time(void) -{ - g_last_frame_time = g_this_frame_time; - time(&g_this_frame_time); - g_float_delta_time = (float)difftime(g_this_frame_time, g_last_frame_time); -} - -float get_time_diff(void) -{ - return g_float_delta_time; -} diff --git a/graphics/src/vulkan_commons.h b/graphics/src/vulkan_commons.h index 8ad3c007..b8bfe577 100644 --- a/graphics/src/vulkan_commons.h +++ b/graphics/src/vulkan_commons.h @@ -58,8 +58,4 @@ struct instance_data_t { alignas(4) uint32_t texture_id; }; -void init_time(void); -void update_time(void); -float get_time_diff(void); - #endif /* VULKAN_GLOBAL_H */ diff --git a/graphics/src/window.c b/graphics/src/window.c index e5342008..c8112f04 100644 --- a/graphics/src/window.c +++ b/graphics/src/window.c @@ -21,29 +21,9 @@ #include "SDL3/SDL_log.h" #include "utilities/commons.h" #include "utilities/errors_common.h" -#include "utilities/time_utils.h" -#include "vulkan/vulkan_core.h" -#include "vulkan_base.h" - -static void fps_print(double* start_time) -{ - static uint32_t frame_counts = 0U; - - double now = time_get_sec_from_start(); - - frame_counts++; - if ((now - *start_time) > 1.0) { - printf("\rFPS: %u", frame_counts); - fflush(stdout); - frame_counts = 0; - *start_time += 1.0; - } -} rse_err_t window_init(SDL_Window** window_handle, bool* is_framebuffer_resized) { - SDL_Init(SDL_INIT_VIDEO); // TODO: Move to initial phase of RSE initialization - (void)is_framebuffer_resized; // TODO: Actually use this parameter? @@ -57,34 +37,6 @@ rse_err_t window_init(SDL_Window** window_handle, bool* is_framebuffer_resized) return RSE_ERROR_NO_ERROR; } -rse_err_t window_loop(struct graphics_context_t* context) -{ - uint8_t done = 0; - SDL_Event event; - double start_time; - - start_time = time_get_sec_from_start(); - - while (0 == done) { - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_EVENT_QUIT: - done = 1; - break; - case SDL_EVENT_MOUSE_BUTTON_DOWN: - break; - } - } - - time_update(); - draw_frame(context); - fps_print(&start_time); - } - - vkDeviceWaitIdle(context->vulkan_handles.device); - return RSE_ERROR_NO_ERROR; -} - void window_terminate(SDL_Window* window_handle) { SDL_DestroyWindow(window_handle); diff --git a/graphics/src/window.h b/graphics/src/window.h index d7ee9499..05c32e1f 100644 --- a/graphics/src/window.h +++ b/graphics/src/window.h @@ -32,14 +32,6 @@ */ rse_err_t window_init(SDL_Window **window_handle, bool *is_framebuffer_resized); -/** - * @brief Main window loop - * - * @param context Graphics context - * @return rse_err_t WINDOW_SUCCESS or error code - */ -rse_err_t window_loop(struct graphics_context_t* context); - /** * @brief Closes window and terminates GLFW * diff --git a/red_scarf_engine/meson.build b/red_scarf_engine/meson.build index cb65ee1a..a6b78e76 100644 --- a/red_scarf_engine/meson.build +++ b/red_scarf_engine/meson.build @@ -17,6 +17,7 @@ executable( ], link_with: [ rse_graphics_lib, + rse_events_lib, rse_utilities_lib, ], ) diff --git a/red_scarf_engine/red_scarf_engine.h b/red_scarf_engine/red_scarf_engine.h index 9709fce0..ef22092c 100644 --- a/red_scarf_engine/red_scarf_engine.h +++ b/red_scarf_engine/red_scarf_engine.h @@ -13,7 +13,6 @@ #define RED_SCARF_ENGINE_H_ #include "utilities/commons.h" -#include "utilities/errors_common.h" typedef struct rse_context_t* rse_context; diff --git a/red_scarf_engine/src/main.c b/red_scarf_engine/src/main.c index 0a29450a..d3f27a1e 100644 --- a/red_scarf_engine/src/main.c +++ b/red_scarf_engine/src/main.c @@ -1,4 +1,5 @@ #include "red_scarf_engine.h" +#include "utilities/errors_common.h" int main(int argc, char** argv) { diff --git a/red_scarf_engine/src/red_scarf_engine.c b/red_scarf_engine/src/red_scarf_engine.c index b1fc76bb..4916fac6 100644 --- a/red_scarf_engine/src/red_scarf_engine.c +++ b/red_scarf_engine/src/red_scarf_engine.c @@ -1,14 +1,30 @@ #include "red_scarf_engine.h" #include "graphics/rse_graphics.h" -#include "graphics/src/graphics_context.h" #include "utilities/commons.h" #include "utilities/errors_common.h" #include "utilities/time_utils.h" +#include "events/rse_events_manager.h" struct rse_context_t { struct graphics_context_t graphics_context; + struct events_context_t events_context; }; +static void fps_print(double* start_time) +{ + static uint32_t frame_counts = 0U; + + double now = time_get_sec_from_start(); + + frame_counts++; + if ((now - *start_time) > 1.0) { + printf("\rFPS: %u", frame_counts); + fflush(stdout); + frame_counts = 0; + *start_time += 1.0; + } +} + rse_err_t rse_init(rse_context* context) { rse_err_t status = RSE_ERROR_NO_ERROR; @@ -18,10 +34,12 @@ rse_err_t rse_init(rse_context* context) rse_context = *context; + SDL_Init(SDL_INIT_VIDEO); SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE); STATUS_CHECK(time_init()); - rse_graphics_init(&(rse_context->graphics_context)); + STATUS_CHECK(rse_events_init(&rse_context->events_context)); + STATUS_CHECK(rse_graphics_init(&rse_context->graphics_context)); return RSE_ERROR_NO_ERROR; } @@ -29,11 +47,24 @@ rse_err_t rse_init(rse_context* context) rse_err_t rse_run(rse_context context) { rse_err_t status = RSE_ERROR_NO_ERROR; + double start_time; + + start_time = time_get_sec_from_start(); STATUS_CHECK(rse_graphics_test_function(&context->graphics_context)); - STATUS_CHECK(rse_graphics_main_loop(&context->graphics_context)); + STATUS_CHECK(rse_graphics_run(&context->graphics_context)); + while(true) { + time_update(); + rse_events_main_loop(&context->events_context); + if (context->events_context.should_stop == EVENT_SHOULD_STOP_ENGINE_TRUE) { + break; + } + rse_graphics_main_loop(&context->graphics_context); + fps_print(&start_time); + } + rse_graphics_deinit(&context->graphics_context); rse_free(context); return status;