Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

215 lines
6.1 KiB

5 years ago
//========= 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;
}