diff --git a/src/game/editor.c b/src/game/editor.c index 9e43dd3..2ad2825 100755 --- a/src/game/editor.c +++ b/src/game/editor.c @@ -47,6 +47,11 @@ struct Debug_Variable static struct Debug_Variable* debug_vars_list = NULL; static int* empty_indices = NULL; +static int window_flags = NK_WINDOW_BORDER | + NK_WINDOW_CLOSABLE | + NK_WINDOW_MOVABLE | + NK_WINDOW_SCROLL_AUTO_HIDE | + NK_WINDOW_SCALABLE; static void editor_on_mousebutton(const struct Event* event); static void editor_camera_update(struct Editor* editor, float dt); @@ -64,15 +69,22 @@ static bool editor_widget_v3(struct nk_context* context, float inc_per_pixel, int row_height); +static void editor_window_scene_heirarchy(struct nk_context* context, struct Editor* editor, struct Game_State* game_state); +static void editor_window_debug_variables(struct nk_context* context, struct Editor* editor); +static void editor_window_property_inspector(struct nk_context* context, struct Editor* editor, struct Game_State* game_state); + void editor_init(struct Editor* editor) { - editor->renderer_settings_window = false; - editor->camera_looking_around = false; - editor->selected_entity = NULL; - editor->top_panel_height = 30; - editor->camera_turn_speed = 50.f; - editor->camera_move_speed = 20.f; - editor->camera_sprint_multiplier = 2.f; + editor->renderer_settings_window = 0; + editor->window_debug_variables = 0; + editor->window_property_inspector = 0; + editor->window_scene_heirarchy = 0; + editor->camera_looking_around = 0; + editor->selected_entity = NULL; + editor->top_panel_height = 30; + editor->camera_turn_speed = 50.f; + editor->camera_move_speed = 20.f; + editor->camera_sprint_multiplier = 2.f; vec4_fill(&editor->selected_entity_colour, 0.f, 1.f, 0.f, 1.f); debug_vars_list = array_new(struct Debug_Variable); empty_indices = array_new(int); @@ -204,13 +216,8 @@ void editor_update(struct Editor* editor, float dt) int win_width = 0, win_height = 0; window_get_drawable_size(game_state->window, &win_width, &win_height); int half_width = win_width / 2, half_height = win_height / 2; - static int window_flags = NK_WINDOW_BORDER | - NK_WINDOW_CLOSABLE | - NK_WINDOW_MOVABLE | - NK_WINDOW_SCROLL_AUTO_HIDE | - NK_WINDOW_SCALABLE; - + /* Top Panel */ if(nk_begin(context, "Top Panel", nk_recti(0, 0, win_width, editor->top_panel_height), NK_WINDOW_NO_SCROLLBAR)) { @@ -227,260 +234,55 @@ void editor_update(struct Editor* editor, float dt) frames = 0; } - nk_layout_row(context, NK_DYNAMIC, editor->top_panel_height - 10, sizeof(top_panel_ratios) / sizeof(float), top_panel_ratios); - if(nk_button_label(context, "Render Settings")) - editor->renderer_settings_window = !editor->renderer_settings_window; - if(nk_button_label(context, "Save config")) - config_vars_save("config.symtres", DIRT_USER); - nk_spacing(context, 1); - nk_labelf(context, NK_TEXT_ALIGN_RIGHT | NK_TEXT_ALIGN_MIDDLE, "FPS : %.d", fps); - nk_layout_row_dynamic(context, editor->top_panel_height, 1); - } - nk_end(context); - + nk_menubar_begin(context); - /* Left */ - if(nk_begin(context, "Editor Left", nk_recti(0, editor->top_panel_height, 300, 700), window_flags)) - { - /* Entities List */ - struct Scene* scene = game_state_get()->scene; - if(nk_tree_push(context, NK_TREE_TAB, "Entities", NK_MAXIMIZED)) + nk_layout_row_begin(context, NK_DYNAMIC, editor->top_panel_height, 5); + nk_layout_row_push(context, 0.1f); + if(nk_menu_begin_label(context, "File", NK_TEXT_CENTERED | NK_TEXT_ALIGN_MIDDLE, nk_vec2(150, 100))) { - nk_layout_row_dynamic(context, 250, 1); - if(nk_group_begin(context, "Entity Name", NK_WINDOW_SCROLL_AUTO_HIDE)) + nk_layout_row_dynamic(context, 25, 1); + nk_menu_item_label(context, "Open", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE); + nk_menu_item_label(context, "Save", 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)) { - - for(int i = 0; i < MAX_ENTITIES; i++) editor_show_entity_in_list(editor, context, scene, &scene->entities[i]); - for(int i = 0; i < MAX_CAMERAS; i++) editor_show_entity_in_list(editor, context, scene, &scene->cameras[i]); - for(int i = 0; i < MAX_LIGHTS; i++) editor_show_entity_in_list(editor, context, scene, &scene->lights[i]); - for(int i = 0; i < MAX_STATIC_MESHES; i++) editor_show_entity_in_list(editor, context, scene, &scene->static_meshes[i]); - - nk_group_end(context); + game_state->game_mode = GAME_MODE_GAME; + game_state->scene->active_camera_index = CAM_GAME; } - nk_tree_pop(context); + nk_menu_end(context); } - /* Debug Variables */ - if(nk_tree_push(context, NK_TREE_TAB, "Debug Variables", NK_MAXIMIZED)) + nk_layout_row_push(context, 0.1f); + if(nk_menu_begin_label(context, "Settings", NK_TEXT_CENTERED | NK_TEXT_ALIGN_MIDDLE, nk_vec2(150, 100))) { - static char variant_str[MAX_VARIANT_STR_LEN] = { '\0' }; - nk_layout_row_dynamic(context, 250, 1); - if(nk_group_begin(context, "Name", NK_WINDOW_SCROLL_AUTO_HIDE)) - { - for(int i = 0; i < array_len(debug_vars_list); i++) - { - struct Debug_Variable* debug_var = &debug_vars_list[i]; - if(debug_var->data.type == VT_NONE) continue; - nk_layout_row_dynamic(context, 20, 2); - nk_label(context, debug_var->name, NK_TEXT_ALIGN_LEFT); - variant_to_str(&debug_var->data, variant_str, MAX_VARIANT_STR_LEN); - nk_label(context, variant_str, NK_TEXT_ALIGN_RIGHT); - memset(variant_str, '\0', MAX_VARIANT_STR_LEN); - } - nk_group_end(context); - } - nk_tree_pop(context); + nk_layout_row_dynamic(context, 25, 1); + if(nk_menu_item_label(context, "Render Settings", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE)) editor->renderer_settings_window = !editor->renderer_settings_window; + nk_menu_end(context); } - } - nk_end(context); - /* Right */ - if(nk_begin(context, "Editor Right", nk_recti(win_width - 300, editor->top_panel_height, 400, 700), window_flags)) - { - /* Entity Inspector */ - if(nk_tree_push(context, NK_TREE_TAB, "Inspector", NK_MAXIMIZED)) + nk_layout_row_push(context, 0.1f); + if(nk_menu_begin_label(context, "Windows", NK_TEXT_CENTERED | NK_TEXT_ALIGN_MIDDLE, nk_vec2(180, 100))) { - const int row_height = 18; - if(editor->selected_entity) - { - struct Scene* scene = game_state_get()->scene; - struct Entity* entity = editor->selected_entity; - - struct Entity* parent_ent = entity->transform.parent; - nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "Name", NK_TEXT_ALIGN_LEFT); nk_label(context, entity->name, NK_TEXT_ALIGN_RIGHT); - nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "ID", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%d", entity->id); - nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "Selected", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%s", entity->editor_selected ? "True" : "False"); - nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "Entity Type", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%s", entity_type_name_get(entity)); - nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "Parent Name", NK_TEXT_ALIGN_LEFT); nk_label(context, parent_ent ? parent_ent->name : "NONE", NK_TEXT_ALIGN_RIGHT); - - /* Transform */ - { - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Position", NK_TEXT_ALIGN_CENTERED); - vec3 abs_pos = { 0.f, 0.f, 0.f }; - transform_get_absolute_position(entity, &abs_pos); - if(editor_widget_v3(context, &abs_pos, "#X", "#Y", "#Z", -FLT_MAX, FLT_MAX, 5.f, 1.f, row_height)) transform_set_position(entity, &abs_pos); - - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Rotation", NK_TEXT_ALIGN_CENTERED); - quat abs_rot = { 0.f, 0.f, 0.f, 1.f }; - transform_get_absolute_rot(entity, &abs_rot); - vec3 rot_angles = { 0.f, 0.f, 0.f }; - rot_angles.x = TO_DEGREES(quat_get_pitch(&abs_rot)); - rot_angles.y = TO_DEGREES(quat_get_yaw(&abs_rot)); - rot_angles.z = TO_DEGREES(quat_get_roll(&abs_rot)); - vec3 curr_rot = { rot_angles.x, rot_angles.y, rot_angles.z }; - - nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "#X", -FLT_MAX, &curr_rot.x, FLT_MAX, 5.f, 1.f); - nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "#Y", -FLT_MAX, &curr_rot.y, FLT_MAX, 5.f, 1.f); - nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "#Z", -FLT_MAX, &curr_rot.z, FLT_MAX, 5.f, 1.f); - - vec3 delta = { 0.f, 0.f, 0.f }; - vec3_sub(&delta, &rot_angles, &curr_rot); - - vec3 AXIS_X = { 1.f, 0.f, 0.f }; - vec3 AXIS_Y = { 0.f, 1.f, 0.f }; - vec3 AXIS_Z = { 0.f, 0.f, 1.f }; - - const float epsilon = 0.0001f; - if(fabsf(delta.x) > epsilon) transform_rotate(entity, &AXIS_X, delta.x, TS_WORLD); - if(fabsf(delta.y) > epsilon) transform_rotate(entity, &AXIS_Y, delta.y, TS_WORLD); - if(fabsf(delta.z) > epsilon) transform_rotate(entity, &AXIS_Z, delta.z, TS_WORLD); - - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Scale", NK_TEXT_ALIGN_CENTERED); - vec3 abs_scale = { 0.f, 0.f, 0.f }; - transform_get_absolute_scale(entity, &abs_scale); - if(editor_widget_v3(context, &abs_scale, "#X", "#Y", "#Z", 0.1f, FLT_MAX, 1.f, 0.1f, row_height)) - { - entity->transform.scale = abs_scale; - transform_update_transmat(entity); - } - } - - /* Light */ - if(entity->type == ET_LIGHT) - { - if(nk_tree_push(context, NK_TREE_TAB, "Light", NK_MAXIMIZED)) - { - struct Light* light = (struct Light*)entity; - if(light->type > LT_POINT) - { - nk_layout_row_dynamic(context, row_height, 1); - nk_label(context, "Invalid light type!", NK_TEXT_ALIGN_CENTERED); - } - else - { - static const char* light_types[] = { "Spot", "Directional", "Point" }; - float combo_width = nk_widget_width(context), combo_height = row_height * (LT_MAX); - - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "Light Type", NK_TEXT_ALIGN_LEFT); - nk_combobox(context, light_types, LT_MAX - 1, &light->type, row_height, nk_vec2(combo_width, combo_height)); - - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Light Color", NK_TEXT_ALIGN_CENTERED); - nk_layout_row_dynamic(context, row_height, 1); - editor_widget_color_combov3(context, &light->color, 200, 300); - - nk_layout_row_dynamic(context, row_height, 1); - nk_property_float(context, "Intensity", 0.f, &light->intensity, 100.f, 0.1f, 0.05f); - - if(light->type != LT_DIR) - { - nk_layout_row_dynamic(context, row_height, 1); - light->outer_angle = TO_RADIANS(nk_propertyf(context, "Outer Angle", TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 360, 1.f, 0.5f)); - - nk_layout_row_dynamic(context, row_height, 1); - light->inner_angle = TO_RADIANS(nk_propertyf(context, "Inner Angle", 1.f, TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 1.f, 0.5f)); - - nk_layout_row_dynamic(context, row_height, 1); - nk_property_int(context, "Radius", 1, &light->radius, INT_MAX, 1, 1); - - nk_layout_row_dynamic(context, row_height, 1); - nk_property_float(context, "Falloff", 0.f, &light->falloff, 100.f, 0.1f, 0.05f); - } - } - nk_tree_pop(context); - } - } - - /* Camera */ - if(entity->type == ET_CAMERA) - { - if(nk_tree_push(context, NK_TREE_TAB, "Camera", NK_MAXIMIZED)) - { - bool update = false; - struct Camera* camera = (struct Camera*)entity; - - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "Orthographic", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE); - bool ortho = nk_checkbox_label(context, "", &camera->ortho); - if(ortho != camera->ortho) - { - update = true; - } - - - if(!camera->ortho) - { - nk_layout_row_dynamic(context, row_height, 1); - float new_fov = nk_propertyf(context, "Fov", 30.f, camera->fov, 90.f, 0.1f, 1.f); - if(new_fov != camera->fov) - { - camera->fov = new_fov; - update = true; - } - - nk_layout_row_dynamic(context, row_height, 2); - nk_label(context, "Aspect Ratio", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%.5f", camera->aspect_ratio); - } - - nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Clear Color", NK_TEXT_ALIGN_CENTERED); - nk_layout_row_dynamic(context, row_height, 1); - editor_widget_color_combov4(context, &camera->clear_color, 200, 300); - - nk_layout_row_dynamic(context, row_height, 1); - float new_zoom = nk_propertyf(context, "Zoom", 1.f, camera->zoom, FLT_MAX, 0.1f, 1.f); - if(new_zoom != camera->zoom) - { - camera->zoom = new_zoom; - update = true; - } - - nk_layout_row_dynamic(context, row_height, 1); - float new_near_z = nk_propertyf(context, "NearZ", -FLT_MAX, camera->nearz, camera->farz, 0.1f, 1.f); - if(new_near_z != camera->nearz) - { - camera->nearz = new_near_z; - update = true; - } + nk_layout_row_dynamic(context, 25, 1); + nk_checkbox_label(context, "Scene Heirarchy", &editor->window_scene_heirarchy); + nk_checkbox_label(context, "Property Inspector", &editor->window_property_inspector); + nk_checkbox_label(context, "Debug Variables", &editor->window_debug_variables); + nk_menu_end(context); + } - nk_layout_row_dynamic(context, row_height, 1); - float new_far_z = nk_propertyf(context, "FarZ", camera->nearz, camera->farz, FLT_MAX, 0.1f, 2.f); - if(new_far_z != camera->farz) - { - camera->farz = new_far_z; - update = true; - } + nk_layout_row_push(context, 0.6f); + nk_spacing(context, 1); - if(update) - { - camera_update_view(entity); - camera_update_proj(entity); - } - nk_tree_pop(context); - } - } - } - else - { - nk_label(context, "No Entity Selected", NK_TEXT_ALIGN_CENTERED); - } - nk_tree_pop(context); - } + nk_layout_row_push(context, 0.1f); + nk_labelf(context, NK_TEXT_ALIGN_RIGHT | NK_TEXT_ALIGN_MIDDLE, "FPS : %.d", fps); + + nk_menubar_end(context); } nk_end(context); - - // if(nk_begin(context, "Editor", nk_recti(0, 0, win_width, win_height), NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BACKGROUND)) - // { - // context->style.window.fixed_background = default_background; - - // - // /* Empty Space in the center */ - // nk_spacing(context, 1); - // - // } - // nk_end(context); - // context->style.window.padding = default_padding; + if(editor->window_scene_heirarchy) editor_window_scene_heirarchy(context, editor, game_state); + if(editor->window_debug_variables) editor_window_debug_variables(context, editor); + if(editor->window_property_inspector) editor_window_property_inspector(context, editor, game_state); /* Render Settings Window */ if(editor->renderer_settings_window) @@ -821,6 +623,246 @@ void editor_show_entity_in_list(struct Editor* editor, struct nk_context* contex if(entity->editor_selected) { editor->selected_entity = entity; + if(!editor->window_property_inspector) editor->window_property_inspector = true; + } + } +} + +void editor_window_scene_heirarchy(struct nk_context* context, struct Editor* editor, struct Game_State* game_state) +{ + if(nk_begin(context, "Scene Heirarchy", nk_recti(0, editor->top_panel_height, 300, 400), window_flags)) + { + struct Scene* scene = game_state_get()->scene; + nk_layout_row_dynamic(context, 350, 1); + if(nk_group_begin(context, "Entity Name", NK_WINDOW_SCROLL_AUTO_HIDE)) + { + + for(int i = 0; i < MAX_ENTITIES; i++) editor_show_entity_in_list(editor, context, scene, &scene->entities[i]); + for(int i = 0; i < MAX_CAMERAS; i++) editor_show_entity_in_list(editor, context, scene, &scene->cameras[i]); + for(int i = 0; i < MAX_LIGHTS; i++) editor_show_entity_in_list(editor, context, scene, &scene->lights[i]); + for(int i = 0; i < MAX_STATIC_MESHES; i++) editor_show_entity_in_list(editor, context, scene, &scene->static_meshes[i]); + + nk_group_end(context); } } + else + { + editor->window_scene_heirarchy = false; + } + nk_end(context); +} + +void editor_window_debug_variables(struct nk_context* context, struct Editor* editor) +{ + if(nk_begin(context, "Debug Variables", nk_recti(0, 500, 300, 400), window_flags)) + { + static char variant_str[MAX_VARIANT_STR_LEN] = { '\0' }; + nk_layout_row_dynamic(context, 250, 1); + if(nk_group_begin(context, "Name", NK_WINDOW_SCROLL_AUTO_HIDE)) + { + for(int i = 0; i < array_len(debug_vars_list); i++) + { + struct Debug_Variable* debug_var = &debug_vars_list[i]; + if(debug_var->data.type == VT_NONE) continue; + nk_layout_row_dynamic(context, 20, 2); + nk_label(context, debug_var->name, NK_TEXT_ALIGN_LEFT); + variant_to_str(&debug_var->data, variant_str, MAX_VARIANT_STR_LEN); + nk_label(context, variant_str, NK_TEXT_ALIGN_RIGHT); + memset(variant_str, '\0', MAX_VARIANT_STR_LEN); + } + nk_group_end(context); + } + } + else + { + editor->window_debug_variables = false; + } + nk_end(context); +} + +void editor_window_property_inspector(struct nk_context* context, struct Editor* editor, struct Game_State* game_state) +{ + int win_width = 0, win_height = 0; + window_get_drawable_size(game_state->window, &win_width, &win_height); + if(nk_begin(context, "Properties", nk_recti(win_width - 300, editor->top_panel_height, 300, 600), window_flags)) + { + const int row_height = 18; + if(editor->selected_entity) + { + struct Scene* scene = game_state_get()->scene; + struct Entity* entity = editor->selected_entity; + + struct Entity* parent_ent = entity->transform.parent; + nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "Name", NK_TEXT_ALIGN_LEFT); nk_label(context, entity->name, NK_TEXT_ALIGN_RIGHT); + nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "ID", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%d", entity->id); + nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "Selected", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%s", entity->editor_selected ? "True" : "False"); + nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "Entity Type", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%s", entity_type_name_get(entity)); + nk_layout_row_dynamic(context, row_height, 2); nk_label(context, "Parent Name", NK_TEXT_ALIGN_LEFT); nk_label(context, parent_ent ? parent_ent->name : "NONE", NK_TEXT_ALIGN_RIGHT); + + /* Transform */ + { + nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Position", NK_TEXT_ALIGN_CENTERED); + vec3 abs_pos = { 0.f, 0.f, 0.f }; + transform_get_absolute_position(entity, &abs_pos); + if(editor_widget_v3(context, &abs_pos, "#X", "#Y", "#Z", -FLT_MAX, FLT_MAX, 5.f, 1.f, row_height)) transform_set_position(entity, &abs_pos); + + nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Rotation", NK_TEXT_ALIGN_CENTERED); + quat abs_rot = { 0.f, 0.f, 0.f, 1.f }; + transform_get_absolute_rot(entity, &abs_rot); + vec3 rot_angles = { 0.f, 0.f, 0.f }; + rot_angles.x = TO_DEGREES(quat_get_pitch(&abs_rot)); + rot_angles.y = TO_DEGREES(quat_get_yaw(&abs_rot)); + rot_angles.z = TO_DEGREES(quat_get_roll(&abs_rot)); + vec3 curr_rot = { rot_angles.x, rot_angles.y, rot_angles.z }; + + nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "#X", -FLT_MAX, &curr_rot.x, FLT_MAX, 5.f, 1.f); + nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "#Y", -FLT_MAX, &curr_rot.y, FLT_MAX, 5.f, 1.f); + nk_layout_row_dynamic(context, row_height, 1); nk_property_float(context, "#Z", -FLT_MAX, &curr_rot.z, FLT_MAX, 5.f, 1.f); + + vec3 delta = { 0.f, 0.f, 0.f }; + vec3_sub(&delta, &rot_angles, &curr_rot); + + vec3 AXIS_X = { 1.f, 0.f, 0.f }; + vec3 AXIS_Y = { 0.f, 1.f, 0.f }; + vec3 AXIS_Z = { 0.f, 0.f, 1.f }; + + const float epsilon = 0.0001f; + if(fabsf(delta.x) > epsilon) transform_rotate(entity, &AXIS_X, delta.x, TS_WORLD); + if(fabsf(delta.y) > epsilon) transform_rotate(entity, &AXIS_Y, delta.y, TS_WORLD); + if(fabsf(delta.z) > epsilon) transform_rotate(entity, &AXIS_Z, delta.z, TS_WORLD); + + nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Scale", NK_TEXT_ALIGN_CENTERED); + vec3 abs_scale = { 0.f, 0.f, 0.f }; + transform_get_absolute_scale(entity, &abs_scale); + if(editor_widget_v3(context, &abs_scale, "#X", "#Y", "#Z", 0.1f, FLT_MAX, 1.f, 0.1f, row_height)) + { + entity->transform.scale = abs_scale; + transform_update_transmat(entity); + } + } + + /* Light */ + if(entity->type == ET_LIGHT) + { + if(nk_tree_push(context, NK_TREE_TAB, "Light", NK_MAXIMIZED)) + { + struct Light* light = (struct Light*)entity; + if(light->type > LT_POINT) + { + nk_layout_row_dynamic(context, row_height, 1); + nk_label(context, "Invalid light type!", NK_TEXT_ALIGN_CENTERED); + } + else + { + static const char* light_types[] = { "Spot", "Directional", "Point" }; + float combo_width = nk_widget_width(context), combo_height = row_height * (LT_MAX); + + nk_layout_row_dynamic(context, row_height, 2); + nk_label(context, "Light Type", NK_TEXT_ALIGN_LEFT); + nk_combobox(context, light_types, LT_MAX - 1, &light->type, row_height, nk_vec2(combo_width, combo_height)); + + nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Light Color", NK_TEXT_ALIGN_CENTERED); + nk_layout_row_dynamic(context, row_height, 1); + editor_widget_color_combov3(context, &light->color, 200, 300); + + nk_layout_row_dynamic(context, row_height, 1); + nk_property_float(context, "Intensity", 0.f, &light->intensity, 100.f, 0.1f, 0.05f); + + if(light->type != LT_DIR) + { + nk_layout_row_dynamic(context, row_height, 1); + light->outer_angle = TO_RADIANS(nk_propertyf(context, "Outer Angle", TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 360, 1.f, 0.5f)); + + nk_layout_row_dynamic(context, row_height, 1); + light->inner_angle = TO_RADIANS(nk_propertyf(context, "Inner Angle", 1.f, TO_DEGREES(light->inner_angle), TO_DEGREES(light->outer_angle), 1.f, 0.5f)); + + nk_layout_row_dynamic(context, row_height, 1); + nk_property_int(context, "Radius", 1, &light->radius, INT_MAX, 1, 1); + + nk_layout_row_dynamic(context, row_height, 1); + nk_property_float(context, "Falloff", 0.f, &light->falloff, 100.f, 0.1f, 0.05f); + } + } + nk_tree_pop(context); + } + } + + /* Camera */ + if(entity->type == ET_CAMERA) + { + if(nk_tree_push(context, NK_TREE_TAB, "Camera", NK_MAXIMIZED)) + { + bool update = false; + struct Camera* camera = (struct Camera*)entity; + + nk_layout_row_dynamic(context, row_height, 2); + nk_label(context, "Orthographic", NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_MIDDLE); + bool ortho = nk_checkbox_label(context, "", &camera->ortho); + if(ortho != camera->ortho) + { + update = true; + } + + + if(!camera->ortho) + { + nk_layout_row_dynamic(context, row_height, 1); + float new_fov = nk_propertyf(context, "Fov", 30.f, camera->fov, 90.f, 0.1f, 1.f); + if(new_fov != camera->fov) + { + camera->fov = new_fov; + update = true; + } + + nk_layout_row_dynamic(context, row_height, 2); + nk_label(context, "Aspect Ratio", NK_TEXT_ALIGN_LEFT); nk_labelf(context, NK_TEXT_ALIGN_RIGHT, "%.5f", camera->aspect_ratio); + } + + nk_layout_row_dynamic(context, row_height, 1); nk_label(context, "Clear Color", NK_TEXT_ALIGN_CENTERED); + nk_layout_row_dynamic(context, row_height, 1); + editor_widget_color_combov4(context, &camera->clear_color, 200, 300); + + nk_layout_row_dynamic(context, row_height, 1); + float new_zoom = nk_propertyf(context, "Zoom", 1.f, camera->zoom, FLT_MAX, 0.1f, 1.f); + if(new_zoom != camera->zoom) + { + camera->zoom = new_zoom; + update = true; + } + + nk_layout_row_dynamic(context, row_height, 1); + float new_near_z = nk_propertyf(context, "NearZ", -FLT_MAX, camera->nearz, camera->farz, 0.1f, 1.f); + if(new_near_z != camera->nearz) + { + camera->nearz = new_near_z; + update = true; + } + + nk_layout_row_dynamic(context, row_height, 1); + float new_far_z = nk_propertyf(context, "FarZ", camera->nearz, camera->farz, FLT_MAX, 0.1f, 2.f); + if(new_far_z != camera->farz) + { + camera->farz = new_far_z; + update = true; + } + + if(update) + { + camera_update_view(entity); + camera_update_proj(entity); + } + nk_tree_pop(context); + } + } + } + else + { + nk_label(context, "No Entity Selected", NK_TEXT_ALIGN_CENTERED); + } + } + else + { + editor->window_property_inspector = false; + } + nk_end(context); } diff --git a/src/game/editor.h b/src/game/editor.h index d06388f..7ed77fa 100755 --- a/src/game/editor.h +++ b/src/game/editor.h @@ -9,8 +9,11 @@ struct Entity; struct Editor { - bool renderer_settings_window; - bool camera_looking_around; + int renderer_settings_window; + int window_scene_heirarchy; + int window_property_inspector; + int window_debug_variables; + int camera_looking_around; struct Entity* selected_entity; int top_panel_height; float camera_turn_speed; diff --git a/src/game/renderer.c b/src/game/renderer.c index bc9f99d..fd6e759 100755 --- a/src/game/renderer.c +++ b/src/game/renderer.c @@ -411,44 +411,46 @@ void renderer_draw(struct Renderer* renderer, struct Scene* scene) } //Editor related rendering - editor_render(game_state->editor, active_camera); - if(game_state->editor->selected_entity) + if(game_state->game_mode == GAME_MODE_EDITOR) { - if(game_state->editor->selected_entity->type == ET_STATIC_MESH) + editor_render(game_state->editor, active_camera); + if(game_state->editor->selected_entity) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - shader_bind(renderer->debug_shader); + if(game_state->editor->selected_entity->type == ET_STATIC_MESH) { - static mat4 mvp; - shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &game_state->editor->selected_entity_colour); - struct Static_Mesh* mesh = (struct Static_Mesh*)game_state->editor->selected_entity; - struct Model* model = &mesh->model; - struct Transform* transform = &mesh->base.transform; - int geometry = model->geometry_index; - mat4_identity(&mvp); - mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat); - shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp); - geom_render(geometry, GDM_TRIANGLES); - } - shader_unbind(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + shader_bind(renderer->debug_shader); + { + static mat4 mvp; + shader_set_uniform_vec4(renderer->debug_shader, "debug_color", &game_state->editor->selected_entity_colour); + struct Static_Mesh* mesh = (struct Static_Mesh*)game_state->editor->selected_entity; + struct Model* model = &mesh->model; + struct Transform* transform = &mesh->base.transform; + int geometry = model->geometry_index; + mat4_identity(&mvp); + mat4_mul(&mvp, &active_camera->view_proj_mat, &transform->trans_mat); + shader_set_uniform_mat4(renderer->debug_shader, "mvp", &mvp); + geom_render(geometry, GDM_TRIANGLES); + } + shader_unbind(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - else - { - //For now just draw a placeholder sphere just to visually denote that the entity is selected - vec3 abs_pos; - quat abs_rot; - transform_get_absolute_position(game_state->editor->selected_entity, &abs_pos); - transform_get_absolute_rot(game_state->editor->selected_entity, &abs_rot); - im_sphere(1.f, abs_pos, abs_rot, game_state->editor->selected_entity_colour, GDM_TRIANGLES); + } + else + { + //For now just draw a placeholder sphere just to visually denote that the entity is selected + vec3 abs_pos; + quat abs_rot; + transform_get_absolute_position(game_state->editor->selected_entity, &abs_pos); + transform_get_absolute_rot(game_state->editor->selected_entity, &abs_rot); + im_sphere(1.f, abs_pos, abs_rot, game_state->editor->selected_entity_colour, GDM_TRIANGLES); + } } } //Immediate mode geometry render im_render(active_camera); - /* Render 2D stuff */ shader_bind(renderer->sprite_batch->shader); { diff --git a/todo.txt b/todo.txt index ba22b7b..45b3b9c 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,5 @@ Todo: - - Implement proper topbar + - Change all usages of bool types and nuklear causing buggy behaviour in editor code - Specific rendering mode for editor related rendering - Basic Editor gizmo for transformation i.e. translate/rotate/scale in world and local coordinates - Add warning to genie build script when running on windows and WindowsSdkVersion cannot be found. This happens when the script is not run from vcvarsall command prompt @@ -207,4 +207,5 @@ Done: * Implemented showing a placeholder when an entity other than a static mesh is selected * Prevented ray casting when clicking on editor window and buttons * Implemented handling drawing other entity types that can be selected in the editor but are not static meshes + * Implemented proper topbar