Team Fortress 2 Source Code as on 22/4/2020
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.

211 lines
5.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "bsplib.h"
  7. #include "vbsp.h"
  8. #include "tier1/UtlBuffer.h"
  9. #include "tier1/utlvector.h"
  10. #include "KeyValues.h"
  11. #include "materialpatch.h"
  12. struct entitySideList_t
  13. {
  14. int firstBrushSide;
  15. int brushSideCount;
  16. };
  17. static bool SideIsNotDispAndHasDispMaterial( int iSide )
  18. {
  19. side_t *pSide = &g_MainMap->brushsides[iSide];
  20. // If it's a displacement, then it's fine to have a displacement-only material.
  21. if ( pSide->pMapDisp )
  22. {
  23. return false;
  24. }
  25. pSide->texinfo;
  26. return true;
  27. }
  28. static void BackSlashToForwardSlash( char *pname )
  29. {
  30. while ( *pname ) {
  31. if ( *pname == '\\' )
  32. *pname = '/';
  33. pname++;
  34. }
  35. }
  36. //-----------------------------------------------------------------------------
  37. // Generate patched material name
  38. //-----------------------------------------------------------------------------
  39. static void GeneratePatchedMaterialName( const char *pMaterialName, char *pBuffer, int nMaxLen )
  40. {
  41. int nLen = Q_snprintf( pBuffer, nMaxLen, "maps/%s/%s_wvt_patch", mapbase, pMaterialName );
  42. Assert( nLen < TEXTURE_NAME_LENGTH - 1 );
  43. if ( nLen >= TEXTURE_NAME_LENGTH - 1 )
  44. {
  45. Error( "Generated worldvertextransition patch name : %s too long! (max = %d)\n", pBuffer, TEXTURE_NAME_LENGTH );
  46. }
  47. BackSlashToForwardSlash( pBuffer );
  48. Q_strlower( pBuffer );
  49. }
  50. static void RemoveKey( KeyValues *kv, const char *pSubKeyName )
  51. {
  52. KeyValues *pSubKey = kv->FindKey( pSubKeyName );
  53. if( pSubKey )
  54. {
  55. kv->RemoveSubKey( pSubKey );
  56. pSubKey->deleteThis();
  57. }
  58. }
  59. void CreateWorldVertexTransitionPatchedMaterial( const char *pOriginalMaterialName, const char *pPatchedMaterialName )
  60. {
  61. KeyValues *kv = LoadMaterialKeyValues( pOriginalMaterialName, 0 );
  62. if( kv )
  63. {
  64. // change shader to Lightmappedgeneric (from worldvertextransition*)
  65. kv->SetName( "LightmappedGeneric" );
  66. // don't need no stinking $basetexture2 or any other second texture vars
  67. RemoveKey( kv, "$basetexture2" );
  68. RemoveKey( kv, "$bumpmap2" );
  69. RemoveKey( kv, "$bumpframe2" );
  70. RemoveKey( kv, "$basetexture2noenvmap" );
  71. RemoveKey( kv, "$blendmodulatetexture" );
  72. RemoveKey( kv, "$maskedblending" );
  73. RemoveKey( kv, "$surfaceprop2" );
  74. // If we didn't want a basetexture on the first texture in the blend, we don't want an envmap at all.
  75. KeyValues *basetexturenoenvmap = kv->FindKey( "$BASETEXTURENOENVMAP" );
  76. if( basetexturenoenvmap->GetInt() )
  77. {
  78. RemoveKey( kv, "$envmap" );
  79. }
  80. Warning( "Patching WVT material: %s\n", pPatchedMaterialName );
  81. WriteMaterialKeyValuesToPak( pPatchedMaterialName, kv );
  82. }
  83. }
  84. int CreateBrushVersionOfWorldVertexTransitionMaterial( int originalTexInfo )
  85. {
  86. // Don't make cubemap tex infos for nodes
  87. if ( originalTexInfo == TEXINFO_NODE )
  88. return originalTexInfo;
  89. texinfo_t *pTexInfo = &texinfo[originalTexInfo];
  90. dtexdata_t *pTexData = GetTexData( pTexInfo->texdata );
  91. const char *pOriginalMaterialName = TexDataStringTable_GetString( pTexData->nameStringTableID );
  92. // Get out of here if the originalTexInfo is already a patched wvt material
  93. if ( Q_stristr( pOriginalMaterialName, "_wvt_patch" ) )
  94. return originalTexInfo;
  95. char patchedMaterialName[1024];
  96. GeneratePatchedMaterialName( pOriginalMaterialName, patchedMaterialName, 1024 );
  97. // Warning( "GeneratePatchedMaterialName: %s %s\n", pMaterialName, patchedMaterialName );
  98. // Make sure the texdata doesn't already exist.
  99. int nTexDataID = FindTexData( patchedMaterialName );
  100. bool bHasTexData = (nTexDataID != -1);
  101. if( !bHasTexData )
  102. {
  103. // Create the new vmt material file
  104. CreateWorldVertexTransitionPatchedMaterial( pOriginalMaterialName, patchedMaterialName );
  105. // Make a new texdata
  106. nTexDataID = AddCloneTexData( pTexData, patchedMaterialName );
  107. }
  108. Assert( nTexDataID != -1 );
  109. texinfo_t newTexInfo;
  110. newTexInfo = *pTexInfo;
  111. newTexInfo.texdata = nTexDataID;
  112. int nTexInfoID = -1;
  113. // See if we need to make a new texinfo
  114. bool bHasTexInfo = false;
  115. if( bHasTexData )
  116. {
  117. nTexInfoID = FindTexInfo( newTexInfo );
  118. bHasTexInfo = (nTexInfoID != -1);
  119. }
  120. // Make a new texinfo if we need to.
  121. if( !bHasTexInfo )
  122. {
  123. nTexInfoID = texinfo.AddToTail( newTexInfo );
  124. }
  125. Assert( nTexInfoID != -1 );
  126. return nTexInfoID;
  127. }
  128. const char *GetShaderNameForTexInfo( int iTexInfo )
  129. {
  130. texinfo_t *pTexInfo = &texinfo[iTexInfo];
  131. dtexdata_t *pTexData = GetTexData( pTexInfo->texdata );
  132. const char *pMaterialName = TexDataStringTable_GetString( pTexData->nameStringTableID );
  133. MaterialSystemMaterial_t hMaterial = FindMaterial( pMaterialName, NULL, false );
  134. const char *pShaderName = GetMaterialShaderName( hMaterial );
  135. return pShaderName;
  136. }
  137. void WorldVertexTransitionFixup( void )
  138. {
  139. CUtlVector<entitySideList_t> sideList;
  140. sideList.SetCount( g_MainMap->num_entities );
  141. int i;
  142. for ( i = 0; i < g_MainMap->num_entities; i++ )
  143. {
  144. sideList[i].firstBrushSide = 0;
  145. sideList[i].brushSideCount = 0;
  146. }
  147. for ( i = 0; i < g_MainMap->nummapbrushes; i++ )
  148. {
  149. sideList[g_MainMap->mapbrushes[i].entitynum].brushSideCount += g_MainMap->mapbrushes[i].numsides;
  150. }
  151. int curSide = 0;
  152. for ( i = 0; i < g_MainMap->num_entities; i++ )
  153. {
  154. sideList[i].firstBrushSide = curSide;
  155. curSide += sideList[i].brushSideCount;
  156. }
  157. int currentEntity = 0;
  158. for ( int iSide = 0; iSide < g_MainMap->nummapbrushsides; ++iSide )
  159. {
  160. side_t *pSide = &g_MainMap->brushsides[iSide];
  161. // skip displacments
  162. if ( pSide->pMapDisp )
  163. continue;
  164. if( pSide->texinfo < 0 )
  165. continue;
  166. const char *pShaderName = GetShaderNameForTexInfo( pSide->texinfo );
  167. if ( !pShaderName || !Q_stristr( pShaderName, "worldvertextransition" ) )
  168. {
  169. continue;
  170. }
  171. while ( currentEntity < g_MainMap->num_entities-1 &&
  172. iSide > sideList[currentEntity].firstBrushSide + sideList[currentEntity].brushSideCount )
  173. {
  174. currentEntity++;
  175. }
  176. pSide->texinfo = CreateBrushVersionOfWorldVertexTransitionMaterial( pSide->texinfo );
  177. }
  178. }