Implement event handler

Added event handler implementation.
Moved enginge specific implementation outside graphics module

Signed-off-by: Piotr Krygier <piotrkrygier@everyonecancode@xyz>
This commit is contained in:
Piotr Krygier
2026-03-04 11:04:53 +01:00
parent bbbe69d73c
commit c6825caa69
18 changed files with 143 additions and 152 deletions
+2 -1
View File
@@ -1,4 +1,5 @@
rse_events_sources = [ rse_events_sources = [
'src/events_manager.c'
] ]
sdl3_dep = dependency('sdl3', sdl3_dep = dependency('sdl3',
@@ -10,7 +11,7 @@ rse_events_lib = shared_library(
include_directories : [ include_directories : [
'../' '../'
], ],
dependencies : [ dependencies : [sdl3_dep,
], ],
link_with: rse_utilities_lib, link_with: rse_utilities_lib,
install : true install : true
+26
View File
@@ -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_ */
+14 -7
View File
@@ -15,6 +15,17 @@
#include "SDL3/SDL_mouse.h" #include "SDL3/SDL_mouse.h"
#include "utilities/commons.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 struct mouse_event_data_t
{ {
float x_pos; float x_pos;
@@ -24,14 +35,10 @@ struct mouse_event_data_t
typedef rse_err_t (*rse_event_handler_t)(void*); typedef rse_err_t (*rse_event_handler_t)(void*);
struct event_handlers struct events_context_t
{ {
rse_event_handler_t mouse_event; enum EVENT_SHOULD_STOP_ENGINE should_stop;
}; rse_event_handler_t event_handlers[EVENT_HANDLER_LAST];
struct events_context
{
struct event_handlers event_handlers;
}; };
#endif /* EVENT_CONTEXT_H_ */ #endif /* EVENT_CONTEXT_H_ */
+36 -18
View File
@@ -9,11 +9,11 @@
* *
*/ */
#include "events_manager.h"
#include "SDL3/SDL_events.h" #include "SDL3/SDL_events.h"
#include "SDL3/SDL_log.h"
#include "SDL3/SDL_mouse.h" #include "SDL3/SDL_mouse.h"
#include "events_context.h" #include "events_context.h"
#include "rse_events_manager.h"
#include "utilities/commons.h" #include "utilities/commons.h"
#include "utilities/errors_common.h" #include "utilities/errors_common.h"
@@ -24,44 +24,62 @@ static rse_err_t default_event(void* args)
return RSE_ERROR_NO_ERROR; 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}; struct mouse_event_data_t mouse_data = {0};
mouse_data.mouse_buttons = SDL_GetMouseState(&mouse_data.x_pos, &mouse_data.y_pos); 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;
for (i = 0U; i < EVENT_HANDLER_LAST; ++i) {
events_context->event_handlers[i] = default_event;
}
return RSE_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
rse_err_t events_set_event_handler(struct events_context* events_context, rse_err_t rse_events_set_event_handler(struct events_context_t* events_context,
enum RSE_EVENT_TYPE event_type, enum EVENT_HANDLER event_type,
rse_event_handler_t event_handler) rse_event_handler_t event_handler)
{ {
switch (event_type) { if (event_type >= EVENT_HANDLER_LAST) {
case RSE_EVENT_TYPE_MOUSE: SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Invalid event type selected");
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; 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; return RSE_ERROR_NO_ERROR;
} }
rse_err_t events_run(struct events_context* context) rse_err_t rse_events_main_loop(struct events_context_t* context)
{ {
SDL_Event event; SDL_Event event;
rse_err_t status = RSE_ERROR_NO_ERROR; 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)) { while (SDL_PollEvent(&event)) {
switch (event.type) { switch (event.type) {
case SDL_EVENT_QUIT: case SDL_EVENT_QUIT:
STATUS_CHECK(quit_event()); STATUS_CHECK(quit_event(context));
break; break;
case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_DOWN:
STATUS_CHECK(mouse_event(context)); STATUS_CHECK(mouse_event(context));
-20
View File
@@ -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_ */
-1
View File
@@ -9,7 +9,6 @@ rse_graphics_sources = [
'src/vulkan_base.c', 'src/vulkan_base.c',
'src/vulkan_buffers.c', 'src/vulkan_buffers.c',
'src/vulkan_commands.c', 'src/vulkan_commands.c',
'src/vulkan_commons.c',
'src/vulkan_image.c', 'src/vulkan_image.c',
'src/vulkan_render_pass.c', 'src/vulkan_render_pass.c',
'src/vulkan_swapchain.c', 'src/vulkan_swapchain.c',
+5 -1
View File
@@ -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 * @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 * @brief Custom function for testing engine. TODO: Remove it whe releasing
* *
*/ */
rse_err_t rse_graphics_test_function(struct graphics_context_t* context); 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 */ #endif /* RSE_GRAPHICS_H */
+15 -4
View File
@@ -245,17 +245,28 @@ rse_err_t rse_graphics_test_function(struct graphics_context_t* context)
return RSE_ERROR_NO_ERROR; 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; rse_err_t status = RSE_ERROR_NO_ERROR;
STATUS_CHECK(vulkan_run(context)); 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); vulkan_deinit(context);
window_terminate(context->window_handle); window_terminate(context->window_handle);
rse_free(context->debug_overlay.pixels); rse_free(context->debug_overlay.pixels);
return status;
} }
+2 -5
View File
@@ -559,12 +559,10 @@ rse_err_t vulkan_run(struct graphics_context_t* context)
STATUS_CHECK(create_sync_objects(context)); STATUS_CHECK(create_sync_objects(context));
init_time();
return status; 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; rse_err_t status = RSE_ERROR_NO_ERROR;
uint32_t image_index = 0U; uint32_t image_index = 0U;
@@ -580,8 +578,6 @@ rse_err_t draw_frame(struct graphics_context_t* context)
STATUS_CHECK(buffers_update(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], 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); 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) void vulkan_deinit(struct graphics_context_t* context)
{ {
vkDeviceWaitIdle(context->vulkan_handles.device);
destroy_buffers(context); destroy_buffers(context);
for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) { for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) {
vkDestroySemaphore(context->vulkan_handles.device, context->vulkan_handles.image_available_semaphores[i], NULL); vkDestroySemaphore(context->vulkan_handles.device, context->vulkan_handles.image_available_semaphores[i], NULL);
+1 -1
View File
@@ -46,6 +46,6 @@ void vulkan_deinit(struct graphics_context_t* context);
* @param context Graphics context * @param context Graphics context
* @return rse_err_t * @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 */ #endif /* GRAPHICS_VULKANBASE_H */
-24
View File
@@ -1,24 +0,0 @@
#include "vulkan_commons.h"
#include <time.h>
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;
}
-4
View File
@@ -58,8 +58,4 @@ struct instance_data_t {
alignas(4) uint32_t texture_id; alignas(4) uint32_t texture_id;
}; };
void init_time(void);
void update_time(void);
float get_time_diff(void);
#endif /* VULKAN_GLOBAL_H */ #endif /* VULKAN_GLOBAL_H */
-48
View File
@@ -21,29 +21,9 @@
#include "SDL3/SDL_log.h" #include "SDL3/SDL_log.h"
#include "utilities/commons.h" #include "utilities/commons.h"
#include "utilities/errors_common.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) 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; (void)is_framebuffer_resized;
// TODO: Actually use this parameter? // 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; 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) void window_terminate(SDL_Window* window_handle)
{ {
SDL_DestroyWindow(window_handle); SDL_DestroyWindow(window_handle);
-8
View File
@@ -32,14 +32,6 @@
*/ */
rse_err_t window_init(SDL_Window **window_handle, bool *is_framebuffer_resized); 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 * @brief Closes window and terminates GLFW
* *
+1
View File
@@ -17,6 +17,7 @@ executable(
], ],
link_with: [ link_with: [
rse_graphics_lib, rse_graphics_lib,
rse_events_lib,
rse_utilities_lib, rse_utilities_lib,
], ],
) )
-1
View File
@@ -13,7 +13,6 @@
#define RED_SCARF_ENGINE_H_ #define RED_SCARF_ENGINE_H_
#include "utilities/commons.h" #include "utilities/commons.h"
#include "utilities/errors_common.h"
typedef struct rse_context_t* rse_context; typedef struct rse_context_t* rse_context;
+1
View File
@@ -1,4 +1,5 @@
#include "red_scarf_engine.h" #include "red_scarf_engine.h"
#include "utilities/errors_common.h"
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
+34 -3
View File
@@ -1,14 +1,30 @@
#include "red_scarf_engine.h" #include "red_scarf_engine.h"
#include "graphics/rse_graphics.h" #include "graphics/rse_graphics.h"
#include "graphics/src/graphics_context.h"
#include "utilities/commons.h" #include "utilities/commons.h"
#include "utilities/errors_common.h" #include "utilities/errors_common.h"
#include "utilities/time_utils.h" #include "utilities/time_utils.h"
#include "events/rse_events_manager.h"
struct rse_context_t { struct rse_context_t {
struct graphics_context_t graphics_context; 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 rse_init(rse_context* context)
{ {
rse_err_t status = RSE_ERROR_NO_ERROR; rse_err_t status = RSE_ERROR_NO_ERROR;
@@ -18,10 +34,12 @@ rse_err_t rse_init(rse_context* context)
rse_context = *context; rse_context = *context;
SDL_Init(SDL_INIT_VIDEO);
SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE); SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
STATUS_CHECK(time_init()); 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; 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 rse_run(rse_context context)
{ {
rse_err_t status = RSE_ERROR_NO_ERROR; 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_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); rse_free(context);
return status; return status;