From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/utils/vbsp/materialpatch.cpp | 880 ++++++++++++++++++------------------ 1 file changed, 440 insertions(+), 440 deletions(-) (limited to 'mp/src/utils/vbsp/materialpatch.cpp') diff --git a/mp/src/utils/vbsp/materialpatch.cpp b/mp/src/utils/vbsp/materialpatch.cpp index e05b979d..96a30edb 100644 --- a/mp/src/utils/vbsp/materialpatch.cpp +++ b/mp/src/utils/vbsp/materialpatch.cpp @@ -1,440 +1,440 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "vbsp.h" -#include "UtlBuffer.h" -#include "utlsymbol.h" -#include "utlrbtree.h" -#include "KeyValues.h" -#include "bsplib.h" -#include "materialpatch.h" -#include "tier1/strtools.h" - -// case insensitive -static CUtlSymbolTable s_SymbolTable( 0, 32, true ); - -struct NameTranslationLookup_t -{ - CUtlSymbol m_OriginalFileName; - CUtlSymbol m_PatchFileName; -}; - -static bool NameTranslationLessFunc( NameTranslationLookup_t const& src1, - NameTranslationLookup_t const& src2 ) -{ - return src1.m_PatchFileName < src2.m_PatchFileName; -} - -CUtlRBTree s_MapPatchedMatToOriginalMat( 0, 256, NameTranslationLessFunc ); - -void AddNewTranslation( const char *pOriginalMaterialName, const char *pNewMaterialName ) -{ - NameTranslationLookup_t newEntry; - - newEntry.m_OriginalFileName = s_SymbolTable.AddString( pOriginalMaterialName ); - newEntry.m_PatchFileName = s_SymbolTable.AddString( pNewMaterialName ); - - s_MapPatchedMatToOriginalMat.Insert( newEntry ); -} - -const char *GetOriginalMaterialNameForPatchedMaterial( const char *pPatchMaterialName ) -{ - const char *pRetName = NULL; - int id; - NameTranslationLookup_t lookup; - lookup.m_PatchFileName = s_SymbolTable.AddString( pPatchMaterialName ); - do - { - id = s_MapPatchedMatToOriginalMat.Find( lookup ); - if( id >= 0 ) - { - NameTranslationLookup_t &found = s_MapPatchedMatToOriginalMat[id]; - lookup.m_PatchFileName = found.m_OriginalFileName; - pRetName = s_SymbolTable.String( found.m_OriginalFileName ); - } - } while( id >= 0 ); - if( !pRetName ) - { - // This isn't a patched material, so just return the original name. - return pPatchMaterialName; - } - return pRetName; -} - - -void CreateMaterialPatchRecursive( KeyValues *pOriginalKeyValues, KeyValues *pPatchKeyValues, int nKeys, const MaterialPatchInfo_t *pInfo ) -{ - int i; - for( i = 0; i < nKeys; i++ ) - { - const char *pVal = pOriginalKeyValues->GetString( pInfo[i].m_pKey, NULL ); - if( !pVal ) - continue; - if( pInfo[i].m_pRequiredOriginalValue && Q_stricmp( pVal, pInfo[i].m_pRequiredOriginalValue ) != 0 ) - continue; - pPatchKeyValues->SetString( pInfo[i].m_pKey, pInfo[i].m_pValue ); - } - KeyValues *pScan; - for( pScan = pOriginalKeyValues->GetFirstTrueSubKey(); pScan; pScan = pScan->GetNextTrueSubKey() ) - { - CreateMaterialPatchRecursive( pScan, pPatchKeyValues->FindKey( pScan->GetName(), true ), nKeys, pInfo ); - } -} - -//----------------------------------------------------------------------------- -// A version which allows you to patch multiple key values -//----------------------------------------------------------------------------- -void CreateMaterialPatch( const char *pOriginalMaterialName, const char *pNewMaterialName, - int nKeys, const MaterialPatchInfo_t *pInfo, MaterialPatchType_t nPatchType ) -{ - char pOldVMTFile[ 512 ]; - char pNewVMTFile[ 512 ]; - - AddNewTranslation( pOriginalMaterialName, pNewMaterialName ); - - Q_snprintf( pOldVMTFile, 512, "materials/%s.vmt", pOriginalMaterialName ); - Q_snprintf( pNewVMTFile, 512, "materials/%s.vmt", pNewMaterialName ); - -// printf( "Creating material patch file %s which points at %s\n", newVMTFile, oldVMTFile ); - - KeyValues *kv = new KeyValues( "patch" ); - if ( !kv ) - { - Error( "Couldn't allocate KeyValues for %s!!!", pNewMaterialName ); - } - - kv->SetString( "include", pOldVMTFile ); - - const char *pSectionName = (nPatchType == PATCH_INSERT) ? "insert" : "replace"; - KeyValues *section = kv->FindKey( pSectionName, true ); - - if( nPatchType == PATCH_REPLACE ) - { - char name[512]; - Q_snprintf( name, 512, "materials/%s.vmt", GetOriginalMaterialNameForPatchedMaterial( pOriginalMaterialName ) ); - KeyValues *origkv = new KeyValues( "blah" ); - - if ( !origkv->LoadFromFile( g_pFileSystem, name ) ) - { - origkv->deleteThis(); - Assert( 0 ); - return; - } - - CreateMaterialPatchRecursive( origkv, section, nKeys, pInfo ); - origkv->deleteThis(); - } - else - { - for ( int i = 0; i < nKeys; ++i ) - { - section->SetString( pInfo[i].m_pKey, pInfo[i].m_pValue ); - } - } - - // Write patched .vmt into a memory buffer - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - kv->RecursiveSaveToFile( buf, 0 ); - - // Add to pak file for this .bsp - AddBufferToPak( GetPakFile(), pNewVMTFile, (void*)buf.Base(), buf.TellPut(), true ); - - // Cleanup - kv->deleteThis(); -} - - -//----------------------------------------------------------------------------- -// Patches a single keyvalue in a material -//----------------------------------------------------------------------------- -void CreateMaterialPatch( const char *pOriginalMaterialName, const char *pNewMaterialName, - const char *pNewKey, const char *pNewValue, MaterialPatchType_t nPatchType ) -{ - MaterialPatchInfo_t info; - info.m_pKey = pNewKey; - info.m_pValue = pNewValue; - CreateMaterialPatch( pOriginalMaterialName, pNewMaterialName, 1, &info, nPatchType ); -} - - -//----------------------------------------------------------------------------- -// Scan material + all subsections for key -//----------------------------------------------------------------------------- -static bool DoesMaterialHaveKey( KeyValues *pKeyValues, const char *pKeyName ) -{ - const char *pVal; - pVal = pKeyValues->GetString( pKeyName, NULL ); - if ( pVal != NULL ) - return true; - - for( KeyValues *pSubKey = pKeyValues->GetFirstTrueSubKey(); pSubKey; pSubKey = pSubKey->GetNextTrueSubKey() ) - { - if ( DoesMaterialHaveKey( pSubKey, pKeyName) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Scan material + all subsections for key/value pair -//----------------------------------------------------------------------------- -static bool DoesMaterialHaveKeyValuePair( KeyValues *pKeyValues, const char *pKeyName, const char *pSearchValue ) -{ - const char *pVal; - pVal = pKeyValues->GetString( pKeyName, NULL ); - if ( pVal != NULL && ( Q_stricmp( pSearchValue, pVal ) == 0 ) ) - return true; - - for( KeyValues *pSubKey = pKeyValues->GetFirstTrueSubKey(); pSubKey; pSubKey = pSubKey->GetNextTrueSubKey() ) - { - if ( DoesMaterialHaveKeyValuePair( pSubKey, pKeyName, pSearchValue ) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Scan material + all subsections for key -//----------------------------------------------------------------------------- -bool DoesMaterialHaveKey( const char *pMaterialName, const char *pKeyName ) -{ - char name[512]; - Q_snprintf( name, 512, "materials/%s.vmt", GetOriginalMaterialNameForPatchedMaterial( pMaterialName ) ); - KeyValues *kv = new KeyValues( "blah" ); - - if ( !kv->LoadFromFile( g_pFileSystem, name ) ) - { - kv->deleteThis(); - return NULL; - } - - bool retVal = DoesMaterialHaveKey( kv, pKeyName ); - - kv->deleteThis(); - return retVal; -} - -//----------------------------------------------------------------------------- -// Scan material + all subsections for key/value pair -//----------------------------------------------------------------------------- -bool DoesMaterialHaveKeyValuePair( const char *pMaterialName, const char *pKeyName, const char *pSearchValue ) -{ - char name[512]; - Q_snprintf( name, 512, "materials/%s.vmt", GetOriginalMaterialNameForPatchedMaterial( pMaterialName ) ); - KeyValues *kv = new KeyValues( "blah" ); - - if ( !kv->LoadFromFile( g_pFileSystem, name ) ) - { - kv->deleteThis(); - return NULL; - } - - bool retVal = DoesMaterialHaveKeyValuePair( kv, pKeyName, pSearchValue ); - - kv->deleteThis(); - return retVal; -} - -//----------------------------------------------------------------------------- -// Gets a material value from a material. Ignores all patches -//----------------------------------------------------------------------------- -bool GetValueFromMaterial( const char *pMaterialName, const char *pKey, char *pValue, int len ) -{ - char name[512]; - Q_snprintf( name, 512, "materials/%s.vmt", GetOriginalMaterialNameForPatchedMaterial( pMaterialName ) ); - KeyValues *kv = new KeyValues( "blah" ); - - if ( !kv->LoadFromFile( g_pFileSystem, name ) ) - { -// Assert( 0 ); - kv->deleteThis(); - return NULL; - } - - const char *pTmpValue = kv->GetString( pKey, NULL ); - if( pTmpValue ) - { - Q_strncpy( pValue, pTmpValue, len ); - } - - kv->deleteThis(); - return ( pTmpValue != NULL ); -} - - -//----------------------------------------------------------------------------- -// Finds the original material associated with a patched material -//----------------------------------------------------------------------------- -MaterialSystemMaterial_t FindOriginalMaterial( const char *materialName, bool *pFound, bool bComplain ) -{ - MaterialSystemMaterial_t matID; - matID = FindMaterial( GetOriginalMaterialNameForPatchedMaterial( materialName ), pFound, bComplain ); - return matID; -} - - -//----------------------------------------------------------------------------- -// Load keyvalues from the local pack file, or from a file -//----------------------------------------------------------------------------- -bool LoadKeyValuesFromPackOrFile( const char *pFileName, KeyValues *pKeyValues ) -{ - CUtlBuffer buf; - if ( ReadFileFromPak( GetPakFile(), pFileName, true, buf ) ) - { - return pKeyValues->LoadFromBuffer( pFileName, buf ); - } - - return pKeyValues->LoadFromFile( g_pFileSystem, pFileName ); -} - - -//----------------------------------------------------------------------------- -// VMT parser -//----------------------------------------------------------------------------- -static void InsertKeyValues( KeyValues &dst, KeyValues& src, bool bCheckForExistence ) -{ - KeyValues *pSrcVar = src.GetFirstSubKey(); - while( pSrcVar ) - { - if ( !bCheckForExistence || dst.FindKey( pSrcVar->GetName() ) ) - { - switch( pSrcVar->GetDataType() ) - { - case KeyValues::TYPE_STRING: - dst.SetString( pSrcVar->GetName(), pSrcVar->GetString() ); - break; - case KeyValues::TYPE_INT: - dst.SetInt( pSrcVar->GetName(), pSrcVar->GetInt() ); - break; - case KeyValues::TYPE_FLOAT: - dst.SetFloat( pSrcVar->GetName(), pSrcVar->GetFloat() ); - break; - case KeyValues::TYPE_PTR: - dst.SetPtr( pSrcVar->GetName(), pSrcVar->GetPtr() ); - break; - } - } - pSrcVar = pSrcVar->GetNextKey(); - } -} - -static void ExpandPatchFile( KeyValues &keyValues ) -{ - int nCount = 0; - while( nCount < 10 && stricmp( keyValues.GetName(), "patch" ) == 0 ) - { -// WriteKeyValuesToFile( "patch.txt", keyValues ); - const char *pIncludeFileName = keyValues.GetString( "include" ); - if( !pIncludeFileName ) - return; - - KeyValues * includeKeyValues = new KeyValues( "vmt" ); - int nBufLen = Q_strlen( pIncludeFileName ) + Q_strlen( "materials/.vmt" ) + 1; - char *pFileName = ( char * )stackalloc( nBufLen ); - Q_strncpy( pFileName, pIncludeFileName, nBufLen ); - bool bSuccess = LoadKeyValuesFromPackOrFile( pFileName, includeKeyValues ); - if ( !bSuccess ) - { - includeKeyValues->deleteThis(); - return; - } - - KeyValues *pInsertSection = keyValues.FindKey( "insert" ); - if( pInsertSection ) - { - InsertKeyValues( *includeKeyValues, *pInsertSection, false ); - keyValues = *includeKeyValues; - } - - KeyValues *pReplaceSection = keyValues.FindKey( "replace" ); - if( pReplaceSection ) - { - InsertKeyValues( *includeKeyValues, *pReplaceSection, true ); - keyValues = *includeKeyValues; - } - - // Could add other commands here, like "delete", "rename", etc. - - includeKeyValues->deleteThis(); - nCount++; - } - - if( nCount >= 10 ) - { - Warning( "Infinite recursion in patch file?\n" ); - } -} - -KeyValues *LoadMaterialKeyValues( const char *pMaterialName, unsigned int nFlags ) -{ - // Load the underlying file - KeyValues *kv = new KeyValues( "blah" ); - - char pFullMaterialName[512]; - Q_snprintf( pFullMaterialName, 512, "materials/%s.vmt", pMaterialName ); - if ( !LoadKeyValuesFromPackOrFile( pFullMaterialName, kv ) ) - { - // Assert( 0 ); - kv->deleteThis(); - return NULL; - } - - if( nFlags & LOAD_MATERIAL_KEY_VALUES_FLAGS_EXPAND_PATCH ) - { - ExpandPatchFile( *kv ); - } - - return kv; -} - -void WriteMaterialKeyValuesToPak( const char *pMaterialName, KeyValues *kv ) -{ - char pFullMaterialName[512]; - Q_snprintf( pFullMaterialName, 512, "materials/%s.vmt", pMaterialName ); - - // Write patched .vmt into a memory buffer - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - kv->RecursiveSaveToFile( buf, 0 ); - - // Add to pak file for this .bsp - AddBufferToPak( GetPakFile(), pFullMaterialName, (void*)buf.Base(), buf.TellPut(), true ); - - // Cleanup - kv->deleteThis(); -} - - -//----------------------------------------------------------------------------- -// Gets a keyvalue from a *patched* material -//----------------------------------------------------------------------------- -bool GetValueFromPatchedMaterial( const char *pMaterialName, const char *pKey, char *pValue, int len ) -{ - // Load the underlying file so that we can check if env_cubemap is in there. - KeyValues *kv = new KeyValues( "blah" ); - - char pFullMaterialName[512]; - Q_snprintf( pFullMaterialName, 512, "materials/%s.vmt", pMaterialName ); - if ( !LoadKeyValuesFromPackOrFile( pFullMaterialName, kv ) ) - { -// Assert( 0 ); - kv->deleteThis(); - return NULL; - } - - ExpandPatchFile( *kv ); - - const char *pTmpValue = kv->GetString( pKey, NULL ); - if( pTmpValue ) - { - Q_strncpy( pValue, pTmpValue, len ); - } - - kv->deleteThis(); - return ( pTmpValue != NULL ); -} +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#include "vbsp.h" +#include "UtlBuffer.h" +#include "utlsymbol.h" +#include "utlrbtree.h" +#include "KeyValues.h" +#include "bsplib.h" +#include "materialpatch.h" +#include "tier1/strtools.h" + +// case insensitive +static CUtlSymbolTable s_SymbolTable( 0, 32, true ); + +struct NameTranslationLookup_t +{ + CUtlSymbol m_OriginalFileName; + CUtlSymbol m_PatchFileName; +}; + +static bool NameTranslationLessFunc( NameTranslationLookup_t const& src1, + NameTranslationLookup_t const& src2 ) +{ + return src1.m_PatchFileName < src2.m_PatchFileName; +} + +CUtlRBTree s_MapPatchedMatToOriginalMat( 0, 256, NameTranslationLessFunc ); + +void AddNewTranslation( const char *pOriginalMaterialName, const char *pNewMaterialName ) +{ + NameTranslationLookup_t newEntry; + + newEntry.m_OriginalFileName = s_SymbolTable.AddString( pOriginalMaterialName ); + newEntry.m_PatchFileName = s_SymbolTable.AddString( pNewMaterialName ); + + s_MapPatchedMatToOriginalMat.Insert( newEntry ); +} + +const char *GetOriginalMaterialNameForPatchedMaterial( const char *pPatchMaterialName ) +{ + const char *pRetName = NULL; + int id; + NameTranslationLookup_t lookup; + lookup.m_PatchFileName = s_SymbolTable.AddString( pPatchMaterialName ); + do + { + id = s_MapPatchedMatToOriginalMat.Find( lookup ); + if( id >= 0 ) + { + NameTranslationLookup_t &found = s_MapPatchedMatToOriginalMat[id]; + lookup.m_PatchFileName = found.m_OriginalFileName; + pRetName = s_SymbolTable.String( found.m_OriginalFileName ); + } + } while( id >= 0 ); + if( !pRetName ) + { + // This isn't a patched material, so just return the original name. + return pPatchMaterialName; + } + return pRetName; +} + + +void CreateMaterialPatchRecursive( KeyValues *pOriginalKeyValues, KeyValues *pPatchKeyValues, int nKeys, const MaterialPatchInfo_t *pInfo ) +{ + int i; + for( i = 0; i < nKeys; i++ ) + { + const char *pVal = pOriginalKeyValues->GetString( pInfo[i].m_pKey, NULL ); + if( !pVal ) + continue; + if( pInfo[i].m_pRequiredOriginalValue && Q_stricmp( pVal, pInfo[i].m_pRequiredOriginalValue ) != 0 ) + continue; + pPatchKeyValues->SetString( pInfo[i].m_pKey, pInfo[i].m_pValue ); + } + KeyValues *pScan; + for( pScan = pOriginalKeyValues->GetFirstTrueSubKey(); pScan; pScan = pScan->GetNextTrueSubKey() ) + { + CreateMaterialPatchRecursive( pScan, pPatchKeyValues->FindKey( pScan->GetName(), true ), nKeys, pInfo ); + } +} + +//----------------------------------------------------------------------------- +// A version which allows you to patch multiple key values +//----------------------------------------------------------------------------- +void CreateMaterialPatch( const char *pOriginalMaterialName, const char *pNewMaterialName, + int nKeys, const MaterialPatchInfo_t *pInfo, MaterialPatchType_t nPatchType ) +{ + char pOldVMTFile[ 512 ]; + char pNewVMTFile[ 512 ]; + + AddNewTranslation( pOriginalMaterialName, pNewMaterialName ); + + Q_snprintf( pOldVMTFile, 512, "materials/%s.vmt", pOriginalMaterialName ); + Q_snprintf( pNewVMTFile, 512, "materials/%s.vmt", pNewMaterialName ); + +// printf( "Creating material patch file %s which points at %s\n", newVMTFile, oldVMTFile ); + + KeyValues *kv = new KeyValues( "patch" ); + if ( !kv ) + { + Error( "Couldn't allocate KeyValues for %s!!!", pNewMaterialName ); + } + + kv->SetString( "include", pOldVMTFile ); + + const char *pSectionName = (nPatchType == PATCH_INSERT) ? "insert" : "replace"; + KeyValues *section = kv->FindKey( pSectionName, true ); + + if( nPatchType == PATCH_REPLACE ) + { + char name[512]; + Q_snprintf( name, 512, "materials/%s.vmt", GetOriginalMaterialNameForPatchedMaterial( pOriginalMaterialName ) ); + KeyValues *origkv = new KeyValues( "blah" ); + + if ( !origkv->LoadFromFile( g_pFileSystem, name ) ) + { + origkv->deleteThis(); + Assert( 0 ); + return; + } + + CreateMaterialPatchRecursive( origkv, section, nKeys, pInfo ); + origkv->deleteThis(); + } + else + { + for ( int i = 0; i < nKeys; ++i ) + { + section->SetString( pInfo[i].m_pKey, pInfo[i].m_pValue ); + } + } + + // Write patched .vmt into a memory buffer + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + kv->RecursiveSaveToFile( buf, 0 ); + + // Add to pak file for this .bsp + AddBufferToPak( GetPakFile(), pNewVMTFile, (void*)buf.Base(), buf.TellPut(), true ); + + // Cleanup + kv->deleteThis(); +} + + +//----------------------------------------------------------------------------- +// Patches a single keyvalue in a material +//----------------------------------------------------------------------------- +void CreateMaterialPatch( const char *pOriginalMaterialName, const char *pNewMaterialName, + const char *pNewKey, const char *pNewValue, MaterialPatchType_t nPatchType ) +{ + MaterialPatchInfo_t info; + info.m_pKey = pNewKey; + info.m_pValue = pNewValue; + CreateMaterialPatch( pOriginalMaterialName, pNewMaterialName, 1, &info, nPatchType ); +} + + +//----------------------------------------------------------------------------- +// Scan material + all subsections for key +//----------------------------------------------------------------------------- +static bool DoesMaterialHaveKey( KeyValues *pKeyValues, const char *pKeyName ) +{ + const char *pVal; + pVal = pKeyValues->GetString( pKeyName, NULL ); + if ( pVal != NULL ) + return true; + + for( KeyValues *pSubKey = pKeyValues->GetFirstTrueSubKey(); pSubKey; pSubKey = pSubKey->GetNextTrueSubKey() ) + { + if ( DoesMaterialHaveKey( pSubKey, pKeyName) ) + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Scan material + all subsections for key/value pair +//----------------------------------------------------------------------------- +static bool DoesMaterialHaveKeyValuePair( KeyValues *pKeyValues, const char *pKeyName, const char *pSearchValue ) +{ + const char *pVal; + pVal = pKeyValues->GetString( pKeyName, NULL ); + if ( pVal != NULL && ( Q_stricmp( pSearchValue, pVal ) == 0 ) ) + return true; + + for( KeyValues *pSubKey = pKeyValues->GetFirstTrueSubKey(); pSubKey; pSubKey = pSubKey->GetNextTrueSubKey() ) + { + if ( DoesMaterialHaveKeyValuePair( pSubKey, pKeyName, pSearchValue ) ) + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Scan material + all subsections for key +//----------------------------------------------------------------------------- +bool DoesMaterialHaveKey( const char *pMaterialName, const char *pKeyName ) +{ + char name[512]; + Q_snprintf( name, 512, "materials/%s.vmt", GetOriginalMaterialNameForPatchedMaterial( pMaterialName ) ); + KeyValues *kv = new KeyValues( "blah" ); + + if ( !kv->LoadFromFile( g_pFileSystem, name ) ) + { + kv->deleteThis(); + return NULL; + } + + bool retVal = DoesMaterialHaveKey( kv, pKeyName ); + + kv->deleteThis(); + return retVal; +} + +//----------------------------------------------------------------------------- +// Scan material + all subsections for key/value pair +//----------------------------------------------------------------------------- +bool DoesMaterialHaveKeyValuePair( const char *pMaterialName, const char *pKeyName, const char *pSearchValue ) +{ + char name[512]; + Q_snprintf( name, 512, "materials/%s.vmt", GetOriginalMaterialNameForPatchedMaterial( pMaterialName ) ); + KeyValues *kv = new KeyValues( "blah" ); + + if ( !kv->LoadFromFile( g_pFileSystem, name ) ) + { + kv->deleteThis(); + return NULL; + } + + bool retVal = DoesMaterialHaveKeyValuePair( kv, pKeyName, pSearchValue ); + + kv->deleteThis(); + return retVal; +} + +//----------------------------------------------------------------------------- +// Gets a material value from a material. Ignores all patches +//----------------------------------------------------------------------------- +bool GetValueFromMaterial( const char *pMaterialName, const char *pKey, char *pValue, int len ) +{ + char name[512]; + Q_snprintf( name, 512, "materials/%s.vmt", GetOriginalMaterialNameForPatchedMaterial( pMaterialName ) ); + KeyValues *kv = new KeyValues( "blah" ); + + if ( !kv->LoadFromFile( g_pFileSystem, name ) ) + { +// Assert( 0 ); + kv->deleteThis(); + return NULL; + } + + const char *pTmpValue = kv->GetString( pKey, NULL ); + if( pTmpValue ) + { + Q_strncpy( pValue, pTmpValue, len ); + } + + kv->deleteThis(); + return ( pTmpValue != NULL ); +} + + +//----------------------------------------------------------------------------- +// Finds the original material associated with a patched material +//----------------------------------------------------------------------------- +MaterialSystemMaterial_t FindOriginalMaterial( const char *materialName, bool *pFound, bool bComplain ) +{ + MaterialSystemMaterial_t matID; + matID = FindMaterial( GetOriginalMaterialNameForPatchedMaterial( materialName ), pFound, bComplain ); + return matID; +} + + +//----------------------------------------------------------------------------- +// Load keyvalues from the local pack file, or from a file +//----------------------------------------------------------------------------- +bool LoadKeyValuesFromPackOrFile( const char *pFileName, KeyValues *pKeyValues ) +{ + CUtlBuffer buf; + if ( ReadFileFromPak( GetPakFile(), pFileName, true, buf ) ) + { + return pKeyValues->LoadFromBuffer( pFileName, buf ); + } + + return pKeyValues->LoadFromFile( g_pFileSystem, pFileName ); +} + + +//----------------------------------------------------------------------------- +// VMT parser +//----------------------------------------------------------------------------- +static void InsertKeyValues( KeyValues &dst, KeyValues& src, bool bCheckForExistence ) +{ + KeyValues *pSrcVar = src.GetFirstSubKey(); + while( pSrcVar ) + { + if ( !bCheckForExistence || dst.FindKey( pSrcVar->GetName() ) ) + { + switch( pSrcVar->GetDataType() ) + { + case KeyValues::TYPE_STRING: + dst.SetString( pSrcVar->GetName(), pSrcVar->GetString() ); + break; + case KeyValues::TYPE_INT: + dst.SetInt( pSrcVar->GetName(), pSrcVar->GetInt() ); + break; + case KeyValues::TYPE_FLOAT: + dst.SetFloat( pSrcVar->GetName(), pSrcVar->GetFloat() ); + break; + case KeyValues::TYPE_PTR: + dst.SetPtr( pSrcVar->GetName(), pSrcVar->GetPtr() ); + break; + } + } + pSrcVar = pSrcVar->GetNextKey(); + } +} + +static void ExpandPatchFile( KeyValues &keyValues ) +{ + int nCount = 0; + while( nCount < 10 && stricmp( keyValues.GetName(), "patch" ) == 0 ) + { +// WriteKeyValuesToFile( "patch.txt", keyValues ); + const char *pIncludeFileName = keyValues.GetString( "include" ); + if( !pIncludeFileName ) + return; + + KeyValues * includeKeyValues = new KeyValues( "vmt" ); + int nBufLen = Q_strlen( pIncludeFileName ) + Q_strlen( "materials/.vmt" ) + 1; + char *pFileName = ( char * )stackalloc( nBufLen ); + Q_strncpy( pFileName, pIncludeFileName, nBufLen ); + bool bSuccess = LoadKeyValuesFromPackOrFile( pFileName, includeKeyValues ); + if ( !bSuccess ) + { + includeKeyValues->deleteThis(); + return; + } + + KeyValues *pInsertSection = keyValues.FindKey( "insert" ); + if( pInsertSection ) + { + InsertKeyValues( *includeKeyValues, *pInsertSection, false ); + keyValues = *includeKeyValues; + } + + KeyValues *pReplaceSection = keyValues.FindKey( "replace" ); + if( pReplaceSection ) + { + InsertKeyValues( *includeKeyValues, *pReplaceSection, true ); + keyValues = *includeKeyValues; + } + + // Could add other commands here, like "delete", "rename", etc. + + includeKeyValues->deleteThis(); + nCount++; + } + + if( nCount >= 10 ) + { + Warning( "Infinite recursion in patch file?\n" ); + } +} + +KeyValues *LoadMaterialKeyValues( const char *pMaterialName, unsigned int nFlags ) +{ + // Load the underlying file + KeyValues *kv = new KeyValues( "blah" ); + + char pFullMaterialName[512]; + Q_snprintf( pFullMaterialName, 512, "materials/%s.vmt", pMaterialName ); + if ( !LoadKeyValuesFromPackOrFile( pFullMaterialName, kv ) ) + { + // Assert( 0 ); + kv->deleteThis(); + return NULL; + } + + if( nFlags & LOAD_MATERIAL_KEY_VALUES_FLAGS_EXPAND_PATCH ) + { + ExpandPatchFile( *kv ); + } + + return kv; +} + +void WriteMaterialKeyValuesToPak( const char *pMaterialName, KeyValues *kv ) +{ + char pFullMaterialName[512]; + Q_snprintf( pFullMaterialName, 512, "materials/%s.vmt", pMaterialName ); + + // Write patched .vmt into a memory buffer + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + kv->RecursiveSaveToFile( buf, 0 ); + + // Add to pak file for this .bsp + AddBufferToPak( GetPakFile(), pFullMaterialName, (void*)buf.Base(), buf.TellPut(), true ); + + // Cleanup + kv->deleteThis(); +} + + +//----------------------------------------------------------------------------- +// Gets a keyvalue from a *patched* material +//----------------------------------------------------------------------------- +bool GetValueFromPatchedMaterial( const char *pMaterialName, const char *pKey, char *pValue, int len ) +{ + // Load the underlying file so that we can check if env_cubemap is in there. + KeyValues *kv = new KeyValues( "blah" ); + + char pFullMaterialName[512]; + Q_snprintf( pFullMaterialName, 512, "materials/%s.vmt", pMaterialName ); + if ( !LoadKeyValuesFromPackOrFile( pFullMaterialName, kv ) ) + { +// Assert( 0 ); + kv->deleteThis(); + return NULL; + } + + ExpandPatchFile( *kv ); + + const char *pTmpValue = kv->GetString( pKey, NULL ); + if( pTmpValue ) + { + Q_strncpy( pValue, pTmpValue, len ); + } + + kv->deleteThis(); + return ( pTmpValue != NULL ); +} -- cgit v1.2.3