summaryrefslogtreecommitdiff
path: root/utils/modelbrowser/modelbrowsermaterialproxies.h
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/modelbrowser/modelbrowsermaterialproxies.h
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/modelbrowser/modelbrowsermaterialproxies.h')
-rw-r--r--utils/modelbrowser/modelbrowsermaterialproxies.h412
1 files changed, 412 insertions, 0 deletions
diff --git a/utils/modelbrowser/modelbrowsermaterialproxies.h b/utils/modelbrowser/modelbrowsermaterialproxies.h
new file mode 100644
index 0000000..0bd3c2f
--- /dev/null
+++ b/utils/modelbrowser/modelbrowsermaterialproxies.h
@@ -0,0 +1,412 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+
+#include <windows.h>
+#include "materialsystem/imaterialproxyfactory.h"
+#include "materialsystem/imaterialvar.h"
+#include "materialsystem/imaterialproxy.h"
+
+class C_BaseEntity;
+
+// Copied and bastardized a few material proxy classes from the TF client dll. The purpose here is
+// to make TF materials for paintable items show the default paint color (using the SelectFirstIfNotZero proxy)
+// and to completely hide the burn detail texture (fake BurnLevel proxy).
+// Implemented a lame material proxy factory that only knows about these two proxies.
+
+//-----------------------------------------------------------------------------
+// Helper class to deal with floating point inputs
+//-----------------------------------------------------------------------------
+class CFloatInput
+{
+public:
+ bool Init( IMaterial *pMaterial, KeyValues *pKeyValues, const char *pKeyName, float flDefault = 0.0f );
+ float GetFloat() const;
+
+private:
+ float m_flValue;
+ IMaterialVar *m_pFloatVar;
+ int m_FloatVecComp;
+};
+
+bool CFloatInput::Init( IMaterial *pMaterial, KeyValues *pKeyValues, const char *pKeyName, float flDefault )
+{
+ m_pFloatVar = NULL;
+ KeyValues *pSection = pKeyValues->FindKey( pKeyName );
+ if (pSection)
+ {
+ if (pSection->GetDataType() == KeyValues::TYPE_STRING)
+ {
+ const char *pVarName = pSection->GetString();
+
+ // Look for numbers...
+ float flValue;
+ int nCount = sscanf( pVarName, "%f", &flValue );
+ if (nCount == 1)
+ {
+ m_flValue = flValue;
+ return true;
+ }
+
+ // Look for array specification...
+ char pTemp[256];
+ if (strchr(pVarName, '['))
+ {
+ // strip off the array...
+ Q_strncpy( pTemp, pVarName, 256 );
+ char *pArray = strchr( pTemp, '[' );
+ *pArray++ = 0;
+
+ char* pIEnd;
+ m_FloatVecComp = strtol( pArray, &pIEnd, 10 );
+
+ // Use the version without the array...
+ pVarName = pTemp;
+ }
+ else
+ {
+ m_FloatVecComp = -1;
+ }
+
+ bool bFoundVar;
+ m_pFloatVar = pMaterial->FindVar( pVarName, &bFoundVar, true );
+ if (!bFoundVar)
+ return false;
+ }
+ else
+ {
+ m_flValue = pSection->GetFloat();
+ }
+ }
+ else
+ {
+ m_flValue = flDefault;
+ }
+ return true;
+}
+
+float CFloatInput::GetFloat() const
+{
+ if (!m_pFloatVar)
+ return m_flValue;
+
+ if( m_FloatVecComp < 0 )
+ return m_pFloatVar->GetFloatValue();
+
+ int iVecSize = m_pFloatVar->VectorSize();
+ if ( m_FloatVecComp >= iVecSize )
+ return 0;
+
+ float v[4];
+ m_pFloatVar->GetVecValue( v, iVecSize );
+ return v[m_FloatVecComp];
+}
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Result proxy; a result (with vector friendliness)
+//
+//-----------------------------------------------------------------------------
+class CResultProxy : public IMaterialProxy
+{
+public:
+ CResultProxy();
+ virtual ~CResultProxy();
+ virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
+ virtual void Release( void ) { delete this; }
+ virtual IMaterial *GetMaterial();
+
+protected:
+ C_BaseEntity *BindArgToEntity( void *pArg );
+ void SetFloatResult( float result );
+
+ IMaterialVar* m_pResult;
+ int m_ResultVecComp;
+};
+
+CResultProxy::CResultProxy() : m_pResult(0)
+{
+}
+
+CResultProxy::~CResultProxy()
+{
+}
+
+
+bool CResultProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
+{
+ char const* pResult = pKeyValues->GetString( "resultVar" );
+ if( !pResult )
+ return false;
+
+ // Look for array specification...
+ char pTemp[256];
+ if (strchr(pResult, '['))
+ {
+ // strip off the array...
+ Q_strncpy( pTemp, pResult, 256 );
+ char *pArray = strchr( pTemp, '[' );
+ *pArray++ = 0;
+
+ char* pIEnd;
+ m_ResultVecComp = strtol( pArray, &pIEnd, 10 );
+
+ // Use the version without the array...
+ pResult = pTemp;
+ }
+ else
+ {
+ m_ResultVecComp = -1;
+ }
+
+ bool foundVar;
+ m_pResult = pMaterial->FindVar( pResult, &foundVar, true );
+ if( !foundVar )
+ return false;
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// A little code to allow us to set single components of vectors
+//-----------------------------------------------------------------------------
+void CResultProxy::SetFloatResult( float result )
+{
+ if (m_pResult->GetType() == MATERIAL_VAR_TYPE_VECTOR)
+ {
+ if ( m_ResultVecComp >= 0 )
+ {
+ m_pResult->SetVecComponentValue( result, m_ResultVecComp );
+ }
+ else
+ {
+ float v[4];
+ int vecSize = m_pResult->VectorSize();
+
+ for (int i = 0; i < vecSize; ++i)
+ v[i] = result;
+
+ m_pResult->SetVecValue( v, vecSize );
+ }
+ }
+ else
+ {
+ m_pResult->SetFloatValue( result );
+ }
+}
+
+C_BaseEntity *CResultProxy::BindArgToEntity( void *pArg )
+{
+ return NULL;
+ /*
+ IClientRenderable *pRend = (IClientRenderable *)pArg;
+ return pRend->GetIClientUnknown()->GetBaseEntity();
+ */
+}
+
+IMaterial *CResultProxy::GetMaterial()
+{
+ return m_pResult->GetOwningMaterial();
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Base functional proxy; two sources (one is optional) and a result
+//
+//-----------------------------------------------------------------------------
+class CFunctionProxy : public CResultProxy
+{
+public:
+ CFunctionProxy();
+ virtual ~CFunctionProxy();
+ virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
+
+protected:
+ void ComputeResultType( MaterialVarType_t& resultType, int& vecSize );
+
+ IMaterialVar* m_pSrc1;
+ IMaterialVar* m_pSrc2;
+};
+
+CFunctionProxy::CFunctionProxy() : m_pSrc1(0), m_pSrc2(0)
+{
+}
+
+CFunctionProxy::~CFunctionProxy()
+{
+}
+
+
+bool CFunctionProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
+{
+ if (!CResultProxy::Init( pMaterial, pKeyValues ))
+ return false;
+
+ char const* pSrcVar1 = pKeyValues->GetString( "srcVar1" );
+ if( !pSrcVar1 )
+ return false;
+
+ bool foundVar;
+ m_pSrc1 = pMaterial->FindVar( pSrcVar1, &foundVar, true );
+ if( !foundVar )
+ return false;
+
+ // Source 2 is optional, some math ops may be single-input
+ char const* pSrcVar2 = pKeyValues->GetString( "srcVar2" );
+ if( pSrcVar2 && (*pSrcVar2) )
+ {
+ m_pSrc2 = pMaterial->FindVar( pSrcVar2, &foundVar, true );
+ if( !foundVar )
+ return false;
+ }
+ else
+ {
+ m_pSrc2 = 0;
+ }
+
+ return true;
+}
+
+
+void CFunctionProxy::ComputeResultType( MaterialVarType_t& resultType, int& vecSize )
+{
+ // Feh, this is ugly. Basically, don't change the result type
+ // unless it's undefined.
+ resultType = m_pResult->GetType();
+ if (resultType == MATERIAL_VAR_TYPE_VECTOR)
+ {
+ if (m_ResultVecComp >= 0)
+ resultType = MATERIAL_VAR_TYPE_FLOAT;
+ vecSize = m_pResult->VectorSize();
+ }
+ else if (resultType == MATERIAL_VAR_TYPE_UNDEFINED)
+ {
+ resultType = m_pSrc1->GetType();
+ if (resultType == MATERIAL_VAR_TYPE_VECTOR)
+ {
+ vecSize = m_pSrc1->VectorSize();
+ }
+ else if ((resultType == MATERIAL_VAR_TYPE_UNDEFINED) && m_pSrc2)
+ {
+ resultType = m_pSrc2->GetType();
+ if (resultType == MATERIAL_VAR_TYPE_VECTOR)
+ {
+ vecSize = m_pSrc2->VectorSize();
+ }
+ }
+ }
+}
+
+
+class CFakeBurnLevelProxy : public CResultProxy
+{
+public:
+ virtual void OnBind( void *pC_BaseEntity )
+ {
+ // Slam burn level to 0 to avoid the burn detail texture showing through in modelbrowser.
+ Assert( m_pResult );
+ if ( m_pResult )
+ {
+ m_pResult->SetFloatValue( 0.0f );
+ }
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// Selects the first var value if it's non-zero, otherwise goes with the second
+//-----------------------------------------------------------------------------
+
+class CSelectFirstIfNonZeroProxy : public CFunctionProxy
+{
+public:
+ virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
+ virtual void OnBind( void *pC_BaseEntity );
+};
+
+bool CSelectFirstIfNonZeroProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
+{
+ // Requires 2 args..
+ bool ok = CFunctionProxy::Init( pMaterial, pKeyValues );
+ ok = ok && m_pSrc2;
+ return ok;
+}
+
+void CSelectFirstIfNonZeroProxy::OnBind( void *pC_BaseEntity )
+{
+ Assert( m_pSrc1 && m_pSrc2 && m_pResult );
+
+ MaterialVarType_t resultType;
+ int vecSize;
+ ComputeResultType( resultType, vecSize );
+
+ switch( resultType )
+ {
+ case MATERIAL_VAR_TYPE_VECTOR:
+ {
+ Vector a, b;
+ m_pSrc1->GetVecValue( a.Base(), vecSize );
+ m_pSrc2->GetVecValue( b.Base(), vecSize );
+
+ if ( !a.IsZero() )
+ {
+ m_pResult->SetVecValue( a.Base(), vecSize );
+ }
+ else
+ {
+ m_pResult->SetVecValue( b.Base(), vecSize );
+ }
+ }
+ break;
+
+ case MATERIAL_VAR_TYPE_FLOAT:
+ if ( m_pSrc1->GetFloatValue() )
+ {
+ SetFloatResult( m_pSrc1->GetFloatValue() );
+ }
+ else
+ {
+ SetFloatResult( m_pSrc2->GetFloatValue() );
+ }
+ break;
+
+ case MATERIAL_VAR_TYPE_INT:
+ if ( m_pSrc1->GetIntValue() )
+ {
+ m_pResult->SetFloatValue( m_pSrc1->GetIntValue() );
+ }
+ else
+ {
+ m_pResult->SetFloatValue( m_pSrc2->GetIntValue() );
+ }
+ break;
+ }
+}
+
+
+class CModelBrowserMaterialProxyFactory : public IMaterialProxyFactory
+{
+public:
+ virtual IMaterialProxy *CreateProxy( const char *proxyName )
+ {
+ if ( V_stricmp( proxyName, "SelectFirstIfNonZero" ) == 0 )
+ {
+ return new CSelectFirstIfNonZeroProxy;
+ }
+ else if ( V_stricmp( proxyName, "BurnLevel" ) == 0 )
+ {
+ return new CFakeBurnLevelProxy;
+ }
+ return NULL;
+ }
+
+ virtual void DeleteProxy( IMaterialProxy *pProxy )
+ {
+ if ( pProxy )
+ {
+ pProxy->Release();
+ }
+ }
+};