diff --git a/README.md b/README.md index 85066b6..5d51cbb 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,10 @@ - ## TODO - - Modify entity loading logic to use the new parsing code by parsing all entity properties into a hashmap first then recreating entity from that + - Implment writing to file through the new Parser and Parser_Object + - Change Config to read/write using new Parser logic + - Store Materials in new format supported by parser + - Add model description file which has the same syntax supported by parser and modify old blender exporter to conform to new standards - Implement sound/listener loading from scene file - Finish loading scene from file - Update makefiles to be able to compile the code in it's current state @@ -325,3 +328,4 @@ * Fixed several bugs with entity loading * Removed duplicate parsing logic * Fixed bugs in stripping key name for input map + * Modify entity loading logic to use the new parsing code by parsing all entity properties into a hashmap first then recreating entity from that diff --git a/assets/test.symtres b/assets/test.symtres new file mode 100644 index 0000000..df8a071 --- /dev/null +++ b/assets/test.symtres @@ -0,0 +1,272 @@ +Entity +{ + name: ROOT + type: 2 + is_listener: false + renderable: false + parent: NONE + position: 0.00000 0.00000 0.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 +} + +Entity +{ + name: player + type: 3 + is_listener: false + renderable: false + parent: ROOT + position: 10.00000 5.00000 100.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + ortho: false + resizeable: true + fov: 60.00000 + nearz: 0.10000 + farz: 1000.00000 + clear_color: 0.30000 0.60000 0.90000 1.00000 + has_fbo: true + fbo_height: 768 + fbo_width: 1024 + fbo_has_render_tex: true + fbo_has_depth_tex: true +} + +Entity +{ + name: Model_Entity + type: 5 + is_listener: false + renderable: true + parent: ROOT + position: 0.00000 0.00000 -5.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Ground + type: 5 + is_listener: false + renderable: true + parent: ROOT + position: 0.00000 -5.00000 0.00000 + scale: 400.00000 2.00000 400.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Light_Ent + type: 4 + is_listener: false + renderable: false + parent: ROOT + position: 20.00000 0.00000 60.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + light_type: 1 + outer_angle: 0.52360 + inner_angle: 0.34907 + falloff: 1.50000 + radius: 20 + intensity: 1.00000 + depth_bias: 0.00050 + valid: true + cast_shadow: false + pcf_enabled: false + color: 1.00000 0.12500 0.33333 +} + +Entity +{ + name: Light_Ent + type: 4 + is_listener: false + renderable: false + parent: ROOT + position: 60.00000 0.00000 40.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + light_type: 1 + outer_angle: 0.52360 + inner_angle: 0.34907 + falloff: 1.50000 + radius: 20 + intensity: 1.00000 + depth_bias: 0.00050 + valid: true + cast_shadow: false + pcf_enabled: false + color: 0.33333 0.20000 0.50000 +} + +Entity +{ + name: Light_Ent + type: 4 + is_listener: false + renderable: false + parent: ROOT + position: 20.00000 0.00000 20.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + light_type: 1 + outer_angle: 0.52360 + inner_angle: 0.34907 + falloff: 1.50000 + radius: 20 + intensity: 1.00000 + depth_bias: 0.00050 + valid: true + cast_shadow: false + pcf_enabled: false + color: 1.00000 0.14286 1.00000 +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 6.00000 0.00000 8.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 8.00000 0.00000 3.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 6.00000 0.00000 7.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 7.00000 0.00000 7.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 6.00000 0.00000 7.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 3.00000 0.00000 2.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 2.00000 0.00000 7.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 10.00000 0.00000 7.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 6.00000 0.00000 4.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + +Entity +{ + name: Suzanne + type: 5 + is_listener: false + renderable: true + parent: Model_Entity + position: 2.00000 0.00000 6.00000 + scale: 1.00000 1.00000 1.00000 + rotation: 0.00000 0.00000 0.00000 1.00000 + material: Blinn_Phong + geometry: default.pamesh +} + diff --git a/build/genie.exe b/build/genie.exe index 7f02240..0abc3e3 100644 Binary files a/build/genie.exe and b/build/genie.exe differ diff --git a/src/common/hashmap.c b/src/common/hashmap.c index 9f8dbba..eb650bb 100644 --- a/src/common/hashmap.c +++ b/src/common/hashmap.c @@ -126,6 +126,11 @@ void hashmap_value_remove(struct Hashmap* hashmap, const char* key) if(index_to_remove != -1) array_remove_at(hashmap->buckets[index], index_to_remove); } +bool hashmap_value_exists(struct Hashmap * hashmap, const char * key) +{ + return hashmap_value_get(hashmap, key); +} + void hashmap_float_set(struct Hashmap* hashmap, const char* key, const float value) { @@ -219,55 +224,64 @@ void hashmap_ptr_set(struct Hashmap* hashmap, const char* key, void* value) float hashmap_float_get(const struct Hashmap* hashmap, const char* key) { - const struct Variant* variant = hashmap_value_get(hashmap, key); + struct Variant* variant = hashmap_value_get(hashmap, key); + if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_FLOAT); return variant->val_float; } int hashmap_int_get(const struct Hashmap* hashmap, const char* key) { - const struct Variant* variant = hashmap_value_get(hashmap, key); + struct Variant* variant = hashmap_value_get(hashmap, key); + if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_INT); return variant->val_int; } double hashmap_double_get(const struct Hashmap* hashmap, const char* key) { - const struct Variant* variant = hashmap_value_get(hashmap, key); + struct Variant* variant = hashmap_value_get(hashmap, key); + if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_DOUBLE); return variant->val_double; } bool hashmap_bool_get(const struct Hashmap* hashmap, const char* key) { - const struct Variant* variant = hashmap_value_get(hashmap, key); + struct Variant* variant = hashmap_value_get(hashmap, key); + if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_BOOL); return variant->val_bool; } vec2 hashmap_vec2_get(const struct Hashmap* hashmap, const char* key) { - const struct Variant* variant = hashmap_value_get(hashmap, key); + struct Variant* variant = hashmap_value_get(hashmap, key); + if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_VEC2); return variant->val_vec2; } vec3 hashmap_vec3_get(const struct Hashmap* hashmap, const char* key) { - const struct Variant* variant = hashmap_value_get(hashmap, key); + struct Variant* variant = hashmap_value_get(hashmap, key); + if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_VEC3); return variant->val_vec3; } vec4 hashmap_vec4_get(const struct Hashmap* hashmap, const char* key) { - const struct Variant* variant = hashmap_value_get(hashmap, key); + struct Variant* variant = hashmap_value_get(hashmap, key); + if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_VEC4); return variant->val_vec4; } quat hashmap_quat_get(const struct Hashmap* hashmap, const char* key) { - const struct Variant* variant = hashmap_value_get(hashmap, key); + struct Variant* variant = hashmap_value_get(hashmap, key); + if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_QUAT); return variant->val_quat; } const mat4* hashmap_mat4_get(const struct Hashmap* hashmap, const char* key) { - const struct Variant* variant = hashmap_value_get(hashmap, key); + struct Variant* variant = hashmap_value_get(hashmap, key); + if(variant->type == VT_STR) variant_from_str(variant, variant->val_str, VT_MAT4); return variant->val_mat4; } diff --git a/src/common/hashmap.h b/src/common/hashmap.h index 079b3a4..3b0758f 100644 --- a/src/common/hashmap.h +++ b/src/common/hashmap.h @@ -14,6 +14,7 @@ struct Variant; struct Hashmap* hashmap_new(void); void hashmap_free(struct Hashmap* hashmap); void hashmap_value_remove(struct Hashmap* hashmap, const char* key); +bool hashmap_value_exists(struct Hashmap* hashmap, const char* key); void hashmap_value_set(struct Hashmap* hashmap, const char* key, const struct Variant* value); struct Variant* hashmap_value_get(const struct Hashmap* hashmap, const char* key); diff --git a/src/common/parser.c b/src/common/parser.c index 513c298..60865e9 100644 --- a/src/common/parser.c +++ b/src/common/parser.c @@ -206,8 +206,8 @@ struct Parser* parser_load_objects(FILE* file, const char* filename) char value_str[MAX_VALUE_LEN]; memset(format_str, '\0', 64); - snprintf(format_str, 64, " %%%d[^: ] : %%%d[^\n]", HASH_MAX_KEY_LEN, MAX_VALUE_LEN); - char* line = strtok(obj_str, "\n"); + snprintf(format_str, 64, " %%%d[^: ] : %%%d[^\r\n]", HASH_MAX_KEY_LEN, MAX_VALUE_LEN); + char* line = strtok(obj_str, "\r\n"); do { memset(key_str, '\0', HASH_MAX_KEY_LEN); @@ -228,7 +228,7 @@ struct Parser* parser_load_objects(FILE* file, const char* filename) } hashmap_str_set(object->data, key_str, value_str); } - while((line = strtok(NULL, "\n")) != NULL); + while((line = strtok(NULL, "\r\n")) != NULL); //log_to_stdout("Object found\nType: %s\n%s\n\n", type_str, obj_str); } diff --git a/src/game/platform.c b/src/game/platform.c index 76bc5c0..3f16965 100644 --- a/src/game/platform.c +++ b/src/game/platform.c @@ -9,6 +9,7 @@ #include #include #include +#include struct Window { diff --git a/src/game/sound.c b/src/game/sound.c index b02ec13..f2c66f8 100644 --- a/src/game/sound.c +++ b/src/game/sound.c @@ -10,11 +10,12 @@ #include #include -#if defined(_MSC_VER) - #include -#else - #include -#endif +//#if defined(_MSC_VER) +// #include +//#else +// #include +//#endif +#include struct Sound_State { diff --git a/src/libsymmetry/entity.c b/src/libsymmetry/entity.c index 5076f6c..a26564a 100644 --- a/src/libsymmetry/entity.c +++ b/src/libsymmetry/entity.c @@ -11,6 +11,8 @@ #include "framebuffer.h" #include "../common/variant.h" #include "../common/common.h" +#include "../common/parser.h" +#include "../common/hashmap.h" #include #include @@ -206,24 +208,25 @@ bool entity_write(struct Entity* entity, FILE* file) } /* First write all properties common to all entity types */ - fprintf(file, "name: %s\n", entity->name); - fprintf(file, "type: %d\n", entity->type); - fprintf(file, "is_listener: %s\n", entity->is_listener ? "true" : "false"); - fprintf(file, "renderable: %s\n", entity->renderable ? "true" : "false"); + fprintf(file, "Entity\n{\n"); + fprintf(file, "\tname: %s\n", entity->name); + fprintf(file, "\ttype: %d\n", entity->type); + fprintf(file, "\tis_listener: %s\n", entity->is_listener ? "true" : "false"); + fprintf(file, "\trenderable: %s\n", entity->renderable ? "true" : "false"); struct Entity* parent = entity_get_parent(entity->id); - fprintf(file, "parent: %s\n", parent ? parent->name : "NONE"); + fprintf(file, "\tparent: %s\n", parent ? parent->name : "NONE"); /* Transform */ - fprintf(file, "position: %.5f %.5f %.5f\n", + fprintf(file, "\tposition: %.5f %.5f %.5f\n", entity->transform.position.x, entity->transform.position.y, entity->transform.position.z); - fprintf(file, "scale: %.5f %.5f %.5f\n", + fprintf(file, "\tscale: %.5f %.5f %.5f\n", entity->transform.scale.x, entity->transform.scale.y, entity->transform.scale.z); - fprintf(file, "rotation: %.5f %.5f %.5f %.5f\n", + fprintf(file, "\trotation: %.5f %.5f %.5f %.5f\n", entity->transform.rotation.x, entity->transform.rotation.y, entity->transform.rotation.z, @@ -233,27 +236,27 @@ bool entity_write(struct Entity* entity, FILE* file) { case ET_CAMERA: { - fprintf(file, "ortho: %s\n", entity->camera.ortho ? "true" : "false"); - fprintf(file, "resizeable: %s\n", entity->camera.resizeable ? "true" : "false"); - fprintf(file, "fov: %.5f\n", entity->camera.fov); - fprintf(file, "nearz: %.5f\n", entity->camera.nearz); - fprintf(file, "farz: %.5f\n", entity->camera.farz); - fprintf(file, "clear_color: %.5f %.5f %.5f %.5f\n", + fprintf(file, "\tortho: %s\n", entity->camera.ortho ? "true" : "false"); + fprintf(file, "\tresizeable: %s\n", entity->camera.resizeable ? "true" : "false"); + fprintf(file, "\tfov: %.5f\n", entity->camera.fov); + fprintf(file, "\tnearz: %.5f\n", entity->camera.nearz); + fprintf(file, "\tfarz: %.5f\n", entity->camera.farz); + fprintf(file, "\tclear_color: %.5f %.5f %.5f %.5f\n", entity->camera.clear_color.x, entity->camera.clear_color.y, entity->camera.clear_color.z, entity->camera.clear_color.w); if(entity->camera.fbo != -1) { - fprintf(file, "has_fbo: true\n"); - fprintf(file, "fbo_height: %d\n", framebuffer_height_get(entity->camera.fbo)); - fprintf(file, "fbo_width: %d\n", framebuffer_width_get(entity->camera.fbo)); - fprintf(file, "fbo_has_render_tex: %s\n", entity->camera.render_tex == -1 ? "false" : "true"); - fprintf(file, "fbo_has_depth_tex: %s\n", entity->camera.depth_tex == -1 ? "false" : "true"); + fprintf(file, "\thas_fbo: true\n"); + fprintf(file, "\tfbo_height: %d\n", framebuffer_height_get(entity->camera.fbo)); + fprintf(file, "\tfbo_width: %d\n", framebuffer_width_get(entity->camera.fbo)); + fprintf(file, "\tfbo_has_render_tex: %s\n", entity->camera.render_tex == -1 ? "false" : "true"); + fprintf(file, "\tfbo_has_depth_tex: %s\n", entity->camera.depth_tex == -1 ? "false" : "true"); } else { - fprintf(file, "has_fbo: false\n"); + fprintf(file, "\thas_fbo: false\n"); } break; } @@ -262,23 +265,23 @@ bool entity_write(struct Entity* entity, FILE* file) /* TODO: Change this after adding proper support for exported models from blender */ struct Material* material = material_get(entity->model.material); struct Geometry* geom = geom_get(entity->model.geometry_index); - fprintf(file, "material: %s\n", material->name); - fprintf(file, "geometry: %s\n", geom->filename); + fprintf(file, "\tmaterial: %s\n", material->name); + fprintf(file, "\tgeometry: %s\n", geom->filename); break; } case ET_LIGHT: { - fprintf(file, "light_type: %d\n", entity->light.valid); - fprintf(file, "outer_angle: %.5f\n", entity->light.outer_angle); - fprintf(file, "inner_angle: %.5f\n", entity->light.inner_angle); - fprintf(file, "falloff: %.5f\n", entity->light.falloff); - fprintf(file, "radius: %d\n", entity->light.radius); - fprintf(file, "intensity: %.5f\n", entity->light.intensity); - fprintf(file, "depth_bias: %.5f\n", entity->light.depth_bias); - fprintf(file, "valid: %s\n", entity->light.valid ? "true" : "false"); - fprintf(file, "cast_shadow: %s\n", entity->light.cast_shadow ? "true" : "false"); - fprintf(file, "pcf_enabled: %s\n", entity->light.pcf_enabled ? "true" : "false"); - fprintf(file, "color: %.5f %.5f %.5f\n", + fprintf(file, "\tlight_type: %d\n", entity->light.valid); + fprintf(file, "\touter_angle: %.5f\n", entity->light.outer_angle); + fprintf(file, "\tinner_angle: %.5f\n", entity->light.inner_angle); + fprintf(file, "\tfalloff: %.5f\n", entity->light.falloff); + fprintf(file, "\tradius: %d\n", entity->light.radius); + fprintf(file, "\tintensity: %.5f\n", entity->light.intensity); + fprintf(file, "\tdepth_bias: %.5f\n", entity->light.depth_bias); + fprintf(file, "\tvalid: %s\n", entity->light.valid ? "true" : "false"); + fprintf(file, "\tcast_shadow: %s\n", entity->light.cast_shadow ? "true" : "false"); + fprintf(file, "\tpcf_enabled: %s\n", entity->light.pcf_enabled ? "true" : "false"); + fprintf(file, "\tcolor: %.5f %.5f %.5f\n", entity->light.color.x, entity->light.color.y, entity->light.color.z); @@ -286,13 +289,13 @@ bool entity_write(struct Entity* entity, FILE* file) } case ET_SOUND_SOURCE: { - fprintf(file, "active: %s\n", entity->sound_source.active ? "true" : "false"); - fprintf(file, "relative: %s\n", entity->sound_source.relative ? "true" : "false"); + fprintf(file, "\tactive: %s\n", entity->sound_source.active ? "true" : "false"); + fprintf(file, "\trelative: %s\n", entity->sound_source.relative ? "true" : "false"); break; } }; - fprintf(file, "\n"); + fprintf(file, "}\n\n"); return true; } @@ -314,334 +317,515 @@ bool entity_save(struct Entity* entity, const char* filename, int directory_type return false; } -struct Entity* entity_read(FILE* file) +struct Entity* entity_read(struct Parser_Object* object) { - if(!file) + assert(object); + + if(object->type != PO_ENTITY) { - log_error("entity:read", "Invalid file handle"); - return false; + log_error("entity:read", "Invalid object type"); + return NULL; } - struct Entity entity = + const char* name = hashmap_str_get(object->data, "name"); + const char* parent_name = hashmap_str_get(object->data, "parent"); + int type = hashmap_int_get(object->data, "type"); + + if(!name) { - .id = -1, - .type = ET_NONE, - .is_listener = false, - .renderable = false, - .marked_for_deletion = false, - .name = "DEFAULT_ENTITY_NAME", - .editor_selected = 0 - }; - - int current_line = 0; - char* material_name = NULL; - char* entity_name = NULL; - char* geometry_name = NULL; - char* parent_name = NULL; - int camera_fbo_width = -1; - int camera_fbo_height = -1; - char line_buffer[MAX_LINE_LEN]; - char prop_str[MAX_ENTITY_PROP_NAME_LEN]; - static struct Variant var_value = { .type = VT_NONE}; - - variant_free(&var_value); - memset(prop_str, '\0', MAX_ENTITY_PROP_NAME_LEN); - memset(line_buffer, '\0', MAX_LINE_LEN); - - while(fgets(line_buffer, MAX_LINE_LEN -1, file)) - { - current_line++; - memset(prop_str, '\0', MAX_ENTITY_PROP_NAME_LEN); - - if(line_buffer[0] == '#') continue; - if(strlen(line_buffer) == 0 || isspace(line_buffer[0])) break; - - char* value_str = strstr(line_buffer, ":"); - if(!value_str) - { - log_warning("Malformed value in line %d", current_line); - continue; - } + log_error("entity:read", "No entity name provided"); + return NULL; + } - value_str++; /* Ignore the colon(:) and set the pointer after it */ - - if(sscanf(line_buffer, " %1024[^: ] : %*s", prop_str) != 1) - { - log_warning("Unable to read property name in line %d", current_line); - continue; - } + if(!parent_name) + { + log_error("entity:read", "No parent name provided"); + return NULL; + } - /* Common entity properties */ - if(strncmp("name", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_STR); - entity_name = str_new(var_value.val_str); - //variant_copy_out(&entity.name, &var_value); - } - else if(strncmp("parent", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_STR); - parent_name = str_new(var_value.val_str); - //variant_copy_out(&entity.name, &var_value); - } - else if(strncmp("type", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_INT); - variant_copy_out(&entity.type, &var_value); - } - else if(strncmp("is_listener", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - variant_copy_out(&entity.is_listener, &var_value); - } - else if(strncmp("renderable", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - variant_copy_out(&entity.renderable, &var_value); - } - - /* Transform */ - else if(strncmp("position", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_VEC3); - variant_copy_out(&entity.transform.position, &var_value); - } - else if(strncmp("scale", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_VEC3); - variant_copy_out(&entity.transform.scale, &var_value); - } - else if(strncmp("rotation", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_QUAT); - variant_copy_out(&entity.transform.rotation, &var_value); - } + if(type < 0 || type >= ET_MAX) + { + log_error("entity:read", "Invalid entity type"); + return NULL; + } - /* Camera */ - else if(strncmp("ortho", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - variant_copy_out(&entity.camera.ortho, &var_value); - } - else if(strncmp("resizeable", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - variant_copy_out(&entity.camera.resizeable, &var_value); - } - else if(strncmp("fov", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_FLOAT); - variant_copy_out(&entity.camera.fov, &var_value); - } - else if(strncmp("nearz", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_FLOAT); - variant_copy_out(&entity.camera.nearz, &var_value); - } - else if(strncmp("farz", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_FLOAT); - variant_copy_out(&entity.camera.farz, &var_value); - } - else if(strncmp("has_fbo", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - entity.camera.fbo = var_value.val_bool ? 0 : -1; - } - else if(strncmp("fbo_height", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_INT); - variant_copy_out(&camera_fbo_height, &var_value); - } - else if(strncmp("fbo_width", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_INT); - variant_copy_out(&camera_fbo_width, &var_value); - } - else if(strncmp("fbo_has_depth_tex", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - entity.camera.depth_tex = var_value.val_bool ? 0 : -1; - } - else if(strncmp("fbo_has_render_tex", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - entity.camera.render_tex = var_value.val_bool ? 0 : -1; - } - else if(strncmp("clear_color", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_VEC4); - variant_copy_out(&entity.camera.clear_color, &var_value); - } + struct Entity* parent = entity_find(parent_name); + struct Entity* entity = entity_create(name, type, parent ? parent->id : -1); + if(!entity) + { + log_error("entity:read", "Failed to create new entity"); + return NULL; + } - /* Light */ - else if(strncmp("light_type", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_INT); - variant_copy_out(&entity.light.type, &var_value); - } - else if(strncmp("outer_angle", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_FLOAT); - variant_copy_out(&entity.light.outer_angle, &var_value); - } - else if(strncmp("inner_angle", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_FLOAT); - variant_copy_out(&entity.light.inner_angle, &var_value); - } - else if(strncmp("falloff", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_FLOAT); - variant_copy_out(&entity.light.falloff, &var_value); - } - else if(strncmp("radius", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_INT); - variant_copy_out(&entity.light.radius, &var_value); - } - else if(strncmp("intensity", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_FLOAT); - variant_copy_out(&entity.light.intensity, &var_value); - } - else if(strncmp("depth_bias", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_FLOAT); - variant_copy_out(&entity.light.depth_bias, &var_value); - } - else if(strncmp("valid", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - variant_copy_out(&entity.light.valid, &var_value); - } - else if(strncmp("cast_shadow", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - variant_copy_out(&entity.light.cast_shadow, &var_value); - } - else if(strncmp("pcf_enabled", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - variant_copy_out(&entity.light.pcf_enabled, &var_value); - } - else if(strncmp("color", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_VEC3); - variant_copy_out(&entity.light.color, &var_value); - } + // Common entity properties + if(hashmap_value_exists(object->data, "is_listener")) + entity->is_listener = hashmap_bool_get(object->data, "is_listener"); + else + entity->is_listener = false; - /* Model */ - else if(strncmp("material", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_STR); - material_name = str_new(var_value.val_str); - } - else if(strncmp("geometry", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_STR); - geometry_name = str_new(var_value.val_str); - } + if(hashmap_value_exists(object->data, "renderable")) + entity->renderable= hashmap_bool_get(object->data, "renderable"); + else + entity->renderable= false; - /* Sound Source */ - else if(strncmp("active", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - variant_copy_out(&entity.sound_source.active, &var_value); - } - else if(strncmp("relative", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_BOOL); - variant_copy_out(&entity.sound_source.relative, &var_value); - } - else if(strncmp("num_attached_buffers", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) - { - variant_from_str(&var_value, value_str, VT_INT); - variant_copy_out(&entity.sound_source.num_attached_buffers, &var_value); - } - else - { - log_warning("Unknown entity property '%s' in line %d", prop_str, current_line); - } + // Transform properties + if(hashmap_value_exists(object->data, "position")) + { + vec3 position = hashmap_vec3_get(object->data, "position"); + transform_translate(entity, &position, TS_PARENT); + } - variant_free(&var_value); + if(hashmap_value_exists(object->data, "rotation")) + { + quat rotation = hashmap_quat_get(object->data, "rotation"); + quat_assign(&entity->transform.rotation, &rotation); } - /* Do the things after assignment */ - struct Entity* parent_entity = NULL; - if(strcmp(parent_name, "NONE") != 0) - parent_entity = entity_find(parent_name); - - struct Entity* new_entity = entity_create(entity_name, entity.type, parent_entity ? parent_entity->id : -1); - free(entity_name); - transform_translate(new_entity, &entity.transform.position, TS_PARENT); - quat_assign(&new_entity->transform.rotation, &entity.transform.rotation); - transform_scale(new_entity, &entity.transform.scale); - - if(entity.renderable) new_entity->renderable = true; - - switch(new_entity->type) + if(hashmap_value_exists(object->data, "scale")) + { + vec3 scale = hashmap_vec3_get(object->data, "scale"); + transform_scale(entity, &scale); + } + + switch(entity->type) { case ET_CAMERA: - new_entity->camera.fbo = -1; - new_entity->camera.depth_tex = -1; - new_entity->camera.render_tex = -1; - new_entity->camera.resizeable = false; - new_entity->camera.nearz = entity.camera.nearz; - new_entity->camera.farz = entity.camera.farz; - new_entity->camera.ortho = entity.camera.ortho; - new_entity->camera.fov = entity.camera.fov; - float aspect_ratio = (float)camera_fbo_width / (float)camera_fbo_height; - new_entity->camera.aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; - camera_update_view(new_entity); - camera_update_proj(new_entity); - if(entity.camera.fbo != -1) + { + bool has_fbo = false; + bool fbo_has_depth_tex = false; + bool fbo_has_render_tex = false; + int fbo_width = -1; + int fbo_height = -1; + + if(hashmap_value_exists(object->data, "fov")) entity->camera.fov = hashmap_float_get(object->data, "fov"); + if(hashmap_value_exists(object->data, "resizeable")) entity->camera.resizeable = hashmap_bool_get(object->data, "resizeable"); + if(hashmap_value_exists(object->data, "nearz")) entity->camera.nearz = hashmap_float_get(object->data, "nearz"); + if(hashmap_value_exists(object->data, "farz")) entity->camera.farz = hashmap_float_get(object->data, "farz"); + if(hashmap_value_exists(object->data, "ortho")) entity->camera.ortho = hashmap_bool_get(object->data, "ortho"); + if(hashmap_value_exists(object->data, "has_fbo")) has_fbo = hashmap_bool_get(object->data, "has_fbo"); + if(hashmap_value_exists(object->data, "fbo_has_depth_tex")) fbo_has_depth_tex = hashmap_bool_get(object->data, "fbo_has_depth_tex"); + if(hashmap_value_exists(object->data, "fbo_has_render_tex")) fbo_has_render_tex = hashmap_bool_get(object->data, "fbo_has_render_tex"); + if(hashmap_value_exists(object->data, "fbo_width")) fbo_width = hashmap_int_get(object->data, "fbo_width"); + if(hashmap_value_exists(object->data, "fbo_height")) fbo_height = hashmap_int_get(object->data, "fbo_height"); + if(hashmap_value_exists(object->data, "clear_color")) { - camera_attach_fbo(new_entity, camera_fbo_width, camera_fbo_height, - entity.camera.depth_tex == -1 ? false : true, - entity.camera.render_tex == -1 ? false : true, - entity.camera.resizeable); + vec4 color = hashmap_vec4_get(object->data, "clear_color"); + vec4_assign(&entity->camera.clear_color, &color); } - vec4_assign(&new_entity->camera.clear_color, &entity.camera.clear_color); - break; - case ET_STATIC_MESH: - model_create(new_entity, geometry_name, material_name); - free(geometry_name); - free(material_name); - break; + + float aspect_ratio = (float)fbo_width / (float)fbo_height; + entity->camera.aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; + + entity->camera.fbo = -1; + entity->camera.render_tex = -1; + entity->camera.depth_tex = -1; + + if(has_fbo) + { + camera_attach_fbo(entity, fbo_width, fbo_height, fbo_has_depth_tex, fbo_has_render_tex, entity->camera.resizeable); + } + + camera_update_proj(entity); + camera_update_view(entity); + + } + break; case ET_LIGHT: - memcpy(&new_entity->light, &entity.light, sizeof(struct Light)); - light_add(new_entity); - break; + { + if(hashmap_value_exists(object->data, "light_type")) entity->light.type = hashmap_int_get(object->data, "type"); + if(hashmap_value_exists(object->data, "outer_angle")) entity->light.outer_angle = hashmap_float_get(object->data, "outer_angle"); + if(hashmap_value_exists(object->data, "inner_angle")) entity->light.inner_angle = hashmap_float_get(object->data, "inner_angle"); + if(hashmap_value_exists(object->data, "falloff")) entity->light.falloff = hashmap_float_get(object->data, "falloff"); + if(hashmap_value_exists(object->data, "intensity")) entity->light.intensity = hashmap_float_get(object->data, "intensity"); + if(hashmap_value_exists(object->data, "depth_bias")) entity->light.depth_bias = hashmap_float_get(object->data, "depth_bias"); + if(hashmap_value_exists(object->data, "color")) entity->light.color = hashmap_vec3_get(object->data, "color"); + if(hashmap_value_exists(object->data, "cast_shadow")) entity->light.cast_shadow = hashmap_bool_get(object->data, "cast_shadow"); + if(hashmap_value_exists(object->data, "pcf_enabled")) entity->light.pcf_enabled = hashmap_bool_get(object->data, "pcf_enabled"); + if(hashmap_value_exists(object->data, "radius")) entity->light.radius = hashmap_int_get(object->data, "radius"); + light_add(entity); + } + break; case ET_SOUND_SOURCE: - platform->sound.source_create(entity.sound_source.relative, - entity.sound_source.num_attached_buffers, - &new_entity->sound_source.source_handle, - &new_entity->sound_source.buffer_handles[0]); + { + if(hashmap_value_exists(object->data, "active")) entity->sound_source.active = hashmap_bool_get(object->data, "active"); + if(hashmap_value_exists(object->data, "relative")) entity->sound_source.relative = hashmap_bool_get(object->data, "relative"); + if(hashmap_value_exists(object->data, "num_attached_buffers")) entity->sound_source.num_attached_buffers = (uint)hashmap_int_get(object->data, "num_attached_buffers"); + platform->sound.source_create(entity->sound_source.relative, + entity->sound_source.num_attached_buffers, + &entity->sound_source.source_handle, + &entity->sound_source.buffer_handles); + } + break; + case ET_PLAYER: + { + + } + break; + case ET_STATIC_MESH: + { + char* geometry_name = NULL; + char* material_name = NULL; + if(hashmap_value_exists(object->data, "geometry")) geometry_name = hashmap_str_get(object->data, "geometry"); + if(hashmap_value_exists(object->data, "material")) material_name = hashmap_str_get(object->data, "material"); + model_create(entity, geometry_name, material_name); + } + break; + default: break; - }; + } + + return entity; - return new_entity; + //struct Entity entity = + //{ + // .id = -1, + // .type = ET_NONE, + // .is_listener = false, + // .renderable = false, + // .marked_for_deletion = false, + // .name = "DEFAULT_ENTITY_NAME", + // .editor_selected = 0 + //}; + // + // int current_line = 0; + //char* material_name = NULL; + //char* entity_name = NULL; + //char* geometry_name = NULL; + //char* parent_name = NULL; + //int camera_fbo_width = -1; + //int camera_fbo_height = -1; + // char line_buffer[MAX_LINE_LEN]; + // char prop_str[MAX_ENTITY_PROP_NAME_LEN]; + //static struct Variant var_value = { .type = VT_NONE}; + + // variant_free(&var_value); + //memset(prop_str, '\0', MAX_ENTITY_PROP_NAME_LEN); + //memset(line_buffer, '\0', MAX_LINE_LEN); + + //while(fgets(line_buffer, MAX_LINE_LEN -1, file)) + //{ + // current_line++; + // memset(prop_str, '\0', MAX_ENTITY_PROP_NAME_LEN); + + // if(line_buffer[0] == '#') continue; + // if(strlen(line_buffer) == 0 || isspace(line_buffer[0])) break; + + // char* value_str = strstr(line_buffer, ":"); + // if(!value_str) + // { + // log_warning("Malformed value in line %d", current_line); + // continue; + // } + + // value_str++; /* Ignore the colon(:) and set the pointer after it */ + // + // if(sscanf(line_buffer, " %1024[^: ] : %*s", prop_str) != 1) + // { + // log_warning("Unable to read property name in line %d", current_line); + // continue; + // } + + // /* Common entity properties */ + // if(strncmp("name", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_STR); + // entity_name = str_new(var_value.val_str); + // //variant_copy_out(&entity.name, &var_value); + // } + // else if(strncmp("parent", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_STR); + // parent_name = str_new(var_value.val_str); + // //variant_copy_out(&entity.name, &var_value); + // } + // else if(strncmp("type", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_INT); + // variant_copy_out(&entity.type, &var_value); + // } + // else if(strncmp("is_listener", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // variant_copy_out(&entity.is_listener, &var_value); + // } + // else if(strncmp("renderable", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // variant_copy_out(&entity.renderable, &var_value); + // } + // + // /* Transform */ + // else if(strncmp("position", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_VEC3); + // variant_copy_out(&entity.transform.position, &var_value); + // } + // else if(strncmp("scale", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_VEC3); + // variant_copy_out(&entity.transform.scale, &var_value); + // } + // else if(strncmp("rotation", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_QUAT); + // variant_copy_out(&entity.transform.rotation, &var_value); + // } + + // /* Camera */ + // else if(strncmp("ortho", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // variant_copy_out(&entity.camera.ortho, &var_value); + // } + // else if(strncmp("resizeable", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // variant_copy_out(&entity.camera.resizeable, &var_value); + // } + // else if(strncmp("fov", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_FLOAT); + // variant_copy_out(&entity.camera.fov, &var_value); + // } + // else if(strncmp("nearz", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_FLOAT); + // variant_copy_out(&entity.camera.nearz, &var_value); + // } + // else if(strncmp("farz", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_FLOAT); + // variant_copy_out(&entity.camera.farz, &var_value); + // } + // else if(strncmp("has_fbo", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // entity.camera.fbo = var_value.val_bool ? 0 : -1; + // } + // else if(strncmp("fbo_height", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_INT); + // variant_copy_out(&camera_fbo_height, &var_value); + // } + // else if(strncmp("fbo_width", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_INT); + // variant_copy_out(&camera_fbo_width, &var_value); + // } + // else if(strncmp("fbo_has_depth_tex", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // entity.camera.depth_tex = var_value.val_bool ? 0 : -1; + // } + // else if(strncmp("fbo_has_render_tex", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // entity.camera.render_tex = var_value.val_bool ? 0 : -1; + // } + // else if(strncmp("clear_color", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_VEC4); + // variant_copy_out(&entity.camera.clear_color, &var_value); + // } + + // /* Light */ + // else if(strncmp("light_type", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_INT); + // variant_copy_out(&entity.light.type, &var_value); + // } + // else if(strncmp("outer_angle", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_FLOAT); + // variant_copy_out(&entity.light.outer_angle, &var_value); + // } + // else if(strncmp("inner_angle", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_FLOAT); + // variant_copy_out(&entity.light.inner_angle, &var_value); + // } + // else if(strncmp("falloff", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_FLOAT); + // variant_copy_out(&entity.light.falloff, &var_value); + // } + // else if(strncmp("radius", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_INT); + // variant_copy_out(&entity.light.radius, &var_value); + // } + // else if(strncmp("intensity", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_FLOAT); + // variant_copy_out(&entity.light.intensity, &var_value); + // } + // else if(strncmp("depth_bias", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_FLOAT); + // variant_copy_out(&entity.light.depth_bias, &var_value); + // } + // else if(strncmp("valid", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // variant_copy_out(&entity.light.valid, &var_value); + // } + // else if(strncmp("cast_shadow", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // variant_copy_out(&entity.light.cast_shadow, &var_value); + // } + // else if(strncmp("pcf_enabled", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // variant_copy_out(&entity.light.pcf_enabled, &var_value); + // } + // else if(strncmp("color", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_VEC3); + // variant_copy_out(&entity.light.color, &var_value); + // } + + // /* Model */ + // else if(strncmp("material", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_STR); + // material_name = str_new(var_value.val_str); + // } + // else if(strncmp("geometry", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_STR); + // geometry_name = str_new(var_value.val_str); + // } + + // /* Sound Source */ + // else if(strncmp("active", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // variant_copy_out(&entity.sound_source.active, &var_value); + // } + // else if(strncmp("relative", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_BOOL); + // variant_copy_out(&entity.sound_source.relative, &var_value); + // } + // else if(strncmp("num_attached_buffers", prop_str, MAX_ENTITY_PROP_NAME_LEN) == 0) + // { + // variant_from_str(&var_value, value_str, VT_INT); + // variant_copy_out(&entity.sound_source.num_attached_buffers, &var_value); + // } + // else + // { + // log_warning("Unknown entity property '%s' in line %d", prop_str, current_line); + // } + + // variant_free(&var_value); + //} + + ///* Do the things after assignment */ + //struct Entity* parent_entity = NULL; + //if(strcmp(parent_name, "NONE") != 0) + // parent_entity = entity_find(parent_name); + // + //struct Entity* new_entity = entity_create(entity_name, entity.type, parent_entity ? parent_entity->id : -1); + //free(entity_name); + //transform_translate(new_entity, &entity.transform.position, TS_PARENT); + //quat_assign(&new_entity->transform.rotation, &entity.transform.rotation); + //transform_scale(new_entity, &entity.transform.scale); + // + //if(entity.renderable) new_entity->renderable = true; + // + //switch(new_entity->type) + //{ + //case ET_CAMERA: + // new_entity->camera.fbo = -1; + // new_entity->camera.depth_tex = -1; + // new_entity->camera.render_tex = -1; + // new_entity->camera.resizeable = false; + // new_entity->camera.nearz = entity.camera.nearz; + // new_entity->camera.farz = entity.camera.farz; + // new_entity->camera.ortho = entity.camera.ortho; + // new_entity->camera.fov = entity.camera.fov; + // float aspect_ratio = (float)camera_fbo_width / (float)camera_fbo_height; + // new_entity->camera.aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; + // camera_update_view(new_entity); + // camera_update_proj(new_entity); + // if(entity.camera.fbo != -1) + // { + // camera_attach_fbo(new_entity, camera_fbo_width, camera_fbo_height, + // entity.camera.depth_tex == -1 ? false : true, + // entity.camera.render_tex == -1 ? false : true, + // entity.camera.resizeable); + // } + // vec4_assign(&new_entity->camera.clear_color, &entity.camera.clear_color); + // break; + //case ET_STATIC_MESH: + // model_create(new_entity, geometry_name, material_name); + // free(geometry_name); + // free(material_name); + // break; + //case ET_LIGHT: + // memcpy(&new_entity->light, &entity.light, sizeof(struct Light)); + // light_add(new_entity); + // break; + //case ET_SOUND_SOURCE: + // platform->sound.source_create(entity.sound_source.relative, + // entity.sound_source.num_attached_buffers, + // &new_entity->sound_source.source_handle, + // &new_entity->sound_source.buffer_handles[0]); + // break; + //}; + + //return new_entity; } -struct Entity* entity_load(const char* filename, int directory_type) +bool entity_load(const char* filename, int directory_type) { FILE* entity_file = platform->file.open(directory_type, filename, "rb"); if(!entity_file) { - log_error("entity:load", "Failed to open entity file %s for writing", filename); - return NULL; + log_error("entity:load", "Failed to open entity file %s for reading", filename); + return false; } - struct Entity* new_entity = NULL; - new_entity = entity_read(entity_file); - if(new_entity) - log_message("Entity %s loaded from %s", new_entity->name, filename); - else - log_error("entity:load", "Failed to load entity from %s", filename); + struct Parser* parsed_file = parser_load_objects(entity_file, filename); + struct Entity* new_entity = false; + + if(!parsed_file) + { + log_error("entity:load", "Failed to parse file '%s' for entity definition", filename); + fclose(entity_file); + return false; + } + + if(array_len(parsed_file->objects) == 0) + { + log_error("entity:load", "No objects found in file %s", filename); + parser_free(parsed_file); + fclose(entity_file); + return false; + } + + int num_entites_loaded = 0; + 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); + if(new_entity) + { + num_entites_loaded++; + log_message("Entity %s loaded from %s", new_entity->name, filename); + } + else + { + log_error("entity:load", "Failed to load entity from %s", filename); + } + } + parser_free(parsed_file); fclose(entity_file); - return new_entity; + return num_entites_loaded > 0 ? true : false; } const char* entity_type_name_get(struct Entity* entity) diff --git a/src/libsymmetry/entity.h b/src/libsymmetry/entity.h index 7448463..6315301 100644 --- a/src/libsymmetry/entity.h +++ b/src/libsymmetry/entity.h @@ -9,6 +9,7 @@ #define MAX_SOUND_SOURCE_BUFFERS 5 struct Material_Param; +struct Parser_Object; enum Entity_Type { @@ -128,9 +129,9 @@ struct Entity* entity_find(const char* name); struct Entity* entity_get_all(void); struct Entity* entity_get_parent(int node); bool entity_save(struct Entity* entity, const char* filename, int directory_type); -struct Entity* entity_load(const char* filename, int directory_type); +bool entity_load(const char* filename, int directory_type); bool entity_write(struct Entity* entity, FILE* file); -struct Entity* entity_read(FILE* file); +struct Entity* entity_read(struct Parser_Object* object); const char* entity_type_name_get(struct Entity* entity); diff --git a/src/libsymmetry/game.c b/src/libsymmetry/game.c index 1593a1e..d27bb86 100644 --- a/src/libsymmetry/game.c +++ b/src/libsymmetry/game.c @@ -201,22 +201,23 @@ void scene_setup(void) // light_ent->light.intensity = 1.f; //} - /* log_message("Sizeof Entity : %d", sizeof(struct Entity)); */ + ///* log_message("Sizeof Entity : %d", sizeof(struct Entity)); */ - /* struct Entity* light_ent = entity_find("Ground"); */ - /* entity_save(light_ent, "ground.ent", DT_INSTALL); */ + ///* struct Entity* light_ent = entity_find("Ground"); */ + ///* entity_save(light_ent, "ground.ent", DT_INSTALL); */ - //scene_save("test.scene", DIRT_INSTALL); + //scene_save("test.symtres", DIRT_INSTALL); //struct Entity* light = entity_load("light.ent", DT_INSTALL); - if(scene_load("test.scene", DIRT_INSTALL)) + if(scene_load("test.symtres", DIRT_INSTALL)) { log_message("Scene loaded!"); struct Entity* player = entity_find("player"); game_state->player_node = player->id; } + /* FILE* obj_file = platform->file.open(DIRT_INSTALL, "obj_test.symtres", "rb"); if(obj_file) { @@ -240,7 +241,7 @@ void scene_setup(void) else { log_warning("Failed to open obj_test.symtres"); - } + }*/ } void debug(float dt) diff --git a/src/libsymmetry/material.c b/src/libsymmetry/material.c index 5dfef74..b99b750 100644 --- a/src/libsymmetry/material.c +++ b/src/libsymmetry/material.c @@ -191,7 +191,7 @@ bool material_register_model(struct Entity* entity, const char* material_name) assert(material_name && entity); bool success = false; int index = material_get_index(material_name); - if(index < -1) + if(index <= -1) { log_error("material:register_model", "Material '%s' not found", material_name); return success; diff --git a/src/libsymmetry/model.c b/src/libsymmetry/model.c index 6ee7d3d..46fa831 100644 --- a/src/libsymmetry/model.c +++ b/src/libsymmetry/model.c @@ -15,8 +15,18 @@ void model_create(struct Entity* entity, const char* geo_name, const char* mater { struct Model* model = &entity->model; /* if no name is given for geometry, use default */ - if(!geo_name) geo_name = "default.pamesh"; - int geo_index = geom_create_from_file(geo_name); + int geo_index = geom_create_from_file(geo_name ? geo_name : "default.pamesh"); + + if(geo_index == -1) + { + log_error("model:create", "Failed to load model %s", geo_name); + geo_index = geom_create_from_file("default.pamesh"); + if(geo_index == -1) + { + log_error("model:create", "Could not load default model 'default.pamesh' "); + return; + } + } model->geometry_index = geo_index; if(!material_register_model(entity, material_name ? material_name : "Unshaded")) diff --git a/src/libsymmetry/scene.c b/src/libsymmetry/scene.c index 4482c36..3fe2941 100644 --- a/src/libsymmetry/scene.c +++ b/src/libsymmetry/scene.c @@ -130,39 +130,39 @@ struct Entity* scene_get_parent(struct Entity* entity) bool scene_load(const char* filename, int directory_type) { - FILE* entity_file = platform->file.open(directory_type, filename, "rb"); - if(!entity_file) - { - log_error("scene:load", "Failed to open scenefile %s for reading", filename); - return false; - } - - int count = 0; - int eof_char = -1; - while(!feof(entity_file)) - { - if(eof_char != -1) ungetc(eof_char, entity_file); - struct Entity* new_entity = NULL; - new_entity = entity_read(entity_file); - if(!new_entity) - { - log_error("scene:load", "Error reading entity"); - } - else - { - log_message("Loaded %s", new_entity->name); - count++; - } - eof_char = fgetc(entity_file); - /* To check end of file, we get the next character and before beginning - loop we check if eof occured, feof only returns true if the last read - was an eof. If it wasn't eof then we return the character back to the - stream and carry on. */ - } - - log_message("%d entites loaded from %s", count, filename); - fclose(entity_file); - return true; + // FILE* entity_file = platform->file.open(directory_type, filename, "r"); + //if(!entity_file) + //{ + // log_error("scene:load", "Failed to open scenefile %s for reading", filename); + // return false; + //} + + //int count = 0; + //int eof_char = -1; + //while(!feof(entity_file)) + //{ + // if(eof_char != -1) ungetc(eof_char, entity_file); + // struct Entity* new_entity = NULL; + // new_entity = entity_read(entity_file); + // if(!new_entity) + // { + // log_error("scene:load", "Error reading entity"); + // } + // else + // { + // log_message("Loaded %s", new_entity->name); + // count++; + // } + // eof_char = fgetc(entity_file); + // /* To check end of file, we get the next character and before beginning + // loop we check if eof occured, feof only returns true if the last read + // was an eof. If it wasn't eof then we return the character back to the + // stream and carry on. */ + //} + + //log_message("%d entites loaded from %s", count, filename); + //fclose(entity_file); + return entity_load(filename, directory_type); } bool scene_save(const char* filename, int directory_type)