diff options
Diffstat (limited to 'game/client/tf/vgui/modelimagepanel.cpp')
| -rw-r--r-- | game/client/tf/vgui/modelimagepanel.cpp | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/game/client/tf/vgui/modelimagepanel.cpp b/game/client/tf/vgui/modelimagepanel.cpp new file mode 100644 index 0000000..e322282 --- /dev/null +++ b/game/client/tf/vgui/modelimagepanel.cpp @@ -0,0 +1,214 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= +#include "cbase.h" +#include "modelimagepanel.h" +#include "iconrenderreceiver.h" +#include "materialsystem/imaterialvar.h" +#include "VGuiMatSurface/IMatSystemSurface.h" +#include "renderparm.h" + + +using namespace vgui; + +const char *g_pszModelImagePanelRTName = "_rt_ModelImagePanel"; +static vgui::DHANDLE<CModelImagePanel> s_hModelImageLockPanel; + +#ifdef STAGING_ONLY +ConVar tf_modelimagepanel_ignore_cache( "tf_modelimagepanel_ignore_cache", "0" ); +#endif + +DECLARE_BUILD_FACTORY( CModelImagePanel ); + +CModelImagePanel::CModelImagePanel( vgui::Panel *pParent, const char *pName ) + : BaseClass( pParent, pName ) +{ + m_pCachedIcon = NULL; + m_pCachedMaterial = NULL; + m_iCachedTextureID = -1; +} + +CModelImagePanel::~CModelImagePanel() +{ + InvalidateImage(); +} + +void CModelImagePanel::PerformLayout() +{ + BaseClass::PerformLayout(); + + InvalidateImage(); +} + +void CModelImagePanel::OnSizeChanged( int wide, int tall ) +{ + BaseClass::OnSizeChanged( wide, tall ); + + InvalidateImage(); +} + +void CModelImagePanel::Paint() +{ + // don't do anything for invalid model + if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID ) + { + return; + } + + // check lock panel + if ( s_hModelImageLockPanel ) + { + // waiting for async copy to finish + if ( s_hModelImageLockPanel->m_pCachedIcon && s_hModelImageLockPanel->m_pCachedIcon->GetTexture() ) + { + s_hModelImageLockPanel = NULL; + } + } + + if ( m_pCachedIcon ) + { + if ( m_pCachedIcon->GetTexture() ) + { + if ( !m_pCachedMaterial && g_pMaterialSystem ) + { + const char *pszTextureName = m_pCachedIcon->GetTexture()->GetName(); + KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" ); + pVMTKeyValues->SetString( "$basetexture", pszTextureName ); + pVMTKeyValues->SetInt( "$translucent", 1 ); + pVMTKeyValues->SetInt( "$vertexcolor", 1 ); + IMaterial *pMaterial = g_pMaterialSystem->FindProceduralMaterial( pszTextureName, TEXTURE_GROUP_VGUI, pVMTKeyValues ); + SafeAssign( &m_pCachedMaterial, pMaterial ); + + bool bFound = false; + IMaterialVar *pVar = m_pCachedMaterial->FindVar( "$basetexture", &bFound ); + if ( bFound && pVar ) + { + pVar->SetTextureValue( m_pCachedIcon->GetTexture() ); + m_pCachedMaterial->RefreshPreservingMaterialVars(); + } + } + + if ( m_iCachedTextureID == -1 ) + { + m_iCachedTextureID = g_pMatSystemSurface->DrawGetTextureId( m_pCachedIcon->GetTexture() ); + g_pMatSystemSurface->DrawSetTextureMaterial( m_iCachedTextureID, m_pCachedMaterial ); + } + } + else + { + // still waiting for texture + BaseClass::Paint(); + return; + } + } + + // just draw the texture if we got one. + if ( m_iCachedTextureID != -1 ) + { + surface()->DrawSetTexture( m_iCachedTextureID ); + surface()->DrawSetColor( 255, 255, 255, 255 ); + const int iWidth = GetWide(); + const int iHeight = GetTall(); + const int iMappingWitdh = m_pCachedMaterial->GetMappingWidth(); + const int iMappingHeight = m_pCachedMaterial->GetMappingHeight(); + float flTexW, flTexH; + if ( iWidth > iMappingWitdh || iHeight > iMappingHeight ) + { + float flScale = iWidth > iHeight ? (float)iMappingWitdh / iWidth : (float)iMappingHeight / iHeight; + flTexW = ( flScale * iWidth ) / iMappingWitdh; + flTexH = ( flScale * iHeight ) / iMappingHeight; + } + else + { + flTexW = (float)( iWidth - 1 ) / iMappingWitdh; + flTexH = (float)( iHeight - 1 ) / iMappingHeight; + } + surface()->DrawTexturedSubRect( 0, 0, iWidth, iHeight, 0.f, 0.f, flTexW, flTexH ); + return; + } + + // can't find available cache render target, don't do anything + if ( s_hModelImageLockPanel != NULL && s_hModelImageLockPanel != this ) + { + BaseClass::Paint(); + return; + } + + CMatRenderContextPtr pRenderContext( materials ); + + // Turn off depth-write to dest alpha so that we get white there instead. The code that uses + // the render target needs a mask of where stuff was rendered. + pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA, false ); + + g_pMatSystemSurface->Set3DPaintTempRenderTarget( g_pszModelImagePanelRTName ); + + BaseClass::Paint(); + + // copy the rendered weapon skin from the render target + Assert( m_pCachedIcon == NULL ); + CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( m_RootMDL.m_MDL.GetMDL() ), g_pMDLCache ); + char buffer[_MAX_PATH]; + CUtlString strMDLName = V_GetFileName( studioHdr.pszName() ); + 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() ); + SafeAssign( &m_pCachedIcon, new CIconRenderReceiver() ); + + // If the icon still exists in the material system, don't bother regenerating it. + if ( materials->IsTextureLoaded( buffer ) +#ifdef STAGING_ONLY + && !tf_modelimagepanel_ignore_cache.GetBool() +#endif + ) + { + ITexture* resTexture = materials->FindTexture( buffer, TEXTURE_GROUP_RUNTIME_COMPOSITE, false, 0 ); + if ( resTexture && resTexture->IsError() == false ) + { + m_pCachedIcon->OnAsyncCreateComplete( resTexture, NULL ); + } + } + else + { + // No icon available yet, need to create it. + ITexture *pRenderTarget = g_pMaterialSystem->FindTexture( g_pszModelImagePanelRTName, TEXTURE_GROUP_RENDER_TARGET ); + if ( pRenderTarget ) + { + pRenderContext->AsyncCreateTextureFromRenderTarget( pRenderTarget, buffer, IMAGE_FORMAT_RGBA8888, false, TEXTUREFLAGS_IMMEDIATE_CLEANUP, m_pCachedIcon, NULL ); + + // make this panel lock the render target + s_hModelImageLockPanel = this; + } + } + + g_pMatSystemSurface->Reset3DPaintTempRenderTarget(); +} + +void CModelImagePanel::SetMDL( MDLHandle_t handle, void *pProxyData /*= NULL*/ ) +{ + BaseClass::SetMDL( handle, pProxyData ); + InvalidateImage(); +} + +void CModelImagePanel::SetMDL( const char *pMDLName, void *pProxyData /*= NULL*/ ) +{ + BaseClass::SetMDL( pMDLName, pProxyData ); +} + +void CModelImagePanel::SetMDLBody( unsigned int nBody ) +{ + SetBody( nBody ); + InvalidateImage(); +} + +void CModelImagePanel::SetMDLSkin( int nSkin ) +{ + SetSkin( nSkin ); + InvalidateImage(); +} + +void CModelImagePanel::InvalidateImage() +{ + SafeRelease( &m_pCachedIcon ); + SafeRelease( &m_pCachedMaterial ); + m_iCachedTextureID = -1; +} |