diff --git a/.gitignore b/.gitignore index 96da2fc..08df936 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bin/* build/* -.vs/* \ No newline at end of file +.vs/* +.vscode diff --git a/build/genie.lua b/build/genie.lua index 2b2665f..6c86acc 100644 --- a/build/genie.lua +++ b/build/genie.lua @@ -75,7 +75,6 @@ solution "Symmetry" configuration {"windows", "vs2017"} includedirs {"../include/windows/sdl2/", "../include/common/soloud/", "../include/windows/"} libdirs {"../lib/windows/sdl2/", "../lib/windows/soloud/", "../lib/windows/ode/"} - links {"SDL2"} configuration "Debug" links {"soloud_x64_d"} @@ -98,19 +97,19 @@ solution "Symmetry" "rmdir release\\assets", "mklink /D release\\assets ..\\..\\..\\assets" } - links {"ode_double"} + links {"ode_double", "SDL2"} configuration {"windows", "Debug", "vs2017"} postbuildcommands { - "copy ..\\..\\lib\\windows\\sdl2\\SDL2.dll debug\\ /Y", + "copy ..\\..\\lib\\windows\\sdl2\\SDL2d.dll debug\\ /Y", "copy ..\\..\\lib\\windows\\soloud\\soloud_x64_d.dll debug\\ /Y", "copy ..\\..\\lib\\windows\\ode\\ode_doubled.dll debug\\ /Y", "copy ..\\..\\lib\\windows\\ode\\ode_doubled.pdb debug\\ /Y", "rmdir debug\\assets", "mklink /D debug\\assets ..\\..\\..\\assets" } - links {"ode_doubled"} + links {"ode_doubled", "SDL2d"} newaction { trigger = "build_addon", diff --git a/lib/windows/sdl2/SDL2-staticd.lib b/lib/windows/sdl2/SDL2-staticd.lib new file mode 100644 index 0000000..cdeaa57 Binary files /dev/null and b/lib/windows/sdl2/SDL2-staticd.lib differ diff --git a/lib/windows/sdl2/SDL2.dll b/lib/windows/sdl2/SDL2.dll index 8e0c64c..934f809 100755 Binary files a/lib/windows/sdl2/SDL2.dll and b/lib/windows/sdl2/SDL2.dll differ diff --git a/lib/windows/sdl2/SDL2.lib b/lib/windows/sdl2/SDL2.lib index b33cfa6..f4941ae 100755 Binary files a/lib/windows/sdl2/SDL2.lib and b/lib/windows/sdl2/SDL2.lib differ diff --git a/lib/windows/sdl2/SDL2d.dll b/lib/windows/sdl2/SDL2d.dll new file mode 100644 index 0000000..657643a Binary files /dev/null and b/lib/windows/sdl2/SDL2d.dll differ diff --git a/lib/windows/sdl2/SDL2d.lib b/lib/windows/sdl2/SDL2d.lib new file mode 100644 index 0000000..86b8bdd Binary files /dev/null and b/lib/windows/sdl2/SDL2d.lib differ diff --git a/lib/windows/sdl2/SDL2main.lib b/lib/windows/sdl2/SDL2main.lib index 66bde49..6129946 100755 Binary files a/lib/windows/sdl2/SDL2main.lib and b/lib/windows/sdl2/SDL2main.lib differ diff --git a/lib/windows/sdl2/SDL2maind.lib b/lib/windows/sdl2/SDL2maind.lib new file mode 100644 index 0000000..dc714c2 Binary files /dev/null and b/lib/windows/sdl2/SDL2maind.lib differ diff --git a/lib/windows/sdl2/SDL2test.lib b/lib/windows/sdl2/SDL2test.lib index 18d08cd..5b03282 100755 Binary files a/lib/windows/sdl2/SDL2test.lib and b/lib/windows/sdl2/SDL2test.lib differ diff --git a/src/common/hashmap.c b/src/common/hashmap.c index 5843673..27280da 100755 --- a/src/common/hashmap.c +++ b/src/common/hashmap.c @@ -24,20 +24,20 @@ static struct Hashmap_Entry* hashmap_entry_new(struct Hashmap* hashmap, const ch static struct Hashmap_Entry* hashmap_entry_new(struct Hashmap* hashmap, const char* key) { - unsigned int index = hashmap_generate_hash(key); - struct Hashmap_Entry* new_entry = NULL; - for(int i = 0; i < array_len(hashmap->buckets[index]); i++) /* Look for duplicates and over-write if found */ - { - if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0) + unsigned int index = hashmap_generate_hash(key); + struct Hashmap_Entry* new_entry = NULL; + for(int i = 0; i < array_len(hashmap->buckets[index]); i++) /* Look for duplicates and over-write if found */ { - new_entry = &hashmap->buckets[index][i]; - if(new_entry->key) free(new_entry->key); - break; + if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0) + { + new_entry = &hashmap->buckets[index][i]; + if(new_entry->key) free(new_entry->key); + break; + } } - } - if(!new_entry) new_entry = array_grow(hashmap->buckets[index], struct Hashmap_Entry); - new_entry->key = str_new(key); - new_entry->value.type = VT_NONE; + if(!new_entry) new_entry = array_grow(hashmap->buckets[index], struct Hashmap_Entry); + new_entry->key = str_new(key); + new_entry->value.type = VT_NONE; variant_free(&new_entry->value); return new_entry; } @@ -55,7 +55,7 @@ struct Hashmap* hashmap_new(void) { struct Hashmap* hashmap = malloc(sizeof(*hashmap)); if(!hashmap) - return NULL; + return NULL; for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) hashmap->buckets[i] = array_new(struct Hashmap_Entry); hashmap->iter_bucket = 0; @@ -65,24 +65,24 @@ struct Hashmap* hashmap_new(void) void hashmap_free(struct Hashmap* hashmap) { - if(!hashmap) return; - for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) - { - for(int j = 0; j < array_len(hashmap->buckets[i]); j++) + if(!hashmap) return; + for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) { - struct Hashmap_Entry* entry = &hashmap->buckets[i][j]; - if(entry->key) - { - free(entry->key); - entry->key = NULL; - } - variant_free(&entry->value); + for(int j = 0; j < array_len(hashmap->buckets[i]); j++) + { + struct Hashmap_Entry* entry = &hashmap->buckets[i][j]; + if(entry->key) + { + free(entry->key); + entry->key = NULL; + } + variant_free(&entry->value); + } + array_free(hashmap->buckets[i]); + hashmap->buckets[i] = NULL; } - array_free(hashmap->buckets[i]); - hashmap->buckets[i] = NULL; - } - free(hashmap); - hashmap = NULL; + free(hashmap); + hashmap = NULL; } void hashmap_value_set(struct Hashmap* hashmap, const char* key, const struct Variant* value) @@ -99,31 +99,31 @@ struct Variant* hashmap_value_get(const struct Hashmap* hashmap, const char* key unsigned int index = hashmap_generate_hash(key); int key_len = (int)strlen(key); int compare_len = key_len < HASH_MAX_KEY_LEN ? key_len : HASH_MAX_KEY_LEN; - for(int i = 0; i < array_len(hashmap->buckets[index]); i++) - { - if(strncmp(key, hashmap->buckets[index][i].key, compare_len) == 0) + for(int i = 0; i < array_len(hashmap->buckets[index]); i++) { - value = &hashmap->buckets[index][i].value; - break; + if(strncmp(key, hashmap->buckets[index][i].key, compare_len) == 0) + { + value = &hashmap->buckets[index][i].value; + break; + } } - } - return value; + return value; } void hashmap_value_remove(struct Hashmap* hashmap, const char* key) { if(!hashmap || !key) return; unsigned int index = hashmap_generate_hash(key); - int index_to_remove = -1; - for(int i = 0; i < array_len(hashmap->buckets[index]); i++) - { - if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0) + int index_to_remove = -1; + for(int i = 0; i < array_len(hashmap->buckets[index]); i++) { - index_to_remove = i; - break; + if(strncmp(key, hashmap->buckets[index][i].key, HASH_MAX_KEY_LEN) == 0) + { + index_to_remove = i; + break; + } } - } - if(index_to_remove != -1) array_remove_at(hashmap->buckets[index], index_to_remove); + if(index_to_remove != -1) array_remove_at(hashmap->buckets[index], index_to_remove); } bool hashmap_value_exists(struct Hashmap * hashmap, const char * key) @@ -302,21 +302,21 @@ void hashmap_debug_print(const struct Hashmap* hashmap) if(!hashmap) return; static char str[128]; memset(str, '\0', 128); - for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) - { - log_message("Bucket : %d", i); - log_message("Bucket len : %d", array_len(hashmap->buckets[i])); - for(int j = 0; j < array_len(hashmap->buckets[i]); j++) + for(int i = 0; i < HASH_MAP_NUM_BUCKETS; i++) { - struct Hashmap_Entry* entry = &hashmap->buckets[i][j]; - const struct Variant* value = &entry->value; - const char* key = entry->key; - log_message("Key : %s", key); - variant_to_str(value, str, 128); - log_message("Value : %s", str); - memset(str, '\0', 128); + log_message("Bucket : %d", i); + log_message("Bucket len : %d", array_len(hashmap->buckets[i])); + for(int j = 0; j < array_len(hashmap->buckets[i]); j++) + { + struct Hashmap_Entry* entry = &hashmap->buckets[i][j]; + const struct Variant* value = &entry->value; + const char* key = entry->key; + log_message("Key : %s", key); + variant_to_str(value, str, 128); + log_message("Value : %s", str); + memset(str, '\0', 128); + } } - } } void hashmap_iter_begin(struct Hashmap* hashmap) @@ -329,23 +329,23 @@ void hashmap_iter_begin(struct Hashmap* hashmap) int hashmap_iter_next(struct Hashmap* hashmap, char** key, struct Variant** value) { assert(hashmap); - for(;hashmap->iter_bucket < HASH_MAP_NUM_BUCKETS; hashmap->iter_bucket++) - { - if(hashmap->buckets[hashmap->iter_bucket]) + for(; hashmap->iter_bucket < HASH_MAP_NUM_BUCKETS; hashmap->iter_bucket++) { - if(++hashmap->iter_index < array_len(hashmap->buckets[hashmap->iter_bucket])) - { - *key = hashmap->buckets[hashmap->iter_bucket][hashmap->iter_index].key; - *value = &hashmap->buckets[hashmap->iter_bucket][hashmap->iter_index].value; - return 1; - } - else - { - hashmap->iter_index = -1; - } + if(hashmap->buckets[hashmap->iter_bucket]) + { + if(++hashmap->iter_index < array_len(hashmap->buckets[hashmap->iter_bucket])) + { + *key = hashmap->buckets[hashmap->iter_bucket][hashmap->iter_index].key; + *value = &hashmap->buckets[hashmap->iter_bucket][hashmap->iter_index].value; + return 1; + } + else + { + hashmap->iter_index = -1; + } + } } - } - return 0; + return 0; } void hashmap_copy(struct Hashmap* from, struct Hashmap* to) @@ -355,6 +355,6 @@ void hashmap_copy(struct Hashmap* from, struct Hashmap* to) HASHMAP_FOREACH(from, from_key, from_val) { - hashmap_value_set(to, from_key, from_val); + hashmap_value_set(to, from_key, from_val); } } diff --git a/src/game/editor.c b/src/game/editor.c index fb6a5a1..8b9c0a8 100755 --- a/src/game/editor.c +++ b/src/game/editor.c @@ -591,33 +591,37 @@ void editor_camera_update(float dt) //Picking //If we're not looking around then allow picking - /* if(input_mousebutton_state_get(MSB_LEFT, KS_RELEASED)) */ - /* { */ - /* log_message("editor picking"); */ - /* int mouse_x = 0, mouse_y = 0; */ - /* platform->mouse_position_get(&mouse_x, &mouse_y); */ - /* struct Ray ray = camera_screen_coord_to_ray(editor_camera, mouse_x, mouse_y); */ - /* //log_message("Ray: %.3f, %.3f, %.3f", ray.direction.x, ray.direction.y, ray.direction.z); */ - - /* struct Scene* scene = game_state_get()->scene; */ - /* struct Raycast_Result ray_result; */ - /* scene_ray_intersect(scene, &ray, &ray_result); */ - - /* if(ray_result.num_entities_intersected > 0) */ - /* { */ - /* //For now, just select the first entity that is intersected */ - /* struct Entity* intersected_entity = ray_result.entities_intersected[0]; */ - - /* if(editor_state.selected_entity && editor_state.selected_entity != intersected_entity) */ - /* { */ - /* editor_state.selected_entity->editor_selected = false; */ - /* editor_state.selected_entity = NULL; */ - /* } */ - - /* intersected_entity->editor_selected = true; */ - /* editor_state.selected_entity = intersected_entity; */ - /* } */ - /* } */ + if(input_mousebutton_state_get(MSB_LEFT, KS_RELEASED)) + { + log_message("editor picking"); + //int mouse_x = 0, mouse_y = 0; + //platform_mouse_position_get(&mouse_x, &mouse_y); + //struct Ray ray = camera_screen_coord_to_ray(editor_camera, mouse_x, mouse_y); + ////log_message("Ray: %.3f, %.3f, %.3f", ray.direction.x, ray.direction.y, ray.direction.z); + + //struct Scene* scene = game_state_get()->scene; + //struct Raycast_Result ray_result; + //scene_ray_intersect(scene, &ray, &ray_result); + + //if(ray_result.num_entities_intersected > 0) + //{ + // //For now, just select the first entity that is intersected + // struct Entity* intersected_entity = ray_result.entities_intersected[0]; + + // if(editor_state.selected_entity && editor_state.selected_entity != intersected_entity) + // { + // editor_state.selected_entity->editor_selected = false; + // editor_state.selected_entity = NULL; + // } + + // intersected_entity->editor_selected = true; + // editor_state.selected_entity = intersected_entity; + //} + } + else if(input_mousebutton_state_get(MSB_LEFT, KS_PRESSED)) + { + log_message("mouse pressed"); + } } total_up_down_rot += turn_up_down; diff --git a/src/game/event.c b/src/game/event.c new file mode 100644 index 0000000..1baae11 --- /dev/null +++ b/src/game/event.c @@ -0,0 +1,242 @@ +#include "event.h" +#include "../common/log.h" + +#include +#include + +#include + +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); + //platform_state->on_keyboard_func(key, scancode, state, repeat, mod_ctrl, mod_shift, mod_alt); + //log_message("Key name : %s", SDL_GetKeyName(key)); + break; + } + case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: + { + int button = event.button.button; + int state = event.button.state; + int num_clicks = event.button.clicks; + int x = event.button.x; + int y = event.button.y; + //platform_state->on_mousebutton_func(button, state, x, y, num_clicks); + break; + } + case SDL_MOUSEMOTION: + { + int xrel = event.motion.xrel; + int yrel = event.motion.yrel; + int x = event.motion.x; + int y = event.motion.y; + //platform_state->on_mousemotion_func(x, y, xrel, yrel); + break; + } + case SDL_MOUSEWHEEL: + { + int x = event.wheel.x; + int y = event.wheel.y; + //platform_state->on_mousewheel_func(x, y); + break; + } + case SDL_TEXTINPUT: + { + //platform_state->on_textinput_func(event.text.text); + break; + } + case SDL_WINDOWEVENT: + { + if(event.window.event == SDL_WINDOWEVENT_RESIZED) + { + //platform_state->on_windowresize_func(event.window.data1, event.window.data2); + } + } + 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_WINDOW_RESIZED: return "Window Resized"; + case EVT_MAX: return "Max Number of Events"; + default: return "Invalid event_type"; + } +} diff --git a/src/game/event.h b/src/game/event.h index b31f252..f67411a 100755 --- a/src/game/event.h +++ b/src/game/event.h @@ -1,37 +1,107 @@ #ifndef EVENT_H #define EVENT_H -#include "variant.h" +#include "../common/linmath.h" +#include "../common/num_types.h" -typedef void (*Event_Handler) (int object_index, const struct Variant* event_params, int num_params); +typedef void (*Event_Handler) (const struct Event* event); + +#define MAX_EVENTS 128 +#define MAX_EVENT_SUBSCRIPTIONS 256 + +enum Event_Types +{ + EVT_NONE = 0, + EVT_KEY_PRESSED, + EVT_KEY_RELEASED, + EVT_MOUSEBUTTON_PRESSED, + EVT_MOUSEBUTTON_RELEASED, + EVT_MOUSEMOTION, + EVT_WINDOW_RESIZED, + EVT_MAX +}; + +struct Key_Event +{ + int scancode; + int key; + int state; + bool repeat; + bool mod_ctrl; + bool mod_shift; + bool mod_alt; +}; + +struct Player_Damage_Event +{ + int damage; + int enemy; + vec3 direction; +}; + +struct Event +{ + int type; + union + { + struct Player_Damage_Event player_damage; + struct Key_Event key; + }; +}; struct Event_Subscription { - int object_index; // If a particular object has subscribed to this - // event then this holds the index of the object - // in it's particular subsystem list. For - // example, for a Transform, it will hold the - // index of the transform in the transform - // list. Otherwise, it holds -1. + int event_type; Event_Handler handler; }; -enum System_Event +struct Event_Manager { - SE_KEYBOARD = 0, - SE_MOUSEBUTTON, - SE_MOUSEMOTION, - SE_WINDOW_RESIZE, - SE_NUM_EVENTS + struct Event event_pool[MAX_EVENTS]; + struct Event_Subscription event_subsciptions[MAX_EVENT_SUBSCRIPTIONS]; + uint32 sdl_event_id; }; -#define BEGIN_EVENT_DEFINITION(event_name) -#define END_EVENT_DEFINITION }; +////Event subsciption example +//void player_init() +//{ +// struct Event_Manager* event_manager = game_state_get()->event_manager; +// event_manager_subscribe(event_manager, EVT_PLAYER_DAMAGE, &on_player_damage); +//} +// +////Event unsubscribe example +//void player_cleanup() +//{ +// struct Event_Manager* event_manager = game_state_get()->event_manager; +// event_manager_unsubscribe(event_manager, EVT_PLAYER_DAMANGE, &on_player_damage); +//} +// +////Event recieve example usage +//void on_player_damage(struct Event* event_data) +//{ +// struct Player_Damage_Event* player_damage_event = &event_data->player_damage; +// damage_player(player_damage_event->damage, player_damage_event->direction); +//} +// +////Event send example usage +//void enemy_tick() +//{ +// struct Event_Manager* event_manager = game_state-get()->event_manager; +// struct Event* new_event = event_manager_create_new_event(event_manager); +// new_event->type = EVT_PLAYER_DAMAGE; +// new_event->player_damage.damage = 20; +// new_event->player_damage.enemy = enemy_id; +// event_manager_send_event(event_manager, new_event); +//} +// -int event_subscribe(int object_index, Event_Handler handler_func); -void event_unsubscribe(int subscription_index); -void event_handle_systemevent(int event_type, const struct Variant* event_params, int num_params); -void event_handle_userevent(int event_type, const struct Variant* event_params, int num_params); -void event_send(int event_type, const struct Variant* event_params, int num_params); +void event_manager_init(struct Event_Manager* event_manager); +void event_manager_subscribe(struct Event_Manager* event_manager, int event_type, Event_Handler subscriber); +void event_manager_unsubscribe(struct Event_Manager* event_manager, int event_type, Event_Handler subscriber); +struct Event* event_manager_create_new_event(struct Event_Manager* event_manager); +void event_manager_send_event(struct Event_Manager* event_manager, struct Event* event); +void event_manager_poll_events(struct Event_Manager* event_manager, bool* out_quit); +void event_manager_cleanup(struct Event_Manager* event_manager); +const char* event_name_get(int event_type); #endif diff --git a/src/game/game.c b/src/game/game.c index 3e47e3f..fa17252 100755 --- a/src/game/game.c +++ b/src/game/game.c @@ -33,6 +33,7 @@ #include "../system/physics.h" #include "../system/platform.h" #include "im_render.h" +#include "event.h" #define UNUSED(a) (void)a #define MIN_NUM(a,b) ((a) < (b) ? (a) : (b)) @@ -66,12 +67,13 @@ bool game_init(struct Window* window) } else { - game_state->window = window; + game_state->window = window; game_state->is_initialized = false; - game_state->game_mode = GAME_MODE_GAME; - game_state->renderer = calloc(1, sizeof(*game_state->renderer)); - game_state->scene = calloc(1, sizeof(*game_state->scene)); - game_state->console = calloc(1, sizeof(*game_state->console)); + game_state->game_mode = GAME_MODE_GAME; + game_state->renderer = calloc(1, sizeof(*game_state->renderer)); + game_state->scene = calloc(1, sizeof(*game_state->scene)); + game_state->console = calloc(1, sizeof(*game_state->console)); + game_state->event_manager = calloc(1, sizeof(*game_state->event_manager)); log_message_callback_set(game_on_log_message); log_warning_callback_set(game_on_log_warning); @@ -87,7 +89,8 @@ bool game_init(struct Window* window) log_message("Loaded GL extentions"); } - + + event_manager_init(game_state->event_manager); input_init(); shader_init(); texture_init(); @@ -490,7 +493,8 @@ bool game_run(void) if(delta_time > MAX_FRAME_TIME) delta_time = (1.f / 60.f); /* To deal with resuming from breakpoint we artificially set delta time */ gui_input_begin(); - platform_poll_events(&should_window_close); + //platform_poll_events(&should_window_close); + event_manager_poll_events(game_state->event_manager, &should_window_close); gui_input_end(); game_update(delta_time, &should_window_close); @@ -1882,10 +1886,12 @@ void game_cleanup(void) framebuffer_cleanup(); texture_cleanup(); shader_cleanup(); + event_manager_cleanup(game_state->event_manager); free(game_state->console); free(game_state->scene); free(game_state->renderer); + free(game_state->event_manager); } free(game_state); game_state = NULL; diff --git a/src/game/game.h b/src/game/game.h index 7633dbf..87a6ed2 100755 --- a/src/game/game.h +++ b/src/game/game.h @@ -10,6 +10,7 @@ struct Entity; struct Player; struct Console; struct Gui_State; +struct Event_Manager; enum Game_Mode { @@ -19,13 +20,14 @@ enum Game_Mode struct Game_State { - bool is_initialized; - int game_mode; - struct Window* window; - struct Renderer* renderer; - struct Scene* scene; - struct Console* console; - struct Gui_State* gui; + bool is_initialized; + int game_mode; + struct Window* window; + struct Renderer* renderer; + struct Scene* scene; + struct Console* console; + struct Gui_State* gui; + struct Event_Manager* event_manager; }; diff --git a/src/game/input.c b/src/game/input.c index 6010b52..e77eeef 100755 --- a/src/game/input.c +++ b/src/game/input.c @@ -11,8 +11,11 @@ #include "../common/parser.h" #include "../system/platform.h" #include "../system/file_io.h" +#include "event.h" +#include "game.h" -static void input_on_key(int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt); +//static void input_on_key(int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt); +static void input_on_key(const struct Event* event); static void input_on_mousebutton(int button, int state, int x, int y, int8 num_clicks); static void input_on_mousemotion(int x, int y, int xrel, int yrel); static void input_on_mousewheel(int x, int y); @@ -21,7 +24,10 @@ static struct Hashmap* key_bindings = NULL; void input_init(void) { - platform_keyboard_callback_set(&input_on_key); + struct Event_Manager* event_manager = game_state_get()->event_manager; + event_manager_subscribe(event_manager, EVT_KEY_PRESSED, &input_on_key); + event_manager_subscribe(event_manager, EVT_KEY_RELEASED, &input_on_key); + //platform_keyboard_callback_set(&input_on_key); platform_mousebutton_callback_set(&input_on_mousebutton); platform_mousemotion_callback_set(&input_on_mousemotion); platform_mousewheel_callback_set(&input_on_mousewheel); @@ -76,6 +82,7 @@ void input_init(void) void input_cleanup(void) { + event_manager_unsubscribe(game_state_get()->event_manager, EVT_KEY_PRESSED, &input_on_key); char* key = NULL; struct Variant* value = NULL; HASHMAP_FOREACH(key_bindings, key, value) @@ -272,8 +279,16 @@ void input_mouse_pos_set(int xpos, int ypos) platform_mouse_global_position_set(xpos, ypos); } -void input_on_key(int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt) +void input_on_key(const struct Event* event) { + assert(event->type == EVT_KEY_PRESSED || event->type == EVT_KEY_RELEASED); + + int key = event->key.key; + int state = event->key.state; + bool mod_ctrl = event->key.mod_ctrl; + bool mod_shift = event->key.mod_shift;; + bool mod_alt = event->key.mod_alt;; + int mods = KMD_NONE; if(mod_ctrl) mods |= KMD_CTRL; if(mod_shift) mods |= KMD_SHIFT; @@ -287,14 +302,14 @@ void input_on_key(int key, int scancode, int state, int repeat, int mod_ctrl, in //Check with primary key if(key_binding->key_primary == key && (key_binding->mods_primary & mods) == key_binding->mods_primary) { - key_binding->state = state; + key_binding->state = event->type == EVT_KEY_PRESSED ? KS_PRESSED : KS_RELEASED; break; } //If not, then check with secondary key if(key_binding->key_secondary == key && (key_binding->mods_secondary & mods) == key_binding->mods_secondary) { - key_binding->state = state; + key_binding->state = event->type == EVT_KEY_PRESSED ? KS_PRESSED : KS_RELEASED; break; } } diff --git a/todo.txt b/todo.txt index d6d1d16..c238d59 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,5 @@ Todo: + - Ray picking for editor - Add warning to genie build script when running on windows and WindowsSdkVersion cannot be found. This happens when the script is not run from vcvarsall command prompt - Improve README and add a screenshot to make the repository ready for making it public - Refactor all global application state into 'Application_Context' struct. A single global instance of which is available everywhere @@ -42,7 +43,6 @@ Todo: - Ogg format loading and playback - Sound streaming - Implment missing sound source properties (inner/outer cone, getting sound source data) - - Ray picking for editor - Shadow maps - Print processor stats and machine capabilites RAM etc on every run to log. - Do input maps really need to be queried by their string names? @@ -57,6 +57,9 @@ Todo: - ??? - Profit! +Improvements: + - Better naming semantics for examples, init/deinit for initialization and cleanup and create/destroy when memory is allocated or deallocated + Bugs: - Better handling of wav format checking at load time diff --git a/tools/launch_cmd.lnk b/tools/launch_cmd.lnk index c17eb2c..58a7907 100755 Binary files a/tools/launch_cmd.lnk and b/tools/launch_cmd.lnk differ diff --git a/tools/launch_vs.bat b/tools/launch_vs.bat new file mode 100644 index 0000000..fb9ad73 --- /dev/null +++ b/tools/launch_vs.bat @@ -0,0 +1,3 @@ +@echo off + +devenv W:\build\vs2017\Symmetry.sln diff --git a/tools/regen_project.bat b/tools/regen_project.bat new file mode 100644 index 0000000..085bef9 --- /dev/null +++ b/tools/regen_project.bat @@ -0,0 +1,4 @@ +@echo off + +cd W:\build\ +genie.exe vs2017 diff --git a/tools/setup_env.bat b/tools/setup_env.bat index 2ee79a1..1fac9c5 100644 --- a/tools/setup_env.bat +++ b/tools/setup_env.bat @@ -1,8 +1,9 @@ @echo off +subst /D "W:" +subst W: %CD%\.. call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 cls set editor=""C:\Applications\Emacs\bin\runemacs.exe"" -set path=W:\tools;%path% rem - +set path=W:\tools;%path% rem