1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
5 #include <CryString/StringUtils.h>
6 #include "dll_string.h"
7 #include <CryCore/functor.h>
8 #include "FileSystem/FileSystem_FileFilter.h"
9 #include "FileDialogs/ExtensionFilter.h"
12 class CDynamicPopupMenu
;
15 //! File types used for File Open dialogs
28 class PLUGIN_API CFileUtil
35 time_t time_create
; //! -1 for FAT file systems
36 time_t time_access
; //! -1 for FAT file systems
51 ETREECOPYUSERCANCELED
,
52 ETREECOPYUSERDIDNTCOPYSOMEITEMS
,
57 COLUMN_TYPE_FILELIST
= 0,
62 typedef std::vector
<FileDesc
> FileArray
;
63 typedef bool (* ScanDirectoryUpdateCallBack
)(const string
& msg
);
64 typedef Functor1
<const char*> SelectSingleFileChangeCallback
;
65 typedef FileSystem::SFileFilter::FileFilterCallback FileFilterCallback
;
67 static bool ScanDirectory(const CString
& path
, const CString
& fileSpec
, FileArray
& files
, bool recursive
= true, bool addDirAlso
= false, ScanDirectoryUpdateCallBack updateCB
= NULL
, bool bSkipPaks
= false);
68 static bool ScanDirectory(const char* path
, const char* fileSpec
, FileArray
& files
, bool recursive
= true, bool addDirAlso
= false, ScanDirectoryUpdateCallBack updateCB
= NULL
, bool bSkipPaks
= false) // for CString conversion
70 return ScanDirectory(CString(path
), CString(fileSpec
), files
, recursive
, addDirAlso
, updateCB
, bSkipPaks
);
73 static void ShowInExplorer(const CString
& path
);
75 static bool CompileLuaFile(const char* luaFilename
);
76 static bool ExtractFile(CString
& file
, bool bMsgBoxAskForExtraction
= true, const char* pDestinationFilename
= NULL
);
77 static void EditTextFile(const char* txtFile
, int line
= 0, ETextFileType fileType
= FILE_TYPE_SCRIPT
, bool bUseGameFolder
= true);
78 static void EditTextureFile(const char* txtureFile
, bool bUseGameFolder
);
79 static bool EditMayaFile(const char* mayaFile
, const bool bExtractFromPak
, const bool bUseGameFolder
);
80 static bool EditFile(const char* filePath
, const bool bExtrackFromPak
, const bool bUseGameFolder
);
82 //! dcc filename calculation and extraction sub-routines
83 static bool CalculateDccFilename(const CString
& assetFilename
, CString
& dccFilename
);
85 //! Reformat filter string for (MFC) CFileDialog style file filtering
86 static void FormatFilterString(CString
& filter
);
88 static void GetFilterFromCustomFileType(CString
& filter
, ECustomFileType fileType
);
90 //! Open file selection dialog.
91 static bool SelectFile(const CString
& fileSpec
, const CString
& searchFolder
, CString
& fullFileName
);
92 //! Open file selection dialog.
93 static bool SelectFiles(const CString
& fileSpec
, const CString
& searchFolder
, std::vector
<CString
>& files
);
94 //! Open file selection dialog.
95 static bool SelectFile(const string
& fileSpec
, const string
& searchFolder
, string
& fullFileName
) // for CString conversion
97 CString cFullFileName
= fullFileName
.GetString();
98 bool result
= SelectFile(fileSpec
.GetString(), searchFolder
.GetString(), cFullFileName
);
99 fullFileName
= cFullFileName
.GetString();
103 //! Display OpenFile dialog and allow to select multiple files.
104 //! @return true if selected, false if canceled.
105 //! @outputFile Inputs and Outputs filename.
106 static bool SelectSingleFile(ECustomFileType fileType
, CString
& outputFile
, const CString
& filter
= "", const CString
& initialDir
= "", const CString
& baseDir
= "", const FileFilterCallback
& fileFilterFunc
= FileFilterCallback());
107 static bool SelectSingleFile(ECustomFileType fileType
, string
& outputFile
, const char* filter
= "", const char* initialDir
= "", const char* baseDir
= "", const FileFilterCallback
& fileFilterFunc
= FileFilterCallback());
108 static bool SelectSingleFile(QWidget
* pParent
, ECustomFileType fileType
, CString
& outputFile
, const CString
& filter
= "", const CString
& initialDir
= "", const CString
& baseDir
= "", const FileFilterCallback
& fileFilterFunc
= FileFilterCallback());
109 static bool SelectSingleFile(QWidget
* pParent
, ECustomFileType fileType
, string
& outputFile
, const char* filter
= "", const char* initialDir
= "", const char* baseDir
= "", const FileFilterCallback
& fileFilterFunc
= FileFilterCallback());
111 //! Display OpenFile dialog and allow to select multiple files.
112 //! @return true if selected, false if canceled.
113 static bool SelectMultipleFiles(ECustomFileType fileType
, std::vector
<CString
>& files
, const CString
& filter
= "", const CString
& initialDir
= "", const CString
& baseDir
= "", const FileFilterCallback
& fileFilterFunc
= FileFilterCallback());
115 //! Display OpenFile dialog and allow to select multiple files.
116 //! @return true if selected, false if canceled.
117 static bool SelectMultipleFiles(ECustomFileType fileType
, std::vector
<string
>& files
, const char* filter
= "", const char* initialDir
= "", const char* baseDir
= "", const FileFilterCallback
& fileFilterFunc
= FileFilterCallback()) // for CString conversion
119 std::vector
<CString
> cFiles
;
120 for (const string
& str
: files
)
121 cFiles
.push_back(str
.GetString());
123 bool result
= SelectMultipleFiles(fileType
, cFiles
, CString(filter
), CString(initialDir
), CString(baseDir
), fileFilterFunc
);
126 for (const CString
& str
: cFiles
)
127 files
.push_back(str
.GetString());
132 static bool SelectSaveFile(const char* fileFilter
, const char* defaulExtension
, const char* startFolder
, string
& fileName
);
133 static bool SelectSaveFile(const CString
& fileFilter
, const CString
& defaulExtension
, const CString
& startFolder
, CString
& fileName
);
135 //! If file is read-only ask user if he wants to overwrite it.
136 //! If yes file is deleted.
137 //! @return True if file was deleted.
138 static bool OverwriteFile(const CString
& filename
);
140 //! If file is read-only ask user if he wants to overwrite it.
141 //! If yes file is deleted.
142 //! @return True if file was deleted.
143 static bool OverwriteFile(const char* filename
) { return OverwriteFile(CString(filename
)); } // for CString conversion
145 //////////////////////////////////////////////////////////////////////////
146 // Interface to Source safe.
147 //////////////////////////////////////////////////////////////////////////
148 //! Checks out the file from source safe.
149 static bool CheckoutFile(const char* filename
);
151 //! Checks in the file to source safe.
152 static bool CheckinFile(const char* filename
);
154 //! Adding the file to Source Control changelist without submitting.
155 static bool AddFileToSourceControl(const char* filename
);
157 //! Creates this directory.
158 static void CreateDirectory(const char* dir
);
160 //! Makes a backup file.
161 static void BackupFile(const char* filename
);
163 //! Makes a backup file, marked with a datestamp, e.g. myfile.20071014.093320.xml
164 //! If bUseBackupSubDirectory is true, moves backup file into a relative subdirectory "backups"
165 static void BackupFileDated(const char* filename
, bool bUseBackupSubDirectory
= false);
167 // ! Added deltree as a copy from the function found in Crypak.
168 static bool Deltree(const char* szFolder
, bool bRecurse
);
170 // Checks if a file or directory exist.
171 // We are using 3 functions here in order to make the names more instructive for the programmers.
172 // Those functions only work for OS files and directories.
173 static bool Exists(const CString
& strPath
, bool boDirectory
, FileDesc
* pDesc
= NULL
);
174 static bool FileExists(const CString
& strFilePath
, FileDesc
* pDesc
= NULL
);
175 static bool FileExists(const char* strFilePath
, FileDesc
* pDesc
= NULL
) { return FileExists(CString(strFilePath
), pDesc
); } // for CString conversion
176 static bool PathExists(const CString
& strPath
);
177 static bool PathExists(const char* strPath
) { return PathExists(CString(strPath
)); }
178 static bool GetDiskFileSize(const char* pFilePath
, uint64
& rOutSize
);
180 // This function should be used only with physical files.
181 static bool IsFileExclusivelyAccessable(const CString
& strFilePath
);
183 // Creates the entire path, if needed.
184 static bool CreatePath(const CString
& strPath
);
186 // Creates the entire path, if needed.
187 static bool CreatePath(const char* strPath
) { return CreatePath(CString(strPath
)); }
189 // Attempts to delete a file (if read only it will set its attributes to normal first).
190 static bool DeleteFile(const CString
& strPath
);
192 // Attempts to remove a directory (if read only it will set its attributes to normal first).
193 static bool RemoveDirectory(const CString
& strPath
);
195 // Copies all the elements from the source directory to the target directory.
196 // It doesn't copy the source folder to the target folder, only it's contents.
197 // THIS FUNCTION IS NOT DESIGNED FOR MULTI-THREADED USAGE
198 static ECopyTreeResult
CopyTree(const CString
& strSourceDirectory
, const CString
& strTargetDirectory
, bool boRecurse
= true, bool boConfirmOverwrite
= false);
200 //////////////////////////////////////////////////////////////////////////
201 // @param LPPROGRESS_ROUTINE pfnProgress - called by the system to notify of file copy progress
202 // @param LPBOOL pbCancel - when the contents of this BOOL are set to TRUE, the system cancels the copy operation
203 static ECopyTreeResult
CopyFile(const CString
& strSourceFile
, const CString
& strTargetFile
, bool boConfirmOverwrite
= false, LPPROGRESS_ROUTINE pfnProgress
= NULL
, LPBOOL pbCancel
= NULL
);
205 //////////////////////////////////////////////////////////////////////////
206 // @param LPPROGRESS_ROUTINE pfnProgress - called by the system to notify of file copy progress
207 // @param LPBOOL pbCancel - when the contents of this BOOL are set to TRUE, the system cancels the copy operation
208 static ECopyTreeResult
CopyFile(const char* strSourceFile
, const char* strTargetFile
, bool boConfirmOverwrite
= false, LPPROGRESS_ROUTINE pfnProgress
= NULL
, LPBOOL pbCancel
= NULL
)
210 return CopyFile(CString(strSourceFile
), CString(strTargetFile
), boConfirmOverwrite
, pfnProgress
, pbCancel
);
213 // As we don't have a FileUtil interface here, we have to duplicate some code :-( in order to keep
214 // function calls clean.
215 // Moves all the elements from the source directory to the target directory.
216 // It doesn't move the source folder to the target folder, only it's contents.
217 // THIS FUNCTION IS NOT DESIGNED FOR MULTI-THREADED USAGE
218 static ECopyTreeResult
MoveTree(const CString
& strSourceDirectory
, const CString
& strTargetDirectory
, bool boRecurse
= true, bool boConfirmOverwrite
= false);
221 static ECopyTreeResult
MoveFile(const CString
& strSourceFile
, const CString
& strTargetFile
, bool boConfirmOverwrite
= false);
223 struct ExtraMenuItems
225 std::vector
<CString
> names
;
226 int selectedIndexIfAny
;
228 ExtraMenuItems() : selectedIndexIfAny(-1) {}
230 int AddItem(const CString
& name
)
232 names
.push_back(name
);
233 return names
.size() - 1;
237 // Show Popup Menu with file commands include Source Control commands
238 // filename: a name of file without path
239 // fullGamePath: a game path to folder like "/Game/Objects" without filename
240 // wnd: pointer to window class, can be NULL
241 // isSelected: output value indicated if Select menu item was chosen, if pointer is 0 - no Select menu item.
242 // pItems: you can specify additional menu items and get the result of selection using this parameter.
243 // return false if source control operation failed
244 static void PopupMenu(const char* filename
, const char* fullGamePath
, CWnd
* wnd
= nullptr, bool* pIsSelected
= nullptr, ExtraMenuItems
* pItems
= nullptr);
245 static void QPopupMenu(const QString
& filename
, const QString
& fullGamePath
, QWidget
* parent
= nullptr, bool* pIsSelected
= nullptr, ExtraMenuItems
* pItems
= nullptr);
247 // creates a unique file name from input fileName by appending a counter number to its name
248 static QString
addUniqueSuffix(const QString
& fileName
);
250 static void GatherAssetFilenamesFromLevel(std::set
<CString
>& rOutFilenames
, bool bMakeLowerCase
= false, bool bMakeUnixPath
= false);
251 static void GatherAssetFilenamesFromLevel(DynArray
<dll_string
>& rOutFilenames
);
253 // Get file attributes include source control attributes if available
254 static uint32
GetAttributes(const char* filename
, bool bUseSourceControl
= true);
256 // Returns true if the files have the same content, false otherwise
257 static bool CompareFiles(const CString
& strFilePath1
, const CString
& strFilePath2
);
259 // Predicators to sort Columns( Ascending/Descending )
260 static bool PredicateFileNameLess(const CFileUtil::FileDesc
& desc1
, const CFileUtil::FileDesc
& desc2
);
261 static bool PredicateFileNameGreater(const CFileUtil::FileDesc
& desc1
, const CFileUtil::FileDesc
& desc2
);
262 static bool PredicateDateLess(const CFileUtil::FileDesc
& desc1
, const CFileUtil::FileDesc
& desc2
);
263 static bool PredicateDateGreater(const CFileUtil::FileDesc
& desc1
, const CFileUtil::FileDesc
& desc2
);
264 static bool PredicateSizeLess(const CFileUtil::FileDesc
& desc1
, const CFileUtil::FileDesc
& desc2
);
265 static bool PredicateSizeGreater(const CFileUtil::FileDesc
& desc1
, const CFileUtil::FileDesc
& desc2
);
267 static CString
FormatInitialFolderForFileDialog(const CString
& folder
);
268 static std::vector
<string
> PickTagsFromPath(const string
& path
);
271 // True means to use the custom file dialog, false means to use the smart file open dialog.
272 static bool s_singleFileDlgPref
[EFILE_TYPE_LAST
];
273 static bool s_multiFileDlgPref
[EFILE_TYPE_LAST
];
275 static bool CustomSelectSingleFile(
277 ECustomFileType fileType
,
279 const CString
& filter
,
280 const CString
& initialDir
,
281 const CString
& baseDir
,
282 const FileFilterCallback
& fileFilterFunc
);
284 static bool CustomSelectMultipleFiles(
285 ECustomFileType fileType
,
286 std::vector
<CString
>& outputFiles
,
287 const CString
& filter
,
288 const CString
& initialDir
,
289 const CString
& baseDir
,
290 const FileFilterCallback
& fileFilterFunc
);
292 static bool ExtractDccFilenameFromAssetDatabase(const CString
& assetFilename
, CString
& dccFilename
);
293 static bool ExtractDccFilenameUsingNamingConventions(const CString
& assetFilename
, CString
& dccFilename
);
297 // A helper for creating a temp file to write to, then copying that over the destination
298 // file only if it changes (to avoid requiring the user to check out source controlled
299 // file unnecessarily)
301 class PLUGIN_API CTempFileHelper
304 CTempFileHelper(const char* pFileName
);
307 // Gets the path to the temp file that should be written to
308 const CString
& GetTempFilePath() { return m_tempFileName
; }
310 // After the temp file has been written and closed, this should be called to update
311 // the destination file.
312 // If bBackup is true CFileUtil::BackupFile will be called if the file has changed.
313 bool UpdateFile(bool bBackup
);
317 CString m_tempFileName
;