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