You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
639 lines
20 KiB
639 lines
20 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include <stdafx.h> |
|
#include "MapWorld.h" |
|
#include "MessageWnd.h" |
|
#include "IEditorTexture.h" |
|
#include "GlobalFunctions.h" |
|
#include "TextureSystem.h" |
|
#include "TextureConverter.h" |
|
#include "filesystem.h" |
|
#include "Hammer.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
|
|
CProgressDlg * CTextureConverter::m_pProgDlg; |
|
int CTextureConverter::m_nSolidCount; |
|
int CTextureConverter::m_nFaceCount; |
|
int CTextureConverter::m_nDecalCount; |
|
int CTextureConverter::m_nCurrentSolid; |
|
int CTextureConverter::m_nCurrentDecal; |
|
int CTextureConverter::m_nSuccesses; |
|
int CTextureConverter::m_nErrors; |
|
int CTextureConverter::m_nSkipped; |
|
int CTextureConverter::m_nWarnings; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Reset counters. |
|
// Input : |
|
// Output : Counters all reset to 0. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::Initialize( void ) |
|
{ |
|
m_nSolidCount = 0; |
|
m_nCurrentSolid = 0; |
|
m_nFaceCount = 0; |
|
m_nDecalCount = 0; |
|
m_nCurrentDecal = 0; |
|
|
|
m_nSuccesses = 0; |
|
m_nErrors = 0; |
|
m_nSkipped = 0; |
|
m_nWarnings = 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Recurse through the contents of the map, passing solid objects on |
|
// to be converted. |
|
// Input : pWorld - pointer to the map to have textures converted. |
|
// Output : All solid faces and decals in the world have WAD3 textures |
|
// converted to VMT. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::ConvertWorldTextures( CMapWorld * pWorld ) |
|
{ |
|
Initialize(); |
|
|
|
// Bring the message window to the front, to display conversion info |
|
g_pwndMessage->Activate(); |
|
|
|
Msg( mwStatus, "Converting textures from WAD to VMT format..." ); |
|
|
|
// Set up a progress meter dialogue |
|
m_pProgDlg = new CProgressDlg; |
|
m_pProgDlg->Create(); |
|
m_pProgDlg->SetStep( 1 ); |
|
m_pProgDlg->SetWindowText( "Preparing to convert textures..." ); |
|
|
|
// Run the converter |
|
ConvertSolids( pWorld ); |
|
ConvertDecals( pWorld ); |
|
DisplayStatistics(); |
|
|
|
// Destroy the progress meter |
|
if ( m_pProgDlg ) |
|
{ |
|
m_pProgDlg->DestroyWindow(); |
|
delete m_pProgDlg; |
|
m_pProgDlg = NULL; |
|
} |
|
|
|
AfxMessageBox( "Conversion complete. Check the Hammer \"Messages\" window for complete details." ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Recurse through the contents of the map, passing solid objects on |
|
// to be converted. |
|
// Input : pWorld - pointer to the map to have textures converted. |
|
// Output : All solid faces in the world have WAD3 textures converted to VMT. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::ConvertSolids( CMapWorld * pWorld ) |
|
{ |
|
// Count total map solids so we know how many we have to do (for progress meter). |
|
pWorld->EnumChildren( ENUMMAPCHILDRENPROC( CountMapSolids ), 0, MAPCLASS_TYPE( CMapSolid ) ); |
|
|
|
m_pProgDlg->SetRange( 0, m_nSolidCount ); |
|
m_pProgDlg->SetStep( 2 ); |
|
m_pProgDlg->SetWindowText( "Converting solids..." ); |
|
|
|
// Cycle through the solids again and convert as necessary. |
|
pWorld->EnumChildren( ENUMMAPCHILDRENPROC( CheckSolidTextures ), 0, MAPCLASS_TYPE( CMapSolid ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Enumeration function, increment the solids counter. |
|
// Input : |
|
// Output : Always return true to continue enumerating. |
|
//----------------------------------------------------------------------------- |
|
bool CTextureConverter::CountMapSolids( CMapSolid *, DWORD ) |
|
{ |
|
m_nSolidCount++; |
|
|
|
return true; // return true to continue enumerating |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Enumeration function, check all the faces of a solid for texture conversion |
|
// Input : pSolid - map solid to be checked. |
|
// Output : Always return true to continue enumerating. |
|
//----------------------------------------------------------------------------- |
|
bool CTextureConverter::CheckSolidTextures( CMapSolid * pSolid, DWORD ) |
|
{ |
|
int nFaceCount; |
|
|
|
m_nCurrentSolid++; |
|
|
|
if ( m_nCurrentSolid % 100 == 0 ) |
|
m_pProgDlg->SetPos( m_nCurrentSolid ); |
|
|
|
// check each face of the solid |
|
nFaceCount = pSolid->GetFaceCount(); |
|
while( nFaceCount-- ) |
|
{ |
|
CheckFaceTexture( pSolid->GetFace( nFaceCount ) ); |
|
} |
|
|
|
return true; // return true to continue enumerating |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Check the texture of a face to determine if conversion is necessary. |
|
// Input : pFace - a map face. |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::CheckFaceTexture( CMapFace * pFace ) |
|
{ |
|
m_nFaceCount++; |
|
|
|
// Criteria for needing conversion is a) being a dummy texture AND b) having no slashes |
|
// in the texture name. |
|
|
|
if ( !pFace->GetTexture()->IsDummy() ) |
|
{ |
|
m_nSkipped++; |
|
return; |
|
} |
|
|
|
if ( strchr( pFace->GetTexture()->GetName(), '/') != NULL ) |
|
{ |
|
m_nSkipped++; |
|
return; |
|
} |
|
|
|
ConvertFaceTexture( pFace ); |
|
} |
|
|
|
|
|
bool TextureEndsIn( const char *pTextureName, const char *pEnd ) |
|
{ |
|
const char *pLast = strrchr( pTextureName, '\\' ); |
|
if ( strrchr( pTextureName, '/' ) > pLast ) |
|
pLast = strrchr( pTextureName, '/' ); |
|
|
|
if ( pLast ) |
|
return stricmp( pLast+1, pEnd ) == 0; |
|
else |
|
return stricmp( pTextureName, pEnd ) == 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Determine if any materials match the old texture of a face and replace |
|
// appropriately. |
|
// Input : pFace - a map face known to need conversion. |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::ConvertFaceTexture( CMapFace * pFace ) |
|
{ |
|
EditorTextureList_t tlMatches; |
|
IEditorTexture *pNewTexture; |
|
|
|
const char *pTextureName = pFace->GetTexture()->GetName(); |
|
|
|
// Check for SKY and SKIP brushes. |
|
char *replacements[][2] = |
|
{ |
|
{ "sky", "tools/toolsskybox" }, |
|
{ "skip", "tools/toolsskip" }, |
|
{ "aaatrigger", "tools/toolstrigger" }, |
|
{ "hint", "tools/toolshint" }, |
|
{ "clip", "tools/toolsclip" }, |
|
{ "null", "tools/toolsnodraw" } |
|
}; |
|
for ( int i=0; i < sizeof( replacements ) / sizeof( replacements[0] ); i++ ) |
|
{ |
|
if ( TextureEndsIn( pTextureName, replacements[i][0] ) ) |
|
{ |
|
pNewTexture = g_Textures.FindActiveTexture( replacements[i][1] ); |
|
if ( pNewTexture ) |
|
{ |
|
ReplaceFaceTexture( pFace, pNewTexture ); |
|
return; |
|
} |
|
} |
|
} |
|
|
|
GetNewTextureMatches( pTextureName, tlMatches ); |
|
|
|
switch( tlMatches.Count() ) |
|
{ |
|
case 0: |
|
MsgConvertFace( pFace, "ERROR: No matching material. Cannot convert." ); |
|
m_nErrors++; |
|
|
|
break; |
|
case 1: |
|
pNewTexture = tlMatches.Element(0); |
|
ReplaceFaceTexture( pFace, pNewTexture ); |
|
|
|
break; |
|
default: |
|
// Multiple matches. For now, just use the first. |
|
pNewTexture = tlMatches.Element(0); |
|
ReplaceFaceTexture( pFace, pNewTexture ); |
|
break; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Recurse through the contents of the map, passing decal objects on |
|
// to be converted. |
|
// Input : pWorld - pointer to the map to have textures converted. |
|
// Output : All decals in the world have WAD3 textures converted to VMT. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::ConvertDecals( CMapWorld * pWorld ) |
|
{ |
|
// Count total map decals so we know how many we have to do (for progress meter). |
|
pWorld->EnumChildren( ENUMMAPCHILDRENPROC( CountMapDecals ), 0, MAPCLASS_TYPE( CMapEntity ) ); |
|
|
|
m_pProgDlg->SetRange( 0, m_nDecalCount ); |
|
m_pProgDlg->SetStep( 3 ); |
|
m_pProgDlg->SetWindowText( "Converting decals..." ); |
|
|
|
// Cycle through the solids again and convert as necessary. |
|
pWorld->EnumChildren( ENUMMAPCHILDRENPROC( CheckDecalTextures ), 0, MAPCLASS_TYPE( CMapEntity ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Enumeration function, increment the decals counter if entity is a decal. |
|
// Input : |
|
// Output : Always return true to continue enumerating. |
|
//----------------------------------------------------------------------------- |
|
bool CTextureConverter::CountMapDecals( CMapEntity * pEnt, DWORD ) |
|
{ |
|
if ( !strcmp( pEnt->GetClassName(), "infodecal" ) ) |
|
m_nDecalCount++; |
|
|
|
return true; // return true to continue enumerating |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Enumeration function, check a decal's texture to determine if |
|
// conversion is necessary. |
|
// Input : pEnt - map decal to be checked. |
|
// Output : Always return true to continue enumerating. |
|
//----------------------------------------------------------------------------- |
|
bool CTextureConverter::CheckDecalTextures( CMapEntity * pEnt, DWORD ) |
|
{ |
|
if ( strcmp( pEnt->GetClassName(), "infodecal" ) ) |
|
return true; // not a decal, return true to continue enumerating |
|
|
|
m_nCurrentDecal++; |
|
|
|
m_pProgDlg->SetPos( m_nCurrentDecal ); |
|
|
|
if ( strchr( pEnt->GetKeyValue( "texture" ), '/') != NULL ) |
|
{ |
|
m_nSkipped++; |
|
} |
|
else |
|
{ |
|
ConvertDecalTexture( pEnt ); |
|
} |
|
|
|
return true; // return true to continue enumerating |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Determine if any materials match the old texture of a decal and replace |
|
// appropriately. |
|
// Input : pEnt - a map decal known to need conversion. |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::ConvertDecalTexture( CMapEntity * pEnt ) |
|
{ |
|
EditorTextureList_t tlMatches; |
|
IEditorTexture *pNewTexture; |
|
|
|
GetNewTextureMatches( pEnt->GetKeyValue( "texture" ), tlMatches ); |
|
|
|
switch( tlMatches.Count() ) |
|
{ |
|
case 0: |
|
MsgConvertDecal( pEnt, "ERROR: No matching material. Cannot convert." ); |
|
m_nErrors++; |
|
|
|
break; |
|
case 1: |
|
pNewTexture = tlMatches.Element(0); |
|
ReplaceDecalTexture( pEnt, pNewTexture ); |
|
|
|
break; |
|
default: |
|
// Multiple matches. For now, just use the first. |
|
pNewTexture = tlMatches.Element(0); |
|
|
|
MsgConvertDecal( pEnt, "WARNING: Multiple matches found. Using first match (%s).", pNewTexture->GetName() ); |
|
m_nWarnings++; |
|
|
|
ReplaceDecalTexture( pEnt, pNewTexture ); |
|
|
|
break; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Look for material matches for an old texture and add them to a list. |
|
// Input : pszOldName - old texture name. |
|
// pMatchList - empty texture list. |
|
// Output : pMatchList - texture list is filled in with matching material textures. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::GetNewTextureMatches( const char * pszOldName, EditorTextureList_t &tlMatchList ) |
|
{ |
|
IEditorTexture * pTexture; |
|
int nIndex; |
|
|
|
nIndex = 0; |
|
pTexture = g_Textures.EnumActiveTextures( &nIndex, tfVMT ); |
|
|
|
// loop through all VMT textures |
|
while ( pTexture != NULL ) |
|
{ |
|
if ( TextureNameMatchesMaterialName( pszOldName, pTexture->GetName() ) ) // check for a match |
|
{ |
|
tlMatchList.AddToTail( pTexture ); |
|
} |
|
|
|
pTexture = g_Textures.EnumActiveTextures( &nIndex, tfVMT ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Compare an old texture name to a new material name. |
|
// Input : pszTextureName - Old texture name. |
|
// pszMaterialName - New material name. |
|
// Output : Return true if the old texture name is the same (case insensitive) |
|
// as the last token (delimiter '/') of the new material name, otherwise |
|
// return false. |
|
//----------------------------------------------------------------------------- |
|
bool CTextureConverter::TextureNameMatchesMaterialName( const char * pszTextureName, const char * pszMaterialName ) |
|
{ |
|
const char * pszPartialMaterialName; // sublocation of the material name |
|
|
|
pszPartialMaterialName = strrchr( pszMaterialName, '/' ); // Find the last '/' |
|
|
|
if ( pszPartialMaterialName != NULL) |
|
{ |
|
pszPartialMaterialName++; // Point to the character after the '/' |
|
} |
|
else |
|
{ |
|
pszPartialMaterialName = pszMaterialName; // No slashes found, just point to the name |
|
} |
|
|
|
// No '/' found in the VMT name, or the name ended in a '/'. This shouldn't happen. |
|
if ( ( pszPartialMaterialName == NULL ) || strlen( pszPartialMaterialName ) == 0 ) |
|
return false; |
|
|
|
if ( stricmp( pszTextureName, pszPartialMaterialName ) == 0 ) |
|
return true; |
|
|
|
return false; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Change the texture on a face, re-scaling if possible. |
|
// Input : pFace - a map face |
|
// pNewTexture - texture to place on the map face. |
|
// Output : pFace has a new texture pointer set. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::ReplaceFaceTexture( CMapFace * pFace, IEditorTexture * pNewTexture ) |
|
{ |
|
if ( !pNewTexture->Load() ) // make sure new texture is loaded |
|
{ |
|
MsgConvertFace( pFace, "WARNING: Couldn't load new material. Texture converted but not re-scaled." ); |
|
m_nWarnings++; |
|
} |
|
|
|
RescaleFaceTexture( pFace, pNewTexture ); |
|
|
|
pFace->SetTexture( pNewTexture ); |
|
|
|
m_nSuccesses++; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Change the texture on a decal |
|
// Input : pEntity - a map decal |
|
// pNewTexture - texture to place on the map face. |
|
// Output : pEnt has a new texture set |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::ReplaceDecalTexture( CMapEntity * pEnt, IEditorTexture * pNewTexture ) |
|
{ |
|
pEnt->SetKeyValue( "texture", pNewTexture->GetName() ); |
|
m_nSuccesses++; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Find a WAD3 texture based on a name search. |
|
// Input : pszName - name of the texture to search for. |
|
// Output : return a texture if found, otherwise NULL. |
|
//----------------------------------------------------------------------------- |
|
IEditorTexture * CTextureConverter::FindWAD3Texture( const char * pszName ) |
|
{ |
|
IEditorTexture * pTexture; |
|
int nIndex; |
|
|
|
nIndex = 0; |
|
pTexture = g_Textures.EnumActiveTextures( &nIndex, tfWAD3 ); |
|
|
|
// loop through all the WAD3 textures |
|
while ( pTexture != NULL ) |
|
{ |
|
if ( !strcmp( pTexture->GetName(), pszName ) ) //check for exact match |
|
return pTexture; |
|
|
|
pTexture = g_Textures.EnumActiveTextures( &nIndex, tfWAD3 ); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Change the scale and shift values of a texture, based on old texture |
|
// image dimensions compared to new texture image dimensions. |
|
// Input : pFace - map face that the texture to be scaled is on. |
|
// pOldTexture - the old texture. |
|
// pNewTexture - the new texture. |
|
// Output : pFace->scale and pface->texture are modified if either the height or |
|
// width (or both) of the texture has changed. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::RescaleFaceTexture( CMapFace * pFace, IEditorTexture * pNewTexture ) |
|
{ |
|
int nNewWidth; |
|
int nNewHeight; |
|
|
|
int nOldWidth = -1; |
|
int nOldHeight = -1; |
|
|
|
// First look for the .resizeinfo in the mod dir (hl2\dod), then the game dir (hl2\hl2). |
|
char resizeInfoFilename[512]; |
|
Q_snprintf( resizeInfoFilename, sizeof( resizeInfoFilename ), "materials\\%s.resizeinfo", pNewTexture->GetName() ); |
|
FileHandle_t fp = g_pFileSystem->Open( resizeInfoFilename, "rt" ); |
|
if ( !fp ) |
|
{ |
|
return; |
|
} |
|
|
|
char line[512]; |
|
int nScanned = 0; |
|
if ( g_pFullFileSystem->ReadLine( line, sizeof( line ), fp ) ) |
|
{ |
|
nScanned = sscanf( line, "%d %d", &nOldWidth, &nOldHeight ); |
|
} |
|
g_pFileSystem->Close( fp ); |
|
if ( nScanned != 2 || nOldWidth < 0 || nOldHeight < 0 || nOldWidth > 5000 || nOldHeight > 5000 ) |
|
return; |
|
|
|
nNewWidth = pNewTexture->GetWidth(); |
|
nNewHeight = pNewTexture->GetHeight(); |
|
|
|
// Divide by 0 checks |
|
if ( ( nOldWidth == 0 ) || ( nOldHeight == 0 ) ) |
|
{ |
|
MsgConvertFace( pFace, |
|
"WARNING: Invalid old texture dimensions (%dx%d). Texture converted but not re-scaled.", |
|
nOldWidth, |
|
nOldHeight |
|
); |
|
m_nWarnings++; |
|
return; |
|
} |
|
|
|
// Divide by 0 checks |
|
if ( ( nNewWidth == 0 ) || ( nNewHeight == 0 ) ) |
|
{ |
|
MsgConvertFace( pFace, |
|
"WARNING: Invalid new material dimensions (%dx%d). Texture converted but not re-scaled.", |
|
nNewWidth, |
|
nNewHeight |
|
); |
|
m_nWarnings++; |
|
return; |
|
} |
|
|
|
|
|
|
|
if ( nOldWidth != nNewWidth ) |
|
{ |
|
// Adjust the width scale by an old to new ratio |
|
pFace->texture.scale[ 0 ] = pFace->texture.scale[ 0 ] * nOldWidth / nNewWidth; |
|
|
|
// Adjust the height shift by a new to old ratio |
|
pFace->texture.UAxis[ 3 ] = pFace->texture.UAxis[ 3 ] * nNewWidth / nOldWidth; |
|
} |
|
|
|
if ( nOldHeight != nNewHeight ) |
|
{ |
|
// Adjust the height scale by an old to new ratio |
|
pFace->texture.scale[ 1 ] = pFace->texture.scale[ 1 ] * nOldHeight / nNewHeight; |
|
|
|
// Adjust the height shift by a new to old ratio |
|
pFace->texture.VAxis[ 3 ] = pFace->texture.VAxis[ 3 ] * nNewHeight / nOldHeight; |
|
} |
|
|
|
pFace->CalcTextureCoords(); // recompute internals base on the new scaling and shifting. |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Send a message to WC's message window about the specified face. |
|
// Input : pFace - The map face the message relates to |
|
// format - The message format string, *printf style |
|
// ... - The remaining arguments of the *printf style message |
|
// Output : A status message is sent to the WC message window. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::MsgConvertFace( CMapFace * pFace, const char * format, ... ) |
|
{ |
|
va_list ptr; |
|
char message[ 1024 ]; |
|
Vector vecFaceCenter; |
|
|
|
pFace->GetCenter( vecFaceCenter ); |
|
|
|
va_start( ptr, format ); |
|
_vsnprintf( message, 1024, format, ptr ); |
|
va_end( ptr ); |
|
|
|
Msg( mwStatus, |
|
"[face] %s at (%d,%d,%d): %s", |
|
pFace->GetTexture()->GetName(), |
|
(int)vecFaceCenter[ 0 ], |
|
(int)vecFaceCenter[ 1 ], |
|
(int)vecFaceCenter[ 2 ], |
|
message |
|
); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Send a message to WC's message window about the specified decal. |
|
// Input : pEnt - The map decal the message relates to |
|
// format - The message format string, *printf style |
|
// ... - The remaining arguments of the *printf style message |
|
// Output : A status message is sent to the WC message window. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::MsgConvertDecal( CMapEntity * pEnt, const char * format, ... ) |
|
{ |
|
va_list ptr; |
|
char message[ 1024 ]; |
|
Vector vecOrigin; |
|
|
|
pEnt->GetOrigin( vecOrigin ); |
|
|
|
va_start( ptr, format ); |
|
_vsnprintf( message, 1024, format, ptr ); |
|
va_end( ptr ); |
|
|
|
Msg( mwStatus, |
|
"[decal] %s at (%d,%d,%d): %s", |
|
pEnt->GetKeyValue("texture"), |
|
(int) vecOrigin.x, |
|
(int) vecOrigin.y, |
|
(int) vecOrigin.z, |
|
message |
|
); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Display information about the full conversion process. |
|
// Input : |
|
// Output : Values of the counters are logged. |
|
//----------------------------------------------------------------------------- |
|
void CTextureConverter::DisplayStatistics( void ) |
|
{ |
|
Msg( mwStatus, "==================" ); |
|
Msg( mwStatus, "Conversion summary:" ); |
|
Msg( mwStatus, "==================" ); |
|
Msg( mwStatus, "Total solids: %10d", m_nSolidCount ); |
|
Msg( mwStatus, "Total faces: %10d", m_nFaceCount ); |
|
Msg( mwStatus, "Total decals: %10d", m_nDecalCount ); |
|
Msg( mwStatus, "Total conversions: %10d", m_nFaceCount + m_nDecalCount ); |
|
Msg( mwStatus, "Successful conversions: %10d", m_nSuccesses ); |
|
Msg( mwStatus, "Skipped conversions %10d", m_nSkipped ); |
|
Msg( mwStatus, "Conversion errors: %10d", m_nErrors ); |
|
Msg( mwStatus, "Conversion warnings: %10d", m_nWarnings ); |
|
}
|
|
|