You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
8.3 KiB
254 lines
8.3 KiB
#include "event.h"
|
|
#include "../common/log.h"
|
|
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include <SDL.h>
|
|
|
|
void event_manager_init(struct Event_Manager* event_manager)
|
|
{
|
|
assert(event_manager);
|
|
|
|
memset(event_manager->event_subsciptions, '\0', sizeof(struct Event_Subscription) * MAX_EVENT_SUBSCRIPTIONS);
|
|
|
|
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
|
|
{
|
|
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
|
|
memset(subscription, '\0', sizeof(struct Event_Subscription));
|
|
subscription->event_type = EVT_NONE;
|
|
}
|
|
|
|
for(int i = 0; i < MAX_EVENTS; i++)
|
|
{
|
|
struct Event* event = &event_manager->event_pool[i];
|
|
memset(event, '\0', sizeof(struct Event));
|
|
event->type = EVT_NONE;
|
|
}
|
|
|
|
event_manager->sdl_event_id = SDL_RegisterEvents(1);
|
|
}
|
|
|
|
void event_manager_subscribe(struct Event_Manager* event_manager, int event_type, Event_Handler handler_func)
|
|
{
|
|
assert(event_manager && event_type < EVT_MAX && event_type > EVT_NONE);
|
|
|
|
//Check if this handler/subscriber already exists
|
|
bool subscribed = false;
|
|
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
|
|
{
|
|
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
|
|
if(subscription->event_type == event_type && subscription->handler == handler_func)
|
|
{
|
|
log_message("Already subscibed to %s event", event_name_get(event_type));
|
|
subscribed = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Now that we've established that we are not subscribed already we find an empty slot and
|
|
//create a new subscription there
|
|
if(!subscribed)
|
|
{
|
|
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
|
|
{
|
|
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
|
|
if(subscription->event_type == EVT_NONE)
|
|
{
|
|
subscription->event_type = event_type;
|
|
subscription->handler = handler_func;
|
|
subscribed = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//if subscribed is still not true, it can only mean that all the existing slots are taken
|
|
//Show an error message in that case
|
|
if(!subscribed)
|
|
log_error("event_manager:subscribe", "Could not subscribe to %s event", event_name_get(event_type));
|
|
}
|
|
|
|
void event_manager_unsubscribe(struct Event_Manager* event_manager, int event_type, Event_Handler subscriber)
|
|
{
|
|
assert(event_manager && event_type < EVT_MAX);
|
|
|
|
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
|
|
{
|
|
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
|
|
if(subscription->event_type == event_type && subscription->handler == subscriber)
|
|
{
|
|
subscription->handler = NULL;
|
|
subscription->event_type = EVT_NONE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void event_manager_send_event(struct Event_Manager* event_manager, struct Event* event)
|
|
{
|
|
assert(event_manager && event);
|
|
|
|
SDL_Event sdl_event;
|
|
SDL_memset(&sdl_event, 0, sizeof(sdl_event));
|
|
sdl_event.type = event_manager->sdl_event_id;
|
|
sdl_event.user.data1 = event;
|
|
int rc = SDL_PushEvent(&sdl_event);
|
|
if(rc != 1)
|
|
{
|
|
log_error("event_manager:send_event", "Could not push event, %s", event_name_get(event->type));
|
|
}
|
|
}
|
|
|
|
struct Event* event_manager_create_new_event(struct Event_Manager* event_manager)
|
|
{
|
|
struct Event* new_event = NULL;
|
|
for(int i = 0; i < MAX_EVENTS; i++)
|
|
{
|
|
if(event_manager->event_pool[i].type == EVT_NONE)
|
|
{
|
|
new_event = &event_manager->event_pool[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!new_event)
|
|
log_warning("Out of event slots, event pool full!");
|
|
|
|
return new_event;
|
|
}
|
|
|
|
void event_manager_poll_events(struct Event_Manager* event_manager, bool* out_quit)
|
|
{
|
|
static SDL_Event event;
|
|
while(SDL_PollEvent(&event) != 0)
|
|
{
|
|
switch(event.type)
|
|
{
|
|
case SDL_QUIT:
|
|
*out_quit = true;
|
|
break;
|
|
case SDL_KEYDOWN: case SDL_KEYUP:
|
|
{
|
|
int scancode = event.key.keysym.scancode;
|
|
int key = event.key.keysym.sym;
|
|
int state = event.key.state;
|
|
bool repeat = event.key.repeat;
|
|
bool mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? true : false;
|
|
bool mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? true : false;
|
|
bool mod_alt = (event.key.keysym.mod & KMOD_ALT) ? true : false;
|
|
|
|
struct Event* new_event = event_manager_create_new_event(event_manager);
|
|
new_event->type = event.type == SDL_KEYDOWN ? EVT_KEY_PRESSED : EVT_KEY_RELEASED;
|
|
new_event->key.key = event.key.keysym.sym;
|
|
new_event->key.scancode = event.key.keysym.scancode;
|
|
new_event->key.state = event.key.state;
|
|
new_event->key.repeat = event.key.repeat == 0 ? false : true;
|
|
new_event->key.mod_ctrl = (event.key.keysym.mod & KMOD_CTRL) ? true : false;
|
|
new_event->key.mod_shift = (event.key.keysym.mod & KMOD_SHIFT) ? true : false;
|
|
new_event->key.mod_alt = (event.key.keysym.mod & KMOD_ALT) ? true : false;
|
|
event_manager_send_event(event_manager, new_event);
|
|
//log_message("Key name : %s", SDL_GetKeyName(key));
|
|
break;
|
|
}
|
|
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP:
|
|
{
|
|
struct Event* new_event = event_manager_create_new_event(event_manager);
|
|
new_event->type = event.type == SDL_MOUSEBUTTONDOWN ? EVT_MOUSEBUTTON_PRESSED : EVT_MOUSEBUTTON_RELEASED;
|
|
new_event->mousebutton.button = event.button.button;
|
|
new_event->mousebutton.state = event.button.state;
|
|
new_event->mousebutton.num_clicks = event.button.clicks;
|
|
new_event->mousebutton.x = event.button.x;
|
|
new_event->mousebutton.y = event.button.y;
|
|
event_manager_send_event(event_manager, new_event);
|
|
break;
|
|
}
|
|
case SDL_MOUSEMOTION:
|
|
{
|
|
struct Event* new_event = event_manager_create_new_event(event_manager);
|
|
new_event->type = EVT_MOUSEMOTION;
|
|
new_event->mousemotion.xrel = event.motion.xrel;
|
|
new_event->mousemotion.yrel = event.motion.yrel;
|
|
new_event->mousemotion.x = event.motion.x;
|
|
new_event->mousemotion.y = event.motion.y;
|
|
event_manager_send_event(event_manager, new_event);
|
|
break;
|
|
}
|
|
case SDL_MOUSEWHEEL:
|
|
{
|
|
struct Event* new_event = event_manager_create_new_event(event_manager);
|
|
new_event->type = EVT_MOUSEWHEEL;
|
|
new_event->mousewheel.x = event.wheel.x;
|
|
new_event->mousewheel.y = event.wheel.y;
|
|
event_manager_send_event(event_manager, new_event);
|
|
break;
|
|
}
|
|
case SDL_TEXTINPUT:
|
|
{
|
|
struct Event* new_event = event_manager_create_new_event(event_manager);
|
|
new_event->type = EVT_TEXT_INPUT;
|
|
memcpy(new_event->text_input.text, event.text.text, 32);
|
|
event_manager_send_event(event_manager, new_event);
|
|
break;
|
|
}
|
|
case SDL_WINDOWEVENT:
|
|
{
|
|
if(event.window.event == SDL_WINDOWEVENT_RESIZED)
|
|
{
|
|
struct Event* new_event = event_manager_create_new_event(event_manager);
|
|
new_event->type = EVT_WINDOW_RESIZED;
|
|
new_event->window_resize.width = event.window.data1;
|
|
new_event->window_resize.height = event.window.data2;
|
|
event_manager_send_event(event_manager, new_event);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
if(event.type == event_manager->sdl_event_id)
|
|
{
|
|
struct Event* user_event = (struct Event*)event.user.data1;
|
|
//log_message("%s event", event_name_get(user_event->type));
|
|
for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++)
|
|
{
|
|
struct Event_Subscription* subscription = &event_manager->event_subsciptions[i];
|
|
if(subscription->event_type == user_event->type)
|
|
{
|
|
if(subscription->handler) subscription->handler(user_event);
|
|
}
|
|
}
|
|
|
|
//return event to the pool now that it is consumed
|
|
memset(user_event, '\0', sizeof(*user_event));
|
|
user_event->type = EVT_NONE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void event_manager_cleanup(struct Event_Manager* event_manager)
|
|
{
|
|
|
|
}
|
|
|
|
const char* event_name_get(int event_type)
|
|
{
|
|
assert(event_type >= EVT_NONE && event_type <= EVT_MAX);
|
|
|
|
switch(event_type)
|
|
{
|
|
case EVT_NONE: return "None";
|
|
case EVT_KEY_PRESSED: return "Key Pressed";
|
|
case EVT_KEY_RELEASED: return "Key Released";
|
|
case EVT_MOUSEBUTTON_PRESSED: return "Mousebutton Pressed";
|
|
case EVT_MOUSEBUTTON_RELEASED: return "Mousebutton Released";
|
|
case EVT_MOUSEMOTION: return "Mouse Motion";
|
|
case EVT_MOUSEWHEEL: return "Mouse Wheel";
|
|
case EVT_WINDOW_RESIZED: return "Window Resized";
|
|
case EVT_TEXT_INPUT: return "Text Input";
|
|
case EVT_MAX: return "Max Number of Events";
|
|
default: return "Invalid event_type";
|
|
}
|
|
}
|
|
|