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.

214 lines
6.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "modelimagepanel.h"
  8. #include "iconrenderreceiver.h"
  9. #include "materialsystem/imaterialvar.h"
  10. #include "VGuiMatSurface/IMatSystemSurface.h"
  11. #include "renderparm.h"
  12. using namespace vgui;
  13. const char *g_pszModelImagePanelRTName = "_rt_ModelImagePanel";
  14. static vgui::DHANDLE<CModelImagePanel> s_hModelImageLockPanel;
  15. #ifdef STAGING_ONLY
  16. ConVar tf_modelimagepanel_ignore_cache( "tf_modelimagepanel_ignore_cache", "0" );
  17. #endif
  18. DECLARE_BUILD_FACTORY( CModelImagePanel );
  19. CModelImagePanel::CModelImagePanel( vgui::Panel *pParent, const char *pName )
  20. : BaseClass( pParent, pName )
  21. {
  22. m_pCachedIcon = NULL;
  23. m_pCachedMaterial = NULL;
  24. m_iCachedTextureID = -1;
  25. }
  26. CModelImagePanel::~CModelImagePanel()
  27. {
  28. InvalidateImage();
  29. }
  30. void CModelImagePanel::PerformLayout()
  31. {
  32. BaseClass::PerformLayout();
  33. InvalidateImage();
  34. }
  35. void CModelImagePanel::OnSizeChanged( int wide, int tall )
  36. {
  37. BaseClass::OnSizeChanged( wide, tall );
  38. InvalidateImage();
  39. }
  40. void CModelImagePanel::Paint()
  41. {
  42. // don't do anything for invalid model
  43. if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
  44. {
  45. return;
  46. }
  47. // check lock panel
  48. if ( s_hModelImageLockPanel )
  49. {
  50. // waiting for async copy to finish
  51. if ( s_hModelImageLockPanel->m_pCachedIcon && s_hModelImageLockPanel->m_pCachedIcon->GetTexture() )
  52. {
  53. s_hModelImageLockPanel = NULL;
  54. }
  55. }
  56. if ( m_pCachedIcon )
  57. {
  58. if ( m_pCachedIcon->GetTexture() )
  59. {
  60. if ( !m_pCachedMaterial && g_pMaterialSystem )
  61. {
  62. const char *pszTextureName = m_pCachedIcon->GetTexture()->GetName();
  63. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  64. pVMTKeyValues->SetString( "$basetexture", pszTextureName );
  65. pVMTKeyValues->SetInt( "$translucent", 1 );
  66. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  67. IMaterial *pMaterial = g_pMaterialSystem->FindProceduralMaterial( pszTextureName, TEXTURE_GROUP_VGUI, pVMTKeyValues );
  68. SafeAssign( &m_pCachedMaterial, pMaterial );
  69. bool bFound = false;
  70. IMaterialVar *pVar = m_pCachedMaterial->FindVar( "$basetexture", &bFound );
  71. if ( bFound && pVar )
  72. {
  73. pVar->SetTextureValue( m_pCachedIcon->GetTexture() );
  74. m_pCachedMaterial->RefreshPreservingMaterialVars();
  75. }
  76. }
  77. if ( m_iCachedTextureID == -1 )
  78. {
  79. m_iCachedTextureID = g_pMatSystemSurface->DrawGetTextureId( m_pCachedIcon->GetTexture() );
  80. g_pMatSystemSurface->DrawSetTextureMaterial( m_iCachedTextureID, m_pCachedMaterial );
  81. }
  82. }
  83. else
  84. {
  85. // still waiting for texture
  86. BaseClass::Paint();
  87. return;
  88. }
  89. }
  90. // just draw the texture if we got one.
  91. if ( m_iCachedTextureID != -1 )
  92. {
  93. surface()->DrawSetTexture( m_iCachedTextureID );
  94. surface()->DrawSetColor( 255, 255, 255, 255 );
  95. const int iWidth = GetWide();
  96. const int iHeight = GetTall();
  97. const int iMappingWitdh = m_pCachedMaterial->GetMappingWidth();
  98. const int iMappingHeight = m_pCachedMaterial->GetMappingHeight();
  99. float flTexW, flTexH;
  100. if ( iWidth > iMappingWitdh || iHeight > iMappingHeight )
  101. {
  102. float flScale = iWidth > iHeight ? (float)iMappingWitdh / iWidth : (float)iMappingHeight / iHeight;
  103. flTexW = ( flScale * iWidth ) / iMappingWitdh;
  104. flTexH = ( flScale * iHeight ) / iMappingHeight;
  105. }
  106. else
  107. {
  108. flTexW = (float)( iWidth - 1 ) / iMappingWitdh;
  109. flTexH = (float)( iHeight - 1 ) / iMappingHeight;
  110. }
  111. surface()->DrawTexturedSubRect( 0, 0, iWidth, iHeight, 0.f, 0.f, flTexW, flTexH );
  112. return;
  113. }
  114. // can't find available cache render target, don't do anything
  115. if ( s_hModelImageLockPanel != NULL && s_hModelImageLockPanel != this )
  116. {
  117. BaseClass::Paint();
  118. return;
  119. }
  120. CMatRenderContextPtr pRenderContext( materials );
  121. // Turn off depth-write to dest alpha so that we get white there instead. The code that uses
  122. // the render target needs a mask of where stuff was rendered.
  123. pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA, false );
  124. g_pMatSystemSurface->Set3DPaintTempRenderTarget( g_pszModelImagePanelRTName );
  125. BaseClass::Paint();
  126. // copy the rendered weapon skin from the render target
  127. Assert( m_pCachedIcon == NULL );
  128. CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_RootMDL.m_MDL.GetMDL() ), g_pMDLCache );
  129. char buffer[_MAX_PATH];
  130. CUtlString strMDLName = V_GetFileName( studioHdr.pszName() );
  131. V_sprintf_safe( buffer, "proc/icon/mdl_%s_body%d_skin%d_w%d_h%d", strMDLName.StripExtension().Get(), m_RootMDL.m_MDL.m_nBody, m_RootMDL.m_MDL.m_nSkin, GetWide(), GetTall() );
  132. SafeAssign( &m_pCachedIcon, new CIconRenderReceiver() );
  133. // If the icon still exists in the material system, don't bother regenerating it.
  134. if ( materials->IsTextureLoaded( buffer )
  135. #ifdef STAGING_ONLY
  136. && !tf_modelimagepanel_ignore_cache.GetBool()
  137. #endif
  138. )
  139. {
  140. ITexture* resTexture = materials->FindTexture( buffer, TEXTURE_GROUP_RUNTIME_COMPOSITE, false, 0 );
  141. if ( resTexture && resTexture->IsError() == false )
  142. {
  143. m_pCachedIcon->OnAsyncCreateComplete( resTexture, NULL );
  144. }
  145. }
  146. else
  147. {
  148. // No icon available yet, need to create it.
  149. ITexture *pRenderTarget = g_pMaterialSystem->FindTexture( g_pszModelImagePanelRTName, TEXTURE_GROUP_RENDER_TARGET );
  150. if ( pRenderTarget )
  151. {
  152. pRenderContext->AsyncCreateTextureFromRenderTarget( pRenderTarget, buffer, IMAGE_FORMAT_RGBA8888, false, TEXTUREFLAGS_IMMEDIATE_CLEANUP, m_pCachedIcon, NULL );
  153. // make this panel lock the render target
  154. s_hModelImageLockPanel = this;
  155. }
  156. }
  157. g_pMatSystemSurface->Reset3DPaintTempRenderTarget();
  158. }
  159. void CModelImagePanel::SetMDL( MDLHandle_t handle, void *pProxyData /*= NULL*/ )
  160. {
  161. BaseClass::SetMDL( handle, pProxyData );
  162. InvalidateImage();
  163. }
  164. void CModelImagePanel::SetMDL( const char *pMDLName, void *pProxyData /*= NULL*/ )
  165. {
  166. BaseClass::SetMDL( pMDLName, pProxyData );
  167. }
  168. void CModelImagePanel::SetMDLBody( unsigned int nBody )
  169. {
  170. SetBody( nBody );
  171. InvalidateImage();
  172. }
  173. void CModelImagePanel::SetMDLSkin( int nSkin )
  174. {
  175. SetSkin( nSkin );
  176. InvalidateImage();
  177. }
  178. void CModelImagePanel::InvalidateImage()
  179. {
  180. SafeRelease( &m_pCachedIcon );
  181. SafeRelease( &m_pCachedMaterial );
  182. m_iCachedTextureID = -1;
  183. }