texassemble/texconv: added wildcard support

This commit is contained in:
Chuck Walbourn 2016-09-12 21:54:08 -07:00
parent 2d27b1447e
commit e35e84f6e1
2 changed files with 194 additions and 2 deletions

View File

@ -34,7 +34,8 @@ using namespace DirectX;
enum OPTIONS
{
OPT_CUBE = 1,
OPT_RECURSIVE = 1,
OPT_CUBE,
OPT_VOLUME,
OPT_ARRAY,
OPT_CUBEARRAY,
@ -68,6 +69,7 @@ struct SValue
SValue g_pOptions[] =
{
{ L"r", OPT_RECURSIVE },
{ L"cube", OPT_CUBE },
{ L"volume", OPT_VOLUME },
{ L"array", OPT_ARRAY },
@ -181,6 +183,12 @@ SValue g_pFilters[] =
namespace
{
inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }
struct find_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) FindClose(h); } };
typedef public std::unique_ptr<void, find_closer> ScopedFindHandle;
#pragma prefast(disable : 26018, "Only used with static internal arrays")
DWORD LookupByName(const wchar_t *pName, const SValue *pArray)
@ -196,6 +204,7 @@ namespace
return 0;
}
const wchar_t* LookupByValue(DWORD pValue, const SValue *pArray)
{
while (pArray->pName)
@ -209,6 +218,82 @@ namespace
return L"";
}
void SearchForFiles(const wchar_t* path, std::list<SConversion>& files, bool recursive)
{
// Process files
WIN32_FIND_DATA findData = {};
ScopedFindHandle hFile(safe_handle(FindFirstFileExW(path,
FindExInfoBasic, &findData,
FindExSearchNameMatch, nullptr,
FIND_FIRST_EX_LARGE_FETCH)));
if (hFile)
{
for (;;)
{
if (!(findData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)))
{
wchar_t drive[_MAX_DRIVE] = {};
wchar_t dir[_MAX_DIR] = {};
_wsplitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0);
SConversion conv;
_wmakepath_s(conv.szSrc, drive, dir, findData.cFileName, nullptr);
files.push_back(conv);
}
if (!FindNextFile(hFile.get(), &findData))
break;
}
}
// Process directories
if (recursive)
{
wchar_t searchDir[MAX_PATH] = {};
{
wchar_t drive[_MAX_DRIVE] = {};
wchar_t dir[_MAX_DIR] = {};
_wsplitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0);
_wmakepath_s(searchDir, drive, dir, L"*", nullptr);
}
hFile.reset(safe_handle(FindFirstFileExW(searchDir,
FindExInfoBasic, &findData,
FindExSearchLimitToDirectories, nullptr,
FIND_FIRST_EX_LARGE_FETCH)));
if (!hFile)
return;
for (;;)
{
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (findData.cFileName[0] != L'.')
{
wchar_t subdir[MAX_PATH] = {};
{
wchar_t drive[_MAX_DRIVE] = {};
wchar_t dir[_MAX_DIR] = {};
wchar_t fname[_MAX_FNAME] = {};
wchar_t ext[_MAX_FNAME] = {};
_wsplitpath_s(path, drive, dir, fname, ext);
wcscat_s(dir, findData.cFileName);
_wmakepath_s(subdir, drive, dir, fname, ext);
}
SearchForFiles(subdir, files, recursive);
}
}
if (!FindNextFile(hFile.get(), &findData))
break;
}
}
}
void PrintFormat(DXGI_FORMAT Format)
{
for (SValue *pFormat = g_pFormats; pFormat->pName; pFormat++)
@ -221,6 +306,7 @@ namespace
}
}
void PrintInfo(const TexMetadata& info)
{
wprintf(L" (%Iux%Iu", info.width, info.height);
@ -298,6 +384,7 @@ namespace
wprintf(L"Usage: texassemble [-cube | - volume | -array | -cubearray] <options> <files>\n");
wprintf(L"\n");
wprintf(L" -r wildcard filename search is recursive\n");
wprintf(L" -cube create cubemap\n");
wprintf(L" -volume create volume map\n");
wprintf(L" -array create texture array\n");
@ -441,6 +528,16 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
break;
}
}
else if (wcspbrk(pArg, L"?*") != nullptr)
{
size_t count = conversion.size();
SearchForFiles(pArg, conversion, (dwOptions & (1 << OPT_RECURSIVE)) != 0);
if (conversion.size() <= count)
{
wprintf(L"No matching files found for %ls\n", pArg);
return 1;
}
}
else
{
SConversion conv;

View File

@ -40,7 +40,8 @@ using Microsoft::WRL::ComPtr;
enum OPTIONS
{
OPT_WIDTH = 1,
OPT_RECURSIVE = 1,
OPT_WIDTH,
OPT_HEIGHT,
OPT_MIPLEVELS,
OPT_FORMAT,
@ -96,12 +97,14 @@ struct SValue
DWORD dwValue;
};
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
SValue g_pOptions[] =
{
{ L"r", OPT_RECURSIVE },
{ L"w", OPT_WIDTH },
{ L"h", OPT_HEIGHT },
{ L"m", OPT_MIPLEVELS },
@ -345,6 +348,12 @@ SValue g_pFeatureLevels[] = // valid feature levels for -fl for maximimum si
namespace
{
inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }
struct find_closer { void operator()(HANDLE h) { assert(h != INVALID_HANDLE_VALUE); if (h) FindClose(h); } };
typedef public std::unique_ptr<void, find_closer> ScopedFindHandle;
inline static bool ispow2(size_t x)
{
return ((x != 0) && !(x & (x - 1)));
@ -380,6 +389,81 @@ namespace
}
void SearchForFiles(const wchar_t* path, std::list<SConversion>& files, bool recursive)
{
// Process files
WIN32_FIND_DATA findData = {};
ScopedFindHandle hFile(safe_handle(FindFirstFileExW(path,
FindExInfoBasic, &findData,
FindExSearchNameMatch, nullptr,
FIND_FIRST_EX_LARGE_FETCH)));
if (hFile)
{
for (;;)
{
if (!(findData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)))
{
wchar_t drive[_MAX_DRIVE] = {};
wchar_t dir[_MAX_DIR] = {};
_wsplitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0);
SConversion conv;
_wmakepath_s(conv.szSrc, drive, dir, findData.cFileName, nullptr);
files.push_back(conv);
}
if (!FindNextFile(hFile.get(), &findData))
break;
}
}
// Process directories
if (recursive)
{
wchar_t searchDir[MAX_PATH] = {};
{
wchar_t drive[_MAX_DRIVE] = {};
wchar_t dir[_MAX_DIR] = {};
_wsplitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0);
_wmakepath_s(searchDir, drive, dir, L"*", nullptr);
}
hFile.reset(safe_handle(FindFirstFileExW(searchDir,
FindExInfoBasic, &findData,
FindExSearchLimitToDirectories, nullptr,
FIND_FIRST_EX_LARGE_FETCH)));
if (!hFile)
return;
for (;;)
{
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (findData.cFileName[0] != L'.')
{
wchar_t subdir[MAX_PATH] = {};
{
wchar_t drive[_MAX_DRIVE] = {};
wchar_t dir[_MAX_DIR] = {};
wchar_t fname[_MAX_FNAME] = {};
wchar_t ext[_MAX_FNAME] = {};
_wsplitpath_s(path, drive, dir, fname, ext);
wcscat_s(dir, findData.cFileName);
_wmakepath_s(subdir, drive, dir, fname, ext);
}
SearchForFiles(subdir, files, recursive);
}
}
if (!FindNextFile(hFile.get(), &findData))
break;
}
}
}
void PrintFormat(DXGI_FORMAT Format)
{
for (SValue *pFormat = g_pFormats; pFormat->pName; pFormat++)
@ -511,6 +595,7 @@ namespace
wprintf(L"Usage: texconv <options> <files>\n");
wprintf(L"\n");
wprintf(L" -r wildcard filename search is recursive\n");
wprintf(L" -w <n> width\n");
wprintf(L" -h <n> height\n");
wprintf(L" -m <n> miplevels\n");
@ -1096,6 +1181,16 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
break;
}
}
else if (wcspbrk(pArg, L"?*") != nullptr)
{
size_t count = conversion.size();
SearchForFiles(pArg, conversion, (dwOptions & (1 << OPT_RECURSIVE)) != 0);
if (conversion.size() <= count)
{
wprintf(L"No matching files found for %ls\n", pArg);
return 1;
}
}
else
{
SConversion conv;