Implemented editor functionality to read/write scene to/from files

dev
Shariq Shah 6 years ago
parent 4849f7d3e4
commit 16beb89250
  1. 455
      assets/test_scene.symtres
  2. 8
      src/game/console.c
  3. 134
      src/game/editor.c
  4. 4
      src/game/editor.h
  5. 2
      src/game/game.c
  6. 8
      src/game/scene.c
  7. 2
      todo.txt

@ -1,455 +0,0 @@
Entity
{
type : 2
scale : 1.000 1.000 1.000
rotation : 0.000 0.000 0.000 1.000
is_listener : false
position : 0.000 0.000 0.000
parent : NONE
name : ROOT
renderable : false
}
Entity
{
type : 3
scale : 1.000 1.000 1.000
fov : 60.0000
rotation : 0.000 0.000 0.000 1.000
zoom : 1.0000
fbo_has_render_tex : true
resizeable : true
nearz : 0.1000
is_listener : false
position : 10.000 5.000 100.000
farz : 1000.0000
fbo_height : 720
parent : ROOT
ortho : false
fbo_width : 1280
fbo_has_depth_tex : true
name : player
renderable : false
has_fbo : true
clear_color : 0.300 0.600 0.900 1.000
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : sphere.symbres
is_listener : false
position : 0.000 50.000 0.000
parent : ROOT
name : Model_Entity
renderable : true
}
Entity
{
type : 5
scale : 400.000 2.000 400.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 0.000 0.000 0.000
parent : ROOT
name : Ground
renderable : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.500 0.500 0.167
radius : 20.0000
is_listener : false
position : 40.000 0.000 120.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.111 0.333 0.250
radius : 20.0000
is_listener : false
position : 180.000 0.000 80.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.200 0.111 0.125
radius : 20.0000
is_listener : false
position : 100.000 0.000 160.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.500 0.167 0.100
radius : 20.0000
is_listener : false
position : 40.000 0.000 200.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 1.000 1.000 0.111
radius : 20.0000
is_listener : false
position : 20.000 0.000 180.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.167 0.125 1.000
radius : 20.0000
is_listener : false
position : 120.000 0.000 20.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 1.000 1.000 0.333
radius : 20.0000
is_listener : false
position : 20.000 0.000 60.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.143 0.167 0.200
radius : 20.0000
is_listener : false
position : 140.000 0.000 100.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.167 0.333 0.167
radius : 20.0000
is_listener : false
position : 120.000 0.000 120.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 4
scale : 1.000 1.000 1.000
inner_angle : 0.3491
falloff : 1.5000
light_type : 2
depth_bias : 0.0005
rotation : 0.000 0.000 0.000 1.000
cast_shadow : false
intensity : 1.0000
color : 0.125 0.250 0.100
radius : 20.0000
is_listener : false
position : 160.000 0.000 200.000
outer_angle : 0.5236
parent : ROOT
name : Light_Ent
pcf_enabled : false
renderable : false
valid : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 9.000 0.000 3.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : sphere.symbres
is_listener : false
position : 3.000 10.000 4.000
parent : ROOT
name : Sphere_Ent
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 9.000 0.000 5.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 9.000 0.000 6.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 10.000 0.000 1.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 9.000 0.000 8.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 4.000 0.000 4.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 6.000 0.000 1.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 10.000 0.000 5.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 5
scale : 1.000 1.000 1.000
material : Blinn_Phong
rotation : 0.000 0.000 0.000 1.000
geometry : default.pamesh
is_listener : false
position : 6.000 0.000 9.000
parent : Model_Entity
name : Suzanne
renderable : true
}
Entity
{
type : 6
scale : 1.000 1.000 1.000
volume : 0.5000
rolloff_factor : 0.9500
rotation : 0.000 0.000 0.000 1.000
loop : true
sound_min_distance : 1.0000
playing : true
is_listener : false
position : 0.000 0.000 0.000
source_filename : sounds/teh_beatz.wav
parent : Suzanne
sound_type : 0
sound_max_distance : 10.0000
name : Sound_Ent
sound_attenuation_type : 1
renderable : false
}

