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.

259 lines
5.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "functionproxy.h"
  9. #include <KeyValues.h>
  10. #include "materialsystem/imaterialvar.h"
  11. #include "materialsystem/imaterial.h"
  12. #include "iclientrenderable.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. //-----------------------------------------------------------------------------
  16. // Helper class to deal with floating point inputs
  17. //-----------------------------------------------------------------------------
  18. bool CFloatInput::Init( IMaterial *pMaterial, KeyValues *pKeyValues, const char *pKeyName, float flDefault )
  19. {
  20. m_pFloatVar = NULL;
  21. KeyValues *pSection = pKeyValues->FindKey( pKeyName );
  22. if (pSection)
  23. {
  24. if (pSection->GetDataType() == KeyValues::TYPE_STRING)
  25. {
  26. const char *pVarName = pSection->GetString();
  27. // Look for numbers...
  28. float flValue;
  29. int nCount = sscanf( pVarName, "%f", &flValue );
  30. if (nCount == 1)
  31. {
  32. m_flValue = flValue;
  33. return true;
  34. }
  35. // Look for array specification...
  36. char pTemp[256];
  37. if (strchr(pVarName, '['))
  38. {
  39. // strip off the array...
  40. Q_strncpy( pTemp, pVarName, 256 );
  41. char *pArray = strchr( pTemp, '[' );
  42. *pArray++ = 0;
  43. char* pIEnd;
  44. m_FloatVecComp = strtol( pArray, &pIEnd, 10 );
  45. // Use the version without the array...
  46. pVarName = pTemp;
  47. }
  48. else
  49. {
  50. m_FloatVecComp = -1;
  51. }
  52. bool bFoundVar;
  53. m_pFloatVar = pMaterial->FindVar( pVarName, &bFoundVar, true );
  54. if (!bFoundVar)
  55. return false;
  56. }
  57. else
  58. {
  59. m_flValue = pSection->GetFloat();
  60. }
  61. }
  62. else
  63. {
  64. m_flValue = flDefault;
  65. }
  66. return true;
  67. }
  68. float CFloatInput::GetFloat() const
  69. {
  70. if (!m_pFloatVar)
  71. return m_flValue;
  72. if( m_FloatVecComp < 0 )
  73. return m_pFloatVar->GetFloatValue();
  74. int iVecSize = m_pFloatVar->VectorSize();
  75. if ( m_FloatVecComp >= iVecSize )
  76. return 0;
  77. float v[4];
  78. m_pFloatVar->GetVecValue( v, iVecSize );
  79. return v[m_FloatVecComp];
  80. }
  81. //-----------------------------------------------------------------------------
  82. //
  83. // Result proxy; a result (with vector friendliness)
  84. //
  85. //-----------------------------------------------------------------------------
  86. CResultProxy::CResultProxy() : m_pResult(0)
  87. {
  88. }
  89. CResultProxy::~CResultProxy()
  90. {
  91. }
  92. bool CResultProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  93. {
  94. char const* pResult = pKeyValues->GetString( "resultVar" );
  95. if( !pResult )
  96. return false;
  97. // Look for array specification...
  98. char pTemp[256];
  99. if (strchr(pResult, '['))
  100. {
  101. // strip off the array...
  102. Q_strncpy( pTemp, pResult, 256 );
  103. char *pArray = strchr( pTemp, '[' );
  104. *pArray++ = 0;
  105. char* pIEnd;
  106. m_ResultVecComp = strtol( pArray, &pIEnd, 10 );
  107. // Use the version without the array...
  108. pResult = pTemp;
  109. }
  110. else
  111. {
  112. m_ResultVecComp = -1;
  113. }
  114. bool foundVar;
  115. m_pResult = pMaterial->FindVar( pResult, &foundVar, true );
  116. if( !foundVar )
  117. return false;
  118. return true;
  119. }
  120. //-----------------------------------------------------------------------------
  121. // A little code to allow us to set single components of vectors
  122. //-----------------------------------------------------------------------------
  123. void CResultProxy::SetFloatResult( float result )
  124. {
  125. if (m_pResult->GetType() == MATERIAL_VAR_TYPE_VECTOR)
  126. {
  127. if ( m_ResultVecComp >= 0 )
  128. {
  129. m_pResult->SetVecComponentValue( result, m_ResultVecComp );
  130. }
  131. else
  132. {
  133. float v[4];
  134. int vecSize = m_pResult->VectorSize();
  135. for (int i = 0; i < vecSize; ++i)
  136. v[i] = result;
  137. m_pResult->SetVecValue( v, vecSize );
  138. }
  139. }
  140. else
  141. {
  142. m_pResult->SetFloatValue( result );
  143. }
  144. }
  145. C_BaseEntity *CResultProxy::BindArgToEntity( void *pArg )
  146. {
  147. IClientRenderable *pRend = (IClientRenderable *)pArg;
  148. return pRend ? pRend->GetIClientUnknown()->GetBaseEntity() : NULL;
  149. }
  150. IMaterial *CResultProxy::GetMaterial()
  151. {
  152. return m_pResult->GetOwningMaterial();
  153. }
  154. //-----------------------------------------------------------------------------
  155. //
  156. // Base functional proxy; two sources (one is optional) and a result
  157. //
  158. //-----------------------------------------------------------------------------
  159. CFunctionProxy::CFunctionProxy() : m_pSrc1(0), m_pSrc2(0)
  160. {
  161. }
  162. CFunctionProxy::~CFunctionProxy()
  163. {
  164. }
  165. bool CFunctionProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  166. {
  167. if (!CResultProxy::Init( pMaterial, pKeyValues ))
  168. return false;
  169. char const* pSrcVar1 = pKeyValues->GetString( "srcVar1" );
  170. if( !pSrcVar1 )
  171. return false;
  172. bool foundVar;
  173. m_pSrc1 = pMaterial->FindVar( pSrcVar1, &foundVar, true );
  174. if( !foundVar )
  175. return false;
  176. // Source 2 is optional, some math ops may be single-input
  177. char const* pSrcVar2 = pKeyValues->GetString( "srcVar2" );
  178. if( pSrcVar2 && (*pSrcVar2) )
  179. {
  180. m_pSrc2 = pMaterial->FindVar( pSrcVar2, &foundVar, true );
  181. if( !foundVar )
  182. return false;
  183. }
  184. else
  185. {
  186. m_pSrc2 = 0;
  187. }
  188. return true;
  189. }
  190. void CFunctionProxy::ComputeResultType( MaterialVarType_t& resultType, int& vecSize )
  191. {
  192. // Feh, this is ugly. Basically, don't change the result type
  193. // unless it's undefined.
  194. resultType = m_pResult->GetType();
  195. if (resultType == MATERIAL_VAR_TYPE_VECTOR)
  196. {
  197. if (m_ResultVecComp >= 0)
  198. resultType = MATERIAL_VAR_TYPE_FLOAT;
  199. vecSize = m_pResult->VectorSize();
  200. }
  201. else if (resultType == MATERIAL_VAR_TYPE_UNDEFINED)
  202. {
  203. resultType = m_pSrc1->GetType();
  204. if (resultType == MATERIAL_VAR_TYPE_VECTOR)
  205. {
  206. vecSize = m_pSrc1->VectorSize();
  207. }
  208. else if ((resultType == MATERIAL_VAR_TYPE_UNDEFINED) && m_pSrc2)
  209. {
  210. resultType = m_pSrc2->GetType();
  211. if (resultType == MATERIAL_VAR_TYPE_VECTOR)
  212. {
  213. vecSize = m_pSrc2->VectorSize();
  214. }
  215. }
  216. }
  217. }