diff --git a/src/game/entity.c b/src/game/entity.c index 205dfc1..fab4e4c 100755 --- a/src/game/entity.c +++ b/src/game/entity.c @@ -52,7 +52,7 @@ void entity_reset(struct Entity * entity, int id) } -bool entity_write(struct Entity* entity, struct Parser_Object* object) +bool entity_write(struct Entity* entity, struct Parser_Object* object, bool write_transform) { if(!object) { @@ -121,10 +121,14 @@ bool entity_write(struct Entity* entity, struct Parser_Object* object) //struct Entity* parent = entity_get_parent(entity->id); //hashmap_str_set(entity_data, "parent", parent ? parent->name : "NONE"); - ///* Transform */ - //hashmap_vec3_set(entity_data, "position", &entity->transform.position); - //hashmap_vec3_set(entity_data, "scale", &entity->transform.scale); - //hashmap_quat_set(entity_data, "rotation", &entity->transform.rotation); + /* Transform */ + if(write_transform) + { + hashmap_vec3_set(entity_data, "position", &entity->transform.position); + hashmap_vec3_set(entity_data, "scale", &entity->transform.scale); + hashmap_quat_set(entity_data, "rotation", &entity->transform.rotation); + } + switch(entity->type) { case ET_CAMERA: @@ -205,15 +209,29 @@ bool entity_save(struct Entity* entity, const char* filename, int directory_type struct Parser* parser = parser_new(); struct Parser_Object* object = parser_object_new(parser, PO_ENTITY); - if(!entity_write(entity, object)) + if(!entity_write(entity, object, false)) { log_error("entity:save", "Failed to save entity : %s to file : %s", entity->name, filename); parser_free(parser); fclose(entity_file); return false; } + // See if the entity has any children, if it does, // write the entity first then, write all its children + int num_children = array_len(entity->transform.children); + for (int i = 0; i < num_children; i++) + { + struct Parser_Object* child_object = parser_object_new(parser, PO_ENTITY); + struct Entity* child_entity = entity->transform.children[i]; + if (!entity_write(child_entity, child_object, true)) + { + log_error("entity:save", "Failed to write child entity : %s for parent entity : %s to file : %s", entity->name, child_entity->name, filename); + parser_free(parser); + fclose(entity_file); + return false; + } + } if(parser_write_objects(parser, entity_file, filename)) log_message("Entity %s saved to %s", entity->name, filename); @@ -223,7 +241,7 @@ bool entity_save(struct Entity* entity, const char* filename, int directory_type return true; } -struct Entity* entity_read(struct Parser_Object* object) +struct Entity* entity_read(struct Parser_Object* object, struct Entity* parent_entity) { assert(object); @@ -259,7 +277,7 @@ struct Entity* entity_read(struct Parser_Object* object) bool fbo_has_render_tex = false; int fbo_width = -1; int fbo_height = -1; - struct Camera* camera = scene_camera_create(scene, name, NULL, 320, 240); + struct Camera* camera = scene_camera_create(scene, name, parent_entity, 320, 240); if(hashmap_value_exists(object->data, "fov")) camera->fov = hashmap_float_get(object->data, "fov"); if(hashmap_value_exists(object->data, "resizeable")) camera->resizeable = hashmap_bool_get(object->data, "resizeable"); if(hashmap_value_exists(object->data, "zoom")) camera->zoom = hashmap_float_get(object->data, "zoom"); @@ -296,7 +314,7 @@ struct Entity* entity_read(struct Parser_Object* object) break; case ET_LIGHT: { - struct Light* light = scene_light_create(scene, name, NULL, LT_POINT); + struct Light* light = scene_light_create(scene, name, parent_entity, LT_POINT); if(hashmap_value_exists(object->data, "light_type")) light->type = hashmap_int_get(object->data, "light_type"); if(hashmap_value_exists(object->data, "outer_angle")) light->outer_angle = hashmap_float_get(object->data, "outer_angle"); if(hashmap_value_exists(object->data, "inner_angle")) light->inner_angle = hashmap_float_get(object->data, "inner_angle"); @@ -312,7 +330,7 @@ struct Entity* entity_read(struct Parser_Object* object) break; case ET_SOUND_SOURCE: { - struct Sound_Source* sound_source = scene_sound_source_create(scene, name, NULL, "sounds/teh_beatz.wav", ST_WAV, true, true); + struct Sound_Source* sound_source = scene_sound_source_create(scene, name, parent_entity, "sounds/teh_beatz.wav", ST_WAV, true, true); struct Sound_Source_Buffer* default_source_buffer = sound_source->source_buffer; uint default_source_instance = sound_source->source_instance; @@ -372,7 +390,7 @@ struct Entity* entity_read(struct Parser_Object* object) int material_type = MAT_UNSHADED; if(hashmap_value_exists(object->data, "geometry")) geometry_name = hashmap_str_get(object->data, "geometry"); if(hashmap_value_exists(object->data, "material_type")) material_type = hashmap_int_get(object->data, "material_type"); - struct Static_Mesh* mesh = scene_static_mesh_create(scene, name, NULL, geometry_name, material_type); + struct Static_Mesh* mesh = scene_static_mesh_create(scene, name, parent_entity, geometry_name, material_type); new_entity = &mesh->base; } break; @@ -385,6 +403,24 @@ struct Entity* entity_read(struct Parser_Object* object) log_warning("Unhandled Entity type '%d' detected", type); break; } + + //If there's a parent entity then it means this is a child entity and we shoud load it's relative transform values + if(parent_entity) + { + vec3 position = { 0.f, 0.f, 0.f }; + quat rotation = { 0.f, 0.f, 0.f, 1.f }; + vec3 scale = { 1.f, 1.f, 1.f }; + + if(hashmap_value_exists(object->data, "position")) position = hashmap_vec3_get(object->data, "position"); + if(hashmap_value_exists(object->data, "rotation")) rotation = hashmap_quat_get(object->data, "rotation"); + if(hashmap_value_exists(object->data, "scale")) scale = hashmap_vec3_get(object->data, "scale"); + + transform_set_position(new_entity, &position); + transform_scale(new_entity, &scale); + quat_mul(&new_entity->transform.rotation, &new_entity->transform.rotation, &rotation); + transform_update_transmat(new_entity); + + } return new_entity; } @@ -417,14 +453,17 @@ bool entity_load(const char* filename, int directory_type) } int num_entites_loaded = 0; + struct Entity* parent_entity = NULL; for(int i = 0; i < array_len(parsed_file->objects); i++) { struct Parser_Object* object = &parsed_file->objects[i]; if(object->type != PO_ENTITY) continue; - new_entity = entity_read(object); + new_entity = entity_read(object, parent_entity); if(new_entity) { + if(i == 0) + parent_entity = new_entity; num_entites_loaded++; log_message("Entity %s loaded from %s", new_entity->name, filename); } diff --git a/src/game/entity.h b/src/game/entity.h index f1b8c37..653be88 100755 --- a/src/game/entity.h +++ b/src/game/entity.h @@ -155,8 +155,8 @@ void entity_init(struct Entity* entity, const char* name, struct Entit void entity_reset(struct Entity* entity, int id); bool entity_save(struct Entity* entity, const char* filename, int directory_type); bool entity_load(const char* filename, int directory_type); -bool entity_write(struct Entity* entity, struct Parser_Object* object); -struct Entity* entity_read(struct Parser_Object* object); +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); void entity_rigidbody_on_move(Rigidbody body); void entity_rigidbody_on_collision(Rigidbody body_A, Rigidbody body_B); diff --git a/src/game/game.c b/src/game/game.c index 35fe27a..153440e 100755 --- a/src/game/game.c +++ b/src/game/game.c @@ -322,6 +322,24 @@ void game_scene_setup(void) light->radius = 20; vec3 light_pos = {0.f, 5.f, 0.f}; transform_translate(light, &light_pos, TS_WORLD); + + struct Static_Mesh* suzanne = scene_static_mesh_create(game_state->scene, "Suz", NULL, "suzanne.symbres", MAT_BLINN); + suzanne->model.material_params[MMP_DIFFUSE_TEX].val_int = texture_create_from_file("white.tga", TU_DIFFUSE); + suzanne->model.material_params[MMP_DIFFUSE].val_float = 0.5f; + suzanne->model.material_params[MMP_SPECULAR].val_float = 1.f; + suzanne->model.material_params[MMP_SPECULAR_STRENGTH].val_float = 1.f; + vec3_fill(&suzanne->model.material_params[MMP_DIFFUSE_COL].val_vec3, 1.f, 0.f, 1.f); + suz_pos.x = 0.f; + suz_pos.y = 5.f; + suz_pos.z = 5.f; + transform_set_position(suzanne, &suz_pos); + + struct Light* suz_light = scene_light_create(game_state->scene, "Suz_Light", suzanne, LT_POINT); + suz_light->color.x = 1.f; + suz_light->color.y = 0.f; + suz_light->color.z = 0.f; + vec3 suz_light_pos = {0.f, 3.f, 0.f}; + transform_translate(suz_light, &suz_light_pos, TS_PARENT); } void game_debug(float dt) diff --git a/src/game/transform.c b/src/game/transform.c index 6a6aa26..fad3982 100755 --- a/src/game/transform.c +++ b/src/game/transform.c @@ -28,7 +28,13 @@ void transform_child_add(struct Entity* parent, struct Entity* child, bool updat /* Check if already added */ for(int i = 0; i < array_len(parent_transform->children); i++) - if(parent_transform->children[i] == child) return; + { + if(parent_transform->children[i] == child) + { + log_warning("Parent : %s already has a child named %s", parent->name, parent_transform->children[i]->name); + return; + } + } struct Entity** new_child_loc = array_grow(parent_transform->children, struct Entity*); *new_child_loc = child; @@ -44,7 +50,7 @@ bool transform_child_remove(struct Entity* parent, struct Entity* child) { if(parent_transform->children[i] == child) { - array_remove_at(parent_transform, i); + array_remove_at(parent_transform->children, i); child->transform.parent = NULL; success = true; return success; @@ -233,6 +239,7 @@ void transform_update_transmat(struct Entity* entity) void transform_destroy(struct Entity* entity) { struct Transform* transform = &entity->transform; + // Remove children int children = array_len(transform->children); if(children > 0) { @@ -242,7 +249,11 @@ void transform_destroy(struct Entity* entity) child->marked_for_deletion = true; } } - + + // Remove this entity from parent's children + if(entity->transform.parent) + transform_child_remove(entity->transform.parent, entity); + /* Remove transform */ array_free(transform->children); vec3_fill(&transform->position, 0.f, 0.f, 0.f); diff --git a/src/system/file_io.c b/src/system/file_io.c index 66d2d4a..91fd40b 100755 --- a/src/system/file_io.c +++ b/src/system/file_io.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "file_io.h" #include "../common/log.h" @@ -81,7 +82,8 @@ FILE* io_file_open(const int directory_type, const char* path, const char* mode) if(!file) { char err_str[256]; - perror(err_str); + memset(&err_str[0], '\0', 256); + perror(&err_str[0]); log_error("io:file_open", "Failed to open file '%s' (%s)", relative_path, err_str); } free(relative_path); diff --git a/todo.txt b/todo.txt index e917849..b592bb1 100644 --- a/todo.txt +++ b/todo.txt @@ -1,13 +1,12 @@ Todo: - - Display default mesh when selected entity type in editor does not have a mesh - - Allow picking and selecting other entity types in editor i.e. the ones that don't have meshes - - Separate entity types in entity heirarchy view by the entity type or use a tree view to show parent/child relation or use differnt colours for different entity types - Finish mesh and material properties serialization to and from file - - Editor functionality to add entity from specific file to scene - Scene read/write to file with scene file only containing names of entity archetypes - Console command to read/write scene to/from file - Editor functionality to read/write scene to/from file + - Display default mesh when selected entity type in editor does not have a mesh + - Allow picking and selecting other entity types in editor i.e. the ones that don't have meshes + - Separate entity types in entity heirarchy view by the entity type or use a tree view to show parent/child relation or use different colours for different entity types ? Entity creator window to create new types of entities and write them to disk - Entity browser window which lists all existing entity types from @@ -319,3 +318,5 @@ Done: * Fixed symlink issue in genie for macos which interferes with fopen operations * Implement/Fix copying libraries to executable folder after build completes on mac os * Fixed all sound related bugs and completede sound to/from file + * Implemented saving/loading entity children when reading/writing entity to file + * Editor functionality to add entity from specific file to scene diff --git a/tools/setup_env.bat b/tools/setup_env.bat index 575c56e..186b081 100644 --- a/tools/setup_env.bat +++ b/tools/setup_env.bat @@ -2,8 +2,7 @@ subst /D "W:" subst W: %CD%\.. -call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 +call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 cls -set editor=""C:\Applications\Emacs\bin\runemacs.exe"" set path=W:\tools;%path% rem