@ -301,9 +301,7 @@ void console_command_scene_save(struct Console* console, const char* command)
return; return;
} }
char full_filename[MAX_FILENAME_LEN]; if(!scene_save(game_state_get()->scene, filename, DIRT_INSTALL))
snprintf(full_filename, MAX_FILENAME_LEN, "scenes/%s.symtres", filename);
if(!scene_save(game_state_get()->scene, full_filename, DIRT_INSTALL))
log_error("scene_save", "Command failed"); log_error("scene_save", "Command failed");
} }
@ -320,9 +318,7 @@ void console_command_scene_load(struct Console* console, const char* command)
return; return;
} }
char full_filename[MAX_FILENAME_LEN]; if(!scene_load(game_state_get()->scene, filename, DIRT_INSTALL))
snprintf(full_filename, MAX_FILENAME_LEN, "scenes/%s.symtres", filename);
if(!scene_load(game_state_get()->scene, full_filename, DIRT_INSTALL))
log_error("scene_load", "Command failed"); log_error("scene_load", "Command failed");
} }

@ -94,6 +94,8 @@ static void editor_axis_set(struct Editor* editor, int axis);
static void editor_entity_select(struct Editor* editor, struct Entity* entity); static void editor_entity_select(struct Editor* editor, struct Entity* entity);
static void editor_tool_set(struct Editor* editor, int mode); static void editor_tool_set(struct Editor* editor, int mode);
static void editor_tool_reset(struct Editor* editor); static void editor_tool_reset(struct Editor* editor);
static void editor_scene_dialog(struct Editor* editor, struct nk_context* context);
static void editor_entity_dialog(struct Editor* editor, struct nk_context* context);
void editor_init(struct Editor* editor) void editor_init(struct Editor* editor)
{ {
@ -101,6 +103,8 @@ void editor_init(struct Editor* editor)
editor->window_settings_editor = 0; editor->window_settings_editor = 0;
editor->window_property_inspector = 0; editor->window_property_inspector = 0;
editor->window_scene_heirarchy = 0; editor->window_scene_heirarchy = 0;
editor->window_scene_dialog = 0;
editor->window_entity_dialog = 0;
editor->camera_looking_around = 0; editor->camera_looking_around = 0;
editor->selected_entity = NULL; editor->selected_entity = NULL;
editor->hovered_entity = NULL; editor->hovered_entity = NULL;
@ -128,6 +132,8 @@ void editor_init(struct Editor* editor)
editor->picking_enabled = true; editor->picking_enabled = true;
editor->draw_cursor_entity = false; editor->draw_cursor_entity = false;
editor->tool_scale_started = false; editor->tool_scale_started = false;
editor->entity_operation_save = false;
editor->scene_operation_save = false;
vec4_fill(&editor->cursor_entity_color, 0.f, 1.f, 1.f, 0.7f); vec4_fill(&editor->cursor_entity_color, 0.f, 1.f, 1.f, 0.7f);
vec4_fill(&editor->hovered_entity_color, 0.53, 0.87, 0.28, 0.5f); vec4_fill(&editor->hovered_entity_color, 0.53, 0.87, 0.28, 0.5f);
@ -339,11 +345,41 @@ void editor_update(struct Editor* editor, float dt)
nk_layout_row_begin(context, NK_DYNAMIC, editor->top_panel_height - 5, 8); nk_layout_row_begin(context, NK_DYNAMIC, editor->top_panel_height - 5, 8);
nk_layout_row_push(context, 0.03f); nk_layout_row_push(context, 0.03f);
if(nk_menu_begin_label(context, "File", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE, nk_vec2(150, 100))) if(nk_menu_begin_label(context, "File", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE, nk_vec2(150, 150)))
{ {
nk_layout_row_dynamic(context, row_height, 1); nk_layout_row_dynamic(context, row_height, 1);
nk_menu_item_label(context, "Open", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE); if(nk_menu_item_label(context, "New Scene", NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_LEFT))
nk_menu_item_label(context, "Save", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE); {
struct Scene* scene = game_state->scene;
scene_destroy(scene);
scene_post_update(scene);
scene_init(scene);
}
if(nk_menu_item_label(context, "Load Scene", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE))
{
editor->window_scene_dialog = editor->window_scene_dialog == 0 ? 1 : 0;
editor->scene_operation_save = false;
}
if(nk_menu_item_label(context, "Save Scene", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE))
{
editor->window_scene_dialog = editor->window_scene_dialog == 0 ? 1 : 0;
editor->scene_operation_save = true;
}
if(nk_menu_item_label(context, "Load Entity", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE))
{
editor->window_entity_dialog = editor->window_entity_dialog == 0 ? 1 : 0;
editor->entity_operation_save = false;
}
if(nk_menu_item_label(context, "Save Entity", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE))
{
editor->window_entity_dialog = editor->window_entity_dialog == 0 ? 1 : 0;
editor->entity_operation_save = true;
}
if(nk_menu_item_label(context, "Back to Game", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE)) if(nk_menu_item_label(context, "Back to Game", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE))
{ {
game_state->game_mode = GAME_MODE_GAME; game_state->game_mode = GAME_MODE_GAME;
@ -368,6 +404,8 @@ void editor_update(struct Editor* editor, float dt)
int debug_vars_visible = debug_vars->visible; int debug_vars_visible = debug_vars->visible;
nk_layout_row_dynamic(context, row_height, 1); nk_layout_row_dynamic(context, row_height, 1);
nk_checkbox_label(context, "Scene Heirarchy", &editor->window_scene_heirarchy); nk_checkbox_label(context, "Scene Heirarchy", &editor->window_scene_heirarchy);
nk_checkbox_label(context, "Property Inspector", &editor->window_property_inspector); nk_checkbox_label(context, "Property Inspector", &editor->window_property_inspector);
nk_checkbox_label(context, "Debug Variables", &debug_vars_visible); nk_checkbox_label(context, "Debug Variables", &debug_vars_visible);
if(debug_vars_visible != (int)debug_vars->visible) if(debug_vars_visible != (int)debug_vars->visible)
@ -675,6 +713,92 @@ void editor_update(struct Editor* editor, float dt)
} }
} }
if(editor->window_scene_dialog) editor_scene_dialog(editor, context);
}
void editor_scene_dialog(struct Editor* editor, struct nk_context* context)
{
struct Game_State* game_state = game_state_get();
struct Scene* scene = game_state->scene;
bool save = editor->scene_operation_save;
int row_height = 25;
int popup_x = 0;
int popup_y = 0;
int popup_width = 200;
int popup_height = 200;
int display_width = 0;
int display_height = 0;
int popup_flags = NK_WINDOW_TITLE | NK_WINDOW_BORDER;
window_get_drawable_size(game_state_get()->window, &display_width, &display_height);
popup_x = (display_width / 2) - (popup_width / 2);
popup_y = (display_height / 2) - (popup_height / 2);
int background_window_flags = NK_WINDOW_BACKGROUND;
int previous_opacity = context->style.window.fixed_background.data.color.a;
context->style.window.fixed_background.data.color.a = 120;
if(nk_begin(context, save ? "Scene Save" : "Scene Load", nk_recti(0, 0, display_width, display_height), background_window_flags))
{
nk_window_set_focus(context, save ? "Scene Save" : "Scene Load");
if(nk_popup_begin(context, NK_POPUP_DYNAMIC, save ? "Save Scene" : "Load Scene", popup_flags, nk_recti(popup_x, popup_y, popup_width, popup_height)))
{
nk_layout_row_dynamic(context, row_height, 1);
nk_label(context, "Enter the name of the scene:", NK_TEXT_ALIGN_CENTERED | NK_TEXT_ALIGN_MIDDLE);
static char scene_filename[MAX_FILENAME_LEN];
static bool copy_scene_filename = true;
if(copy_scene_filename)
{
memset(scene_filename, '\0', MAX_FILENAME_LEN);
}
int scene_filename_flags = NK_EDIT_SIG_ENTER | NK_EDIT_GOTO_END_ON_ACTIVATE | NK_EDIT_FIELD;
int scene_filename_state = nk_edit_string_zero_terminated(context, scene_filename_flags, scene_filename, MAX_FILENAME_LEN, NULL);
if(scene_filename_state & NK_EDIT_ACTIVATED)
{
copy_scene_filename = false;
}
else if(scene_filename_state & NK_EDIT_COMMITED)
{
if(save)
scene_save(scene, scene_filename, DIRT_INSTALL);
else
scene_load(scene, scene_filename, DIRT_INSTALL);
copy_scene_filename = true;
editor->window_scene_dialog = 0;
nk_popup_close(context);
}
nk_layout_row_dynamic(context, row_height, 3);
if(nk_button_label(context, "OK"))
{
if(save)
scene_save(scene, scene_filename, DIRT_INSTALL);
else
scene_load(scene, scene_filename, DIRT_INSTALL);
copy_scene_filename = true;
editor->window_scene_dialog = 0;
nk_popup_close(context);
}
nk_spacing(context, 1);
if(nk_button_label(context, "Cancel"))
{
copy_scene_filename = true;
editor->window_scene_dialog = 0;
nk_popup_close(context);
}
nk_popup_end(context);
}
nk_end(context);
}
else
{
editor->window_scene_dialog = 0;
}
context->style.window.fixed_background.data.color.a = previous_opacity;
} }
void editor_on_mousebutton_release(const struct Event* event) void editor_on_mousebutton_release(const struct Event* event)
@ -2044,3 +2168,7 @@ void editor_window_settings_editor(struct nk_context* context, struct Editor* ed
nk_end(context); nk_end(context);
} }
void editor_entity_dialog(struct Editor* editor, struct nk_context* context)
{
}

