Counter Strike : Global Offensive Source Code
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.

213 lines
5.9 KiB

  1. //====== Copyright � 1996-2007, 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 && basetexturenoenvmap->GetInt() )
  77. {
  78. RemoveKey( kv, "$envmap" );
  79. }
  80. Warning( "Patching WVT material: %s\n", pPatchedMaterialName );
  81. WriteMaterialKeyValuesToPak( pPatchedMaterialName, kv );
  82. AddNewTranslation( pOriginalMaterialName, pPatchedMaterialName );
  83. }
  84. }
  85. int CreateBrushVersionOfWorldVertexTransitionMaterial( int originalTexInfo )
  86. {
  87. // Don't make cubemap tex infos for nodes
  88. if ( originalTexInfo == TEXINFO_NODE )
  89. return originalTexInfo;
  90. texinfo_t *pTexInfo = &texinfo[originalTexInfo];
  91. dtexdata_t *pTexData = GetTexData( pTexInfo->texdata );
  92. const char *pOriginalMaterialName = TexDataStringTable_GetString( pTexData->nameStringTableID );
  93. // Get out of here if the originalTexInfo is already a patched wvt material
  94. if ( Q_stristr( pOriginalMaterialName, "_wvt_patch" ) )
  95. return originalTexInfo;
  96. char patchedMaterialName[1024];
  97. GeneratePatchedMaterialName( pOriginalMaterialName, patchedMaterialName, 1024 );
  98. // Warning( "GeneratePatchedMaterialName: %s %s\n", pMaterialName, patchedMaterialName );
  99. // Make sure the texdata doesn't already exist.
  100. int nTexDataID = FindTexData( patchedMaterialName );
  101. bool bHasTexData = (nTexDataID != -1);
  102. if( !bHasTexData )
  103. {
  104. // Create the new vmt material file
  105. CreateWorldVertexTransitionPatchedMaterial( pOriginalMaterialName, patchedMaterialName );
  106. // Make a new texdata
  107. nTexDataID = AddCloneTexData( pTexData, patchedMaterialName );
  108. }
  109. Assert( nTexDataID != -1 );
  110. texinfo_t newTexInfo;
  111. newTexInfo = *pTexInfo;
  112. newTexInfo.texdata = nTexDataID;
  113. int nTexInfoID = -1;
  114. // See if we need to make a new texinfo
  115. bool bHasTexInfo = false;
  116. if( bHasTexData )
  117. {
  118. nTexInfoID = FindTexInfo( newTexInfo );
  119. bHasTexInfo = (nTexInfoID != -1);
  120. }
  121. // Make a new texinfo if we need to.
  122. if( !bHasTexInfo )
  123. {
  124. nTexInfoID = texinfo.AddToTail( newTexInfo );
  125. }
  126. Assert( nTexInfoID != -1 );
  127. return nTexInfoID;
  128. }
  129. const char *GetShaderNameForTexInfo( int iTexInfo )
  130. {
  131. texinfo_t *pTexInfo = &texinfo[iTexInfo];
  132. dtexdata_t *pTexData = GetTexData( pTexInfo->texdata );
  133. const char *pMaterialName = TexDataStringTable_GetString( pTexData->nameStringTableID );
  134. MaterialSystemMaterial_t hMaterial = FindMaterial( pMaterialName, NULL, false );
  135. const char *pShaderName = GetMaterialShaderName( hMaterial );
  136. return pShaderName;
  137. }
  138. void WorldVertexTransitionFixup( void )
  139. {
  140. CUtlVector<entitySideList_t> sideList;
  141. sideList.SetCount( g_MainMap->num_entities );
  142. int i;
  143. for ( i = 0; i < g_MainMap->num_entities; i++ )
  144. {
  145. sideList[i].firstBrushSide = 0;
  146. sideList[i].brushSideCount = 0;
  147. }
  148. for ( i = 0; i < g_MainMap->nummapbrushes; i++ )
  149. {
  150. sideList[g_MainMap->mapbrushes[i].entitynum].brushSideCount += g_MainMap->mapbrushes[i].numsides;
  151. }
  152. int curSide = 0;
  153. for ( i = 0; i < g_MainMap->num_entities; i++ )
  154. {
  155. sideList[i].firstBrushSide = curSide;
  156. curSide += sideList[i].brushSideCount;
  157. }
  158. int currentEntity = 0;
  159. for ( int iSide = 0; iSide < g_MainMap->nummapbrushsides; ++iSide )
  160. {
  161. side_t *pSide = &g_MainMap->brushsides[iSide];
  162. // skip displacments
  163. if ( pSide->pMapDisp )
  164. continue;
  165. if( pSide->texinfo < 0 )
  166. continue;
  167. const char *pShaderName = GetShaderNameForTexInfo( pSide->texinfo );
  168. if ( !pShaderName || !Q_stristr( pShaderName, "worldvertextransition" ) )
  169. {
  170. continue;
  171. }
  172. while ( currentEntity < g_MainMap->num_entities-1 &&
  173. iSide > sideList[currentEntity].firstBrushSide + sideList[currentEntity].brushSideCount )
  174. {
  175. currentEntity++;
  176. }
  177. pSide->texinfo = CreateBrushVersionOfWorldVertexTransitionMaterial( pSide->texinfo );
  178. }
  179. }