Fixed several bugs and implementing loading saving entity archetypes when loading and saving scenes

dev
Shariq Shah 6 years ago
parent 239d44ac6e
commit 4f3632bb3e
  1. 7
      assets/entities/Suzanne.symtres
  2. 14
      assets/entities/default.symtres
  3. 2
      src/common/array.h
  4. 13
      src/game/console.c
  5. 27
      src/game/editor.c
  6. 7
      src/game/entity.c
  7. 1
      src/game/framebuffer.c
  8. 13
      src/game/game.c
  9. 11
      src/game/player.c
  10. 7
      src/game/renderer.c
  11. 36
      src/game/scene.c
  12. 1
      src/game/scene.h
  13. 10
      todo.txt

@ -2,8 +2,13 @@ Entity
{ {
type : 6 type : 6
material : 0 material : 0
diffuse_color : 1.000 0.000 1.000 1.000
geometry : suzanne.symbres geometry : suzanne.symbres
specular : 1.0000
active : true active : true
name : Suzanne_0 diffuse_texture : white.tga
diffuse : 0.5000
specular_strength : 1.0000
name : Suzanne_Saved
} }

@ -0,0 +1,14 @@
Entity
{
type : 6
material : 0
diffuse_color : 1.000 0.000 1.000 1.000
geometry : suzanne.symbres
specular : 1.0000
active : true
diffuse_texture : default.tga
diffuse : 1.0000
specular_strength : 1.0000
name : Suzanne_Default
}

@ -20,7 +20,7 @@ int array_copy_(void* arr_src, void** arr_dest);
#define array_grow(array, type) (type*) array_grow_((void**)&array) #define array_grow(array, type) (type*) array_grow_((void**)&array)
#define array_push(array, value, type) {type* new_val = array_grow(array, type); \ #define array_push(array, value, type) {type* new_val = array_grow(array, type); \
*new_val = value;} *new_val = value;}
#define array_get_last(array, type) (type*) (&array[array_len(array)]) #define array_get_last(array, type) (type*) (&array[array_len(array) - 1])
#define array_set_last(array, val, type) {type* last = array_get_last(array, type); \ #define array_set_last(array, val, type) {type* last = array_get_last(array, type); \
*last = val} *last = val}
#define array_pop(array) array_pop_((void**)&array) #define array_pop(array) array_pop_((void**)&array)

@ -15,6 +15,7 @@ static struct nk_color console_message_color[CMT_MAX];
static int console_filter(const struct nk_text_edit *box, nk_rune unicode); static int console_filter(const struct nk_text_edit *box, nk_rune unicode);
static void console_command_scene_empty(struct Console* console, const char* command);
static void console_command_scene_save(struct Console* console, const char* command); static void console_command_scene_save(struct Console* console, const char* command);
static void console_command_scene_load(struct Console* console, const char* command); static void console_command_scene_load(struct Console* console, const char* command);
static void console_command_entity_save(struct Console* console, const char* command); static void console_command_entity_save(struct Console* console, const char* command);
@ -45,6 +46,7 @@ void console_init(struct Console* console)
} }
console->console_commands = hashmap_new(); console->console_commands = hashmap_new();
hashmap_ptr_set(console->console_commands, "scene_empty", &console_command_scene_empty);
hashmap_ptr_set(console->console_commands, "scene_save", &console_command_scene_save); hashmap_ptr_set(console->console_commands, "scene_save", &console_command_scene_save);
hashmap_ptr_set(console->console_commands, "scene_load", &console_command_scene_load); hashmap_ptr_set(console->console_commands, "scene_load", &console_command_scene_load);
hashmap_ptr_set(console->console_commands, "entity_save", &console_command_entity_save); hashmap_ptr_set(console->console_commands, "entity_save", &console_command_entity_save);
@ -266,3 +268,14 @@ void console_command_scene_load(struct Console* console, const char* command)
if(!scene_load(game_state_get()->scene, full_filename, DIRT_INSTALL)) if(!scene_load(game_state_get()->scene, full_filename, DIRT_INSTALL))
log_error("scene_load", "Command failed"); log_error("scene_load", "Command failed");
} }
void console_command_scene_empty(struct Console* console, const char* command)
{
char filename[MAX_FILENAME_LEN];
memset(filename, '\0', MAX_FILENAME_LEN);
struct Scene* scene = game_state_get()->scene;
scene_destroy(scene);
scene_post_update(scene);
scene_init(scene);
}

