diff --git a/src/common/limits.h b/src/common/limits.h new file mode 100644 index 0000000..3444afe --- /dev/null +++ b/src/common/limits.h @@ -0,0 +1,23 @@ +#ifndef SYMMETRY_LIMITS_H +#define SYMMETRY_LIMITS_H + +#define MAX_ENTITY_NAME_LEN 128 + +#define MAX_FILENAME_LEN 128 + +#define MAX_EVENTS 128 +#define MAX_EVENT_SUBSCRIPTIONS 256 + +#define MAX_SCENE_ENTITIES 32 +#define MAX_SCENE_LIGHTS 30 +#define MAX_SCENE_CAMERAS 2 +#define MAX_SCENE_STATIC_MESHES 1024 +#define MAX_SCENE_SOUND_SOURCES 128 +#define MAX_SCENE_ENTITY_ARCHETYPES 32 +#define MAX_SCENE_ENEMIES 64 + +#define MAX_UNIFORM_NAME_LEN 64 + +#define MAX_MATERIAL_REGISTERED_STATIC_MESHES 1024 + +#endif diff --git a/src/common/version.h b/src/common/version.h index b0f6c1d..28d9455 100755 --- a/src/common/version.h +++ b/src/common/version.h @@ -4,7 +4,7 @@ /* Auto generated version file. DO NOT MODIFY */ #define SYMMETRY_VERSION_MAJOR 0 #define SYMMETRY_VERSION_MINOR 1 -#define SYMMETRY_VERSION_REVISION 315 +#define SYMMETRY_VERSION_REVISION 316 #define SYMMETRY_VERSION_BRANCH "dev" #endif \ No newline at end of file diff --git a/src/game/console.c b/src/game/console.c index 3e6784c..e1bb915 100755 --- a/src/game/console.c +++ b/src/game/console.c @@ -260,7 +260,7 @@ void console_command_entity_load(struct Console* console, const char* command) return; } - struct Entity* new_entity = entity_load(filename, DIRT_INSTALL); + struct Entity* new_entity = entity_load(filename, DIRT_INSTALL, true); if(!new_entity) { log_error("entity_load", "Could not create entity from '%s'", filename); diff --git a/src/game/editor.c b/src/game/editor.c index 73ce889..98b235b 100755 --- a/src/game/editor.c +++ b/src/game/editor.c @@ -1692,42 +1692,42 @@ void editor_window_scene_hierarchy(struct nk_context* context, struct Editor* ed { if(nk_tree_push(context, NK_TREE_TAB, "Cameras", NK_MAXIMIZED)) { - for(int i = 0; i < MAX_CAMERAS; i++) + for(int i = 0; i < MAX_SCENE_CAMERAS; i++) editor_show_entity_in_list(editor, context, scene, &scene->cameras[i]); nk_tree_pop(context); } if(nk_tree_push(context, NK_TREE_TAB, "Lights", NK_MAXIMIZED)) { - for(int i = 0; i < MAX_LIGHTS; i++) + for(int i = 0; i < MAX_SCENE_LIGHTS; i++) editor_show_entity_in_list(editor, context, scene, &scene->lights[i]); nk_tree_pop(context); } if(nk_tree_push(context, NK_TREE_TAB, "Static Meshes", NK_MAXIMIZED)) { - for(int i = 0; i < MAX_STATIC_MESHES; i++) + for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) editor_show_entity_in_list(editor, context, scene, &scene->static_meshes[i]); nk_tree_pop(context); } if(nk_tree_push(context, NK_TREE_TAB, "Sound Sources", NK_MAXIMIZED)) { - for(int i = 0; i < MAX_SOUND_SOURCES; i++) + for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++) editor_show_entity_in_list(editor, context, scene, &scene->sound_sources[i]); nk_tree_pop(context); } if(nk_tree_push(context, NK_TREE_TAB, "Enemies", NK_MAXIMIZED)) { - for(int i = 0; i < MAX_ENEMIES; i++) + for(int i = 0; i < MAX_SCENE_ENEMIES; i++) editor_show_entity_in_list(editor, context, scene, &scene->enemies[i]); nk_tree_pop(context); } if(nk_tree_push(context, NK_TREE_TAB, "Entities", NK_MAXIMIZED)) { - for(int i = 0; i < MAX_ENTITIES; i++) + for(int i = 0; i < MAX_SCENE_ENTITIES; i++) editor_show_entity_in_list(editor, context, scene, &scene->entities[i]); nk_tree_pop(context); } @@ -2431,7 +2431,7 @@ void editor_entity_dialog(struct Editor* editor, struct nk_context* context) } else { - struct Entity* new_entity = entity_load(entity_filename, DIRT_INSTALL); + struct Entity* new_entity = entity_load(entity_filename, DIRT_INSTALL, true); if(new_entity) { editor_entity_select(editor, new_entity); @@ -2451,7 +2451,7 @@ void editor_entity_dialog(struct Editor* editor, struct nk_context* context) } else { - struct Entity* new_entity = entity_load(entity_filename, DIRT_INSTALL); + struct Entity* new_entity = entity_load(entity_filename, DIRT_INSTALL, true); if(new_entity) { editor_entity_select(editor, new_entity); diff --git a/src/game/enemy.c b/src/game/enemy.c index ea0ff96..e3d0755 100644 --- a/src/game/enemy.c +++ b/src/game/enemy.c @@ -6,9 +6,12 @@ #include "../common/log.h" #include "../common/hashmap.h" #include "../common/parser.h" +#include "event.h" #include +static void enemy_on_scene_loaded(struct Event* event, void* enemy_ptr); + void enemy_init(struct Enemy* enemy, int type) { struct Game_State* game_state = game_state_get(); @@ -36,8 +39,8 @@ void enemy_init(struct Enemy* enemy, int type) enemy->Turret.turn_speed = 10.f; enemy->health = 100; enemy->damage = 10; - weapon_sound = scene_sound_source_create(scene, weapon_name_buffer, enemy, "sounds/bullet_1.wav", ST_WAV, false, false); - mesh = scene_static_mesh_create(scene, mesh_name_buffer, enemy, "suzanne.symbres", MAT_BLINN); + //weapon_sound = scene_sound_source_create(scene, weapon_name_buffer, enemy, "sounds/bullet_1.wav", ST_WAV, false, false); + //mesh = scene_static_mesh_create(scene, mesh_name_buffer, enemy, "suzanne.symbres", MAT_BLINN); break; } default: @@ -45,16 +48,16 @@ void enemy_init(struct Enemy* enemy, int type) break; } - enemy->weapon_sound = weapon_sound ? weapon_sound : NULL; - if(!weapon_sound) - log_error("enemy:init", "Failed to add weapon sound for %s", enemy->base.name); + //enemy->weapon_sound = weapon_sound ? weapon_sound : NULL; + //if(!weapon_sound) + // log_error("enemy:init", "Failed to add weapon sound for %s", enemy->base.name); - enemy->mesh = mesh ? mesh : NULL; - if(!mesh) - log_error("enemy:init", "Failed to add mesh from file for %s", enemy->base.name); + //enemy->mesh = mesh ? mesh : NULL; + //if(!mesh) + // log_error("enemy:init", "Failed to add mesh from file for %s", enemy->base.name); - if(enemy->mesh) enemy->mesh->base.flags |= EF_TRANSIENT; - if(enemy->weapon_sound) enemy->weapon_sound->base.flags |= EF_TRANSIENT; + struct Event_Manager* event_manager = game_state->event_manager; + event_manager_subscribe_with_object(event_manager, EVT_SCENE_LOADED, &enemy_on_scene_loaded, (void*)enemy); } void enemy_weapon_sound_set(struct Enemy* enemy, const char* sound_filename, int type) @@ -98,6 +101,9 @@ void enemy_reset(struct Enemy* enemy) enemy->type = -1; enemy->damage = 0; enemy->health = 0; + + struct Event_Manager* event_manager = game_state_get()->event_manager; + event_manager_unsubscribe_with_object(event_manager, EVT_SCENE_LOADED, &enemy_on_scene_loaded, (void*)enemy); } struct Enemy* enemy_read(struct Parser_Object* object, const char* name, struct Entity* parent_entity) @@ -143,3 +149,23 @@ void enemy_write(struct Enemy* enemy, struct Hashmap* entity_data) break; } } + +void enemy_on_scene_loaded(struct Event* event, void* enemy_ptr) +{ + struct Enemy* enemy = (struct Enemy*)enemy_ptr; + + // Assign pointers to mesh and sound child entities + for(int i = 0; i < array_len(enemy->base.transform.children); i++) + { + struct Entity* child = enemy->base.transform.children[i]; + if(child->type == ET_STATIC_MESH) + enemy->mesh = (struct Static_Mesh*)child; + else if(child->type == ET_SOUND_SOURCE) + enemy->weapon_sound = (struct Sound_Source*)child; + } + + if(enemy->mesh) enemy->mesh->base.flags |= EF_TRANSIENT; + if(enemy->weapon_sound) enemy->weapon_sound->base.flags |= EF_TRANSIENT; + + // Do other post-scene-load initialization stuff per enemy type here +} diff --git a/src/game/entity.c b/src/game/entity.c index e637a0f..6cfb0c4 100755 --- a/src/game/entity.c +++ b/src/game/entity.c @@ -19,6 +19,7 @@ #include "game.h" #include "texture.h" #include "enemy.h" +#include "event.h" #include #include @@ -538,7 +539,7 @@ struct Entity* entity_read(struct Parser_Object* object, struct Entity* parent_e return new_entity; } -struct Entity* entity_load(const char* filename, int directory_type) +struct Entity* entity_load(const char* filename, int directory_type, bool send_on_load_event) { char prefixed_filename[MAX_FILENAME_LEN + 16]; snprintf(prefixed_filename, MAX_FILENAME_LEN + 16, "entities/%s.symtres", filename); @@ -595,6 +596,19 @@ struct Entity* entity_load(const char* filename, int directory_type) } } + // Send simulated scene loaded event since this entity has been loaded while the scene has already been loaded + if(send_on_load_event) + { + struct Game_State* game_state = game_state_get(); + struct Event_Manager* event_manager = game_state->event_manager; + struct Event on_scene_loaded_event = + { + .type = EVT_SCENE_LOADED, + }; + strncpy(on_scene_loaded_event.scene_load.filename, game_state->scene->filename, MAX_FILENAME_LEN); + event_manager_send_event_entity(event_manager, &on_scene_loaded_event, parent_entity); + } + parser_free(parsed_file); fclose(entity_file); return parent_entity; diff --git a/src/game/entity.h b/src/game/entity.h index e426eaa..e534ea2 100755 --- a/src/game/entity.h +++ b/src/game/entity.h @@ -7,8 +7,7 @@ #include "../system/sound.h" #include "bounding_volumes.h" #include "material.h" - -#define MAX_ENTITY_NAME_LEN 128 +#include "../common/limits.h" struct Entity; @@ -212,7 +211,7 @@ struct Enemy void entity_init(struct Entity* entity, const char* name, struct Entity* parent); void entity_reset(struct Entity* entity, int id); bool entity_save(struct Entity* entity, const char* filename, int directory_type); -struct Entity* entity_load(const char* filename, int directory_type); +struct Entity* entity_load(const char* filename, int directory_type, bool send_on_scene_load_event); bool entity_write(struct Entity* entity, struct Parser_Object* object, bool write_transform); struct Entity* entity_read(struct Parser_Object* object, struct Entity* parent_entity); const char* entity_type_name_get(struct Entity* entity); diff --git a/src/game/event.c b/src/game/event.c index 332bedf..0262378 100644 --- a/src/game/event.c +++ b/src/game/event.c @@ -10,13 +10,12 @@ 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)); + memset(subscription, 0, sizeof(struct Event_Subscription)); subscription->event_type = EVT_NONE; + subscription->type = EST_NONE; } for(int i = 0; i < MAX_EVENTS; i++) @@ -38,7 +37,7 @@ void event_manager_subscribe(struct Event_Manager* event_manager, int event_type 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) + if(subscription->type == EST_WITHOUT_OBJECT && subscription->event_type == event_type && subscription->handler == handler_func) { log_message("Already subscibed to %s event", event_name_get(event_type)); subscribed = true; @@ -53,11 +52,12 @@ void event_manager_subscribe(struct Event_Manager* event_manager, int event_type for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++) { struct Event_Subscription* subscription = &event_manager->event_subsciptions[i]; - if(subscription->event_type == EVT_NONE) + if(subscription->type == EST_NONE) { + subscription->type = EST_WITHOUT_OBJECT; subscription->event_type = event_type; - subscription->handler = handler_func; - subscribed = true; + subscription->handler = handler_func; + subscribed = true; break; } } @@ -69,17 +69,38 @@ void event_manager_subscribe(struct Event_Manager* event_manager, int event_type 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) +void event_manager_unsubscribe(struct Event_Manager* event_manager, int event_type, Event_Handler handler_func) { 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) + if(subscription->type != EST_WITHOUT_OBJECT) continue; + if(subscription->event_type == event_type && subscription->handler == handler_func) { - subscription->handler = NULL; + subscription->handler = NULL; subscription->event_type = EVT_NONE; + subscription->type = EST_NONE; + break; + } + } +} + +void event_manager_unsubscribe_with_object(struct Event_Manager* event_manager, int event_type, Event_Handler_Object handler_func, void* 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->type != EST_WITH_OBJECT) continue; + if(subscription->event_type == event_type && subscription->handler_with_object == handler_func && subscription->subscriber == subscriber) + { + subscription->handler_with_object = NULL; + subscription->event_type = EVT_NONE; + subscription->type = EST_NONE; + subscription->subscriber = NULL; break; } } @@ -212,9 +233,20 @@ void event_manager_poll_events(struct Event_Manager* event_manager, bool* out_qu for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++) { struct Event_Subscription* subscription = &event_manager->event_subsciptions[i]; + if(subscription->type == EST_NONE) continue; + if(subscription->event_type == user_event->type) { - if(subscription->handler) subscription->handler(user_event); + if(subscription->type == EST_WITHOUT_OBJECT) + { + if(subscription->handler) + subscription->handler(user_event); + } + else if(subscription->type == EST_WITH_OBJECT) + { + if(subscription->handler_with_object) + subscription->handler_with_object(user_event, subscription->subscriber); + } } } @@ -228,6 +260,49 @@ void event_manager_poll_events(struct Event_Manager* event_manager, bool* out_qu } } +void event_manager_subscribe_with_object(struct Event_Manager* event_manager, int event_type, Event_Handler_Object handler_func, void* subscriber) +{ + 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->type == EST_WITH_OBJECT && subscription->event_type == event_type && subscription->handler_with_object == handler_func && subscription->subscriber != subscriber) + { + 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->type == EST_NONE) + { + subscription->type = EST_WITH_OBJECT; + subscription->event_type = event_type; + subscription->handler_with_object = handler_func; + subscription->subscriber = subscriber; + 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_with_obejct", "Could not subscribe to %s event", event_name_get(event_type)); + +} + void event_manager_cleanup(struct Event_Manager* event_manager) { @@ -248,7 +323,25 @@ const char* event_name_get(int event_type) case EVT_MOUSEWHEEL: return "Mouse Wheel"; case EVT_WINDOW_RESIZED: return "Window Resized"; case EVT_TEXT_INPUT: return "Text Input"; + case EVT_SCENE_LOADED: return "Scene Loaded"; case EVT_MAX: return "Max Number of Events"; default: return "Invalid event_type"; } } + +void event_manager_send_event_entity(struct Event_Manager* event_manager, struct Event* event, struct Entity* entity) +{ + // Check if this entity has a subscription, if it does, + // call the registered callback with this entity as the parameter to simulate an event + for(int i = 0; i < MAX_EVENT_SUBSCRIPTIONS; i++) + { + struct Event_Subscription* subscription = &event_manager->event_subsciptions[i]; + if(subscription->type != EST_WITH_OBJECT) continue; + + if(subscription->event_type == event->type && subscription->subscriber == entity && subscription->handler_with_object) + { + subscription->handler_with_object(event, (void*)entity); + break; + } + } +} diff --git a/src/game/event.h b/src/game/event.h index 1eed1f7..089d7fb 100755 --- a/src/game/event.h +++ b/src/game/event.h @@ -3,11 +3,13 @@ #include "../common/linmath.h" #include "../common/num_types.h" +#include "../common/limits.h" + +struct Entity; typedef void (*Event_Handler) (const struct Event* event); +typedef void (*Event_Handler_Object) (const struct Event* event, void* subscriber); -#define MAX_EVENTS 128 -#define MAX_EVENT_SUBSCRIPTIONS 256 enum Event_Types { @@ -20,9 +22,17 @@ enum Event_Types EVT_MOUSEWHEEL, EVT_WINDOW_RESIZED, EVT_TEXT_INPUT, + EVT_SCENE_LOADED, EVT_MAX }; +enum Event_Subscription_Type +{ + EST_NONE = 0, + EST_WITHOUT_OBJECT, + EST_WITH_OBJECT +}; + struct Key_Event { int scancode; @@ -68,6 +78,11 @@ struct Window_Resized_Event int height; }; +struct Scene_Loaded_Event +{ + char filename[MAX_FILENAME_LEN]; +}; + struct Event { int type; @@ -79,13 +94,27 @@ struct Event struct Mousemotion_Event mousemotion; struct Text_Input_Event text_input; struct Window_Resized_Event window_resize; + struct Scene_Loaded_Event scene_load; }; }; struct Event_Subscription { - int event_type; - Event_Handler handler; + int type; + int event_type; + union + { + struct + { + Event_Handler handler; + }; + + struct + { + Event_Handler_Object handler_with_object; + void* subscriber; + }; + }; }; struct Event_Manager @@ -96,10 +125,13 @@ struct Event_Manager }; 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_subscribe(struct Event_Manager* event_manager, int event_type, Event_Handler event_handler_func); +void event_manager_subscribe_with_object(struct Event_Manager* event_manager, int event_type, Event_Handler_Object handler_func, void* subscriber); void event_manager_unsubscribe(struct Event_Manager* event_manager, int event_type, Event_Handler subscriber); +void event_manager_unsubscribe_with_object(struct Event_Manager* event_manager, int event_type, Event_Handler_Object handler_func, void* 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_send_event_entity(struct Event_Manager* event_manager, struct Event* event, struct Entity* entity); 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); diff --git a/src/game/material.c b/src/game/material.c index bc86ca4..34e3d75 100755 --- a/src/game/material.c +++ b/src/game/material.c @@ -27,7 +27,7 @@ bool material_init(struct Material* material, int material_type) { material->lit = true; char custom_defines[64]; - snprintf(custom_defines, 64, "#define MAX_LIGHTS %d", MAX_LIGHTS); + snprintf(custom_defines, 64, "#define MAX_LIGHTS %d", MAX_SCENE_LIGHTS); material->shader = shader_create("blinn_phong.vert", "blinn_phong.frag", custom_defines); if(material->shader == -1) diff --git a/src/game/material.h b/src/game/material.h index 1099e88..fcdd9b6 100755 --- a/src/game/material.h +++ b/src/game/material.h @@ -4,11 +4,10 @@ #include "../common/linmath.h" #include "../common/num_types.h" #include "../common/variant.h" +#include "../common/limits.h" struct Static_Mesh; -#define MAX_UNIFORM_NAME_LEN 64 -#define MAX_MATERIAL_REGISTERED_STATIC_MESHES 1024 struct Uniform { diff --git a/src/game/player.c b/src/game/player.c index a7303f1..e1745e0 100755 --- a/src/game/player.c +++ b/src/game/player.c @@ -267,7 +267,7 @@ void player_on_mousebutton_released(const struct Event* event) vec3_scale(&collision_point, &collision_point, distance); vec3_add(&collision_point, &collision_point, &bullet_ray.origin); //struct Static_Mesh* bullet = scene_static_mesh_create(game_state_get()->scene, "bullet", NULL, "cube.symbres", MAT_UNSHADED); - struct Light* bullet = entity_load("Spot", DIRT_INSTALL); + struct Light* bullet = entity_load("Spot", DIRT_INSTALL, true); if(bullet) transform_set_position(bullet, &collision_point); sound_source_play(game_state->sound, player->weapon_sound); } diff --git a/src/game/renderer.c b/src/game/renderer.c index 1b5ff94..ff6db59 100755 --- a/src/game/renderer.c +++ b/src/game/renderer.c @@ -103,7 +103,7 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene) char uniform_name[MAX_UNIFORM_NAME_LEN]; memset(uniform_name, '\0', MAX_UNIFORM_NAME_LEN); int light_count = -1; - for(int j = 0; j < MAX_LIGHTS; j++) + for(int j = 0; j < MAX_SCENE_LIGHTS; j++) { struct Light* light = &scene->lights[j]; /* TODO: Cull lights according to camera frustum */ if(!(light->base.flags & EF_ACTIVE) || !light->valid) continue; @@ -253,7 +253,7 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene) { static mat4 mvp; shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &renderer->settings.debug_draw_color); - for(int i = 0; i < MAX_STATIC_MESHES; i++) + for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) { struct Static_Mesh* mesh = &scene->static_meshes[i]; if(!(mesh->base.flags & EF_ACTIVE)) continue; @@ -274,7 +274,7 @@ void renderer_render(struct Renderer* renderer, struct Scene* scene) if(renderer->settings.debug_draw_physics) { static vec4 physics_draw_color = { 0.f, 0.f, 1.f, 1.f }; - for(int i = 0; i < MAX_STATIC_MESHES; i++) + for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) { struct Static_Mesh* mesh = &scene->static_meshes[i]; if(!(mesh->base.flags & EF_ACTIVE) || (!mesh->collision.collision_shape && !mesh->collision.rigidbody)) continue; @@ -361,7 +361,7 @@ void renderer_on_framebuffer_size_changed(const struct Event* event) struct Scene* scene = game_state_get()->scene; float aspect = (float)width / (float)height; - for(int i = 0; i < MAX_CAMERAS; i++) + for(int i = 0; i < MAX_SCENE_CAMERAS; i++) { struct Camera* viewer = &scene->cameras[i]; if(viewer->resizeable) diff --git a/src/game/scene.c b/src/game/scene.c index 8591473..77d0a54 100755 --- a/src/game/scene.c +++ b/src/game/scene.c @@ -19,6 +19,7 @@ #include "renderer.h" #include "sound_source.h" #include "enemy.h" +#include "event.h" #include #include @@ -41,14 +42,14 @@ void scene_init(struct Scene* scene) scene->root_entity.id = 0; scene->root_entity.type = ET_ROOT; - for(int i = 0; i < MAX_ENTITIES; i++) entity_reset(&scene->entities[i], i); - for(int i = 0; i < MAX_LIGHTS; i++) + for(int i = 0; i < MAX_SCENE_ENTITIES; i++) entity_reset(&scene->entities[i], i); + for(int i = 0; i < MAX_SCENE_LIGHTS; i++) { entity_reset(&scene->lights[i], i); scene->lights[i].type = ET_LIGHT; } - for(int i = 0; i < MAX_STATIC_MESHES; i++) + for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) { entity_reset(&scene->static_meshes[i], i); struct Static_Mesh* mesh = &scene->static_meshes[i]; @@ -59,11 +60,11 @@ void scene_init(struct Scene* scene) mesh->model.material = NULL; } - for(int i = 0; i < MAX_SOUND_SOURCES; i++) entity_reset(&scene->sound_sources[i], i); + for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++) entity_reset(&scene->sound_sources[i], i); int width = 1280, height = 720; window_get_drawable_size(game_state->window, &width, &height); - for(int i = 0; i < MAX_CAMERAS; i++) + for(int i = 0; i < MAX_SCENE_CAMERAS; i++) { entity_init(&scene->cameras[i], NULL, &scene->root_entity); camera_init(&scene->cameras[i], width, height); @@ -71,10 +72,10 @@ void scene_init(struct Scene* scene) scene->cameras[i].base.id = i; } - for(int i = 0; i < MAX_ENTITY_ARCHETYPES; i++) + for(int i = 0; i < MAX_SCENE_ENTITY_ARCHETYPES; i++) memset(&scene->entity_archetypes[i][0], '\0', MAX_FILENAME_LEN); - for(int i = 0; i < MAX_ENEMIES; i++) + for(int i = 0; i < MAX_SCENE_ENEMIES; i++) { entity_reset(&scene->enemies[i], i); scene->enemies->base.type = ET_ENEMY; @@ -156,7 +157,7 @@ bool scene_load(struct Scene* scene, const char* filename, int directory_type) struct Hashmap* entity_entry_data = object->data; if(hashmap_value_exists(object->data, "filename")) { - struct Entity* loaded_entity = entity_load(hashmap_str_get(entity_entry_data, "filename"), DIRT_INSTALL); + struct Entity* loaded_entity = entity_load(hashmap_str_get(entity_entry_data, "filename"), DIRT_INSTALL, false); if(loaded_entity) { vec3 position = { 0.f, 0.f, 0.f }; @@ -208,6 +209,16 @@ bool scene_load(struct Scene* scene, const char* filename, int directory_type) parser_free(parsed_file); fclose(scene_file); strncpy(scene->filename, filename, MAX_FILENAME_LEN); + if(num_objects_loaded > 0) + { + struct Event_Manager* event_manager = game_state_get()->event_manager; + struct Event* scene_loaded_event = event_manager_create_new_event(event_manager); + scene_loaded_event->type = EVT_SCENE_LOADED; + memset(scene_loaded_event->scene_load.filename, '\0', MAX_FILENAME_LEN); + strncpy(scene_loaded_event->scene_load.filename, filename, MAX_FILENAME_LEN); + event_manager_send_event(event_manager, scene_loaded_event); + } + return num_objects_loaded > 0 ? true : false; } @@ -267,32 +278,32 @@ void scene_write_entity_list(struct Scene* scene, int entity_type, struct Parser switch(entity_type) { case ET_DEFAULT: - max_length = MAX_ENTITIES; + max_length = MAX_SCENE_ENTITIES; entity = &scene->entities[0]; stride = sizeof(struct Entity); break; case ET_LIGHT: - max_length = MAX_LIGHTS; + max_length = MAX_SCENE_LIGHTS; entity = &scene->lights[0].base; stride = sizeof(struct Light); break; case ET_STATIC_MESH: - max_length = MAX_STATIC_MESHES; + max_length = MAX_SCENE_STATIC_MESHES; entity = &scene->static_meshes[0].base; stride = sizeof(struct Static_Mesh); break; case ET_CAMERA: - max_length = MAX_CAMERAS; + max_length = MAX_SCENE_CAMERAS; entity = &scene->cameras[0].base; stride = sizeof(struct Camera); break; case ET_SOUND_SOURCE: - max_length = MAX_SOUND_SOURCES; + max_length = MAX_SCENE_SOUND_SOURCES; entity = &scene->sound_sources[0].base; stride = sizeof(struct Sound_Source); break; case ET_ENEMY: - max_length = MAX_ENEMIES; + max_length = MAX_SCENE_ENEMIES; entity = &scene->enemies[0].base; stride = sizeof(struct Enemy); break; @@ -338,13 +349,13 @@ void scene_destroy(struct Scene* scene) { assert(scene); - for(int i = 0; i < MAX_ENTITIES; i++) scene_entity_base_remove(scene, &scene->entities[i]); - for(int i = 0; i < MAX_CAMERAS; i++) scene_camera_remove(scene, &scene->cameras[i]); - for(int i = 0; i < MAX_LIGHTS; i++) scene_light_remove(scene, &scene->lights[i]); - for(int i = 0; i < MAX_STATIC_MESHES; i++) scene_static_mesh_remove(scene, &scene->static_meshes[i]); - for(int i = 0; i < MAX_SOUND_SOURCES; i++) scene_sound_source_remove(scene, &scene->sound_sources[i]); - for(int i = 0; i < MAX_ENEMIES; i++) scene_enemy_remove(scene, &scene->enemies[i]); - for(int i = 0; i < MAX_ENTITY_ARCHETYPES; i++) memset(&scene->entity_archetypes[i][0], '\0', MAX_FILENAME_LEN); + for(int i = 0; i < MAX_SCENE_ENTITIES; i++) scene_entity_base_remove(scene, &scene->entities[i]); + for(int i = 0; i < MAX_SCENE_CAMERAS; i++) scene_camera_remove(scene, &scene->cameras[i]); + for(int i = 0; i < MAX_SCENE_LIGHTS; i++) scene_light_remove(scene, &scene->lights[i]); + for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) scene_static_mesh_remove(scene, &scene->static_meshes[i]); + for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++) scene_sound_source_remove(scene, &scene->sound_sources[i]); + for(int i = 0; i < MAX_SCENE_ENEMIES; i++) scene_enemy_remove(scene, &scene->enemies[i]); + for(int i = 0; i < MAX_SCENE_ENTITY_ARCHETYPES; i++) memset(&scene->entity_archetypes[i][0], '\0', MAX_FILENAME_LEN); player_destroy(&scene->player); entity_reset(&scene->root_entity, 0); scene->root_entity.flags &= ~EF_ACTIVE; @@ -355,7 +366,7 @@ void scene_update(struct Scene* scene, float dt) if(game_state_get()->game_mode == GAME_MODE_GAME) { player_update(&scene->player, scene, dt); - for(int i = 0; i < MAX_ENEMIES; i++) + for(int i = 0; i < MAX_SCENE_ENEMIES; i++) { if(scene->enemies[i].base.flags & EF_ACTIVE) enemy_update(&scene->enemies[i], scene, dt); @@ -368,7 +379,7 @@ void scene_post_update(struct Scene* scene) assert(scene); struct Sound* sound = game_state_get()->sound; - for(int i = 0; i < MAX_ENTITIES; i++) + for(int i = 0; i < MAX_SCENE_ENTITIES; i++) { struct Entity* entity = &scene->entities[i]; if(!(entity->flags & EF_ACTIVE)) continue; @@ -382,7 +393,7 @@ void scene_post_update(struct Scene* scene) if(entity->transform.is_modified) entity->transform.is_modified = false; } - for(int i = 0; i < MAX_CAMERAS; i++) + for(int i = 0; i < MAX_SCENE_CAMERAS; i++) { struct Camera* camera = &scene->cameras[i]; if(!(camera->base.flags & EF_ACTIVE)) continue; @@ -400,7 +411,7 @@ void scene_post_update(struct Scene* scene) } } - for(int i = 0; i < MAX_SOUND_SOURCES; i++) + for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++) { struct Sound_Source* sound_source = &scene->sound_sources[i]; if(!(sound_source->base.flags & EF_ACTIVE)) continue; @@ -418,7 +429,7 @@ void scene_post_update(struct Scene* scene) } } - for(int i = 0; i < MAX_STATIC_MESHES; i++) + for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) { struct Static_Mesh* static_mesh = &scene->static_meshes[i]; if(!(static_mesh->base.flags & EF_ACTIVE)) continue; @@ -445,7 +456,7 @@ void scene_post_update(struct Scene* scene) } } - for(int i = 0; i < MAX_LIGHTS; i++) + for(int i = 0; i < MAX_SCENE_LIGHTS; i++) { struct Light* light = &scene->lights[i]; if(!(light->base.flags & EF_ACTIVE)) continue; @@ -459,7 +470,7 @@ void scene_post_update(struct Scene* scene) if(light->base.transform.is_modified) light->base.transform.is_modified = false; } - for(int i = 0; i < MAX_ENEMIES; i++) + for(int i = 0; i < MAX_SCENE_ENEMIES; i++) { struct Enemy* enemy = &scene->enemies[i]; if(!(enemy->base.flags & EF_ACTIVE)) continue; @@ -483,7 +494,7 @@ struct Entity* scene_entity_create(struct Scene* scene, const char* name, struct assert(scene); struct Entity* new_entity = NULL; - for(int i = 0; i < MAX_ENTITIES; i++) + for(int i = 0; i < MAX_SCENE_ENTITIES; i++) { struct Entity* entity = &scene->entities[i]; if(!(entity->flags & EF_ACTIVE)) @@ -511,7 +522,7 @@ struct Light* scene_light_create(struct Scene* scene, const char* name, struct E { assert(scene); struct Light* new_light = NULL; - for(int i = 0; i < MAX_LIGHTS; i++) + for(int i = 0; i < MAX_SCENE_LIGHTS; i++) { struct Light* light = &scene->lights[i]; if(!(light->base.flags & EF_ACTIVE)) @@ -539,7 +550,7 @@ struct Camera* scene_camera_create(struct Scene* scene, const char* name, struct { assert(scene); struct Camera* new_camera = NULL; - for(int i = 0; i < MAX_CAMERAS; i++) + for(int i = 0; i < MAX_SCENE_CAMERAS; i++) { struct Camera* camera = &scene->cameras[i]; if(!(camera->base.flags & EF_ACTIVE)) @@ -567,7 +578,7 @@ struct Static_Mesh* scene_static_mesh_create(struct Scene* scene, const char* na { assert(scene); struct Static_Mesh* new_static_mesh = NULL; - for(int i = 0; i < MAX_STATIC_MESHES; i++) + for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) { struct Static_Mesh* static_mesh = &scene->static_meshes[i]; if(!(static_mesh->base.flags & EF_ACTIVE)) @@ -599,7 +610,7 @@ struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* assert(scene && filename); struct Sound* sound = game_state_get()->sound; struct Sound_Source* new_sound_source = NULL; - for(int i = 0; i < MAX_SOUND_SOURCES; i++) + for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++) { struct Sound_Source* sound_source = &scene->sound_sources[i]; if(!(sound_source->base.flags & EF_ACTIVE)) @@ -657,7 +668,7 @@ struct Enemy* scene_enemy_create(struct Scene* scene, const char* name, struct E { assert(scene); struct Enemy* new_enemy = NULL; - for(int i = 0; i < MAX_ENEMIES; i++) + for(int i = 0; i < MAX_SCENE_ENEMIES; i++) { struct Enemy* enemy = &scene->enemies[i]; if(!(enemy->base.flags & EF_ACTIVE)) @@ -738,7 +749,7 @@ struct Entity* scene_entity_find(struct Scene* scene, const char* name) assert(scene && name); struct Entity* entity = NULL; - for(int i = 0; i < MAX_ENTITIES; i++) + for(int i = 0; i < MAX_SCENE_ENTITIES; i++) { if(strncmp(name, scene->entities[i].name, MAX_ENTITY_NAME_LEN) == 0) { @@ -755,7 +766,7 @@ struct Light* scene_light_find(struct Scene* scene, const char* name) assert(scene && name); struct Light* light = NULL; - for(int i = 0; i < MAX_LIGHTS; i++) + for(int i = 0; i < MAX_SCENE_LIGHTS; i++) { if(strncmp(name, scene->lights[i].base.name, MAX_ENTITY_NAME_LEN) == 0) { @@ -772,7 +783,7 @@ struct Camera* scene_camera_find(struct Scene* scene, const char* name) assert(scene && name); struct Camera* camera = NULL; - for(int i = 0; i < MAX_CAMERAS; i++) + for(int i = 0; i < MAX_SCENE_CAMERAS; i++) { if(strncmp(name, scene->cameras[i].base.name, MAX_ENTITY_NAME_LEN) == 0) { @@ -789,7 +800,7 @@ struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name assert(scene && name); struct Static_Mesh* static_mesh = NULL; - for(int i = 0; i < MAX_STATIC_MESHES; i++) + for(int i = 0; i < MAX_SCENE_STATIC_MESHES; i++) { if(strncmp(name, scene->static_meshes[i].base.name, MAX_ENTITY_NAME_LEN) == 0) { @@ -806,7 +817,7 @@ struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* na assert(scene && name); struct Sound_Source* sound_source = NULL; - for(int i = 0; i < MAX_SOUND_SOURCES; i++) + for(int i = 0; i < MAX_SCENE_SOUND_SOURCES; i++) { if(strncmp(name, scene->sound_sources[i].base.name, MAX_ENTITY_NAME_LEN) == 0) { @@ -823,7 +834,7 @@ struct Enemy* scene_enemy_get(struct Scene* scene, const char* name) assert(scene && name); struct Enemy* enemy = NULL; - for(int i = 0; i < MAX_ENEMIES; i++) + for(int i = 0; i < MAX_SCENE_ENEMIES; i++) { if(strncmp(name, scene->enemies[i].base.name, MAX_ENTITY_NAME_LEN) == 0) { @@ -906,31 +917,31 @@ void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Re { case ET_DEFAULT: if(!(ray_mask & ERM_DEFAULT)) continue; - max_length = MAX_ENTITIES; + max_length = MAX_SCENE_ENTITIES; entity = &scene->entities[0]; stride = sizeof(struct Entity); break; case ET_LIGHT: if(!(ray_mask & ERM_LIGHT)) continue; - max_length = MAX_LIGHTS; + max_length = MAX_SCENE_LIGHTS; entity = &scene->lights[0].base; stride = sizeof(struct Light); break; case ET_STATIC_MESH: if(!(ray_mask & ERM_STATIC_MESH)) continue; - max_length = MAX_STATIC_MESHES; + max_length = MAX_SCENE_STATIC_MESHES; entity = &scene->static_meshes[0].base; stride = sizeof(struct Static_Mesh); break; case ET_CAMERA: if(!(ray_mask & ERM_CAMERA)) continue; - max_length = MAX_CAMERAS; + max_length = MAX_SCENE_CAMERAS; entity = &scene->cameras[0].base; stride = sizeof(struct Camera); break; case ET_SOUND_SOURCE: if(!(ray_mask & ERM_SOUND_SOURCE)) continue; - max_length = MAX_SOUND_SOURCES; + max_length = MAX_SCENE_SOUND_SOURCES; entity = &scene->sound_sources[0].base; stride = sizeof(struct Sound_Source); break; @@ -981,31 +992,31 @@ struct Entity* scene_ray_intersect_closest(struct Scene* scene, struct Ray* ray, { case ET_DEFAULT: if(!(ray_mask & ERM_DEFAULT)) continue; - max_length = MAX_ENTITIES; + max_length = MAX_SCENE_ENTITIES; entity = &scene->entities[0]; stride = sizeof(struct Entity); break; case ET_LIGHT: if(!(ray_mask & ERM_LIGHT)) continue; - max_length = MAX_LIGHTS; + max_length = MAX_SCENE_LIGHTS; entity = &scene->lights[0].base; stride = sizeof(struct Light); break; case ET_STATIC_MESH: if(!(ray_mask & ERM_STATIC_MESH)) continue; - max_length = MAX_STATIC_MESHES; + max_length = MAX_SCENE_STATIC_MESHES; entity = &scene->static_meshes[0].base; stride = sizeof(struct Static_Mesh); break; case ET_CAMERA: if(!(ray_mask & ERM_CAMERA)) continue; - max_length = MAX_CAMERAS; + max_length = MAX_SCENE_CAMERAS; entity = &scene->cameras[0].base; stride = sizeof(struct Camera); break; case ET_SOUND_SOURCE: if(!(ray_mask & ERM_SOUND_SOURCE)) continue; - max_length = MAX_SOUND_SOURCES; + max_length = MAX_SCENE_SOUND_SOURCES; entity = &scene->sound_sources[0].base; stride = sizeof(struct Sound_Source); break; @@ -1068,7 +1079,7 @@ int scene_entity_archetype_add(struct Scene* scene, const char* filename) // check if we have already added this archetype, if we have, return that index // otherwise add it and return the index int index = -1; - for(int i = 0; i < MAX_ENTITY_ARCHETYPES; i++) + for(int i = 0; i < MAX_SCENE_ENTITY_ARCHETYPES; i++) { if(strncmp(filename, &scene->entity_archetypes[i][0], MAX_FILENAME_LEN) == 0) { @@ -1079,7 +1090,7 @@ int scene_entity_archetype_add(struct Scene* scene, const char* filename) if(index == -1) { - for(int i = 0; i < MAX_ENTITY_ARCHETYPES; i++) + for(int i = 0; i < MAX_SCENE_ENTITY_ARCHETYPES; i++) { if(scene->entity_archetypes[i][0] == '\0') { @@ -1103,7 +1114,7 @@ struct Entity* scene_entity_duplicate(struct Scene* scene, struct Entity* entity struct Entity* new_entity = NULL; if(entity->archetype_index != -1) { - new_entity = entity_load(scene->entity_archetypes[entity->archetype_index], DIRT_INSTALL); + new_entity = entity_load(scene->entity_archetypes[entity->archetype_index], DIRT_INSTALL, true); if(new_entity) scene_entity_parent_set(scene, new_entity, entity->transform.parent); return new_entity; } diff --git a/src/game/scene.h b/src/game/scene.h index 66c1451..435b337 100755 --- a/src/game/scene.h +++ b/src/game/scene.h @@ -3,14 +3,7 @@ #include "entity.h" #include "renderer.h" - -#define MAX_ENTITIES 32 -#define MAX_LIGHTS 30 -#define MAX_CAMERAS 2 -#define MAX_STATIC_MESHES 1024 -#define MAX_SOUND_SOURCES 128 -#define MAX_ENTITY_ARCHETYPES 32 -#define MAX_ENEMIES 64 +#include "../common/limits.h" struct Ray; struct Raycast_Result; @@ -20,13 +13,13 @@ struct Scene char filename[MAX_FILENAME_LEN]; struct Entity root_entity; struct Player player; - struct Entity entities[MAX_ENTITIES]; - struct Static_Mesh static_meshes[MAX_STATIC_MESHES]; - struct Camera cameras[MAX_CAMERAS]; - struct Light lights[MAX_LIGHTS]; - struct Sound_Source sound_sources[MAX_SOUND_SOURCES]; - struct Enemy enemies[MAX_ENEMIES]; - char entity_archetypes[MAX_ENTITY_ARCHETYPES][MAX_FILENAME_LEN]; + struct Entity entities[MAX_SCENE_ENTITIES]; + struct Static_Mesh static_meshes[MAX_SCENE_STATIC_MESHES]; + struct Camera cameras[MAX_SCENE_CAMERAS]; + struct Light lights[MAX_SCENE_LIGHTS]; + struct Sound_Source sound_sources[MAX_SCENE_SOUND_SOURCES]; + struct Enemy enemies[MAX_SCENE_ENEMIES]; + char entity_archetypes[MAX_SCENE_ENTITY_ARCHETYPES][MAX_FILENAME_LEN]; int active_camera_index; }; diff --git a/src/system/file_io.h b/src/system/file_io.h index 9f87ef9..bba9d6b 100755 --- a/src/system/file_io.h +++ b/src/system/file_io.h @@ -4,7 +4,7 @@ #include #include -#define MAX_FILENAME_LEN 128 +#include "../common/limits.h" enum Directory_Type { diff --git a/todo.txt b/todo.txt index f83bb52..c016f1e 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,4 @@ Todo: - - Imlement reading/writing enemy mesh and weapon sound to file and resetting it in code - Enemy ray casting and shooting - Player shooting - Player jump cooldown, don't allow jump until a certian time interval has passed, even if we're grounded @@ -34,6 +33,7 @@ Todo: - Command to reload entities only - Serialize player, camera properties to file - Change mouse behaviour to lock cursor when looking around so as not to interfere with gui elements when in editor mode + - Resource manager that loads/unloads/reloads all types of assets and caches them when required so that we don't end up constantly loading files from disk - Folder management api to create/delete folders when none exist. Dirent would suffice for our simple needs? ? Entity creator window to create new types of entities and write them to disk @@ -401,4 +401,6 @@ Done: * Move player movement related variables from function to player struct and load them from config file * Screen mouse coordinates to world-coordinates for aiming * Sound source entity functions that automatically track if handles are valid and create/update as necessary - * Apply sound source properties to source instance whenever a new instance is created \ No newline at end of file + * Apply sound source properties to source instance whenever a new instance is created + * Imlemented reading/writing enemy mesh and weapon sound to file and resetting it in code + * Implemented on_load and on_update callbacks for enemies. Different enemy types have different callbacks that are assigned when they are created. \ No newline at end of file