1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2024-12-23 01:59:43 +08:00
hl2sdk/cl_dll/mathproxy.cpp

828 lines
20 KiB
C++

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterial.h"
#include <KeyValues.h>
#include "materialsystem/IMaterialVar.h"
#include "FunctionProxy.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class C_BaseEntity;
//-----------------------------------------------------------------------------
// Adds two vars...
//-----------------------------------------------------------------------------
class CAddProxy : public CFunctionProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
};
bool CAddProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
// Requires 2 args..
bool ok = CFunctionProxy::Init( pMaterial, pKeyValues );
ok = ok && m_pSrc2;
return ok;
}
void CAddProxy::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, c;
m_pSrc1->GetVecValue( a.Base(), vecSize );
m_pSrc2->GetVecValue( b.Base(), vecSize );
VectorAdd( a, b, c );
m_pResult->SetVecValue( c.Base(), vecSize );
}
break;
case MATERIAL_VAR_TYPE_FLOAT:
SetFloatResult( m_pSrc1->GetFloatValue() + m_pSrc2->GetFloatValue() );
break;
case MATERIAL_VAR_TYPE_INT:
m_pResult->SetFloatValue( m_pSrc1->GetIntValue() + m_pSrc2->GetIntValue() );
break;
}
}
EXPOSE_INTERFACE( CAddProxy, IMaterialProxy, "Add" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Subtracts two vars...
//-----------------------------------------------------------------------------
class CSubtractProxy : public CFunctionProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
};
bool CSubtractProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
// Requires 2 args..
bool ok = CFunctionProxy::Init( pMaterial, pKeyValues );
ok = ok && m_pSrc2;
return ok;
}
void CSubtractProxy::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, c;
m_pSrc1->GetVecValue( a.Base(), vecSize );
m_pSrc2->GetVecValue( b.Base(), vecSize );
VectorSubtract( a, b, c );
m_pResult->SetVecValue( c.Base(), vecSize );
}
break;
case MATERIAL_VAR_TYPE_FLOAT:
SetFloatResult( m_pSrc1->GetFloatValue() - m_pSrc2->GetFloatValue() );
break;
case MATERIAL_VAR_TYPE_INT:
m_pResult->SetFloatValue( m_pSrc1->GetIntValue() - m_pSrc2->GetIntValue() );
break;
}
}
EXPOSE_INTERFACE( CSubtractProxy, IMaterialProxy, "Subtract" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Multiplies two vars...
//-----------------------------------------------------------------------------
class CMultiplyProxy : public CFunctionProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
};
bool CMultiplyProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
// Requires 2 args..
bool ok = CFunctionProxy::Init( pMaterial, pKeyValues );
ok = ok && m_pSrc2;
return ok;
}
void CMultiplyProxy::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, c;
m_pSrc1->GetVecValue( a.Base(), vecSize );
m_pSrc2->GetVecValue( b.Base(), vecSize );
VectorMultiply( a, b, c );
m_pResult->SetVecValue( c.Base(), vecSize );
}
break;
case MATERIAL_VAR_TYPE_FLOAT:
SetFloatResult( m_pSrc1->GetFloatValue() * m_pSrc2->GetFloatValue() );
break;
case MATERIAL_VAR_TYPE_INT:
m_pResult->SetFloatValue( m_pSrc1->GetIntValue() * m_pSrc2->GetIntValue() );
break;
}
}
EXPOSE_INTERFACE( CMultiplyProxy, IMaterialProxy, "Multiply" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// divides two vars...
//-----------------------------------------------------------------------------
class CDivideProxy : public CFunctionProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
};
bool CDivideProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
// Requires 2 args..
bool ok = CFunctionProxy::Init( pMaterial, pKeyValues );
ok = ok && m_pSrc2;
return ok;
}
void CDivideProxy::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, c;
m_pSrc1->GetVecValue( a.Base(), vecSize );
m_pSrc2->GetVecValue( b.Base(), vecSize );
VectorDivide( a, b, c );
m_pResult->SetVecValue( c.Base(), vecSize );
}
break;
case MATERIAL_VAR_TYPE_FLOAT:
if (m_pSrc2->GetFloatValue() != 0)
{
SetFloatResult( m_pSrc1->GetFloatValue() / m_pSrc2->GetFloatValue() );
}
else
{
SetFloatResult( m_pSrc1->GetFloatValue() );
}
break;
case MATERIAL_VAR_TYPE_INT:
if (m_pSrc2->GetIntValue() != 0)
{
m_pResult->SetFloatValue( m_pSrc1->GetIntValue() / m_pSrc2->GetIntValue() );
}
else
{
m_pResult->SetFloatValue( m_pSrc1->GetIntValue() );
}
break;
}
}
EXPOSE_INTERFACE( CDivideProxy, IMaterialProxy, "Divide" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// clamps a var...
//-----------------------------------------------------------------------------
class CClampProxy : public CFunctionProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Min;
CFloatInput m_Max;
};
bool CClampProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CFunctionProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Min.Init( pMaterial, pKeyValues, "min", 0 ))
return false;
if (!m_Max.Init( pMaterial, pKeyValues, "max", 1 ))
return false;
return true;
}
void CClampProxy::OnBind( void *pC_BaseEntity )
{
Assert( m_pSrc1 && m_pResult );
MaterialVarType_t resultType;
int vecSize;
ComputeResultType( resultType, vecSize );
float flMin = m_Min.GetFloat();
float flMax = m_Max.GetFloat();
if (flMin > flMax)
{
float flTemp = flMin;
flMin = flMax;
flMax = flTemp;
}
switch( resultType )
{
case MATERIAL_VAR_TYPE_VECTOR:
{
Vector a;
m_pSrc1->GetVecValue( a.Base(), vecSize );
for (int i = 0; i < vecSize; ++i)
{
if (a[i] < flMin)
a[i] = flMin;
else if (a[i] > flMax)
a[i] = flMax;
}
m_pResult->SetVecValue( a.Base(), vecSize );
}
break;
case MATERIAL_VAR_TYPE_FLOAT:
{
float src = m_pSrc1->GetFloatValue();
if (src < flMin)
src = flMin;
else if (src > flMax)
src = flMax;
SetFloatResult( src );
}
break;
case MATERIAL_VAR_TYPE_INT:
{
int src = m_pSrc1->GetIntValue();
if (src < flMin)
src = flMin;
else if (src > flMax)
src = flMax;
m_pResult->SetIntValue( src );
}
break;
}
}
EXPOSE_INTERFACE( CClampProxy, IMaterialProxy, "Clamp" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Creates a sinusoid
//-----------------------------------------------------------------------------
// sinePeriod: time that it takes to go through whole sine wave in seconds (default: 1.0f)
// sineMax : the max value for the sine wave (default: 1.0f )
// sineMin: the min value for the sine wave (default: 0.0f )
class CSineProxy : public CResultProxy
{
public:
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_SinePeriod;
CFloatInput m_SineMax;
CFloatInput m_SineMin;
CFloatInput m_SineTimeOffset;
};
bool CSineProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_SinePeriod.Init( pMaterial, pKeyValues, "sinePeriod", 1.0f ))
return false;
if (!m_SineMax.Init( pMaterial, pKeyValues, "sineMax", 1.0f ))
return false;
if (!m_SineMin.Init( pMaterial, pKeyValues, "sineMin", 0.0f ))
return false;
if (!m_SineTimeOffset.Init( pMaterial, pKeyValues, "timeOffset", 0.0f ))
return false;
return true;
}
void CSineProxy::OnBind( void *pC_BaseEntity )
{
Assert( m_pResult );
float flValue;
float flSineTimeOffset = m_SineTimeOffset.GetFloat();
float flSineMax = m_SineMax.GetFloat();
float flSineMin = m_SineMin.GetFloat();
float flSinePeriod = m_SinePeriod.GetFloat();
if (flSinePeriod == 0)
flSinePeriod = 1;
// get a value in [0,1]
flValue = ( sin( 2.0f * M_PI * (gpGlobals->curtime - flSineTimeOffset) / flSinePeriod ) * 0.5f ) + 0.5f;
// get a value in [min,max]
flValue = ( flSineMax - flSineMin ) * flValue + flSineMin;
SetFloatResult( flValue );
}
EXPOSE_INTERFACE( CSineProxy, IMaterialProxy, "Sine" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// copies a var...
//-----------------------------------------------------------------------------
class CEqualsProxy : public CFunctionProxy
{
public:
void OnBind( void *pC_BaseEntity );
};
void CEqualsProxy::OnBind( void *pC_BaseEntity )
{
Assert( m_pSrc1 && m_pResult );
MaterialVarType_t resultType;
int vecSize;
ComputeResultType( resultType, vecSize );
switch( resultType )
{
case MATERIAL_VAR_TYPE_VECTOR:
{
Vector a;
m_pSrc1->GetVecValue( a.Base(), vecSize );
m_pResult->SetVecValue( a.Base(), vecSize );
}
break;
case MATERIAL_VAR_TYPE_FLOAT:
SetFloatResult( m_pSrc1->GetFloatValue() );
break;
case MATERIAL_VAR_TYPE_INT:
m_pResult->SetIntValue( m_pSrc1->GetIntValue() );
break;
}
}
EXPOSE_INTERFACE( CEqualsProxy, IMaterialProxy, "Equals" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Get the fractional part of a var
//-----------------------------------------------------------------------------
class CFracProxy : public CFunctionProxy
{
public:
void OnBind( void *pC_BaseEntity );
};
void CFracProxy::OnBind( void *pC_BaseEntity )
{
Assert( m_pSrc1 && m_pResult );
MaterialVarType_t resultType;
int vecSize;
ComputeResultType( resultType, vecSize );
switch( resultType )
{
case MATERIAL_VAR_TYPE_VECTOR:
{
Vector a;
m_pSrc1->GetVecValue( a.Base(), vecSize );
a[0] -= ( float )( int )a[0];
a[1] -= ( float )( int )a[1];
a[2] -= ( float )( int )a[2];
m_pResult->SetVecValue( a.Base(), vecSize );
}
break;
case MATERIAL_VAR_TYPE_FLOAT:
{
float a = m_pSrc1->GetFloatValue();
a -= ( int )a;
SetFloatResult( a );
}
break;
case MATERIAL_VAR_TYPE_INT:
// don't do anything besides assignment!
m_pResult->SetIntValue( m_pSrc1->GetIntValue() );
break;
}
}
EXPOSE_INTERFACE( CFracProxy, IMaterialProxy, "Frac" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Linear ramp proxy
//-----------------------------------------------------------------------------
class CLinearRampProxy : public CResultProxy
{
public:
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Rate;
CFloatInput m_InitialValue;
};
bool CLinearRampProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Rate.Init( pMaterial, pKeyValues, "rate", 1 ))
return false;
if (!m_InitialValue.Init( pMaterial, pKeyValues, "initialValue", 0 ))
return false;
return true;
}
void CLinearRampProxy::OnBind( void *pC_BaseEntity )
{
Assert( m_pResult );
float flValue;
// get a value in [0,1]
flValue = m_Rate.GetFloat() * gpGlobals->curtime + m_InitialValue.GetFloat();
SetFloatResult( flValue );
}
EXPOSE_INTERFACE( CLinearRampProxy, IMaterialProxy, "LinearRamp" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Uniform noise proxy
//-----------------------------------------------------------------------------
class CUniformNoiseProxy : public CResultProxy
{
public:
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_flMinVal;
CFloatInput m_flMaxVal;
};
bool CUniformNoiseProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_flMinVal.Init( pMaterial, pKeyValues, "minVal", 0 ))
return false;
if (!m_flMaxVal.Init( pMaterial, pKeyValues, "maxVal", 1 ))
return false;
return true;
}
void CUniformNoiseProxy::OnBind( void *pC_BaseEntity )
{
SetFloatResult( random->RandomFloat( m_flMinVal.GetFloat(), m_flMaxVal.GetFloat() ) );
}
EXPOSE_INTERFACE( CUniformNoiseProxy, IMaterialProxy, "UniformNoise" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Gaussian noise proxy
//-----------------------------------------------------------------------------
class CGaussianNoiseProxy : public CResultProxy
{
public:
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Mean;
CFloatInput m_StdDev;
CFloatInput m_flMinVal;
CFloatInput m_flMaxVal;
};
bool CGaussianNoiseProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Mean.Init( pMaterial, pKeyValues, "mean", 0.0f ))
return false;
if (!m_StdDev.Init( pMaterial, pKeyValues, "halfwidth", 1.0f ))
return false;
if (!m_flMinVal.Init( pMaterial, pKeyValues, "minVal", -FLT_MAX ))
return false;
if (!m_flMaxVal.Init( pMaterial, pKeyValues, "maxVal", FLT_MAX ))
return false;
return true;
}
void CGaussianNoiseProxy::OnBind( void *pC_BaseEntity )
{
float flMean = m_Mean.GetFloat();
float flStdDev = m_StdDev.GetFloat();
float flVal = randomgaussian->RandomFloat( flMean, flStdDev );
float flMaxVal = m_flMaxVal.GetFloat();
float flMinVal = m_flMinVal.GetFloat();
if (flMinVal > flMaxVal)
{
float flTemp = flMinVal;
flMinVal = flMaxVal;
flMaxVal = flTemp;
}
// clamp
if (flVal < flMinVal)
flVal = flMinVal;
else if ( flVal > flMaxVal )
flVal = flMaxVal;
SetFloatResult( flVal );
}
EXPOSE_INTERFACE( CGaussianNoiseProxy, IMaterialProxy, "GaussianNoise" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Exponential proxy
//-----------------------------------------------------------------------------
class CExponentialProxy : public CFunctionProxy
{
public:
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Scale;
CFloatInput m_Offset;
CFloatInput m_flMinVal;
CFloatInput m_flMaxVal;
};
bool CExponentialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CFunctionProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Scale.Init( pMaterial, pKeyValues, "scale", 1.0f ))
return false;
if (!m_Offset.Init( pMaterial, pKeyValues, "offset", 0.0f ))
return false;
if (!m_flMinVal.Init( pMaterial, pKeyValues, "minVal", -FLT_MAX ))
return false;
if (!m_flMaxVal.Init( pMaterial, pKeyValues, "maxVal", FLT_MAX ))
return false;
return true;
}
void CExponentialProxy::OnBind( void *pC_BaseEntity )
{
float flVal = m_Scale.GetFloat() * exp(m_pSrc1->GetFloatValue( ) + m_Offset.GetFloat());
float flMaxVal = m_flMaxVal.GetFloat();
float flMinVal = m_flMinVal.GetFloat();
if (flMinVal > flMaxVal)
{
float flTemp = flMinVal;
flMinVal = flMaxVal;
flMaxVal = flTemp;
}
// clamp
if (flVal < flMinVal)
flVal = flMinVal;
else if ( flVal > flMaxVal )
flVal = flMaxVal;
SetFloatResult( flVal );
}
EXPOSE_INTERFACE( CExponentialProxy, IMaterialProxy, "Exponential" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Absolute value proxy
//-----------------------------------------------------------------------------
class CAbsProxy : public CFunctionProxy
{
public:
virtual void OnBind( void *pC_BaseEntity );
};
void CAbsProxy::OnBind( void *pC_BaseEntity )
{
SetFloatResult( fabs(m_pSrc1->GetFloatValue( )) );
}
EXPOSE_INTERFACE( CAbsProxy, IMaterialProxy, "Abs" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Empty proxy-- used to comment out large proxy blocks
//-----------------------------------------------------------------------------
class CEmptyProxy : public IMaterialProxy
{
public:
CEmptyProxy() {}
virtual ~CEmptyProxy() {}
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ) { return true; }
virtual void OnBind( void *pC_BaseEntity ) {}
virtual void Release( void ) { delete this; }
};
EXPOSE_INTERFACE( CEmptyProxy, IMaterialProxy, "Empty" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Comparison proxy
//-----------------------------------------------------------------------------
class CLessOrEqualProxy : public CFunctionProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
IMaterialVar *m_pLessVar;
IMaterialVar *m_pGreaterVar;
};
bool CLessOrEqualProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pLessEqualVar = pKeyValues->GetString( "lessEqualVar" );
if( !pLessEqualVar )
return false;
bool foundVar;
m_pLessVar = pMaterial->FindVar( pLessEqualVar, &foundVar, true );
if( !foundVar )
return false;
char const* pGreaterVar = pKeyValues->GetString( "greaterVar" );
if( !pGreaterVar )
return false;
foundVar;
m_pGreaterVar = pMaterial->FindVar( pGreaterVar, &foundVar, true );
if( !foundVar )
return false;
// Compare 2 args..
bool ok = CFunctionProxy::Init( pMaterial, pKeyValues );
ok = ok && m_pSrc2;
return ok;
}
void CLessOrEqualProxy::OnBind( void *pC_BaseEntity )
{
Assert( m_pSrc1 && m_pSrc2 && m_pLessVar && m_pGreaterVar && m_pResult );
IMaterialVar *pSourceVar;
if (m_pSrc1->GetFloatValue() <= m_pSrc2->GetFloatValue())
{
pSourceVar = m_pLessVar;
}
else
{
pSourceVar = m_pGreaterVar;
}
int vecSize = 0;
MaterialVarType_t 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 = pSourceVar->GetType();
if (resultType == MATERIAL_VAR_TYPE_VECTOR)
{
vecSize = pSourceVar->VectorSize();
}
}
switch( resultType )
{
case MATERIAL_VAR_TYPE_VECTOR:
{
Vector src;
pSourceVar->GetVecValue( src.Base(), vecSize );
m_pResult->SetVecValue( src.Base(), vecSize );
}
break;
case MATERIAL_VAR_TYPE_FLOAT:
SetFloatResult( pSourceVar->GetFloatValue() );
break;
case MATERIAL_VAR_TYPE_INT:
m_pResult->SetFloatValue( pSourceVar->GetIntValue() );
break;
}
}
EXPOSE_INTERFACE( CLessOrEqualProxy, IMaterialProxy, "LessOrEqual" IMATERIAL_PROXY_INTERFACE_VERSION );