@ -15,6 +15,8 @@ struct Editor
int window_settings_editor; int window_settings_editor;
int window_scene_heirarchy; int window_scene_heirarchy;
int window_property_inspector; int window_property_inspector;
int window_scene_dialog;
int window_entity_dialog;
int camera_looking_around; int camera_looking_around;
struct Entity* selected_entity; struct Entity* selected_entity;
struct Static_Mesh* cursor_entity; struct Static_Mesh* cursor_entity;
@ -52,6 +54,8 @@ struct Editor
vec4 axis_color_y; vec4 axis_color_y;
vec4 axis_color_z; vec4 axis_color_z;
bool picking_enabled; bool picking_enabled;
bool scene_operation_save;
bool entity_operation_save;
}; };
void editor_init(struct Editor* editor_state); void editor_init(struct Editor* editor_state);

@ -118,7 +118,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); scene_load(game_state->scene, "default", DIRT_INSTALL);
game_state->is_initialized = true; game_state->is_initialized = true;
return game_state->is_initialized; return game_state->is_initialized;
} }

@ -78,7 +78,9 @@ void scene_init(struct Scene* scene)
bool scene_load(struct Scene* scene, const char* filename, int directory_type) bool scene_load(struct Scene* scene, const char* filename, int directory_type)
{ {
FILE* scene_file = io_file_open(directory_type, filename, "rb"); char prefixed_filename[MAX_FILENAME_LEN + 16];
snprintf(prefixed_filename, MAX_FILENAME_LEN + 16, "scenes/%s.symtres", filename);
FILE* scene_file = io_file_open(directory_type, prefixed_filename, "rb");
if(!scene_file) if(!scene_file)
{ {
log_error("scene:load", "Failed to open scene file %s for reading"); log_error("scene:load", "Failed to open scene file %s for reading");
@ -197,7 +199,9 @@ bool scene_load(struct Scene* scene, const char* filename, int directory_type)
bool scene_save(struct Scene* scene, const char* filename, int directory_type) bool scene_save(struct Scene* scene, const char* filename, int directory_type)
{ {
FILE* scene_file = io_file_open(directory_type, filename, "w"); char prefixed_filename[MAX_FILENAME_LEN + 16];
snprintf(prefixed_filename, MAX_FILENAME_LEN + 16, "scenes/%s.symtres", filename);
FILE* scene_file = io_file_open(directory_type, prefixed_filename, "w");
if(!scene_file) if(!scene_file)
{ {
log_error("scene:save", "Failed to open scene file %s for writing"); log_error("scene:save", "Failed to open scene file %s for writing");

@ -12,7 +12,6 @@ Todo:
- Multisampled buffers to bring back aa - Multisampled buffers to bring back aa
- Implement behaviour that avoids writing normal entities that do not have children or parent to file to avoid inconsistencies when loading them - Implement behaviour that avoids writing normal entities that do not have children or parent to file to avoid inconsistencies when loading them
- Change mouse behaviour to lock cursor when looking around so as not to interfere with gui elements when in editor mode - Change mouse behaviour to lock cursor when looking around so as not to interfere with gui elements when in editor mode
- Editor functionality to read/write scene to/from file
- Folder management api to create/delete folders when none exist. Dirent would suffice for our simple needs? - Folder management api to create/delete folders when none exist. Dirent would suffice for our simple needs?
- Display default mesh when selected entity type in editor does not have a mesh - Display default mesh when selected entity type in editor does not have a mesh
- Allow picking and selecting other entity types in editor i.e. the ones that don't have meshes - Allow picking and selecting other entity types in editor i.e. the ones that don't have meshes
@ -371,3 +370,4 @@ Done:
* Added button to reset local transformations for selected entity in property inspector * Added button to reset local transformations for selected entity in property inspector
* Implmented renaming scene objects in editor * Implmented renaming scene objects in editor
* Implemented setting/resetting parent entity for entity * Implemented setting/resetting parent entity for entity
* Editor functionality to read/write scene to/from file
Loading…
Cancel
Save