From 06d1eced8c8a388c1903e6ee576de6b2a1601de9 Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Sun, 12 May 2019 15:10:24 +1000 Subject: [PATCH] Re-implemented entity to file read/write and corresponding console command to save entity to file --- src/game/console.c | 26 +++- src/game/entity.c | 373 +++++++++++++++++++-------------------------- src/game/player.c | 6 +- src/system/sound.c | 5 + src/system/sound.h | 1 + todo.txt | 3 +- 6 files changed, 194 insertions(+), 220 deletions(-) diff --git a/src/game/console.c b/src/game/console.c index c5a999f..9ab9802 100755 --- a/src/game/console.c +++ b/src/game/console.c @@ -16,6 +16,7 @@ static struct nk_color console_message_color[CMT_MAX]; static int console_filter(const struct nk_text_edit *box, nk_rune unicode); static void console_command_entity_save(struct Console* console, const char* command); +static void console_command_entity_load(struct Console* console, const char* command); void console_init(struct Console* console) { @@ -42,6 +43,7 @@ void console_init(struct Console* console) console->console_commands = hashmap_new(); hashmap_ptr_set(console->console_commands, "entity_save", &console_command_entity_save); + hashmap_ptr_set(console->console_commands, "entity_load", &console_command_entity_load); } void console_toggle(struct Console* console) @@ -168,7 +170,7 @@ void console_command_entity_save(struct Console* console, const char* command) if(params_read != 2) { log_warning("Invalid parameters for command"); - log_warning("Usage: entity_name [entity name] [file name]"); + log_warning("Usage: entity_save [entity name] [file name]"); return; } @@ -183,6 +185,26 @@ void console_command_entity_save(struct Console* console, const char* command) snprintf(full_filename, MAX_FILENAME_LEN, "entities/%s.symtres", filename); if(!entity_save(entity, full_filename, DIRT_INSTALL)) log_error("entity_save", "Command failed"); - } +void console_command_entity_load(struct Console* console, const char* command) +{ + char filename[MAX_FILENAME_LEN]; + memset(filename, '\0', MAX_FILENAME_LEN); + + int params_read = sscanf(command, "%s", filename); + if(params_read != 1) + { + log_warning("Invalid parameters for command"); + log_warning("Usage: entity_load [file name]"); + return; + } + + char full_filename[MAX_FILENAME_LEN]; + snprintf(full_filename, MAX_FILENAME_LEN, "entities/%s.symtres", filename); + if(!entity_load(full_filename, DIRT_INSTALL)) + { + log_error("entity_load", "Could not create entity from '%s'", full_filename); + return; + } +} diff --git a/src/game/entity.c b/src/game/entity.c index 4937b83..79d3542 100755 --- a/src/game/entity.c +++ b/src/game/entity.c @@ -15,6 +15,8 @@ #include "../common/hashmap.h" #include "../system/file_io.h" #include "../system/physics.h" +#include "scene.h" +#include "game.h" #include #include @@ -221,233 +223,172 @@ bool entity_save(struct Entity* entity, const char* filename, int directory_type struct Entity* entity_read(struct Parser_Object* object) { - return NULL; - //assert(object); - - //if(object->type != PO_ENTITY) - //{ - // log_error("entity:read", "Invalid object type"); - // return NULL; - //} - - //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) - //{ - // log_error("entity:read", "No entity name provided"); - // return NULL; - //} - - //if(!parent_name) - //{ - // log_error("entity:read", "No parent name provided"); - // return NULL; - //} - - //if(type < 0 || type >= ET_MAX) - //{ - // log_error("entity:read", "Invalid entity type"); - // return NULL; - //} - - //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; - //} - - //// 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; - - //if(hashmap_value_exists(object->data, "renderable")) - // entity->renderable= hashmap_bool_get(object->data, "renderable"); - //else - // entity->renderable= false; - - //// Transform properties - //if(hashmap_value_exists(object->data, "position")) - //{ - // vec3 position = hashmap_vec3_get(object->data, "position"); - // transform_translate(entity, &position, TS_PARENT); - //} + assert(object); - //if(hashmap_value_exists(object->data, "rotation")) - //{ - // quat rotation = hashmap_quat_get(object->data, "rotation"); - // quat_assign(&entity->transform.rotation, &rotation); - //} + struct Scene* scene = game_state_get()->scene; + if(object->type != PO_ENTITY) + { + log_error("entity:read", "Invalid object type"); + return NULL; + } - //if(hashmap_value_exists(object->data, "scale")) - //{ - // vec3 scale = hashmap_vec3_get(object->data, "scale"); - // transform_scale(entity, &scale); - //} + const char* name = hashmap_str_get(object->data, "name"); + int type = hashmap_int_get(object->data, "type"); - //switch(entity->type) - //{ - //case ET_CAMERA: - //{ - // 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, "zoom")) entity->camera.zoom = hashmap_float_get(object->data, "zoom"); - // 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")) - // { - // vec4 color = hashmap_vec4_get(object->data, "clear_color"); - // vec4_assign(&entity->camera.clear_color, &color); - // } + if(!name) + { + log_error("entity:read", "No entity name provided"); + return NULL; + } - // float aspect_ratio = (float)fbo_width / (float)fbo_height; - // entity->camera.aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; + if(type < 0 || type >= ET_MAX) + { + log_error("entity:read", "Invalid entity type"); + return NULL; + } - // entity->camera.fbo = -1; - // entity->camera.render_tex = -1; - // entity->camera.depth_tex = -1; + struct Entity* new_entity = NULL; + switch(type) + { + case ET_CAMERA: + { + bool has_fbo = false; + bool fbo_has_depth_tex = false; + 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); + 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"); + if(hashmap_value_exists(object->data, "nearz")) camera->nearz = hashmap_float_get(object->data, "nearz"); + if(hashmap_value_exists(object->data, "farz")) camera->farz = hashmap_float_get(object->data, "farz"); + if(hashmap_value_exists(object->data, "ortho")) 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")) + { + vec4 color = hashmap_vec4_get(object->data, "clear_color"); + vec4_assign(&camera->clear_color, &color); + } - // if(has_fbo) - // { - // camera_attach_fbo(entity, fbo_width, fbo_height, fbo_has_depth_tex, fbo_has_render_tex, entity->camera.resizeable); - // } + float aspect_ratio = (float)fbo_width / (float)fbo_height; + camera->aspect_ratio = aspect_ratio <= 0.f ? (4.f / 3.f) : aspect_ratio; - // camera_update_proj(entity); - // camera_update_view(entity); + camera->fbo = -1; + camera->render_tex = -1; + camera->depth_tex = -1; - //} - //break; - //case ET_LIGHT: - //{ - // 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: - //{ - // struct Sound_Source* sound_source = &entity->sound_source; - // sound_source->type = ST_WAV; - // sound_source->playing = false; - // sound_source->loop = false; - // sound_source->source_instance = 0; - // sound_source->min_distance = 1.f; - // sound_source->max_distance = 1000.f; - // sound_source->volume = 1.f; - // sound_source->rolloff_factor = 1.f; - // sound_source->attenuation_type = SA_EXPONENTIAL; - // sound_source->source_buffer = NULL; - // sound_source->source_filename = NULL; - - // if(hashmap_value_exists(object->data, "playing")) sound_source->playing = hashmap_bool_get(object->data, "playing"); - // if(hashmap_value_exists(object->data, "loop")) sound_source->loop = hashmap_bool_get(object->data, "loop"); - // if(hashmap_value_exists(object->data, "sound_min_distance")) sound_source->min_distance = hashmap_float_get(object->data, "sound_min_distance"); - // if(hashmap_value_exists(object->data, "sound_max_distance")) sound_source->max_distance = hashmap_float_get(object->data, "sound_max_distance"); - // if(hashmap_value_exists(object->data, "volume")) sound_source->volume = hashmap_float_get(object->data, "volume"); - // if(hashmap_value_exists(object->data, "rolloff_factor")) sound_source->rolloff_factor = hashmap_float_get(object->data, "rolloff_factor"); - // if(hashmap_value_exists(object->data, "source_filename")) sound_source->source_filename = str_new(hashmap_str_get(object->data, "source_filename")); - // if(hashmap_value_exists(object->data, "sound_type")) sound_source->type = hashmap_int_get(object->data, "sound_type"); - // if(hashmap_value_exists(object->data, "sound_attenuation_type")) sound_source->attenuation_type = hashmap_int_get(object->data, "sound_attenuation_type"); - // if(sound_source->source_filename) - // { - // sound_source->source_buffer = platform->sound.source_create(sound_source->source_filename, sound_source->type); - // if(sound_source->source_buffer) - // { - // sound_source->source_instance = platform->sound.source_instance_create(sound_source->source_buffer, true); - - // vec3 abs_pos = {0.f, 0.f, 0.f}; - // vec3 abs_fwd = {0.f, 0.f, -1.f}; - // vec3 abs_up = {0.f, 1.f, 0.f}; - // transform_get_absolute_position(entity, &abs_pos); - // transform_get_absolute_forward(entity, &abs_fwd); - // transform_get_absolute_up(entity, &abs_up); - // platform->sound.source_instance_update_position(entity->sound_source.source_instance, abs_pos.x, abs_pos.y, abs_pos.z); - - // platform->sound.source_instance_loop_set(sound_source->source_instance, sound_source->loop); - // platform->sound.source_instance_min_max_distance_set(sound_source->source_instance, sound_source->min_distance, sound_source->max_distance); - // platform->sound.source_instance_attenuation_set(sound_source->source_instance, sound_source->attenuation_type, sound_source->rolloff_factor); - // platform->sound.source_instance_volume_set(sound_source->source_instance, sound_source->volume); - - // platform->sound.update_3d(); - // if(sound_source->playing) platform->sound.source_instance_play(sound_source->source_instance); - // } - // else - // { - // log_error("Failed to create sound source from '%s'", sound_source->source_filename); - // free(sound_source->source_filename); - // sound_source->source_filename = NULL; - // } - // } - // else - // { - // log_error("entity:read", "No filename provided for sound source for entity '%s'", entity->name); - // } - //} - //break; - //case ET_PLAYER: - //{ + if(has_fbo) + { + camera_attach_fbo(camera, fbo_width, fbo_height, fbo_has_depth_tex, fbo_has_render_tex, camera->resizeable); + } - //} - //break; - //case ET_STATIC_MODEL: - //{ - // 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; - //case ET_ROOT: - //{ - // scene_root_set(entity); - //} - //break; - //default: - // log_warning("Unhandled Entity type '%d' detected", entity->type); - // break; - //} + camera_update_proj(camera); + camera_update_view(camera); + new_entity = &camera->base; + } + break; + case ET_LIGHT: + { + struct Light* light = scene_light_create(scene, name, NULL, LT_POINT); + if(hashmap_value_exists(object->data, "light_type")) light->type = hashmap_int_get(object->data, "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"); + if(hashmap_value_exists(object->data, "falloff")) light->falloff = hashmap_float_get(object->data, "falloff"); + if(hashmap_value_exists(object->data, "intensity")) light->intensity = hashmap_float_get(object->data, "intensity"); + if(hashmap_value_exists(object->data, "depth_bias")) light->depth_bias = hashmap_float_get(object->data, "depth_bias"); + if(hashmap_value_exists(object->data, "color")) light->color = hashmap_vec3_get(object->data, "color"); + if(hashmap_value_exists(object->data, "cast_shadow")) light->cast_shadow = hashmap_bool_get(object->data, "cast_shadow"); + if(hashmap_value_exists(object->data, "pcf_enabled")) light->pcf_enabled = hashmap_bool_get(object->data, "pcf_enabled"); + if(hashmap_value_exists(object->data, "radius")) light->radius = hashmap_int_get(object->data, "radius"); + new_entity = &light->base; + } + break; + case ET_SOUND_SOURCE: + { + struct Sound_Source* sound_source = scene_sound_source_create(scene, name, NULL, "default.wav", ST_WAV, true, true); + sound_source->type = ST_WAV; + sound_source->playing = false; + sound_source->loop = false; + sound_source->source_instance = 0; + sound_source->min_distance = 1.f; + sound_source->max_distance = 1000.f; + sound_source->volume = 1.f; + sound_source->rolloff_factor = 1.f; + sound_source->attenuation_type = SA_EXPONENTIAL; + sound_source->source_buffer = NULL; + + if(hashmap_value_exists(object->data, "playing")) sound_source->playing = hashmap_bool_get(object->data, "playing"); + if(hashmap_value_exists(object->data, "loop")) sound_source->loop = hashmap_bool_get(object->data, "loop"); + if(hashmap_value_exists(object->data, "sound_min_distance")) sound_source->min_distance = hashmap_float_get(object->data, "sound_min_distance"); + if(hashmap_value_exists(object->data, "sound_max_distance")) sound_source->max_distance = hashmap_float_get(object->data, "sound_max_distance"); + if(hashmap_value_exists(object->data, "volume")) sound_source->volume = hashmap_float_get(object->data, "volume"); + if(hashmap_value_exists(object->data, "rolloff_factor")) sound_source->rolloff_factor = hashmap_float_get(object->data, "rolloff_factor"); + if(hashmap_value_exists(object->data, "sound_type")) sound_source->type = hashmap_int_get(object->data, "sound_type"); + if(hashmap_value_exists(object->data, "sound_attenuation_type")) sound_source->attenuation_type = hashmap_int_get(object->data, "sound_attenuation_type"); + if(hashmap_value_exists(object->data, "source_filename")) + { + struct Sound* sound = game_state_get()->sound; + sound_source->source_buffer = sound_source_create(sound, hashmap_str_get(object->data, "source_filename"), sound_source->type); + if(sound_source->source_buffer) + { + sound_source->source_instance = sound_source_instance_create(sound, sound_source->source_buffer, true); + + vec3 abs_pos = {0.f, 0.f, 0.f}; + transform_get_absolute_position(sound_source, &abs_pos); + sound_source_instance_update_position(sound, sound_source->source_instance, abs_pos); + + sound_source_instance_loop_set(sound, sound_source->source_instance, sound_source->loop); + sound_source_instance_min_max_distance_set(sound, sound_source->source_instance, sound_source->min_distance, sound_source->max_distance); + sound_source_instance_attenuation_set(sound, sound_source->source_instance, sound_source->attenuation_type, sound_source->rolloff_factor); + sound_source_instance_volume_set(sound, sound_source->source_instance, sound_source->volume); + + sound_update_3d(sound); + if(sound_source->playing) + sound_source_instance_play(sound, sound_source->source_instance); + } + else + { + log_error("Failed to create sound source from '%s'", hashmap_str_get(object->data, "source_filename")); + } + } + else + { + log_error("entity:read", "No filename provided for sound source for entity '%s'", name); + } + new_entity = &sound_source->base; + } + break; + case ET_PLAYER: + { - //if(entity->is_listener) - //{ - // vec3 abs_pos = {0.f, 0.f, 0.f}; - // vec3 abs_fwd = {0.f, 0.f, -1.f}; - // vec3 abs_up = {0.f, 1.f, 0.f}; - // transform_get_absolute_position(entity, &abs_pos); - // transform_get_absolute_forward(entity, &abs_fwd); - // transform_get_absolute_up(entity, &abs_up); - - // platform->sound.listener_update(abs_pos.x, abs_pos.y, abs_pos.z, - // abs_fwd.x, abs_fwd.y, abs_fwd.z, - // abs_up.x, abs_up.y, abs_up.z); - //} + } + break; + case ET_STATIC_MESH: + { + const char* geometry_name = NULL; + 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); + new_entity = &mesh->base; + } + break; + case ET_ROOT: + { + //scene_root_set(entity); + } + break; + default: + log_warning("Unhandled Entity type '%d' detected", type); + break; + } - //return entity; + return new_entity; } bool entity_load(const char* filename, int directory_type) diff --git a/src/game/player.c b/src/game/player.c index 31d5cec..423a2d7 100755 --- a/src/game/player.c +++ b/src/game/player.c @@ -9,16 +9,18 @@ #include "../common/log.h" #include "entity.h" #include "../system/config_vars.h" +#include "../system/platform.h" #include "game.h" void player_init(struct Player* player, struct Scene* scene) { + struct Game_State* game_state = game_state_get(); entity_init(player, "Player", &scene->root_entity); player->base.active = true; player->base.id = 1; player->base.type = ET_PLAYER; - struct Hashmap* config = game_state_get()->cvars; + struct Hashmap* config = game_state->cvars; player->move_speed = hashmap_int_get(config, "player_move_speed"); player->move_speed_multiplier = hashmap_int_get(config, "player_move_speed_multiplier"); player->turn_speed = hashmap_int_get(config, "player_turn_speed"); @@ -44,6 +46,8 @@ void player_init(struct Player* player, struct Scene* scene) vec3 cam_axis = {-1.f, 0.f, 0.f}; transform_rotate(player_camera, &cam_axis, 85.f, TS_LOCAL); + + sound_listener_set(game_state->sound, player); } void player_destroy(struct Player* player) diff --git a/src/system/sound.c b/src/system/sound.c index 8e041a6..8367bb9 100755 --- a/src/system/sound.c +++ b/src/system/sound.c @@ -63,6 +63,11 @@ void sound_listener_update(struct Sound* sound) up.x, up.y, up.z); // Up } +void sound_listener_set(struct Sound* sound, struct Entity* listener) +{ + sound->listener = listener; +} + void sound_master_volume_set(struct Sound* sound, float volume) { if(volume < 0.f) volume = 0.f; diff --git a/src/system/sound.h b/src/system/sound.h index 4e3336a..a02515d 100755 --- a/src/system/sound.h +++ b/src/system/sound.h @@ -48,6 +48,7 @@ struct Sound bool sound_init(struct Sound* sound); void sound_cleanup(struct Sound* sound); void sound_master_volume_set(struct Sound* sound, float volume); +void sound_listener_set(struct Sound* sound, struct Entity* listener); void sound_update_3d(struct Sound* sound); void sound_listener_update(struct Sound* sound); diff --git a/todo.txt b/todo.txt index 85eb0b0..a3c6a8b 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,5 @@ Todo: - - Entity to file read/write + - Finish mesh and material properties serialization to and from file - Console command to read/write entity to file and add it to scene - Editor functionality to add entity from specific file to scene - Scene read/write to file with scene file only containing names of @@ -302,4 +302,5 @@ Done: * Fix releasing ALT in translate tool not reverting back to previous axis * Disabled editor functionalites when console is toggled + * Entity to file read/write