From 9ea7ac3d7f778d7f7964533ca19730c6e99661cd Mon Sep 17 00:00:00 2001 From: Fabio Pellacini Date: Sat, 15 Aug 2020 22:21:40 +0200 Subject: [PATCH] Bugfix in gui dialog (#1013) --- apps/ysceneitrace/ysceneitrace.cpp | 12 +-- apps/ysceneitraces/ysceneitraces.cpp | 2 +- apps/ysceneview/ysceneview.cpp | 10 +-- libs/yocto/yocto_sceneio.cpp | 4 +- libs/yocto_gui/yocto_imgui.cpp | 120 ++++++++++++++------------- 5 files changed, 76 insertions(+), 72 deletions(-) diff --git a/apps/ysceneitrace/ysceneitrace.cpp b/apps/ysceneitrace/ysceneitrace.cpp index e5a64aab8..5e70fd9c8 100644 --- a/apps/ysceneitrace/ysceneitrace.cpp +++ b/apps/ysceneitrace/ysceneitrace.cpp @@ -46,9 +46,9 @@ void print_obj_camera(scene_camera* camera); // Application scene struct app_state { // loading options - string filename = "app->yaml"; + string filename = "scene.json"; string imagename = "out.png"; - string outname = "out.yaml"; + string outname = "out.json"; string name = ""; // scene @@ -268,7 +268,7 @@ void load_scene_async(app_states* apps, const string& filename, app->name = path{filename}.filename().string() + " [loading]"; app->filename = filename; app->imagename = path{filename}.replace_extension(".png").string(); - app->outname = path{filename}.replace_extension(".edited.yaml").string(); + app->outname = path{filename}.replace_extension(".edited.json").string(); app->params = apps->params; app->status = "load"; app->loader = std::async(std::launch::async, [app, camera_name, @@ -457,14 +457,14 @@ T1* get_element( void draw_widgets(gui_window* win, app_states* apps, const gui_input& input) { static string load_path = "", save_path = "", error_message = ""; if (draw_filedialog_button(win, "load", true, "load", load_path, false, "./", - "", "*.yaml;*.obj;*.pbrt")) { + "", "*.json;*.obj;*.pbrt")) { load_scene_async(apps, load_path); load_path = ""; } continue_line(win); if (draw_filedialog_button(win, "save", apps->selected && apps->selected->ok, "save", save_path, true, path{save_path}.parent_path().string(), - path{save_path}.filename().string(), "*.yaml;*.obj;*.pbrt")) { + path{save_path}.filename().string(), "*.json;*.obj;*.pbrt")) { auto app = apps->selected; app->outname = save_path; save_scene(app->outname, app->ioscene, app->error); @@ -598,7 +598,7 @@ void draw_widgets(gui_window* win, app_states* apps, const gui_input& input) { } end_header(win); } - if (!app->ioscene->instances.empty() && begin_header(win, "objects")) { + if (!app->ioscene->instances.empty() && begin_header(win, "instances")) { draw_combobox(win, "instance##2", app->selected_instance, app->ioscene->instances, true); if (draw_widgets(win, app->ioscene, app->selected_instance)) { diff --git a/apps/ysceneitraces/ysceneitraces.cpp b/apps/ysceneitraces/ysceneitraces.cpp index 03205e60d..c7b380da7 100644 --- a/apps/ysceneitraces/ysceneitraces.cpp +++ b/apps/ysceneitraces/ysceneitraces.cpp @@ -41,7 +41,7 @@ using namespace yocto; // Application state struct app_state { // loading options - string filename = "scene.yaml"; + string filename = "scene.json"; string imagename = "out.png"; string name = ""; diff --git a/apps/ysceneview/ysceneview.cpp b/apps/ysceneview/ysceneview.cpp index ddb9f8dd0..3dd1923ef 100644 --- a/apps/ysceneview/ysceneview.cpp +++ b/apps/ysceneview/ysceneview.cpp @@ -111,7 +111,7 @@ void load_scene_async( auto app = apps->states.emplace_back(new app_state{}); app->filename = filename; app->imagename = path{filename}.replace_extension(".png").string(); - app->outname = path{filename}.replace_extension(".edited.yaml").string(); + app->outname = path{filename}.replace_extension(".edited.json").string(); app->name = path{app->filename}.filename().string(); app->drawgl_prms = apps->drawgl_prms; app->status = "load"; @@ -417,14 +417,14 @@ T1* get_element( void draw_widgets(gui_window* win, app_states* apps, const gui_input& input) { static auto load_path = ""s, save_path = ""s, error_message = ""s; if (draw_filedialog_button(win, "load", true, "load", load_path, false, "./", - "", "*.yaml;*.obj;*.pbrt")) { + "", "*.json;*.obj;*.pbrt")) { load_scene_async(apps, load_path); load_path = ""; } continue_line(win); if (draw_filedialog_button(win, "save", apps->selected && apps->selected->ok, "save", save_path, true, path{save_path}.parent_path().string(), - path{save_path}.filename().string(), "*.yaml;*.obj;*.pbrt")) { + path{save_path}.filename().string(), "*.json;*.obj;*.pbrt")) { auto app = apps->selected; app->outname = save_path; save_scene(app->outname, app->ioscene, app->error); @@ -514,10 +514,10 @@ void draw_widgets(gui_window* win, app_states* apps, const gui_input& input) { } end_header(win); } - if (!app->ioscene->instances.empty() && begin_header(win, "objects")) { + if (!app->ioscene->instances.empty() && begin_header(win, "instances")) { draw_combobox( win, "instance##2", app->selected_instance, app->ioscene->instances); - if (!draw_widgets(win, app->ioscene, app->selected_instance)) { + if (draw_widgets(win, app->ioscene, app->selected_instance)) { auto ioobject = app->selected_instance; auto globject = get_element( ioobject, app->ioscene->instances, app->glscene->instances); diff --git a/libs/yocto/yocto_sceneio.cpp b/libs/yocto/yocto_sceneio.cpp index d2d6913ba..500e4ed59 100644 --- a/libs/yocto/yocto_sceneio.cpp +++ b/libs/yocto/yocto_sceneio.cpp @@ -440,7 +440,7 @@ static bool load_json_scene(const string& filename, scene_model* scene, } }; - // parse yaml reference + // parse json reference auto get_ref = [&material_error, &get_value](const json& ejs, const string& name, auto& value, const auto& refs) -> bool { @@ -808,7 +808,7 @@ static bool save_json_scene(const string& filename, const scene_model* scene, 0, 2 + (int)scene->shapes.size() + (int)scene->textures.size()}; if (progress_cb) progress_cb("save scene", progress.x++, progress.y); - // save yaml file + // save json file auto js = json::object(); // asset diff --git a/libs/yocto_gui/yocto_imgui.cpp b/libs/yocto_gui/yocto_imgui.cpp index ba5249b65..cca511d5f 100644 --- a/libs/yocto_gui/yocto_imgui.cpp +++ b/libs/yocto_gui/yocto_imgui.cpp @@ -430,25 +430,59 @@ struct filedialog_state { vector extensions = {}; filedialog_state() {} - filedialog_state(const string& dirname, const string& filename, bool save, - const string& filter) { + filedialog_state(const string& dirname, const string& filename, + const string& filter, bool save) { + set(dirname, filename, filter, save); + } + + void set(const string& dirname, const string& filename, const string& filter, + bool save) { this->save = save; - set_filter(filter); - set_dirname(dirname); - set_filename(filename); + _set_filter(filter); + _set_dirname(dirname); + _set_filename(filename); } - void set_dirname(const string& name) { - dirname = name; - dirname = normalize_path(dirname); - if (dirname == "") dirname = "./"; - if (dirname.back() != '/') dirname += '/'; - refresh(); + + void _set_dirname(const string& name) { + if (exists(path{name}) && is_directory(path{name})) { + dirname = name; + } else if (exists(path{dirname}) && is_directory(path{dirname})) { + // leave it like this + } else { + dirname = std::filesystem::current_path().string(); + } + dirname = canonical(path{dirname}).string(); + entries.clear(); + for (auto entry : directory_iterator(path{dirname})) { + if (remove_hidden && entry.path().stem().string()[0] == '.') continue; + if (entry.is_directory()) { + entries.push_back({entry.path().filename().string() + "/", true}); + } else { + entries.push_back({entry.path().filename().string(), false}); + } + } + std::sort(entries.begin(), entries.end(), [](auto& a, auto& b) { + if (a.second == b.second) return a.first < b.first; + return a.second; + }); } - void set_filename(const string& name) { + + void _set_filename(const string& name) { filename = name; - check_filename(); + if (filename.empty()) return; + auto ext = path{filename}.extension().string(); + if (std::find(extensions.begin(), extensions.end(), ext) == + extensions.end()) { + filename = ""; + return; + } + if (!save && !exists(path{dirname} / path{filename})) { + filename = ""; + return; + } } - void set_filter(const string& flt) { + + void _set_filter(const string& flt) { auto globs = vector{""}; for (auto i = 0; i < flt.size(); i++) { if (flt[i] == ';') { @@ -468,64 +502,32 @@ struct filedialog_state { } } } - void check_filename() { - if (filename.empty()) return; - auto ext = get_extension(filename); - if (std::find(extensions.begin(), extensions.end(), ext) == - extensions.end()) { - filename = ""; - return; - } - if (!save && !exists_file(dirname + filename)) { - filename = ""; - return; - } - } - void select_entry(int idx) { + + void select(int idx) { if (entries[idx].second) { - set_dirname(dirname + entries[idx].first); + set((path{dirname} / path{entries[idx].first}).string(), filename, filter, + save); } else { - set_filename(entries[idx].first); + set(dirname, entries[idx].first, filter, save); } } - void refresh() { - entries.clear(); - for (auto entry : directory_iterator(path{dirname})) { - if (remove_hidden && entry.path().stem().string()[0] == '.') continue; - if (entry.is_directory()) { - entries.push_back({entry.path().stem().string() + "/", true}); - } else { - entries.push_back({entry.path().stem().string(), false}); - } - } - std::sort(entries.begin(), entries.end(), [](auto& a, auto& b) { - if (a.second == b.second) return a.first < b.first; - return a.second; - }); - } - - string get_path() const { return dirname + filename; } - bool exists_file(const string& filename) { - auto f = fopen(filename.c_str(), "r"); - if (!f) return false; - fclose(f); - return true; - } + string get_path() const { return (path{dirname} / path{filename}).string(); } }; + bool draw_filedialog(gui_window* win, const char* lbl, string& path, bool save, const string& dirname, const string& filename, const string& filter) { static auto states = unordered_map{}; ImGui::SetNextWindowSize({500, 300}, ImGuiCond_FirstUseEver); if (ImGui::BeginPopupModal(lbl)) { if (states.find(lbl) == states.end()) { - states[lbl] = filedialog_state{dirname, filename, save, filter}; + states[lbl] = filedialog_state{dirname, filename, filter, save}; } auto& state = states.at(lbl); char dir_buffer[1024]; snprintf(dir_buffer, sizeof(dir_buffer), "%s", state.dirname.c_str()); if (ImGui::InputText("dir", dir_buffer, sizeof(dir_buffer))) { - state.set_dirname(dir_buffer); + state.set(dir_buffer, state.filename, state.filter, save); } auto current_item = -1; if (ImGui::ListBox( @@ -536,17 +538,17 @@ bool draw_filedialog(gui_window* win, const char* lbl, string& path, bool save, return true; }, &state, (int)state.entries.size())) { - state.select_entry(current_item); + state.select(current_item); } char file_buffer[1024]; snprintf(file_buffer, sizeof(file_buffer), "%s", state.filename.c_str()); if (ImGui::InputText("file", file_buffer, sizeof(file_buffer))) { - state.set_filename(file_buffer); + state.set(state.dirname, file_buffer, state.filter, save); } char filter_buffer[1024]; snprintf(filter_buffer, sizeof(filter_buffer), "%s", state.filter.c_str()); if (ImGui::InputText("filter", filter_buffer, sizeof(filter_buffer))) { - state.set_filter(filter_buffer); + state.set(state.dirname, state.filename, filter_buffer, save); } auto ok = false, exit = false; if (ImGui::Button("Ok")) { @@ -568,10 +570,12 @@ bool draw_filedialog(gui_window* win, const char* lbl, string& path, bool save, return false; } } + bool draw_filedialog_button(gui_window* win, const char* button_lbl, bool button_active, const char* lbl, string& path, bool save, const string& dirname, const string& filename, const string& filter) { if (is_glmodal_open(win, lbl)) { + draw_button(win, button_lbl, button_active); return draw_filedialog(win, lbl, path, save, dirname, filename, filter); } else { if (draw_button(win, button_lbl, button_active)) {