diff options
Diffstat (limited to 'indra/newview/llfilepicker.cpp')
-rw-r--r-- | indra/newview/llfilepicker.cpp | 677 |
1 files changed, 436 insertions, 241 deletions
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 2516bece8d..3df6c2a15b 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -36,17 +36,11 @@ #include "llviewercontrol.h" #include "llwindow.h" // beforeDialog() -#if LL_SDL -#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers -#endif // LL_SDL - -#ifdef LL_FLTK - #include "FL/Fl.H" - #include "FL/Fl_Native_File_Chooser.H" +#if LL_NFD +#include "nfd.hpp" +#if LL_USE_SDL_WINDOW +#include "nfd_sdl2.h" #endif - -#if LL_LINUX || __FreeBSD__ -#include "llhttpconstants.h" // file picker uses some of thes constants on Linux #endif // @@ -70,6 +64,7 @@ LLFilePicker LLFilePicker::sInstance; #define MATERIAL_TEXTURES_FILTER L"GLTF Import (*.gltf; *.glb; *.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.gltf;*.glb;*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0" #define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0" +#define LUA_FILTER L"Script files (*.lua)\0*.lua\0" #endif #ifdef LL_DARWIN @@ -87,7 +82,7 @@ LLFilePicker::LLFilePicker() { reset(); -#if LL_WINDOWS +#if LL_WINDOWS && !LL_NFD mOFN.lStructSize = sizeof(OPENFILENAMEW); mOFN.hwndOwner = NULL; // Set later mOFN.hInstance = NULL; @@ -172,7 +167,431 @@ void LLFilePicker::reset() mCurrentFile = 0; } +#if LL_NFD +std::vector<nfdfilteritem_t> LLFilePicker::setupFilter(ELoadFilter filter) +{ + std::vector<nfdfilteritem_t> filter_vec; + switch (filter) + { + case FFLOAD_EXE: #if LL_WINDOWS + filter_vec.emplace_back(nfdfilteritem_t{"Executables", "exe"}); +#endif + break; + case FFLOAD_ALL: + // Empty to allow picking all files by default + break; + case FFLOAD_WAV: + filter_vec.emplace_back(nfdfilteritem_t{"Sounds", "wav"}); + break; + case FFLOAD_IMAGE: + filter_vec.emplace_back(nfdfilteritem_t{"Images", "tga,bmp,jpg,jpeg,png"}); + break; + case FFLOAD_ANIM: + filter_vec.emplace_back(nfdfilteritem_t{"Animations", "bvh,anim"}); + break; + case FFLOAD_GLTF: + case FFLOAD_MATERIAL: + filter_vec.emplace_back(nfdfilteritem_t{"GLTF Files", "gltf,glb"}); + break; + case FFLOAD_COLLADA: + filter_vec.emplace_back(nfdfilteritem_t{"Scene", "dae"}); + break; + case FFLOAD_XML: + filter_vec.emplace_back(nfdfilteritem_t{"XML files", "xml"}); + break; + case FFLOAD_SLOBJECT: + filter_vec.emplace_back(nfdfilteritem_t{"Objects", "slobject"}); + break; + case FFLOAD_RAW: + filter_vec.emplace_back(nfdfilteritem_t{"RAW files", "raw"}); + break; + case FFLOAD_MODEL: + filter_vec.emplace_back(nfdfilteritem_t{"Model files", "dae"}); + break; + case FFLOAD_HDRI: + filter_vec.emplace_back(nfdfilteritem_t{"EXR files", "exr"}); + break; + case FFLOAD_MATERIAL_TEXTURE: + filter_vec.emplace_back(nfdfilteritem_t{"GLTF Import", "gltf,glb,tga,bmp,jpg,jpeg,png"}); + filter_vec.emplace_back(nfdfilteritem_t{"GLTF Files", "gltf,glb"}); + filter_vec.emplace_back(nfdfilteritem_t{"Images", "tga,bmp,jpg,jpeg,png"}); + break; + case FFLOAD_SCRIPT: + filter_vec.emplace_back(nfdfilteritem_t{"Script files (*.lsl)", "lsl"}); + break; + case FFLOAD_DICTIONARY: + filter_vec.emplace_back(nfdfilteritem_t{"Dictionary files", "dic,xcu"}); + break; + case FFLOAD_LUA: + filter_vec.emplace_back(nfdfilteritem_t{"Script files (*.lua)", "lua"}); + break; + default: + break; + } + return filter_vec; +} + +bool LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking) +{ + if( mLocked ) + { + return false; + } + bool success = false; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return false; + } + + // initialize NFD + NFD::Guard nfdGuard; + + // auto-freeing memory + NFD::UniquePath outPath; + + // prepare filters for the dialog + auto filterItem = setupFilter(filter); + + nfdwindowhandle_t windowHandle = nfdwindowhandle_t(); +#if LL_USE_SDL_WINDOW + if(!NFD_GetNativeWindowFromSDLWindow((SDL_Window*)gViewerWindow->getPlatformWindow(), &windowHandle)) + { + windowHandle = nfdwindowhandle_t(); + } +#elif LL_WINDOWS + windowHandle = { NFD_WINDOW_HANDLE_TYPE_WINDOWS, gViewerWindow->getWindow()->getPlatformWindow() }; +#endif + + if (blocking) + { + // Modal, so pause agent + send_agent_pause(); + } + + reset(); + + // show the dialog + nfdresult_t result = NFD::OpenDialog(outPath, filterItem.data(), narrow(filterItem.size()), nullptr, windowHandle); + if (result == NFD_OKAY) + { + mFiles.push_back(outPath.get()); + success = true; + } + + if (blocking) + { + send_agent_resume(); + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + } + + return success; +} + +bool LLFilePicker::getOpenFileModeless(ELoadFilter filter, + void (*callback)(bool, std::vector<std::string> &, void*), + void *userdata) +{ + if( mLocked ) + return false; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return false; + } + + reset(); + LL_WARNS() << "NOT IMPLEMENTED" << LL_ENDL; + return false; +} + +bool LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking) +{ + if( mLocked ) + { + return false; + } + bool success = false; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return false; + } + + // initialize NFD + NFD::Guard nfdGuard; + + auto filterItem = setupFilter(filter); + + reset(); + + if (blocking) + { + // Modal, so pause agent + send_agent_pause(); + } + + nfdwindowhandle_t windowHandle = nfdwindowhandle_t(); +#if LL_USE_SDL_WINDOW + if(!NFD_GetNativeWindowFromSDLWindow((SDL_Window*)gViewerWindow->getPlatformWindow(), &windowHandle)) + { + windowHandle = nfdwindowhandle_t(); + } +#elif LL_WINDOWS + windowHandle = { NFD_WINDOW_HANDLE_TYPE_WINDOWS, gViewerWindow->getWindow()->getPlatformWindow() }; +#endif + + // auto-freeing memory + NFD::UniquePathSet outPaths; + + // show the dialog + nfdresult_t result = NFD::OpenDialogMultiple(outPaths, filterItem.data(), narrow(filterItem.size()), nullptr, windowHandle); + if (result == NFD_OKAY) + { + LL_INFOS() << "Success!" << LL_ENDL; + + nfdpathsetsize_t numPaths; + NFD::PathSet::Count(outPaths, numPaths); + + nfdpathsetsize_t i; + for (i = 0; i < numPaths; ++i) + { + NFD::UniquePathSetPath path; + NFD::PathSet::GetPath(outPaths, i, path); + mFiles.push_back(path.get()); + LL_INFOS() << "Path " << i << ": " << path.get() << LL_ENDL; + } + success = true; + } + else if (result == NFD_CANCEL) + { + LL_INFOS() << "User pressed cancel." << LL_ENDL; + } + else + { + LL_INFOS() << "Error: " << NFD::GetError() << LL_ENDL; + } + + if (blocking) + { + send_agent_resume(); + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + } + + return success; +} + +bool LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, + void (*callback)(bool, std::vector<std::string> &, void*), + void *userdata ) +{ + if( mLocked ) + return false; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return false; + } + + reset(); + + LL_WARNS() << "NOT IMPLEMENTED" << LL_ENDL; + return false; +} + +bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, bool blocking) +{ + if( mLocked ) + { + return false; + } + bool success = false; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return false; + } + + // initialize NFD + NFD::Guard nfdGuard; + + std::vector<nfdfilteritem_t> filter_vec; + std::string saved_filename = filename; + switch( filter ) + { + case FFSAVE_ALL: + filter_vec.emplace_back(nfdfilteritem_t{"WAV Sounds", "wav"}); + filter_vec.emplace_back(nfdfilteritem_t{"Targa, Bitmap Images", "tga,bmp"}); + break; + case FFSAVE_WAV: + if (filename.empty()) + { + saved_filename = "untitled.wav"; + } + filter_vec.emplace_back(nfdfilteritem_t{"WAV Sounds", "wav"}); + break; + case FFSAVE_TGA: + if (filename.empty()) + { + saved_filename = "untitled.tga"; + } + filter_vec.emplace_back(nfdfilteritem_t{"Targa Images", "tga"}); + break; + case FFSAVE_BMP: + if (filename.empty()) + { + saved_filename = "untitled.bmp"; + } + filter_vec.emplace_back(nfdfilteritem_t{"Bitmap Images", "bmp"}); + break; + case FFSAVE_PNG: + if (filename.empty()) + { + saved_filename = "untitled.png"; + } + filter_vec.emplace_back(nfdfilteritem_t{"PNG Images", "png"}); + break; + case FFSAVE_TGAPNG: + if (filename.empty()) + { + saved_filename = "untitled.png"; + } + + filter_vec.emplace_back(nfdfilteritem_t{"PNG Images", "png"}); + filter_vec.emplace_back(nfdfilteritem_t{"Targa Images", "tga"}); + filter_vec.emplace_back(nfdfilteritem_t{"JPEG Images", "jpg,jpeg"}); + filter_vec.emplace_back(nfdfilteritem_t{"Jpeg2000 Images", "j2c"}); + filter_vec.emplace_back(nfdfilteritem_t{"Bitmap Images", "bmp"}); + break; + case FFSAVE_JPEG: + if (filename.empty()) + { + saved_filename = "untitled.jpeg"; + } + filter_vec.emplace_back(nfdfilteritem_t{"JPEG Images", "jpg,jpeg"}); + break; + case FFSAVE_AVI: + if (filename.empty()) + { + saved_filename = "untitled.avi"; + } + filter_vec.emplace_back(nfdfilteritem_t{"AVI Movie File", "avi"}); + break; + case FFSAVE_ANIM: + if (filename.empty()) + { + saved_filename = "untitled.xaf"; + } + filter_vec.emplace_back(nfdfilteritem_t{"XAF Anim File", "xaf"}); + break; + case FFSAVE_XML: + if (filename.empty()) + { + saved_filename = "untitled.xml"; + } + filter_vec.emplace_back(nfdfilteritem_t{"XML File", "xml"}); + break; + case FFSAVE_COLLADA: + if (filename.empty()) + { + saved_filename = "untitled.collada"; + } + filter_vec.emplace_back(nfdfilteritem_t{"COLLADA File", "collada"}); + break; + case FFSAVE_RAW: + if (filename.empty()) + { + saved_filename = "untitled.raw"; + } + filter_vec.emplace_back(nfdfilteritem_t{"RAW files", "raw"}); + break; + case FFSAVE_J2C: + if (filename.empty()) + { + saved_filename = "untitled.j2c"; + } + filter_vec.emplace_back(nfdfilteritem_t{"Compressed Images", "j2c"}); + break; + case FFSAVE_SCRIPT: + if (filename.empty()) + { + saved_filename = "untitled.lsl"; + } + filter_vec.emplace_back(nfdfilteritem_t{"LSL Files", "lsl"}); + break; + default: + return false; + } + + nfdwindowhandle_t windowHandle = nfdwindowhandle_t(); +#if LL_USE_SDL_WINDOW + if(!NFD_GetNativeWindowFromSDLWindow((SDL_Window*)gViewerWindow->getPlatformWindow(), &windowHandle)) + { + windowHandle = nfdwindowhandle_t(); + } +#elif LL_WINDOWS + windowHandle = { NFD_WINDOW_HANDLE_TYPE_WINDOWS, gViewerWindow->getWindow()->getPlatformWindow() }; +#endif + + reset(); + + if (blocking) + { + // Modal, so pause agent + send_agent_pause(); + } + + { + NFD::UniquePath savePath; + + // show the dialog + nfdresult_t result = NFD::SaveDialog(savePath, filter_vec.data(), narrow(filter_vec.size()), nullptr, saved_filename.c_str(), windowHandle); + if (result == NFD_OKAY) { + mFiles.push_back(savePath.get()); + success = true; + } + gKeyboard->resetKeys(); + } + + if (blocking) + { + send_agent_resume(); + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + } + + return success; +} + +bool LLFilePicker::getSaveFileModeless(ESaveFilter filter, + const std::string& filename, + void (*callback)(bool, std::string&, void*), + void *userdata) +{ + if( mLocked ) + return false; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return false; + } + + reset(); + LL_WARNS() << "NOT IMPLEMENTED" << LL_ENDL; + return false; +} +#elif LL_WINDOWS bool LLFilePicker::setupFilter(ELoadFilter filter) { @@ -246,6 +665,10 @@ bool LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = DICTIONARY_FILTER \ L"\0"; break; + case FFLOAD_LUA: + mOFN.lpstrFilter = LUA_FILTER \ + L"\0"; + break; default: res = false; break; @@ -675,7 +1098,6 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF break; case FFLOAD_HDRI: allowedv->push_back("exr"); - case FFLOAD_MODEL: case FFLOAD_COLLADA: allowedv->push_back("dae"); break; @@ -1108,231 +1530,6 @@ bool LLFilePicker::getSaveFileModeless(ESaveFilter filter, #elif LL_LINUX || __FreeBSD__ -#if LL_FLTK - -bool LLFilePicker::getSaveFileModeless(ESaveFilter filter, - const std::string& filename, - void (*callback)(bool, std::string&, void*), - void *userdata) -{ - LL_ERRS() << "NOT IMPLEMENTED" << LL_ENDL; - return FALSE; -} - -bool LLFilePicker::getOpenFileModeless(ELoadFilter filter, - void (*callback)(bool, std::vector<std::string> &, void*), - void *userdata) -{ - LL_ERRS() << "NOT IMPLEMENTED" << LL_ENDL; - return FALSE; -} - -bool LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, - void (*callback)(bool, std::vector<std::string> &, void*), - void *userdata ) -{ - LL_ERRS() << "NOT IMPLEMENTED" << LL_ENDL; - return FALSE; -} - - - -bool LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking ) -{ - return openFileDialog( filter, blocking, eSaveFile ); -} - -bool LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) -{ - return openFileDialog( filter, blocking, eOpenFile ); -} - -bool LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) -{ - return openFileDialog( filter, blocking, eOpenMultiple ); -} - -bool LLFilePicker::openFileDialog( int32_t filter, bool blocking, EType aType ) -{ - if ( check_local_file_access_enabled() == false ) - return false; - gViewerWindow->getWindow()->beforeDialog(); - reset(); - Fl_Native_File_Chooser::Type flType = Fl_Native_File_Chooser::BROWSE_FILE; - if( aType == eOpenMultiple ) - flType = Fl_Native_File_Chooser::BROWSE_MULTI_FILE; - else if( aType == eSaveFile ) - flType = Fl_Native_File_Chooser::BROWSE_SAVE_FILE; - Fl_Native_File_Chooser flDlg; - std::string file_dialog_title; - std::string file_dialog_filter; - if (aType == EType::eSaveFile) - { - std::string file_type("all_files"); - switch ((ESaveFilter) filter) - { - case FFSAVE_ALL: - break; - case FFSAVE_TGA: - file_type = "targa_image_files"; - file_dialog_filter = "*.tga"; - break; - case FFSAVE_BMP: - file_type = "bitmap_image_files"; - file_dialog_filter = "*.bmp"; - break; - case FFSAVE_AVI: - file_type = "avi_movie_file"; - file_dialog_filter = "*.avi"; - break; - case FFSAVE_ANIM: - file_type = "xaf_animation_file"; - file_dialog_filter = "*.xaf"; - break; - case FFSAVE_XML: - file_type = "xml_file"; - file_dialog_filter = "*.xml"; - break; - case FFSAVE_COLLADA: - file_type = "collada_files"; - file_dialog_filter = "*.dae"; - break; - case FFSAVE_RAW: - file_type = "raw_file"; - file_dialog_filter = "*.raw"; - break; - case FFSAVE_J2C: - file_type = "compressed_image_files"; - file_dialog_filter = "*.j2c"; - break; - case FFSAVE_PNG: - file_type = "png_image_files"; - file_dialog_filter = "*.png"; - break; - case FFSAVE_JPEG: - file_type = "jpeg_image_files"; - file_dialog_filter = "*.{jpg,jpeg}"; - break; - case FFSAVE_SCRIPT: - file_type = "script_files"; - file_dialog_filter = "*.lsl"; - break; - case FFSAVE_TGAPNG: - file_type = "save_texture_image_files"; - file_dialog_filter = "*.{tga,png}"; - break; - case FFSAVE_WAV: - file_type = "sound_files"; - file_dialog_filter = "*.wav"; - break; - case FFSAVE_GLTF: - file_type = "gltf_asset_file"; - file_dialog_filter = "*.{gltf,glb}"; - break; - } - file_dialog_title = LLTrans::getString("save_file_verb") + " " + LLTrans::getString(file_type); - file_dialog_filter = LLTrans::getString(file_type) + " \t" + file_dialog_filter; - } - else - { - std::string file_type("all_files"); - switch ((ELoadFilter) filter) - { - case FFLOAD_ALL: - break; - case FFLOAD_WAV: - file_type = "sound_files"; - file_dialog_filter = "*.wav"; - break; - case FFLOAD_IMAGE: - file_type = "image_files"; - file_dialog_filter = "*.{tga,bmp,jpg,jpeg,png}"; - break; - case FFLOAD_ANIM: - file_type = "animation_files"; - file_dialog_filter = "*.{bvh,anim}"; - break; - case FFLOAD_XML: - file_type = "xml_file"; - file_dialog_filter = "*.xml"; - break; - case FFLOAD_SLOBJECT: - file_type = "xml_file"; - file_dialog_filter = "*.slobject"; - break; - case FFLOAD_RAW: - file_type = "raw_file"; - file_dialog_filter = "*.raw"; - break; - case FFLOAD_MODEL: - case FFLOAD_COLLADA: - file_type = "collada_files"; - file_dialog_filter = "*.dae"; - break; - case FFLOAD_SCRIPT: - file_type = "script_files"; - file_dialog_filter = "*.lsl"; - break; - case FFLOAD_DICTIONARY: - file_type = "dictionary_files"; - file_dialog_filter = "*.{dic,xcu}"; - break; - case FFLOAD_DIRECTORY: - file_type = "choose_the_directory"; - break; - case FFLOAD_EXE: - file_type = "executable_files"; - break; - case FFLOAD_GLTF: - case FFLOAD_MATERIAL: - file_type = "gltf_asset_file"; - file_dialog_filter = "*.{gltg,glb}"; - break; - case FFLOAD_MATERIAL_TEXTURE: - file_dialog_filter = "*.{gltf,glb,tga,bmp,jpg,jpeg,png}"; - file_type = "image_files"; - break; - case FFLOAD_HDRI: - file_dialog_filter = "*.exr"; - - } - if (aType == EType::eOpenMultiple) - { - file_dialog_title = LLTrans::getString("load_files"); - } - else - { - file_dialog_title = LLTrans::getString("load_file_verb") + " " + LLTrans::getString(file_type); - file_dialog_filter = LLTrans::getString(file_type) + " \t" + file_dialog_filter; - } - } - flDlg.title(file_dialog_title.c_str()); - flDlg.type(flType); - if (!file_dialog_filter.empty()) - { - flDlg.filter(file_dialog_filter.c_str()); - } - int res = flDlg.show(); - gViewerWindow->getWindow()->afterDialog(); - if( res == 0 ) - { - int32_t count = flDlg.count(); - if( count < 0 ) - count = 0; - for( int32_t i = 0; i < count; ++i ) - { - char const *pFile = flDlg.filename(i); - if( pFile && strlen(pFile) > 0 ) - mFiles.push_back( pFile ); - } - } - else if( res == -1 ) - { - LL_WARNS() << "FLTK failed: " << flDlg.errmsg() << LL_ENDL; - } - return mFiles.empty()?FALSE:TRUE; -} -#else // Hacky stubs designed to facilitate fake getSaveFile and getOpenFile with // static results, when we don't have a real filepicker. @@ -1420,17 +1617,15 @@ bool LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, return false; } -#endif // LL_FLTK - #else // not implemented -bool LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking ) +bool LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) { reset(); return false; } -bool LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) +bool LLFilePicker::getOpenFile( ELoadFilter filter ) { reset(); return false; |