diff --git a/.gitmodules b/.gitmodules index 442ccb09..49262670 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,3 +18,6 @@ [submodule "deps/imgui/ImGuizmo"] path = deps/imgui/ImGuizmo url = https://github.com/nmwsharp/ImGuizmo.git +[submodule "deps/imgui/ImGuiFileDialog"] + path = deps/imgui/ImGuiFileDialog + url = https://github.com/aiekick/ImGuiFileDialog.git diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index b54ff63e..827051a1 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -22,6 +22,11 @@ if(NOT TARGET glm::glm) set_target_properties(glm PROPERTIES LINKER_LANGUAGE CXX) endif() +## IconFontCppHeaders +if(NOT TARGET IconFontCppHeaders) + add_subdirectory(IconFontCppHeaders) +endif() + ## Imgui if(NOT TARGET imgui) add_subdirectory(imgui) @@ -41,8 +46,3 @@ endif() if(NOT TARGET stb) add_subdirectory(stb) endif() - -## IconFontCppHeaders -if(NOT TARGET IconFontCppHeaders) - add_subdirectory(IconFontCppHeaders) -endif() diff --git a/deps/imgui/CMakeLists.txt b/deps/imgui/CMakeLists.txt index b4a8b365..51df9880 100644 --- a/deps/imgui/CMakeLists.txt +++ b/deps/imgui/CMakeLists.txt @@ -36,6 +36,11 @@ list(APPEND SRCS ImGuizmo/ImGuizmo.cpp ) +# ImGuiFileDialog sources +list(APPEND SRCS + ImGuiFileDialog/ImGuiFileDialog.cpp + ) + # Add per-backend sources if("${POLYSCOPE_BACKEND_OPENGL3_GLFW}") @@ -63,6 +68,10 @@ endif() add_library(imgui ${SRCS}) target_compile_features(imgui PUBLIC cxx_std_11) set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE TRUE) +target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/config") +target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/ImGuiFileDialog/") +target_link_libraries(imgui PUBLIC IconFontCppHeaders) +target_compile_definitions(imgui PUBLIC CUSTOM_IMGUIFILEDIALOG_CONFIG="polyscope_imgui_file_dialog_config.h") # Per-backend settings if("${POLYSCOPE_BACKEND_OPENGL3_GLFW}") diff --git a/deps/imgui/ImGuiFileDialog b/deps/imgui/ImGuiFileDialog new file mode 160000 index 00000000..ee77f190 --- /dev/null +++ b/deps/imgui/ImGuiFileDialog @@ -0,0 +1 @@ +Subproject commit ee77f190861193a995435c388682f1512f6fd29a diff --git a/deps/imgui/config/polyscope_imgui_file_dialog_config.h b/deps/imgui/config/polyscope_imgui_file_dialog_config.h new file mode 100644 index 00000000..dd34deb4 --- /dev/null +++ b/deps/imgui/config/polyscope_imgui_file_dialog_config.h @@ -0,0 +1,22 @@ +#pragma once + +#include "IconFontCppHeaders/IconsLucide.h" +#include "ImGuiFileDialogConfig.h" + +#define USE_PLACES_FEATURE +#define PLACES_PANE_DEFAULT_SHOWN false +#define USE_PLACES_BOOKMARKS +#define USE_PLACES_DEVICES + +#define dirEntryString ICON_LC_FOLDER " " +#define linkEntryString ICON_LC_FILE_SYMLINK " " +#define fileEntryString ICON_LC_FILE " " + +#define createDirButtonString ICON_LC_FOLDER_PLUS +#define resetButtonString ICON_LC_REFRESH_CW +#define editPathButtonString ICON_LC_PENCIL + +#define addPlaceButtonString ICON_LC_BOOKMARK_PLUS +#define removePlaceButtonString ICON_LC_BOOKMARK_MINUS +#define validatePlaceButtonString ICON_LC_CHECK +#define editPlaceButtonString ICON_LC_PENCIL diff --git a/examples/demo-app/demo_app.cpp b/examples/demo-app/demo_app.cpp index afe26351..b60b5e77 100644 --- a/examples/demo-app/demo_app.cpp +++ b/examples/demo-app/demo_app.cpp @@ -19,6 +19,10 @@ #include "polyscope/volume_grid.h" #include "polyscope/volume_mesh.h" +#include "IconFontCppHeaders/IconsLucide.h" +#include "ImGuiFileDialog.h" + +#include #include #include #include @@ -868,6 +872,15 @@ void processFile(std::string filename) { } } +enum class DemoFileDialogAction { None, OpenMesh, Save }; + +DemoFileDialogAction demoFileDialogAction = DemoFileDialogAction::None; +char demoSelectedFileDialogPath[4096] = ""; + +void setDemoSelectedFileDialogPath(const std::string& path) { + std::snprintf(demoSelectedFileDialogPath, sizeof(demoSelectedFileDialogPath), "%s", path.c_str()); +} + void callback() { static int numPoints = 2000; @@ -880,6 +893,52 @@ void callback() { ImGui::InputInt("num points", &numPoints); ImGui::InputFloat("param value", ¶m); + ImGui::SetNextItemOpen(true, ImGuiCond_Once); + if (ImGui::TreeNode("File dialogs")) { + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::InputText("Selected path", demoSelectedFileDialogPath, sizeof(demoSelectedFileDialogPath), + ImGuiInputTextFlags_ReadOnly); + + if (ImGui::Button(ICON_LC_FOLDER_OPEN " Open mesh file")) { + IGFD::FileDialogConfig config; + config.flags = ImGuiFileDialogFlags_Modal; + ImGuiFileDialog::Instance()->OpenDialog("DemoFileDialog", ICON_LC_FOLDER_OPEN " Open a mesh", + "Mesh files{.obj,.ply,.mesh},All files{.*}", config); + demoFileDialogAction = DemoFileDialogAction::OpenMesh; + } + + if (ImGui::Button(ICON_LC_SAVE " Save file")) { + IGFD::FileDialogConfig config; + config.fileName = "output.obj"; + config.flags = ImGuiFileDialogFlags_Modal | ImGuiFileDialogFlags_ConfirmOverwrite; + ImGuiFileDialog::Instance()->OpenDialog("DemoFileDialog", ICON_LC_SAVE " Choose an output file", ".obj", config); + demoFileDialogAction = DemoFileDialogAction::Save; + } + ImGui::TreePop(); + } + + if (demoFileDialogAction != DemoFileDialogAction::None) { + const ImVec2 viewportSize = ImGui::GetMainViewport()->WorkSize; + const ImVec2 minDialogSize(viewportSize.x * 0.5f, viewportSize.y * 0.5f); + const ImVec2 maxDialogSize(viewportSize.x * 0.9f, viewportSize.y * 0.9f); + if (ImGuiFileDialog::Instance()->Display("DemoFileDialog", ImGuiWindowFlags_NoCollapse, minDialogSize, + maxDialogSize)) { + if (ImGuiFileDialog::Instance()->IsOk()) { + if (demoFileDialogAction == DemoFileDialogAction::OpenMesh) { + const std::string path = ImGuiFileDialog::Instance()->GetFilePathName(); + setDemoSelectedFileDialogPath(path); + processFile(path); + } else { + const std::string path = ImGuiFileDialog::Instance()->GetFilePathName(); + setDemoSelectedFileDialogPath(path); + std::cout << "Selected output file: " << path << std::endl; + } + } + ImGuiFileDialog::Instance()->Close(); + demoFileDialogAction = DemoFileDialogAction::None; + } + } + if (ImGui::Button("run subroutine")) { // mySubroutine(); }