@ -174,9 +174,12 @@ void editor_init_camera(struct Editor* editor, struct Hashmap* cvars)
editor_camera->clear_color.z = 0.9f; editor_camera->clear_color.z = 0.9f;
editor_camera->clear_color.w = 1.f; editor_camera->clear_color.w = 1.f;
int render_width = hashmap_int_get(cvars, "render_width"); if(editor_camera->fbo == -1)
int render_height = hashmap_int_get(cvars, "render_height"); {
camera_attach_fbo(editor_camera, render_width, render_height, true, true, true); int render_width = hashmap_int_get(cvars, "render_width");
int render_height = hashmap_int_get(cvars, "render_height");
camera_attach_fbo(editor_camera, render_width, render_height, true, true, true);
}
vec3 cam_pos = {5.f, 20.f, 50.f}; vec3 cam_pos = {5.f, 20.f, 50.f};
transform_translate(editor_camera, &cam_pos, TS_WORLD); transform_translate(editor_camera, &cam_pos, TS_WORLD);
@ -1328,10 +1331,10 @@ void editor_camera_update(struct Editor* editor, float dt)
{ {
struct Game_State* game_state = game_state_get(); struct Game_State* game_state = game_state_get();
struct Gui* gui = game_state->gui; struct Gui* gui = game_state->gui;
if(game_state->console->visible) if(game_state->console->visible || nk_item_is_any_active(&gui->context))
return; return;
struct Camera* editor_camera = &game_state_get()->scene->cameras[CAM_EDITOR]; struct Camera* editor_camera = &game_state->scene->cameras[CAM_EDITOR];
static float total_up_down_rot = 0.f; static float total_up_down_rot = 0.f;
float move_speed = editor->camera_move_speed, turn_speed = editor->camera_turn_speed; float move_speed = editor->camera_move_speed, turn_speed = editor->camera_turn_speed;
float turn_up_down = 0.f; float turn_up_down = 0.f;
@ -1347,7 +1350,7 @@ void editor_camera_update(struct Editor* editor, float dt)
if(input_map_state_get("Turn_Right", KS_PRESSED)) turn_left_right += turn_speed; if(input_map_state_get("Turn_Right", KS_PRESSED)) turn_left_right += turn_speed;
if(input_map_state_get("Turn_Left", KS_PRESSED)) turn_left_right -= turn_speed; if(input_map_state_get("Turn_Left", KS_PRESSED)) turn_left_right -= turn_speed;
if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED) && !nk_item_is_any_active(&game_state_get()->gui->context)) if(input_mousebutton_state_get(MSB_RIGHT, KS_PRESSED) && !nk_item_is_any_active(&gui->context))
{ {
const float scale = 0.5f; const float scale = 0.5f;
int cursor_lr, cursor_ud; int cursor_lr, cursor_ud;
@ -1488,10 +1491,16 @@ void editor_widget_color_combov4(struct nk_context* context, vec4* color, int wi
void editor_cleanup(struct Editor* editor) void editor_cleanup(struct Editor* editor)
{ {
event_manager_unsubscribe(game_state_get()->event_manager, EVT_MOUSEBUTTON_PRESSED, &editor_on_mousebutton_press); struct Event_Manager* event_manager = game_state_get()->event_manager;
event_manager_unsubscribe(game_state_get()->event_manager, EVT_MOUSEBUTTON_RELEASED, &editor_on_mousebutton_release); event_manager_unsubscribe(event_manager, EVT_MOUSEBUTTON_PRESSED, &editor_on_mousebutton_press);
event_manager_unsubscribe(event_manager, EVT_MOUSEBUTTON_RELEASED, &editor_on_mousebutton_release);
event_manager_unsubscribe(event_manager, EVT_MOUSEMOTION, &editor_on_mousemotion);
event_manager_unsubscribe(event_manager, EVT_KEY_PRESSED, &editor_on_key_press);
event_manager_unsubscribe(event_manager, EVT_KEY_RELEASED, &editor_on_key_release);
for(int i = 0; i < array_len(debug_vars_list); i++) for(int i = 0; i < array_len(debug_vars_list); i++)
editor_debugvar_slot_remove(i); editor_debugvar_slot_remove(i);
array_free(debug_vars_list); array_free(debug_vars_list);
array_free(empty_indices); array_free(empty_indices);
} }

@ -506,7 +506,14 @@ struct Entity* entity_load(const char* filename, int directory_type)
if(new_entity) if(new_entity)
{ {
if(i == 0) if(i == 0)
{
new_entity->archetype_index = scene_entity_archetype_add(game_state_get()->scene, filename);
parent_entity = new_entity; parent_entity = new_entity;
}
// We don't want this entity to be saved when we're saving the scene because
// this entity and its parent will be loaded from this same file next time the scene is loaded
if(i != 0)
new_entity->flags |= EF_TRANSIENT;
num_entites_loaded++; num_entites_loaded++;
log_message("Entity %s loaded from %s", new_entity->name, filename); log_message("Entity %s loaded from %s", new_entity->name, filename);
} }

@ -95,6 +95,7 @@ int framebuffer_create(int width, int height, bool has_depth, bool has_color, bo
{ {
index = *array_get_last(empty_indices, int); index = *array_get_last(empty_indices, int);
array_pop(empty_indices); array_pop(empty_indices);
framebuffer = &fbo_list[index];
} }
framebuffer->handle = fbo; framebuffer->handle = fbo;

@ -102,10 +102,10 @@ bool game_init(struct Window* window, struct Hashmap* cvars)
gui_init(game_state->gui); gui_init(game_state->gui);
console_init(game_state->console); console_init(game_state->console);
geom_init(); geom_init();
physics_init(); //physics_init();
physics_gravity_set(0.f, -9.8f, 0.f); //physics_gravity_set(0.f, -9.8f, 0.f);
physics_body_set_moved_callback(entity_rigidbody_on_move); //physics_body_set_moved_callback(entity_rigidbody_on_move);
physics_body_set_collision_callback(entity_rigidbody_on_collision); //physics_body_set_collision_callback(entity_rigidbody_on_collision);
sound_init(game_state->sound); sound_init(game_state->sound);
renderer_init(game_state->renderer); renderer_init(game_state->renderer);
@ -115,6 +115,7 @@ bool game_init(struct Window* window, struct Hashmap* cvars)
/* Debug scene setup */ /* Debug scene setup */
//game_scene_setup(); //game_scene_setup();
scene_load(game_state->scene, "scenes/default.symtres", DIRT_INSTALL);
game_state->is_initialized = true; game_state->is_initialized = true;
return game_state->is_initialized; return game_state->is_initialized;
} }
@ -557,7 +558,7 @@ void game_update(float dt, bool* window_should_close)
scene_update(game_state->scene, dt); scene_update(game_state->scene, dt);
if(game_state->game_mode == GAME_MODE_GAME) if(game_state->game_mode == GAME_MODE_GAME)
{ {
physics_step(dt); //physics_step(dt);
} }
else if(game_state->game_mode == GAME_MODE_EDITOR) else if(game_state->game_mode == GAME_MODE_EDITOR)
{ {
@ -1912,7 +1913,7 @@ void game_cleanup(void)
texture_cleanup(); texture_cleanup();
shader_cleanup(); shader_cleanup();
sound_cleanup(game_state->sound); sound_cleanup(game_state->sound);
physics_cleanup(); //physics_cleanup();
event_manager_cleanup(game_state->event_manager); event_manager_cleanup(game_state->event_manager);
free(game_state->editor); free(game_state->editor);

@ -40,9 +40,13 @@ void player_init(struct Player* player, struct Scene* scene)
player->camera_node->base.flags |= EF_TRANSIENT; player->camera_node->base.flags |= EF_TRANSIENT;
player->mesh->base.flags |= EF_TRANSIENT; player->mesh->base.flags |= EF_TRANSIENT;
int render_width = hashmap_int_get(config, "render_width"); if(player_camera->fbo == -1)
int render_height = hashmap_int_get(config, "render_height"); {
camera_attach_fbo(player_camera, render_width, render_height, true, true, true); int render_width = hashmap_int_get(config, "render_width");
int render_height = hashmap_int_get(config, "render_height");
camera_attach_fbo(player_camera, render_width, render_height, true, true, true);
}
transform_parent_set(player_camera, player, true); transform_parent_set(player_camera, player, true);
vec3 cam_translation = {0.f, 20.f, 2.f}; vec3 cam_translation = {0.f, 20.f, 2.f};
@ -58,6 +62,7 @@ void player_init(struct Player* player, struct Scene* scene)
void player_destroy(struct Player* player) void player_destroy(struct Player* player)
{ {
entity_reset(player, player->base.id); entity_reset(player, player->base.id);
scene_entity_base_remove(game_state_get()->scene, &player->base);
player->base.flags = EF_NONE; player->base.flags = EF_NONE;
} }

@ -459,8 +459,11 @@ void renderer_on_framebuffer_size_changed(const struct Event* event)
for(int i = 0; i < MAX_CAMERAS; i++) for(int i = 0; i < MAX_CAMERAS; i++)
{ {
struct Camera* viewer = &scene->cameras[i]; struct Camera* viewer = &scene->cameras[i];
viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f; if(viewer->resizeable)
camera_update_proj(viewer); {
viewer->aspect_ratio = aspect > 0.f ? aspect : 4.f / 3.f;
camera_update_proj(viewer);
}
} }
framebuffer_resize_all(width, height); framebuffer_resize_all(width, height);

@ -279,7 +279,6 @@ void scene_write_entity_list(struct Scene* scene, int entity_type, struct Parser
while(count < max_length) while(count < max_length)
{ {
//((char*)entity) += stride * count; //((char*)entity) += stride * count;
((char*)entity) += stride;
if(!(entity->flags & EF_TRANSIENT) && (entity->flags & EF_ACTIVE)) if(!(entity->flags & EF_TRANSIENT) && (entity->flags & EF_ACTIVE))
{ {
@ -295,6 +294,7 @@ void scene_write_entity_list(struct Scene* scene, int entity_type, struct Parser
} }
} }
count++; count++;
((char*)entity) += stride;
} }
} }
@ -634,6 +634,7 @@ void scene_light_remove(struct Scene* scene, struct Light* light)
void scene_camera_remove(struct Scene* scene, struct Camera* camera) void scene_camera_remove(struct Scene* scene, struct Camera* camera)
{ {
assert(scene && camera); assert(scene && camera);
camera_reset(camera);
scene_entity_base_remove(scene, &camera->base); scene_entity_base_remove(scene, &camera->base);
} }
@ -926,3 +927,36 @@ bool scene_save_(const char* filename, int directory_type)
return success; return success;
} }
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++)
{
if(strncmp(filename, &scene->entity_archetypes[i][0], MAX_FILENAME_LEN) == 0)
{
index = i;
break;
}
}
if(index == -1)
{
for(int i = 0; i < MAX_ENTITY_ARCHETYPES; i++)
{
if(scene->entity_archetypes[i][0] == '\0')
{
strncpy(&scene->entity_archetypes[i][0], filename, MAX_FILENAME_LEN);
index = i;
break;
}
}
}
if(index == -1)
log_warning("Out of archetype indices!");
return index;
}

