mirror of
https://github.com/microsoft/DirectXTex
synced 2024-12-25 02:41:04 +00:00
texassemble/texconv: added wildcard support
This commit is contained in:
parent
2d27b1447e
commit
e35e84f6e1
@ -34,7 +34,8 @@ using namespace DirectX;
|
|||||||
|
|
||||||
enum OPTIONS
|
enum OPTIONS
|
||||||
{
|
{
|
||||||
OPT_CUBE = 1,
|
OPT_RECURSIVE = 1,
|
||||||
|
OPT_CUBE,
|
||||||
OPT_VOLUME,
|
OPT_VOLUME,
|
||||||
OPT_ARRAY,
|
OPT_ARRAY,
|
||||||
OPT_CUBEARRAY,
|
OPT_CUBEARRAY,
|
||||||
@ -68,6 +69,7 @@ struct SValue
|
|||||||
|
|
||||||
SValue g_pOptions[] =
|
SValue g_pOptions[] =
|
||||||
{
|
{
|
||||||
|
{ L"r", OPT_RECURSIVE },
|
||||||
{ L"cube", OPT_CUBE },
|
{ L"cube", OPT_CUBE },
|
||||||
{ L"volume", OPT_VOLUME },
|
{ L"volume", OPT_VOLUME },
|
||||||
{ L"array", OPT_ARRAY },
|
{ L"array", OPT_ARRAY },
|
||||||
@ -181,6 +183,12 @@ SValue g_pFilters[] =
|
|||||||
|
|
||||||
namespace
|
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")
|
#pragma prefast(disable : 26018, "Only used with static internal arrays")
|
||||||
|
|
||||||
DWORD LookupByName(const wchar_t *pName, const SValue *pArray)
|
DWORD LookupByName(const wchar_t *pName, const SValue *pArray)
|
||||||
@ -196,6 +204,7 @@ namespace
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const wchar_t* LookupByValue(DWORD pValue, const SValue *pArray)
|
const wchar_t* LookupByValue(DWORD pValue, const SValue *pArray)
|
||||||
{
|
{
|
||||||
while (pArray->pName)
|
while (pArray->pName)
|
||||||
@ -209,6 +218,82 @@ namespace
|
|||||||
return L"";
|
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)
|
void PrintFormat(DXGI_FORMAT Format)
|
||||||
{
|
{
|
||||||
for (SValue *pFormat = g_pFormats; pFormat->pName; pFormat++)
|
for (SValue *pFormat = g_pFormats; pFormat->pName; pFormat++)
|
||||||
@ -221,6 +306,7 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PrintInfo(const TexMetadata& info)
|
void PrintInfo(const TexMetadata& info)
|
||||||
{
|
{
|
||||||
wprintf(L" (%Iux%Iu", info.width, info.height);
|
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"Usage: texassemble [-cube | - volume | -array | -cubearray] <options> <files>\n");
|
||||||
wprintf(L"\n");
|
wprintf(L"\n");
|
||||||
|
wprintf(L" -r wildcard filename search is recursive\n");
|
||||||
wprintf(L" -cube create cubemap\n");
|
wprintf(L" -cube create cubemap\n");
|
||||||
wprintf(L" -volume create volume map\n");
|
wprintf(L" -volume create volume map\n");
|
||||||
wprintf(L" -array create texture array\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;
|
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
|
else
|
||||||
{
|
{
|
||||||
SConversion conv;
|
SConversion conv;
|
||||||
|
@ -40,7 +40,8 @@ using Microsoft::WRL::ComPtr;
|
|||||||
|
|
||||||
enum OPTIONS
|
enum OPTIONS
|
||||||
{
|
{
|
||||||
OPT_WIDTH = 1,
|
OPT_RECURSIVE = 1,
|
||||||
|
OPT_WIDTH,
|
||||||
OPT_HEIGHT,
|
OPT_HEIGHT,
|
||||||
OPT_MIPLEVELS,
|
OPT_MIPLEVELS,
|
||||||
OPT_FORMAT,
|
OPT_FORMAT,
|
||||||
@ -96,12 +97,14 @@ struct SValue
|
|||||||
DWORD dwValue;
|
DWORD dwValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SValue g_pOptions[] =
|
SValue g_pOptions[] =
|
||||||
{
|
{
|
||||||
|
{ L"r", OPT_RECURSIVE },
|
||||||
{ L"w", OPT_WIDTH },
|
{ L"w", OPT_WIDTH },
|
||||||
{ L"h", OPT_HEIGHT },
|
{ L"h", OPT_HEIGHT },
|
||||||
{ L"m", OPT_MIPLEVELS },
|
{ L"m", OPT_MIPLEVELS },
|
||||||
@ -345,6 +348,12 @@ SValue g_pFeatureLevels[] = // valid feature levels for -fl for maximimum si
|
|||||||
|
|
||||||
namespace
|
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)
|
inline static bool ispow2(size_t x)
|
||||||
{
|
{
|
||||||
return ((x != 0) && !(x & (x - 1)));
|
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)
|
void PrintFormat(DXGI_FORMAT Format)
|
||||||
{
|
{
|
||||||
for (SValue *pFormat = g_pFormats; pFormat->pName; pFormat++)
|
for (SValue *pFormat = g_pFormats; pFormat->pName; pFormat++)
|
||||||
@ -511,6 +595,7 @@ namespace
|
|||||||
|
|
||||||
wprintf(L"Usage: texconv <options> <files>\n");
|
wprintf(L"Usage: texconv <options> <files>\n");
|
||||||
wprintf(L"\n");
|
wprintf(L"\n");
|
||||||
|
wprintf(L" -r wildcard filename search is recursive\n");
|
||||||
wprintf(L" -w <n> width\n");
|
wprintf(L" -w <n> width\n");
|
||||||
wprintf(L" -h <n> height\n");
|
wprintf(L" -h <n> height\n");
|
||||||
wprintf(L" -m <n> miplevels\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;
|
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
|
else
|
||||||
{
|
{
|
||||||
SConversion conv;
|
SConversion conv;
|
||||||
|
Loading…
Reference in New Issue
Block a user