diff --git a/.gitmodules b/.gitmodules index d63fd70b..d08aa505 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "extern/Nuked-OPL3"] path = extern/Nuked-OPL3 url = https://github.com/nukeykt/Nuked-OPL3.git +[submodule "extern/pfd"] + path = extern/pfd + url = https://github.com/samhocevar/portable-file-dialogs.git diff --git a/CMakeLists.txt b/CMakeLists.txt index de4eefbc..99f1089b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -347,6 +347,7 @@ src/gui/font_unifont.cpp src/gui/font_icon.cpp src/gui/fonts.cpp src/gui/debug.cpp +src/gui/fileDialog.cpp src/gui/intConst.cpp src/gui/guiConst.cpp diff --git a/extern/pfd b/extern/pfd new file mode 160000 index 00000000..dea8520d --- /dev/null +++ b/extern/pfd @@ -0,0 +1 @@ +Subproject commit dea8520de18af09eefdbc18aaf7c24409d18491b diff --git a/src/gui/fileDialog.cpp b/src/gui/fileDialog.cpp new file mode 100644 index 00000000..54b38739 --- /dev/null +++ b/src/gui/fileDialog.cpp @@ -0,0 +1,109 @@ +#include "fileDialog.h" +#include "ImGuiFileDialog.h" +#include "../../extern/pfd/portable-file-dialogs.h" + +bool FurnaceGUIFileDialog::openLoad(String header, std::vector filter, String path, double dpiScale) { + if (opened) return false; + saving=false; + curPath=path; + if (sysDialog) { + dialogO=new pfd::open_file(header,path,filter); + } else { + String parsedFilter; + if (filter.size()&1) return false; + + for (size_t i=0; iDpiScale=dpiScale; + ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,parsedFilter.c_str(),path); + } + return true; +} + +bool FurnaceGUIFileDialog::openSave(String header, std::vector filter, String path, double dpiScale) { + curPath=path; + if (sysDialog) { + // TODO + } else { + String parsedFilter; + ImGuiFileDialog::Instance()->DpiScale=dpiScale; + ImGuiFileDialog::Instance()->OpenModal("FileDialog",header,parsedFilter.c_str(),path,1,nullptr,ImGuiFileDialogFlags_ConfirmOverwrite); + } + return true; +} + +bool FurnaceGUIFileDialog::accepted() { + if (sysDialog) { + return (fileName!=""); + } else { + return ImGuiFileDialog::Instance()->IsOk(); + } +} + +void FurnaceGUIFileDialog::close() { + if (sysDialog) { + if (saving) { + if (dialogS!=NULL) { + delete dialogS; + dialogS=NULL; + } + } else { + if (dialogO!=NULL) { + delete dialogO; + dialogO=NULL; + printf("deleting\n"); + } + } + } else { + ImGuiFileDialog::Instance()->Close(); + } +} + +bool FurnaceGUIFileDialog::render(const ImVec2& min, const ImVec2& max) { + if (sysDialog) { + if (saving) { + if (dialogS!=NULL) { + if (dialogS->ready(1)) { + fileName=dialogS->result(); + printf("returning %s\n",fileName.c_str()); + return true; + } + } + } else { + if (dialogO!=NULL) { + if (dialogO->ready(1)) { + if (dialogO->result().empty()) { + fileName=""; + printf("returning nothing\n"); + } else { + fileName=dialogO->result()[0]; + printf("returning %s\n",fileName.c_str()); + } + return true; + } + } + } + return false; + } else { + return ImGuiFileDialog::Instance()->Display("FileDialog",ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove,min,max); + } +} + +String FurnaceGUIFileDialog::getPath() { + if (sysDialog) { + return curPath; + } else { + return ImGuiFileDialog::Instance()->GetCurrentPath(); + } +} + +String FurnaceGUIFileDialog::getFileName() { + if (sysDialog) { + return fileName; + } else { + return ImGuiFileDialog::Instance()->GetFilePathName(); + } +} \ No newline at end of file diff --git a/src/gui/fileDialog.h b/src/gui/fileDialog.h new file mode 100644 index 00000000..057bef1f --- /dev/null +++ b/src/gui/fileDialog.h @@ -0,0 +1,31 @@ +#include "../ta-utils.h" +#include "imgui.h" + +namespace pfd { + class open_file; + class save_file; +} + +class FurnaceGUIFileDialog { + bool sysDialog; + bool opened; + bool saving; + String curPath; + String fileName; + pfd::open_file* dialogO; + pfd::save_file* dialogS; + public: + bool openLoad(String header, std::vector filter, String path, double dpiScale); + bool openSave(String header, std::vector filter, String path, double dpiScale); + bool accepted(); + void close(); + bool render(const ImVec2& min, const ImVec2& max); + String getPath(); + String getFileName(); + FurnaceGUIFileDialog(bool system): + sysDialog(system), + opened(false), + saving(false), + dialogO(NULL), + dialogS(NULL) {} +}; \ No newline at end of file diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index eff4cd2e..fe53b911 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4585,11 +4585,11 @@ bool dirExists(String what) { } void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { - ImGuiFileDialog::Instance()->DpiScale=dpiScale; switch (type) { case GUI_FILE_OPEN: if (!dirExists(workingDirSong)) workingDirSong=getHomeDir(); - ImGuiFileDialog::Instance()->OpenModal("FileDialog","Open File","compatible files{.fur,.dmf},.*",workingDirSong); + fileDialog->openLoad("Open File",{"compatible files", ".fur,.dmf", "all files", ".*"},workingDirSong,dpiScale); + //ImGuiFileDialog::Instance()->OpenModal("FileDialog","Open File","compatible files{.fur,.dmf},.*",workingDirSong); break; case GUI_FILE_SAVE: if (!dirExists(workingDirSong)) workingDirSong=getHomeDir(); @@ -5942,42 +5942,42 @@ bool FurnaceGUI::loop() { if (patternOpen) nextWindow=GUI_WINDOW_PATTERN; } - if (ImGuiFileDialog::Instance()->Display("FileDialog",ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove,ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale))) { + if (fileDialog->render(ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale))) { //ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_NavEnableKeyboard; switch (curFileDialog) { case GUI_FILE_OPEN: case GUI_FILE_SAVE: case GUI_FILE_SAVE_DMF_LEGACY: - workingDirSong=ImGuiFileDialog::Instance()->GetCurrentPath()+DIR_SEPARATOR_STR; + workingDirSong=fileDialog->getPath()+DIR_SEPARATOR_STR; break; case GUI_FILE_INS_OPEN: case GUI_FILE_INS_SAVE: - workingDirIns=ImGuiFileDialog::Instance()->GetCurrentPath()+DIR_SEPARATOR_STR; + workingDirIns=fileDialog->getPath()+DIR_SEPARATOR_STR; break; case GUI_FILE_WAVE_OPEN: case GUI_FILE_WAVE_SAVE: - workingDirWave=ImGuiFileDialog::Instance()->GetCurrentPath()+DIR_SEPARATOR_STR; + workingDirWave=fileDialog->getPath()+DIR_SEPARATOR_STR; break; case GUI_FILE_SAMPLE_OPEN: case GUI_FILE_SAMPLE_SAVE: - workingDirSample=ImGuiFileDialog::Instance()->GetCurrentPath()+DIR_SEPARATOR_STR; + workingDirSample=fileDialog->getPath()+DIR_SEPARATOR_STR; break; case GUI_FILE_EXPORT_AUDIO_ONE: case GUI_FILE_EXPORT_AUDIO_PER_SYS: case GUI_FILE_EXPORT_AUDIO_PER_CHANNEL: - workingDirAudioExport=ImGuiFileDialog::Instance()->GetCurrentPath()+DIR_SEPARATOR_STR; + workingDirAudioExport=fileDialog->getPath()+DIR_SEPARATOR_STR; break; case GUI_FILE_EXPORT_VGM: case GUI_FILE_EXPORT_ROM: - workingDirVGMExport=ImGuiFileDialog::Instance()->GetCurrentPath()+DIR_SEPARATOR_STR; + workingDirVGMExport=fileDialog->getPath()+DIR_SEPARATOR_STR; break; case GUI_FILE_LOAD_MAIN_FONT: case GUI_FILE_LOAD_PAT_FONT: - workingDirFont=ImGuiFileDialog::Instance()->GetCurrentPath()+DIR_SEPARATOR_STR; + workingDirFont=fileDialog->getPath()+DIR_SEPARATOR_STR; break; } - if (ImGuiFileDialog::Instance()->IsOk()) { - fileName=ImGuiFileDialog::Instance()->GetFilePathName(); + if (fileDialog->accepted()) { + fileName=fileDialog->getFileName(); if (fileName!="") { if (curFileDialog==GUI_FILE_SAVE) { if (ImGuiFileDialog::Instance()->GetCurrentFilter()=="Furnace song") { @@ -6103,7 +6103,7 @@ bool FurnaceGUI::loop() { curFileDialog=GUI_FILE_OPEN; } } - ImGuiFileDialog::Instance()->Close(); + fileDialog->close(); } if (warnQuit) { @@ -6805,6 +6805,7 @@ FurnaceGUI::FurnaceGUI(): displayNew(false), curFileDialog(GUI_FILE_OPEN), warnAction(GUI_WARN_OPEN), + fileDialog(NULL), scrW(1280), scrH(800), dpiScale(1), diff --git a/src/gui/gui.h b/src/gui/gui.h index dc985e8d..9bf68e52 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -27,6 +27,8 @@ #include #include +#include "fileDialog.h" + #define rightClickable if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) ImGui::SetKeyboardFocusHere(-1); #define handleUnimportant if (settings.insFocusesPattern && patternOpen) {nextWindow=GUI_WINDOW_PATTERN;} @@ -476,6 +478,8 @@ class FurnaceGUI { FurnaceGUIFileDialogs curFileDialog; FurnaceGUIWarnings warnAction; + FurnaceGUIFileDialog* fileDialog; + int scrW, scrH; double dpiScale; @@ -536,6 +540,7 @@ class FurnaceGUI { int stepOnInsert; // TODO flags int unifiedDataView; + int sysFileDialog; // end unsigned int maxUndoSteps; String mainFontPath; @@ -581,6 +586,8 @@ class FurnaceGUI { avoidRaisingPattern(0), insFocusesPattern(1), stepOnInsert(0), + unifiedDataView(0), + sysFileDialog(0), maxUndoSteps(100), mainFontPath(""), patFontPath(""), diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index c8f6763b..eb09e86f 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -182,6 +182,11 @@ void FurnaceGUI::drawSettings() { settings.restartOnFlagChange=restartOnFlagChangeB; } + bool sysFileDialogB=settings.sysFileDialog; + if (ImGui::Checkbox("Use system file picker",&sysFileDialogB)) { + settings.sysFileDialog=sysFileDialogB; + } + ImGui::Text("Wrap pattern cursor horizontally:"); if (ImGui::RadioButton("No##wrapH0",settings.wrapHorizontal==0)) { settings.wrapHorizontal=0; @@ -892,6 +897,8 @@ void FurnaceGUI::syncSettings() { settings.avoidRaisingPattern=e->getConfInt("avoidRaisingPattern",0); settings.insFocusesPattern=e->getConfInt("insFocusesPattern",1); settings.stepOnInsert=e->getConfInt("stepOnInsert",0); + settings.unifiedDataView=e->getConfInt("unifiedDataView",0); + settings.sysFileDialog=e->getConfInt("sysFileDialog",0); clampSetting(settings.mainFontSize,2,96); clampSetting(settings.patFontSize,2,96); @@ -930,6 +937,8 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.avoidRaisingPattern,0,1); clampSetting(settings.insFocusesPattern,0,1); clampSetting(settings.stepOnInsert,0,1); + clampSetting(settings.unifiedDataView,0,1); + clampSetting(settings.sysFileDialog,0,1); // keybinds LOAD_KEYBIND(GUI_ACTION_OPEN,FURKMOD_CMD|SDLK_o); @@ -1082,6 +1091,9 @@ void FurnaceGUI::syncSettings() { decodeKeyMap(noteKeys,e->getConfString("noteKeys",DEFAULT_NOTE_KEYS)); parseKeybinds(); + + if (fileDialog!=NULL) delete fileDialog; + fileDialog=new FurnaceGUIFileDialog(settings.sysFileDialog); } #define PUT_UI_COLOR(source) e->setConf(#source,(int)ImGui::GetColorU32(uiColors[source])); @@ -1129,6 +1141,8 @@ void FurnaceGUI::commitSettings() { e->setConf("avoidRaisingPattern",settings.avoidRaisingPattern); e->setConf("insFocusesPattern",settings.insFocusesPattern); e->setConf("stepOnInsert",settings.stepOnInsert); + e->setConf("unifiedDataView",settings.unifiedDataView); + e->setConf("sysFileDialog",settings.sysFileDialog); PUT_UI_COLOR(GUI_COLOR_BACKGROUND); PUT_UI_COLOR(GUI_COLOR_FRAME_BACKGROUND);