@ -56,6 +56,7 @@ struct Entity* scene_base_entity_get(struct Scene* scene, int id, int type
void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent); void scene_entity_parent_set(struct Scene* scene, struct Entity* entity, struct Entity* parent);
void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity); // Sets root entity as parent void scene_entity_parent_reset(struct Scene* scene, struct Entity* entity); // Sets root entity as parent
int scene_entity_archetype_add(struct Scene* scene, const char* filename);
void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Result* out_results); void scene_ray_intersect(struct Scene* scene, struct Ray* ray, struct Raycast_Result* out_results);

@ -1,5 +1,7 @@
Todo: Todo:
- Save default entity archetype to be loaded when there is not other archetype or in case of an error as fallback - Fix cameras not resizing to current resolution when scene is loaded/reloaded
- Allow renaming scene objects in editor
- Add parameter to entity_load command that renames the newly loaded object to whatever the second specified parameter is
- Bring back debug variable display in editor and allow showing colours, textures etc - Bring back debug variable display in editor and allow showing colours, textures etc
- Implment/Test reading/writing scene that has a mixture of default entites and entity archetypes - Implment/Test reading/writing scene that has a mixture of default entites and entity archetypes
- Serialize player, camera properties to file - Serialize player, camera properties to file
@ -18,6 +20,7 @@ Todo:
- Better, more accurate picking - Better, more accurate picking
- Editor related messages/notifications in the bottom status bar - Editor related messages/notifications in the bottom status bar
? Disable entity picking when tool is in use or only allow picking when pressing ALT ? Disable entity picking when tool is in use or only allow picking when pressing ALT
? Maybe remove physics engine and ode all together if we're not using it or investigate the memory leaks that it causes if we're going to keep it?
- Disable editor event recievers on game mode change - Disable editor event recievers on game mode change
- Editor Undo - Editor Undo
- Duplicate with Ctrl-D - Duplicate with Ctrl-D
@ -123,6 +126,7 @@ Bugs:
- Fix shader preprocessor failing when the file in //include directive is empty - Fix shader preprocessor failing when the file in //include directive is empty
- Fix bug with blinn shader reaching maximum uniform number on mac - Fix bug with blinn shader reaching maximum uniform number on mac
- Fix delete in editor not working when the cursor is hovering over scene heirarchy window - Fix delete in editor not working when the cursor is hovering over scene heirarchy window
- Investigate memory leaks caused by nuklear or opengl related operations in gui_update
Done: Done:
* Input * Input
@ -337,4 +341,6 @@ Done:
* Implemented flags that specify whether an entity should be written to file or not for example to avoid writing cameras and player to file * Implemented flags that specify whether an entity should be written to file or not for example to avoid writing cameras and player to file
* In editor, only show entities with specific flags * In editor, only show entities with specific flags
* Fixed bugs with meshes being registered to uninitialized materials and not rendering * Fixed bugs with meshes being registered to uninitialized materials and not rendering
* Added EF_SKIP_RENDER flag to allow entites to skip rendering * Added EF_SKIP_RENDER flag to allow entites to skip rendering
* Save default entity archetype to be loaded when there is not other archetype or in case of an error as fallback
* Ensure cameras are not initialized multiple times
Loading…
Cancel
Save