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.

225 lines
6.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. // Purpose:
  3. //
  4. // $NoKeywords: $
  5. //=====================================================================================//
  6. #include "cbase.h"
  7. #include "proxyentity.h"
  8. #include "materialsystem/imaterial.h"
  9. #include "materialsystem/imaterialvar.h"
  10. #include "debugoverlay_shared.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. class C_FleshEffectTarget;
  14. void AddFleshProxyTarget( C_FleshEffectTarget *pTarget );
  15. void RemoveFleshProxy( C_FleshEffectTarget *pTarget );
  16. //=============================================================================
  17. //
  18. // Flesh effect target (used for orchestrating the "Invisible Alyx" moment
  19. //
  20. //=============================================================================
  21. class C_FleshEffectTarget : public C_BaseEntity
  22. {
  23. DECLARE_CLASS( C_FleshEffectTarget, C_BaseEntity );
  24. public:
  25. float GetRadius( void )
  26. {
  27. if ( m_flScaleTime <= 0.0f )
  28. return m_flRadius;
  29. float dt = ( gpGlobals->curtime - m_flScaleStartTime );
  30. if ( dt >= m_flScaleTime )
  31. return m_flRadius;
  32. return SimpleSplineRemapVal( ( dt / m_flScaleTime ), 0.0f, 1.0f, m_flStartRadius, m_flRadius );
  33. }
  34. virtual void Release( void )
  35. {
  36. // Remove us from the list of targets
  37. RemoveFleshProxy( this );
  38. }
  39. virtual void OnDataChanged( DataUpdateType_t updateType )
  40. {
  41. BaseClass::OnDataChanged( updateType );
  42. if ( updateType == DATA_UPDATE_CREATED )
  43. {
  44. // Add us to the list of flesh proxy targets
  45. AddFleshProxyTarget( this );
  46. }
  47. }
  48. float m_flRadius;
  49. float m_flStartRadius;
  50. float m_flScaleStartTime;
  51. float m_flScaleTime;
  52. DECLARE_CLIENTCLASS();
  53. };
  54. void RecvProxy_FleshEffect_Radius( const CRecvProxyData *pData, void *pStruct, void *pOut )
  55. {
  56. C_FleshEffectTarget *pTarget = (C_FleshEffectTarget *) pStruct;
  57. float flRadius = pData->m_Value.m_Float;
  58. //If changed, update our internal information
  59. if ( pTarget->m_flRadius != flRadius )
  60. {
  61. pTarget->m_flStartRadius = pTarget->m_flRadius;
  62. pTarget->m_flScaleStartTime = gpGlobals->curtime;
  63. }
  64. pTarget->m_flRadius = flRadius;
  65. }
  66. IMPLEMENT_CLIENTCLASS_DT( C_FleshEffectTarget, DT_FleshEffectTarget, CFleshEffectTarget )
  67. RecvPropFloat( RECVINFO(m_flRadius), 0, RecvProxy_FleshEffect_Radius ),
  68. RecvPropFloat( RECVINFO(m_flScaleTime) ),
  69. END_RECV_TABLE()
  70. CUtlVector< C_FleshEffectTarget * > g_FleshProxyTargets;
  71. void AddFleshProxyTarget( C_FleshEffectTarget *pTarget )
  72. {
  73. // Take it!
  74. g_FleshProxyTargets.AddToTail( pTarget );
  75. }
  76. void RemoveFleshProxy( C_FleshEffectTarget *pTarget )
  77. {
  78. int nIndex = g_FleshProxyTargets.Find( pTarget );
  79. if ( nIndex != g_FleshProxyTargets.InvalidIndex() )
  80. {
  81. g_FleshProxyTargets.Remove( nIndex );
  82. }
  83. }
  84. // $sineVar : name of variable that controls the FleshInterior level (float)
  85. class CFleshInteriorMaterialProxy : public CEntityMaterialProxy
  86. {
  87. public:
  88. CFleshInteriorMaterialProxy();
  89. virtual ~CFleshInteriorMaterialProxy();
  90. virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
  91. virtual void OnBind( C_BaseEntity *pEntity );
  92. virtual IMaterial *GetMaterial();
  93. private:
  94. IMaterialVar *m_pMaterialParamFleshEffectCenterRadius1;
  95. IMaterialVar *m_pMaterialParamFleshEffectCenterRadius2;
  96. IMaterialVar *m_pMaterialParamFleshEffectCenterRadius3;
  97. IMaterialVar *m_pMaterialParamFleshEffectCenterRadius4;
  98. IMaterialVar *m_pMaterialParamFleshGlobalOpacity;
  99. IMaterialVar *m_pMaterialParamFleshSubsurfaceTint;
  100. };
  101. CFleshInteriorMaterialProxy::CFleshInteriorMaterialProxy()
  102. {
  103. m_pMaterialParamFleshEffectCenterRadius1 = NULL;
  104. m_pMaterialParamFleshEffectCenterRadius2 = NULL;
  105. m_pMaterialParamFleshEffectCenterRadius3 = NULL;
  106. m_pMaterialParamFleshEffectCenterRadius4 = NULL;
  107. m_pMaterialParamFleshGlobalOpacity = NULL;
  108. m_pMaterialParamFleshSubsurfaceTint = NULL;
  109. }
  110. CFleshInteriorMaterialProxy::~CFleshInteriorMaterialProxy()
  111. {
  112. // Do nothing
  113. }
  114. bool CFleshInteriorMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
  115. {
  116. bool bFoundVar = false;
  117. m_pMaterialParamFleshEffectCenterRadius1 = pMaterial->FindVar( "$FleshEffectCenterRadius1", &bFoundVar, false );
  118. if ( bFoundVar == false)
  119. return false;
  120. m_pMaterialParamFleshEffectCenterRadius2 = pMaterial->FindVar( "$FleshEffectCenterRadius2", &bFoundVar, false );
  121. if ( bFoundVar == false)
  122. return false;
  123. m_pMaterialParamFleshEffectCenterRadius3 = pMaterial->FindVar( "$FleshEffectCenterRadius3", &bFoundVar, false );
  124. if ( bFoundVar == false)
  125. return false;
  126. m_pMaterialParamFleshEffectCenterRadius4 = pMaterial->FindVar( "$FleshEffectCenterRadius4", &bFoundVar, false );
  127. if ( bFoundVar == false)
  128. return false;
  129. m_pMaterialParamFleshGlobalOpacity = pMaterial->FindVar( "$FleshGlobalOpacity", &bFoundVar, false );
  130. if ( bFoundVar == false)
  131. return false;
  132. m_pMaterialParamFleshSubsurfaceTint = pMaterial->FindVar( "$FleshSubsurfaceTint", &bFoundVar, false );
  133. if ( bFoundVar == false)
  134. return false;
  135. return true;
  136. }
  137. void CFleshInteriorMaterialProxy::OnBind( C_BaseEntity *pEnt )
  138. {
  139. IMaterialVar *pParams[] =
  140. {
  141. m_pMaterialParamFleshEffectCenterRadius1,
  142. m_pMaterialParamFleshEffectCenterRadius2,
  143. m_pMaterialParamFleshEffectCenterRadius3,
  144. m_pMaterialParamFleshEffectCenterRadius4
  145. };
  146. float vEffectCenterRadius[4];
  147. for ( int i = 0; i < ARRAYSIZE( pParams ); i++ )
  148. {
  149. if ( i < g_FleshProxyTargets.Count() )
  150. {
  151. // Setup the target
  152. if ( g_FleshProxyTargets[i]->IsAbsQueriesValid() == false )
  153. continue;
  154. Vector vecAbsOrigin = g_FleshProxyTargets[i]->GetAbsOrigin();
  155. vEffectCenterRadius[0] = vecAbsOrigin.x;
  156. vEffectCenterRadius[1] = vecAbsOrigin.y;
  157. vEffectCenterRadius[2] = vecAbsOrigin.z;
  158. vEffectCenterRadius[3] = g_FleshProxyTargets[i]->GetRadius();
  159. }
  160. else
  161. {
  162. // Clear the target
  163. vEffectCenterRadius[0] = vEffectCenterRadius[1] = vEffectCenterRadius[2] = vEffectCenterRadius[3] = 0.0f;
  164. }
  165. // Set the value either way
  166. pParams[i]->SetVecValue( vEffectCenterRadius, 4 );
  167. }
  168. // Subsurface texture. NOTE: This texture bleeds through the color of the flesh texture so expect
  169. // to have to set this brighter than white to really see the subsurface texture glow through.
  170. if ( m_pMaterialParamFleshSubsurfaceTint != NULL )
  171. {
  172. float vSubsurfaceTintColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  173. // !!! Test code. REPLACE ME!
  174. // vSubsurfaceTintColor[0] = vSubsurfaceTintColor[1] = vSubsurfaceTintColor[2] = sinf( gpGlobals->curtime * 3.0f ) + 1.0f; // * 0.5f + 0.5f;
  175. m_pMaterialParamFleshSubsurfaceTint->SetVecValue( vSubsurfaceTintColor, 4 );
  176. }
  177. }
  178. IMaterial *CFleshInteriorMaterialProxy::GetMaterial()
  179. {
  180. if ( m_pMaterialParamFleshEffectCenterRadius1 == NULL)
  181. return NULL;
  182. return m_pMaterialParamFleshEffectCenterRadius1->GetOwningMaterial();
  183. }
  184. EXPOSE_INTERFACE( CFleshInteriorMaterialProxy, IMaterialProxy, "FleshInterior" IMATERIAL_PROXY_INTERFACE_VERSION );