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
|
---|