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.

567 lines
17 KiB

  1. //====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "importkeyvaluebase.h"
  7. #include "dmserializers.h"
  8. #include "datamodel/idatamodel.h"
  9. #include "datamodel/dmelement.h"
  10. #include "datamodel/dmattributevar.h"
  11. #include "tier1/KeyValues.h"
  12. #include "tier1/UtlBuffer.h"
  13. #include "datamodel/dmattribute.h"
  14. #include "filesystem.h"
  15. #include "tier2/tier2.h"
  16. //-----------------------------------------------------------------------------
  17. // Serialization class for make sheet files
  18. //-----------------------------------------------------------------------------
  19. class CImportTex : public IDmSerializer
  20. {
  21. public:
  22. virtual const char *GetName() const { return "tex_source1"; }
  23. virtual const char *GetDescription() const { return "Valve Texture Configuration File"; }
  24. virtual bool IsBinaryFormat() const { return false; }
  25. virtual bool StoresVersionInFile() const { return false; }
  26. virtual int GetCurrentVersion() const { return 0; } // doesn't store a version
  27. virtual const char *GetImportedFormat() const { return "tex"; }
  28. virtual int GetImportedVersion() const { return 1; }
  29. bool Serialize( CUtlBuffer &outBuf, CDmElement *pRoot ) { return false; }
  30. // Read from the UtlBuffer, return true if successful, and return the read-in root in ppRoot.
  31. bool Unserialize( CUtlBuffer &buf, const char *pEncodingName, int nEncodingVersion, const char *pSourceFormatName,
  32. int nSourceFormatVersion, DmFileId_t fileid, DmConflictResolution_t idConflictResolution, CDmElement **ppRoot );
  33. private:
  34. bool ParseOptionKey( const char *pKeyName, const char *pKeyValue, CDmElement *pTexture );
  35. const char *GetPossiblyQuotedWord( const char *pInBuf, char *pOutbuf );
  36. bool GetKeyValueFromBuffer( CUtlBuffer &buffer, char *key, char *val );
  37. CDmElement *AddProcessor( CDmElement *pElement, const char *pProcessorType, const char *pName );
  38. CDmElement *FindProcessor( CDmElement *pElement, const char *pProcessorType, const char *pName );
  39. // Information for the mipmap processor
  40. bool m_bNoNice;
  41. bool m_bAlphatestMipmapping;
  42. float m_flAlphatestMipmapThreshhold;
  43. float m_flAlphatestMipmapHiFreqThreshhold;
  44. };
  45. //-----------------------------------------------------------------------------
  46. // Singleton instance
  47. //-----------------------------------------------------------------------------
  48. static CImportTex s_ImportTex;
  49. void InstallTEXImporter( IDataModel *pFactory )
  50. {
  51. pFactory->AddSerializer( &s_ImportTex );
  52. }
  53. //-----------------------------------------------------------------------------
  54. // Processors
  55. //-----------------------------------------------------------------------------
  56. CDmElement *CImportTex::AddProcessor( CDmElement *pElement, const char *pProcessorType, const char *pName )
  57. {
  58. CDmrElementArray< CDmElement > processors( pElement, "processors", true );
  59. CDmElement* pProcessor = CreateElement< CDmElement >( pProcessorType, pName, pElement->GetFileId() );
  60. processors.AddToTail( pProcessor );
  61. return pProcessor;
  62. }
  63. CDmElement *CImportTex::FindProcessor( CDmElement *pElement, const char *pProcessorType, const char *pName )
  64. {
  65. CDmrElementArrayConst< CDmElement > processors( pElement, "processors" );
  66. for ( int i = 0; i < processors.Count(); ++i )
  67. {
  68. if ( !Q_stricmp( pProcessorType, processors[i]->GetTypeString() ) && !Q_stricmp( pName, processors[i]->GetName() ) )
  69. return processors[i];
  70. }
  71. return NULL;
  72. }
  73. //-----------------------------------------------------------------------------
  74. // Parses key values out of the txt file
  75. //-----------------------------------------------------------------------------
  76. bool CImportTex::ParseOptionKey( const char *pKeyName, const char *pKeyValue, CDmElement *pTexture )
  77. {
  78. int iValue = atoi( pKeyValue ); // To properly have "clamps 0" and not enable the clamping
  79. if( !Q_stricmp( pKeyName, "startframe" ) )
  80. {
  81. pTexture->SetValue( "startFrame", iValue );
  82. }
  83. else if( !Q_stricmp( pKeyName, "endframe" ) )
  84. {
  85. pTexture->SetValue( "endFrame", iValue );
  86. }
  87. else if ( !Q_stricmp( pKeyName, "cubemap" ) )
  88. {
  89. pTexture->SetValue( "textureType", iValue ? 1 : 0 );
  90. }
  91. else if( !Q_stricmp( pKeyName, "volumetexture" ) )
  92. {
  93. pTexture->SetValue( "volumeTextureDepth", iValue );
  94. /*
  95. // FIXME: Volume textures don't currently support DXT compression
  96. m_vtfProcOptions.flags0 |= VtfProcessingOptions::OPT_NOCOMPRESS;
  97. */
  98. }
  99. else if( !Q_stricmp( pKeyName, "clamps" ) )
  100. {
  101. pTexture->SetValue( "clamps", iValue ? true : false );
  102. }
  103. else if( !Q_stricmp( pKeyName, "clampt" ) )
  104. {
  105. pTexture->SetValue( "clampt", iValue ? true : false );
  106. }
  107. else if( !Q_stricmp( pKeyName, "clampu" ) )
  108. {
  109. pTexture->SetValue( "clampu", iValue ? true : false );
  110. }
  111. else if ( !Q_stricmp( pKeyName, "nodebug" ) )
  112. {
  113. pTexture->SetValue( "noDebugOverride", iValue ? true : false );
  114. }
  115. else if( !Q_stricmp( pKeyName, "pointsample" ) )
  116. {
  117. if ( iValue != 0 )
  118. {
  119. pTexture->SetValue( "filterType", 4 );
  120. }
  121. }
  122. else if( !Q_stricmp( pKeyName, "trilinear" ) )
  123. {
  124. if ( iValue != 0 )
  125. {
  126. pTexture->SetValue( "filterType", 2 );
  127. }
  128. }
  129. else if( !Q_stricmp( pKeyName, "anisotropic" ) )
  130. {
  131. if ( iValue != 0 )
  132. {
  133. pTexture->SetValue( "filterType", 1 );
  134. }
  135. }
  136. else if( !Q_stricmp( pKeyName, "nomip" ) )
  137. {
  138. pTexture->SetValue( "noMip", iValue ? true : false );
  139. }
  140. else if( !Q_stricmp( pKeyName, "nolod" ) )
  141. {
  142. pTexture->SetValue( "noLod", iValue ? true : false );
  143. }
  144. else if( !Q_stricmp( pKeyName, "nonice" ) )
  145. {
  146. m_bNoNice = iValue ? true : false;
  147. }
  148. else if( !Q_stricmp( pKeyName, "alphatest" ) )
  149. {
  150. m_bAlphatestMipmapping = iValue ? true : false;
  151. }
  152. else if( !Q_stricmp( pKeyName, "alphatest_threshhold" ) )
  153. {
  154. m_flAlphatestMipmapThreshhold = (float)atof( pKeyValue );
  155. }
  156. else if( !Q_stricmp( pKeyName, "alphatest_hifreq_threshhold" ) )
  157. {
  158. m_flAlphatestMipmapHiFreqThreshhold = (float)atof( pKeyValue );
  159. }
  160. else if( !Q_stricmp( pKeyName, "dxt5" ) )
  161. {
  162. pTexture->SetValue( "hintDxt5Compression", iValue ? true : false );
  163. }
  164. else if( !Q_stricmp( pKeyName, "nocompress" ) )
  165. {
  166. pTexture->SetValue( "noCompression", iValue ? true : false );
  167. }
  168. else if ( !Q_stricmp( pKeyName, "numchannels" ) )
  169. {
  170. CDmElement *pProcessor = AddProcessor( pTexture, "DmeTP_ChangeColorChannels", "changeColorChannels" );
  171. pProcessor->SetValue( "maxChannels", iValue );
  172. }
  173. else
  174. {
  175. Warning("unrecognized option in text file - %s\n", pKeyName );
  176. }
  177. return true;
  178. #if 0
  179. else if ( !Q_stricmp( pKeyName, "skybox" ) )
  180. {
  181. // We're going to treat it like a cubemap until the very end (we have to load and process all cubemap
  182. // faces at once, so we can match their edges with the texture compression and mipmapping).
  183. m_bIsSkyBox = iValue ? true : false;
  184. m_bIsCubeMap = iValue ? true : false;
  185. }
  186. else if ( !Q_stricmp( pKeyName, "skyboxcropped" ) )
  187. {
  188. m_bIsCroppedSkyBox = iValue ? true : false;
  189. }
  190. else if( !Q_stricmp( pKeyName, "bumpscale" ) )
  191. {
  192. m_flBumpScale = atof( pKeyValue );
  193. }
  194. else if( !Q_stricmp( pKeyName, "border" ) )
  195. {
  196. SetFlagValue( m_nFlags, TEXTUREFLAGS_BORDER, iValue );
  197. // Gets applied to s, t and u We currently assume black border color
  198. }
  199. else if( !Q_stricmp( pKeyName, "normal" ) )
  200. {
  201. SetFlagValue( m_nFlags, TEXTUREFLAGS_NORMAL, iValue );
  202. // Normal maps not supported for manual mip painting
  203. m_bManualMip = false;
  204. }
  205. else if( !Q_stricmp( pKeyName, "normalga" ) )
  206. {
  207. m_bNormalToDXT5GA = iValue ? true : false;
  208. SetFlagValue( m_vtfProcOptions.flags0, VtfProcessingOptions::OPT_NORMAL_GA, iValue );
  209. }
  210. else if( !Q_stricmp( pKeyName, "invertgreen" ) )
  211. {
  212. m_bNormalInvertGreen = iValue ? true : false;
  213. }
  214. else if( !Q_stricmp( pKeyName, "ssbump" ) )
  215. {
  216. SetFlagValue( m_nFlags, TEXTUREFLAGS_SSBUMP, iValue );
  217. }
  218. else if( !Q_stricmp( pKeyName, "allmips" ) )
  219. {
  220. SetFlagValue( m_nFlags, TEXTUREFLAGS_ALL_MIPS, iValue );
  221. }
  222. else if( !Q_stricmp( pKeyName, "rendertarget" ) )
  223. {
  224. SetFlagValue( m_nFlags, TEXTUREFLAGS_RENDERTARGET, iValue );
  225. }
  226. else if( !Q_stricmp( pKeyName, "oneovermiplevelinalpha" ) )
  227. {
  228. SetFlagValue( m_vtfProcOptions.flags0, VtfProcessingOptions::OPT_SET_ALPHA_ONEOVERMIP, iValue );
  229. }
  230. else if( !Q_stricmp( pKeyName, "premultcolorbyoneovermiplevel" ) )
  231. {
  232. SetFlagValue( m_vtfProcOptions.flags0, VtfProcessingOptions::OPT_PREMULT_COLOR_ONEOVERMIP, iValue );
  233. }
  234. else if ( !Q_stricmp( pKeyName, "normaltodudv" ) )
  235. {
  236. m_bNormalToDuDv = iValue ? true : false;
  237. SetFlagValue( m_vtfProcOptions.flags0, VtfProcessingOptions::OPT_NORMAL_DUDV, iValue );
  238. }
  239. else if ( !Q_stricmp( pKeyName, "stripalphachannel" ) )
  240. {
  241. m_bStripAlphaChannel = iValue ? true : false;
  242. }
  243. else if ( !Q_stricmp( pKeyName, "stripcolorchannel" ) )
  244. {
  245. m_bStripColorChannel = iValue ? true : false;
  246. }
  247. else if ( !Q_stricmp( pKeyName, "normalalphatodudvluminance" ) )
  248. {
  249. m_bAlphaToLuminance = iValue ? true : false;
  250. }
  251. else if ( !Q_stricmp( pKeyName, "dudv" ) )
  252. {
  253. m_bDuDv = iValue ? true : false;
  254. }
  255. else if( !Q_stricmp( pKeyName, "reduce" ) )
  256. {
  257. m_nReduceX = atoi(pKeyValue);
  258. m_nReduceY = m_nReduceX;
  259. }
  260. else if( !Q_stricmp( pKeyName, "reducex" ) )
  261. {
  262. m_nReduceX = atoi(pKeyValue);
  263. }
  264. else if( !Q_stricmp( pKeyName, "reducey" ) )
  265. {
  266. m_nReduceY = atoi(pKeyValue);
  267. }
  268. else if( !Q_stricmp( pKeyName, "maxwidth" ) )
  269. {
  270. m_nMaxDimensionX = atoi(pKeyValue);
  271. }
  272. else if( !Q_stricmp( pKeyName, "maxwidth_360" ) )
  273. {
  274. m_nMaxDimensionX_360 = atoi(pKeyValue);
  275. }
  276. else if( !Q_stricmp( pKeyName, "maxheight" ) )
  277. {
  278. m_nMaxDimensionY = atoi(pKeyValue);
  279. }
  280. else if( !Q_stricmp( pKeyName, "maxheight_360" ) )
  281. {
  282. m_nMaxDimensionY_360 = atoi(pKeyValue);
  283. }
  284. else if( !Q_stricmp( pKeyName, "alphatodistance" ) )
  285. {
  286. m_bAlphaToDistance = iValue ? true : false;
  287. }
  288. else if( !Q_stricmp( pKeyName, "distancespread" ) )
  289. {
  290. m_flDistanceSpread = atof(pKeyValue);
  291. }
  292. else if( !Q_stricmp( pKeyName, "pfmscale" ) )
  293. {
  294. m_pfmscale=atof(pKeyValue);
  295. VTexMsg( "pfmscale = %.2f\n", m_pfmscale );
  296. }
  297. else if ( !Q_stricmp( pKeyName, "pfm" ) )
  298. {
  299. if ( iValue )
  300. g_eMode = BITMAP_FILE_TYPE_PFM;
  301. }
  302. else if ( !Q_stricmp( pKeyName, "specvar" ) )
  303. {
  304. int iDecayChannel = -1;
  305. if ( !Q_stricmp( pKeyValue, "red" ) || !Q_stricmp( pKeyValue, "r" ) )
  306. iDecayChannel = 0;
  307. if ( !Q_stricmp( pKeyValue, "green" ) || !Q_stricmp( pKeyValue, "g" ) )
  308. iDecayChannel = 1;
  309. if ( !Q_stricmp( pKeyValue, "blue" ) || !Q_stricmp( pKeyValue, "b" ) )
  310. iDecayChannel = 2;
  311. if ( !Q_stricmp( pKeyValue, "alpha" ) || !Q_stricmp( pKeyValue, "a" ) )
  312. iDecayChannel = 3;
  313. if ( iDecayChannel >= 0 && iDecayChannel < 4 )
  314. {
  315. m_vtfProcOptions.flags0 |= ( VtfProcessingOptions::OPT_DECAY_R | VtfProcessingOptions::OPT_DECAY_EXP_R ) << iDecayChannel;
  316. m_vtfProcOptions.numNotDecayMips[iDecayChannel] = 0;
  317. m_vtfProcOptions.clrDecayGoal[iDecayChannel] = 0;
  318. m_vtfProcOptions.fDecayExponentBase[iDecayChannel] = 0.75;
  319. m_bManualMip = false;
  320. SetFlagValue( m_nFlags, TEXTUREFLAGS_ALL_MIPS, 1 );
  321. }
  322. }
  323. else if ( Q_stricmp( pKeyName, "manualmip" ) == 0 )
  324. {
  325. if ( ( m_nVolumeTextureDepth == 1 ) && !( m_nFlags & ( TEXTUREFLAGS_NORMAL | TEXTUREFLAGS_NOMIP ) ) )
  326. {
  327. m_bManualMip = true;
  328. }
  329. }
  330. else if ( !Q_stricmp( pKeyName, "mipblend" ) )
  331. {
  332. SetFlagValue( m_nFlags, TEXTUREFLAGS_ALL_MIPS, 1 );
  333. // Possible values
  334. if ( !Q_stricmp( pKeyValue, "detail" ) ) // Skip 2 mips and fade to gray -> (128, 128, 128, -)
  335. {
  336. for( int ch = 0; ch < 3; ++ ch )
  337. {
  338. m_vtfProcOptions.flags0 |= VtfProcessingOptions::OPT_DECAY_R << ch;
  339. // m_vtfProcOptions.flags0 &= ~(VtfProcessingOptions::OPT_DECAY_EXP_R << ch);
  340. m_vtfProcOptions.numNotDecayMips[ch] = 2;
  341. m_vtfProcOptions.clrDecayGoal[ch] = 128;
  342. }
  343. }
  344. /*
  345. else if ( !Q_stricmp( pKeyValue, "additive" ) ) // Skip 2 mips and fade to black -> (0, 0, 0, -)
  346. {
  347. for( int ch = 0; ch < 3; ++ ch )
  348. {
  349. m_vtfProcOptions.flags0 |= VtfProcessingOptions::OPT_DECAY_R << ch;
  350. m_vtfProcOptions.flags0 &= ~(VtfProcessingOptions::OPT_DECAY_EXP_R << ch);
  351. m_vtfProcOptions.numDecayMips[ch] = 2;
  352. m_vtfProcOptions.clrDecayGoal[ch] = 0;
  353. }
  354. }
  355. else if ( !Q_stricmp( pKeyValue, "alphablended" ) ) // Skip 2 mips and fade out alpha to 0
  356. {
  357. for( int ch = 3; ch < 4; ++ ch )
  358. {
  359. m_vtfProcOptions.flags0 |= VtfProcessingOptions::OPT_DECAY_R << ch;
  360. m_vtfProcOptions.flags0 &= ~(VtfProcessingOptions::OPT_DECAY_EXP_R << ch);
  361. m_vtfProcOptions.numDecayMips[ch] = 2;
  362. m_vtfProcOptions.clrDecayGoal[ch] = 0;
  363. }
  364. }
  365. */
  366. else
  367. {
  368. // Parse the given value:
  369. // skip=3:r=255:g=255:b=255:a=255 - linear decay
  370. // r=0e.75 - exponential decay targeting 0 with exponent base 0.75
  371. int nSteps = 0; // default
  372. for ( char const *szParse = pKeyValue; szParse; szParse = strchr( szParse, ':' ), szParse ? ++ szParse : 0 )
  373. {
  374. if ( char const *sz = StringAfterPrefix( szParse, "skip=" ) )
  375. {
  376. szParse = sz;
  377. nSteps = atoi(sz);
  378. }
  379. else if ( StringHasPrefix( szParse, "r=" ) ||
  380. StringHasPrefix( szParse, "g=" ) ||
  381. StringHasPrefix( szParse, "b=" ) ||
  382. StringHasPrefix( szParse, "a=" ) )
  383. {
  384. int ch = 0;
  385. switch ( *szParse )
  386. {
  387. case 'g': case 'G': ch = 1; break;
  388. case 'b': case 'B': ch = 2; break;
  389. case 'a': case 'A': ch = 3; break;
  390. }
  391. szParse += 2;
  392. m_vtfProcOptions.flags0 |= VtfProcessingOptions::OPT_DECAY_R << ch;
  393. m_vtfProcOptions.flags0 &= ~(VtfProcessingOptions::OPT_DECAY_EXP_R << ch);
  394. m_vtfProcOptions.numNotDecayMips[ch] = nSteps;
  395. m_vtfProcOptions.clrDecayGoal[ch] = atoi( szParse );
  396. while ( isdigit( *szParse ) )
  397. ++ szParse;
  398. // Exponential decay
  399. if ( ( *szParse == 'e' || *szParse == 'E' ) && ( szParse[1] == '.' ) )
  400. {
  401. m_vtfProcOptions.flags0 |= VtfProcessingOptions::OPT_DECAY_EXP_R << ch;
  402. m_vtfProcOptions.fDecayExponentBase[ch] = ( float ) atof( szParse + 1 );
  403. }
  404. }
  405. else
  406. {
  407. Warning( "invalid mipblend setting \"%s\"\n", pKeyValue );
  408. }
  409. }
  410. }
  411. }
  412. else if( !Q_stricmp( pKeyName, "srgb" ) )
  413. {
  414. // Do nothing for now...this will be removed shortly
  415. }
  416. #endif
  417. }
  418. const char *CImportTex::GetPossiblyQuotedWord( const char *pInBuf, char *pOutbuf )
  419. {
  420. pInBuf += strspn( pInBuf, " \t" ); // skip whitespace
  421. const char *pWordEnd;
  422. bool bQuote = false;
  423. if (pInBuf[0]=='"')
  424. {
  425. pInBuf++;
  426. pWordEnd=strchr(pInBuf,'"');
  427. bQuote = true;
  428. }
  429. else
  430. {
  431. pWordEnd=strchr(pInBuf,' ');
  432. if (! pWordEnd )
  433. pWordEnd = strchr(pInBuf,'\t' );
  434. if (! pWordEnd )
  435. pWordEnd = pInBuf+strlen(pInBuf);
  436. }
  437. if ((! pWordEnd ) || (pWordEnd == pInBuf ) )
  438. return NULL; // no word found
  439. memcpy( pOutbuf, pInBuf, pWordEnd-pInBuf );
  440. pOutbuf[pWordEnd-pInBuf]=0;
  441. pInBuf = pWordEnd;
  442. if ( bQuote )
  443. pInBuf++;
  444. return pInBuf;
  445. }
  446. // GetKeyValueFromBuffer:
  447. // fills in "key" and "val" respectively and returns "true" if succeeds.
  448. // returns false if:
  449. // a) end-of-buffer is reached (then "val" is empty)
  450. // b) error occurs (then "val" is the error message)
  451. //
  452. bool CImportTex::GetKeyValueFromBuffer( CUtlBuffer &buffer, char *key, char *val )
  453. {
  454. char buf[2048];
  455. while( buffer.GetBytesRemaining() )
  456. {
  457. buffer.GetLine( buf, sizeof( buf ) );
  458. // Scanning algorithm
  459. char *pComment = strpbrk( buf, "#\n\r" );
  460. if ( pComment )
  461. *pComment = 0;
  462. pComment = strstr( buf, "//" );
  463. if ( pComment)
  464. *pComment = 0;
  465. const char *scan = buf;
  466. scan=GetPossiblyQuotedWord( scan, key );
  467. if ( scan )
  468. {
  469. scan=GetPossiblyQuotedWord( scan, val );
  470. if ( scan )
  471. return true;
  472. else
  473. {
  474. sprintf( val, "parameter %s has no value", key );
  475. return false;
  476. }
  477. }
  478. }
  479. val[0] = 0;
  480. return false;
  481. }
  482. //-----------------------------------------------------------------------------
  483. // Main entry point for the unserialization
  484. //-----------------------------------------------------------------------------
  485. bool CImportTex::Unserialize( CUtlBuffer &buf, const char *pEncodingName, int nEncodingVersion, const char *pSourceFormatName,
  486. int nSourceFormatVersion, DmFileId_t fileid, DmConflictResolution_t idConflictResolution, CDmElement **ppRoot )
  487. {
  488. *ppRoot = NULL;
  489. m_bNoNice = m_bAlphatestMipmapping = false;
  490. m_flAlphatestMipmapThreshhold = m_flAlphatestMipmapHiFreqThreshhold = 0.0f;
  491. CDmElement *pTexture = CreateElement< CDmElement >( "DmePrecompiledTexture", "root", DMFILEID_INVALID );
  492. pTexture->SetValue( "imageFileName", "__unspecified_texture" );
  493. char pKey[2048];
  494. char pVal[2048];
  495. while( GetKeyValueFromBuffer( buf, pKey, pVal ) )
  496. {
  497. ParseOptionKey( pKey, pVal, pTexture );
  498. }
  499. if ( pVal[0] )
  500. {
  501. Warning( "Error importing txt file! %s\n", pVal );
  502. return false;
  503. }
  504. // Prefer to do mipmapping as one of the final processors
  505. if ( !pTexture->GetValue< bool >( "noMip" ) || !pTexture->GetValue< bool >( "noLod" ) )
  506. {
  507. CDmElement *pProcessor = AddProcessor( pTexture, "DmeTP_ComputeMipmaps", "computeMipmaps" );
  508. pProcessor->SetValue( "noNiceFiltering", m_bNoNice );
  509. pProcessor->SetValue( "alphaTestDownsampling", m_bAlphatestMipmapping );
  510. pProcessor->SetValue( "alphaTestDownsampleThreshhold", m_flAlphatestMipmapThreshhold );
  511. pProcessor->SetValue( "alphaTestDownsampleHiFreqThreshhold" , m_flAlphatestMipmapHiFreqThreshhold );
  512. }
  513. *ppRoot = pTexture;
  514. bool bOk = g_pDataModel->UpdateUnserializedElements( pSourceFormatName, nSourceFormatVersion, fileid, idConflictResolution, ppRoot );
  515. if ( !bOk )
  516. {
  517. *ppRoot = NULL;
  518. }
  519. return bOk;
  520. }