[760] | 1 |
|
---|
| 2 | /*
|
---|
| 3 | GetFilePath.h
|
---|
| 4 |
|
---|
| 5 | A convenient way to search the NVSDK for media files
|
---|
| 6 | */
|
---|
| 7 |
|
---|
| 8 |
|
---|
| 9 | #ifndef H_GETFILEPATH_H
|
---|
| 10 | #define H_GETFILEPATH_H
|
---|
| 11 |
|
---|
| 12 | #include <windows.h>
|
---|
| 13 | #include <TCHAR.H>
|
---|
| 14 | #include <string>
|
---|
| 15 | #include "shared/NV_Common.h"
|
---|
| 16 | #include "shared/NV_Error.h"
|
---|
| 17 | #include "shared/nvFileSearch.h"
|
---|
| 18 |
|
---|
| 19 | typedef std::basic_string<TCHAR> tstring;
|
---|
| 20 |
|
---|
| 21 | namespace GetFilePath
|
---|
| 22 | {
|
---|
| 23 | static tstring strStartPath;
|
---|
| 24 |
|
---|
| 25 | typedef tstring (*GetFilePathFunction)(const tstring &, bool bVerbose );
|
---|
| 26 |
|
---|
| 27 | // This variable allows us to recursively search for media
|
---|
| 28 | class NVMediaSearch : public NVFileSearch
|
---|
| 29 | {
|
---|
| 30 | public:
|
---|
| 31 | tstring m_strPath;
|
---|
| 32 | virtual bool FileFoundCallback(const WIN32_FIND_DATA& FindData, const tstring& strDir)
|
---|
| 33 | {
|
---|
| 34 | UNREFERENCED_PARAMETER(FindData);
|
---|
| 35 | m_strPath = strDir;
|
---|
| 36 |
|
---|
| 37 | return false;
|
---|
| 38 | }
|
---|
| 39 | };
|
---|
| 40 |
|
---|
| 41 |
|
---|
| 42 | static tstring GetModulePath() { return strStartPath; }
|
---|
| 43 | static void SetModulePath(const tstring &strPath)
|
---|
| 44 | {
|
---|
| 45 | tstring::size_type Pos = strPath.find_last_of(_T("\\"), strPath.size());
|
---|
| 46 | if (Pos != strPath.npos)
|
---|
| 47 | strStartPath = strPath.substr(0, Pos);
|
---|
| 48 | else
|
---|
| 49 | strStartPath = _T(".");
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | static void SetDefaultModulePath()
|
---|
| 53 | {
|
---|
| 54 | DWORD ret;
|
---|
| 55 | TCHAR buf[MAX_PATH];
|
---|
| 56 | ret = GetModuleFileName( NULL, buf, MAX_PATH ); // get name for current module
|
---|
| 57 | if( ret == 0 )
|
---|
| 58 | {
|
---|
| 59 | FMsg(TEXT("SetDefaultModulePath() GetModuleFileName() failed!\n"));
|
---|
| 60 | assert( false );
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | SetModulePath( buf );
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 |
|
---|
| 67 |
|
---|
| 68 | static tstring GetFullPath(const tstring &strRelativePath)
|
---|
| 69 | {
|
---|
| 70 | TCHAR buf[MAX_PATH];
|
---|
| 71 | TCHAR *pAdr;
|
---|
| 72 | GetFullPathName(strRelativePath.data(), MAX_PATH, buf, &pAdr);
|
---|
| 73 | return buf;
|
---|
| 74 | }
|
---|
| 75 |
|
---|
| 76 | //a helper class to save and restore the currentDirectory
|
---|
| 77 | class DirectorySaver
|
---|
| 78 | {
|
---|
| 79 | private:
|
---|
| 80 | TCHAR savedDirectory[MAX_PATH];
|
---|
| 81 | public:
|
---|
| 82 | DirectorySaver( )
|
---|
| 83 | {
|
---|
| 84 | // Save current directory
|
---|
| 85 | GetCurrentDirectory(MAX_PATH, savedDirectory);
|
---|
| 86 | }
|
---|
| 87 | ~DirectorySaver( )
|
---|
| 88 | {
|
---|
| 89 | // return to previous directory
|
---|
| 90 | SetCurrentDirectory(this->savedDirectory);
|
---|
| 91 | }
|
---|
| 92 | };
|
---|
| 93 |
|
---|
| 94 | // Recursively searchs the given path until it finds the file. Returns "" if
|
---|
| 95 | // file can't be found
|
---|
| 96 | static tstring FindMediaFile(const tstring &strFilename, const tstring &mediaPath, bool bVerbose = false )
|
---|
| 97 | {
|
---|
| 98 | WIN32_FIND_DATA findInfo;
|
---|
| 99 | HANDLE hFind;
|
---|
| 100 | tstring result;
|
---|
| 101 |
|
---|
| 102 |
|
---|
| 103 | //save and auto restore the current working directory
|
---|
| 104 | DirectorySaver whenIGoOutOfScopeTheCurrentWorkingDirectoryWillBeRestored;
|
---|
| 105 |
|
---|
| 106 | if (!SetCurrentDirectory(mediaPath.data()))
|
---|
| 107 | {
|
---|
| 108 | // DWORD tmp2 = GetLastError();
|
---|
| 109 | if( bVerbose )
|
---|
| 110 | {
|
---|
| 111 | FMsg(TEXT("FindMediaFile Couldn't SetCurrentDirectory to [%s]. Returning empty string\n"), mediaPath.c_str() );
|
---|
| 112 | }
|
---|
| 113 | return _T("");
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 | // check if file is in current directory
|
---|
| 117 | FILE *fp;
|
---|
| 118 | fp = _tfopen(strFilename.data(), _T("r"));
|
---|
| 119 | if (fp)
|
---|
| 120 | {
|
---|
| 121 | fclose(fp);
|
---|
| 122 | return mediaPath + _T("\\") + strFilename;
|
---|
| 123 | }
|
---|
| 124 | else
|
---|
| 125 | {
|
---|
| 126 | if( bVerbose )
|
---|
| 127 | {
|
---|
| 128 | // report where the file is NOT
|
---|
| 129 | FMsg(TEXT("FindMediaFile: File [%s] is not in %s\n"), strFilename.c_str(), mediaPath.c_str() );
|
---|
| 130 | }
|
---|
| 131 | }
|
---|
| 132 |
|
---|
| 133 | // if file not in current directory, search for all directories
|
---|
| 134 | // and search inside them until the file is found
|
---|
| 135 | hFind = FindFirstFile( _T( "*.*" ) , &findInfo);
|
---|
| 136 | if (hFind == INVALID_HANDLE_VALUE)
|
---|
| 137 | return _T("");
|
---|
| 138 |
|
---|
| 139 | result = _T("");
|
---|
| 140 | do
|
---|
| 141 | {
|
---|
| 142 | if (findInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
---|
| 143 | {
|
---|
| 144 | // Make sure we don't try to delete the '.' or '..' directories
|
---|
| 145 | if ((_tcscmp(findInfo.cFileName, _T("..")) == 0) || (_tcscmp(findInfo.cFileName, _T(".")) == 0))
|
---|
| 146 | continue;
|
---|
| 147 |
|
---|
| 148 | // Add directory to the media path
|
---|
| 149 | // Keep same original file name
|
---|
| 150 | result = FindMediaFile(strFilename, mediaPath + _T("\\") + findInfo.cFileName, bVerbose );
|
---|
| 151 | if (result != _T(""))
|
---|
| 152 | break;
|
---|
| 153 | }
|
---|
| 154 | } while (FindNextFile(hFind, &findInfo));
|
---|
| 155 |
|
---|
| 156 | FindClose(hFind);
|
---|
| 157 |
|
---|
| 158 | return result;
|
---|
| 159 | }
|
---|
| 160 |
|
---|
| 161 | //////////////////////////////////////////////////////////////////////////////
|
---|
| 162 | // Gets the full path to the requested file by searching in the MEDIA directory.
|
---|
| 163 | // (note: for a pointer to a 1-parameter version of this function, see below.)
|
---|
| 164 | static tstring GetFilePath(const tstring& strFileName, bool bVerbose )
|
---|
| 165 | {
|
---|
| 166 | // Check if strFilename already points to a file
|
---|
| 167 | FILE *fp;
|
---|
| 168 | fp = _tfopen(strFileName.data(), _T("r"));
|
---|
| 169 | if (fp)
|
---|
| 170 | {
|
---|
| 171 | fclose(fp);
|
---|
| 172 | return strFileName;
|
---|
| 173 | }
|
---|
| 174 |
|
---|
| 175 | // You should call SetModulePath before using GetFilePath()
|
---|
| 176 | // If not, it will set the module path for you
|
---|
| 177 |
|
---|
| 178 | tstring strMediaPath = GetModulePath();
|
---|
| 179 | if( strMediaPath.empty() == true )
|
---|
| 180 | {
|
---|
| 181 | SetDefaultModulePath();
|
---|
| 182 | strMediaPath = GetModulePath();
|
---|
| 183 | }
|
---|
| 184 |
|
---|
| 185 | // Find the last occurrence of '\' or '/'
|
---|
| 186 | // This has the effect of backing up 4 directories, implying a direct dependence on
|
---|
| 187 | // the location of the calling .exe in order to start looking for media in the right
|
---|
| 188 | // place. This is bad, so a more general search for the first subdirectory \MEDIA
|
---|
| 189 | // should be put in place
|
---|
| 190 | // TODO : see above
|
---|
| 191 | strMediaPath = strMediaPath.substr(0, strMediaPath.find_last_of(_T("\\/")));
|
---|
| 192 | strMediaPath = strMediaPath.substr(0, strMediaPath.find_last_of(_T("\\/")));
|
---|
| 193 | strMediaPath = strMediaPath.substr(0, strMediaPath.find_last_of(_T("\\/")));
|
---|
| 194 | strMediaPath = strMediaPath.substr(0, strMediaPath.find_last_of(_T("\\/")));
|
---|
| 195 | strMediaPath += _T("\\MEDIA");
|
---|
| 196 |
|
---|
| 197 | tstring result;
|
---|
| 198 | result = FindMediaFile(strFileName, strMediaPath, bVerbose);
|
---|
| 199 |
|
---|
| 200 | if (result != _T(""))
|
---|
| 201 | return result;
|
---|
| 202 |
|
---|
| 203 | //////////////////// for local shaders /////////////////////////
|
---|
| 204 | strMediaPath = GetModulePath();
|
---|
| 205 | strMediaPath += _T("\\Shaders");
|
---|
| 206 |
|
---|
| 207 | result = FindMediaFile(strFileName, strMediaPath, bVerbose);
|
---|
| 208 |
|
---|
| 209 | if (result != _T(""))
|
---|
| 210 | return result;
|
---|
| 211 |
|
---|
| 212 | //////////////////// for local ../shaders /////////////////////////
|
---|
| 213 | strMediaPath = GetModulePath();
|
---|
| 214 | strMediaPath = strMediaPath.substr(0, strMediaPath.find_last_of(_T("\\/")));
|
---|
| 215 | strMediaPath += _T("\\Shaders");
|
---|
| 216 |
|
---|
| 217 | result = FindMediaFile(strFileName, strMediaPath, bVerbose);
|
---|
| 218 |
|
---|
| 219 | if (result != _T(""))
|
---|
| 220 | return result;
|
---|
| 221 |
|
---|
| 222 | // If prog gets to here, the find has failed.
|
---|
| 223 | // Return the input file name so other apps can report the failure
|
---|
| 224 | // to find the file.
|
---|
| 225 | if( bVerbose )
|
---|
| 226 | FMsg(TEXT("GetFilePath() Couldn't find : %s\n"), strFileName.c_str() );
|
---|
| 227 |
|
---|
| 228 | return strFileName;
|
---|
| 229 | };
|
---|
| 230 |
|
---|
| 231 | // Use these wrapper functions if you need to pass a pointer [callback]
|
---|
| 232 | // to a 1-parameter version of the GetFilePath() function:
|
---|
| 233 | static tstring GetFilePath(const tstring& strFileName) {
|
---|
| 234 | return GetFilePath(strFileName, false);
|
---|
| 235 | }
|
---|
| 236 | static tstring GetFilePathVerbose(const tstring& strFileName) {
|
---|
| 237 | return GetFilePath(strFileName, true);
|
---|
| 238 | }
|
---|
| 239 |
|
---|
| 240 | }; // namespace GetFilePath
|
---|
| 241 |
|
---|
| 242 |
|
---|
| 243 | #endif
|
---|