diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/client/C_MaterialModifyControl.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/client/C_MaterialModifyControl.cpp')
| -rw-r--r-- | mp/src/game/client/C_MaterialModifyControl.cpp | 1596 |
1 files changed, 798 insertions, 798 deletions
diff --git a/mp/src/game/client/C_MaterialModifyControl.cpp b/mp/src/game/client/C_MaterialModifyControl.cpp index 55ff2ec5..f038022e 100644 --- a/mp/src/game/client/C_MaterialModifyControl.cpp +++ b/mp/src/game/client/C_MaterialModifyControl.cpp @@ -1,798 +1,798 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Material Modify control entity.
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "proxyentity.h"
-#include "materialsystem/imaterial.h"
-#include "materialsystem/imaterialvar.h"
-#include "materialsystem/itexture.h"
-#include "iviewrender.h"
-#include "texture_group_names.h"
-#include "baseanimatedtextureproxy.h"
-#include "toolframework_client.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#define MATERIAL_MODIFY_STRING_SIZE 255
-#define MATERIAL_MODIFY_ANIMATION_UNSET -1
-
-// Must match MaterialModifyControl.cpp
-enum MaterialModifyMode_t
-{
- MATERIAL_MODIFY_MODE_NONE = 0,
- MATERIAL_MODIFY_MODE_SETVAR = 1,
- MATERIAL_MODIFY_MODE_ANIM_SEQUENCE = 2,
- MATERIAL_MODIFY_MODE_FLOAT_LERP = 3,
-};
-
-// forward declarations
-void ToolFramework_RecordMaterialParams( IMaterial *pMaterial );
-
-ConVar debug_materialmodifycontrol_client( "debug_materialmodifycontrol_client", "0" );
-
-struct materialanimcommands_t
-{
- int iFrameStart;
- int iFrameEnd;
- bool bWrap;
- float flFrameRate;
-};
-
-struct materialfloatlerpcommands_t
-{
- int flStartValue;
- int flEndValue;
- float flTransitionTime;
-};
-
-//------------------------------------------------------------------------------
-// FIXME: This really should inherit from something more lightweight
-//------------------------------------------------------------------------------
-
-class C_MaterialModifyControl : public C_BaseEntity
-{
-public:
-
- DECLARE_CLASS( C_MaterialModifyControl, C_BaseEntity );
-
- C_MaterialModifyControl();
-
- void OnPreDataChanged( DataUpdateType_t updateType );
- void OnDataChanged( DataUpdateType_t updateType );
- bool ShouldDraw();
-
- IMaterial *GetMaterial( void ) { return m_pMaterial; }
- const char *GetMaterialVariableName( void ) { return m_szMaterialVar; }
- const char *GetMaterialVariableValue( void ) { return m_szMaterialVarValue; }
-
- DECLARE_CLIENTCLASS();
-
- // Animated texture and Float Lerp usage
- bool HasNewAnimationCommands( void ) { return m_bHasNewAnimationCommands; }
- void ClearAnimationCommands( void ) { m_bHasNewAnimationCommands = false; }
-
- // Animated texture usage
- void GetAnimationCommands( materialanimcommands_t *pCommands );
-
- // FloatLerp usage
- void GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands );
-
- void SetAnimationStartTime( float flTime )
- {
- m_flAnimationStartTime = flTime;
- }
- float GetAnimationStartTime( void ) const
- {
- return m_flAnimationStartTime;
- }
-
- MaterialModifyMode_t GetModifyMode( void ) const
- {
- return ( MaterialModifyMode_t)m_nModifyMode;
- }
-private:
-
- char m_szMaterialName[MATERIAL_MODIFY_STRING_SIZE];
- char m_szMaterialVar[MATERIAL_MODIFY_STRING_SIZE];
- char m_szMaterialVarValue[MATERIAL_MODIFY_STRING_SIZE];
- IMaterial *m_pMaterial;
-
- bool m_bHasNewAnimationCommands;
-
- // Animation commands from the server
- int m_iFrameStart;
- int m_iFrameEnd;
- bool m_bWrap;
- float m_flFramerate;
- bool m_bNewAnimCommandsSemaphore;
- bool m_bOldAnimCommandsSemaphore;
-
- // Float lerp commands from the server
- float m_flFloatLerpStartValue;
- float m_flFloatLerpEndValue;
- float m_flFloatLerpTransitionTime;
- bool m_bFloatLerpWrap;
- float m_flAnimationStartTime;
-
- int m_nModifyMode;
-};
-
-IMPLEMENT_CLIENTCLASS_DT(C_MaterialModifyControl, DT_MaterialModifyControl, CMaterialModifyControl)
- RecvPropString( RECVINFO( m_szMaterialName ) ),
- RecvPropString( RECVINFO( m_szMaterialVar ) ),
- RecvPropString( RECVINFO( m_szMaterialVarValue ) ),
- RecvPropInt( RECVINFO(m_iFrameStart) ),
- RecvPropInt( RECVINFO(m_iFrameEnd) ),
- RecvPropInt( RECVINFO(m_bWrap) ),
- RecvPropFloat( RECVINFO(m_flFramerate) ),
- RecvPropInt( RECVINFO(m_bNewAnimCommandsSemaphore) ),
- RecvPropFloat( RECVINFO(m_flFloatLerpStartValue) ),
- RecvPropFloat( RECVINFO(m_flFloatLerpEndValue) ),
- RecvPropFloat( RECVINFO(m_flFloatLerpTransitionTime) ),
- RecvPropInt( RECVINFO(m_bFloatLerpWrap) ),
- RecvPropInt( RECVINFO(m_nModifyMode) ),
-END_RECV_TABLE()
-
-//------------------------------------------------------------------------------
-// Purpose:
-//------------------------------------------------------------------------------
-C_MaterialModifyControl::C_MaterialModifyControl()
-{
- m_pMaterial = NULL;
- m_bOldAnimCommandsSemaphore = false;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void C_MaterialModifyControl::OnPreDataChanged( DataUpdateType_t updateType )
-{
- BaseClass::OnPreDataChanged( updateType );
-
- m_bOldAnimCommandsSemaphore = m_bNewAnimCommandsSemaphore;
-}
-
-//------------------------------------------------------------------------------
-// Purpose:
-//------------------------------------------------------------------------------
-void C_MaterialModifyControl::OnDataChanged( DataUpdateType_t updateType )
-{
- if( updateType == DATA_UPDATE_CREATED )
- {
- m_pMaterial = materials->FindMaterial( m_szMaterialName, TEXTURE_GROUP_OTHER );
-
- // Clear out our variables
- m_bHasNewAnimationCommands = true;
- }
-
- // Detect changes in the anim commands
- if ( m_bNewAnimCommandsSemaphore != m_bOldAnimCommandsSemaphore )
- {
- m_bHasNewAnimationCommands = true;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void C_MaterialModifyControl::GetAnimationCommands( materialanimcommands_t *pCommands )
-{
- pCommands->iFrameStart = m_iFrameStart;
- pCommands->iFrameEnd = m_iFrameEnd;
- pCommands->bWrap = m_bWrap;
- pCommands->flFrameRate = m_flFramerate;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void C_MaterialModifyControl::GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands )
-{
- pCommands->flStartValue = m_flFloatLerpStartValue;
- pCommands->flEndValue = m_flFloatLerpEndValue;
- pCommands->flTransitionTime = m_flFloatLerpTransitionTime;
-}
-
-//------------------------------------------------------------------------------
-// Purpose: We don't draw.
-//------------------------------------------------------------------------------
-bool C_MaterialModifyControl::ShouldDraw()
-{
- return false;
-}
-
-//=============================================================================
-//
-// THE MATERIALMODIFYPROXY ITSELF
-//
-class CMaterialModifyProxy : public CBaseAnimatedTextureProxy
-{
-public:
- CMaterialModifyProxy();
- virtual ~CMaterialModifyProxy();
- virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
- virtual void OnBind( void *pEntity );
- virtual IMaterial *GetMaterial();
-
-private:
- void OnBindSetVar( C_MaterialModifyControl *pControl );
- void OnBindAnimatedTexture( C_MaterialModifyControl *pControl );
- void OnBindFloatLerp( C_MaterialModifyControl *pControl );
- float GetAnimationStartTime( void* pArg );
- void AnimationWrapped( void* pArg );
-
- IMaterial *m_pMaterial;
-
- // texture animation stuff
- int m_iFrameStart;
- int m_iFrameEnd;
- bool m_bReachedEnd;
- bool m_bCustomWrap;
- float m_flCustomFramerate;
-
- // float lerp stuff
- IMaterialVar *m_pMaterialVar;
- int m_flStartValue;
- int m_flEndValue;
- float m_flStartTime;
- float m_flTransitionTime;
-};
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-CMaterialModifyProxy::CMaterialModifyProxy()
-{
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-CMaterialModifyProxy::~CMaterialModifyProxy()
-{
-}
-
-bool CMaterialModifyProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
-{
- // set var stuff
- m_pMaterial = pMaterial;
-
- // float lerp stuff
- m_flStartValue = MATERIAL_MODIFY_ANIMATION_UNSET;
- m_flEndValue = MATERIAL_MODIFY_ANIMATION_UNSET;
-
- // animated stuff
-// m_pMaterial = pMaterial;
-// m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET;
-// m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET;
-// m_bReachedEnd = false;
-// return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
-
- return true;
-}
-
-void CMaterialModifyProxy::OnBind( void *pEntity )
-{
- // Get the modified material vars from the entity input
- IClientRenderable *pRend = (IClientRenderable *)pEntity;
- if ( pRend )
- {
- C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity();
-
- if ( pBaseEntity )
- {
- if( debug_materialmodifycontrol_client.GetBool() )
- {
-// DevMsg( 1, "%s\n", pBaseEntity->GetDebugName() );
- }
- int numChildren = 0;
- bool gotOne = false;
- for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
- {
- numChildren++;
- C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild );
- if ( !pControl )
- continue;
-
- if( debug_materialmodifycontrol_client.GetBool() )
- {
-// DevMsg( 1, "pControl: 0x%p\n", pControl );
- }
-
- switch( pControl->GetModifyMode() )
- {
- case MATERIAL_MODIFY_MODE_NONE:
- break;
- case MATERIAL_MODIFY_MODE_SETVAR:
- gotOne = true;
- OnBindSetVar( pControl );
- break;
- case MATERIAL_MODIFY_MODE_ANIM_SEQUENCE:
- OnBindAnimatedTexture( pControl );
- break;
- case MATERIAL_MODIFY_MODE_FLOAT_LERP:
- OnBindFloatLerp( pControl );
- break;
- default:
- Assert( 0 );
- break;
- }
- }
- if( gotOne )
- {
-// DevMsg( 1, "numChildren: %d\n", numChildren );
- }
- }
- }
-
- if ( ToolsEnabled() )
- {
- ToolFramework_RecordMaterialParams( GetMaterial() );
- }
-}
-
-IMaterial *CMaterialModifyProxy::GetMaterial()
-{
- return m_pMaterial;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CMaterialModifyProxy::OnBindSetVar( C_MaterialModifyControl *pControl )
-{
- IMaterial *pMaterial = pControl->GetMaterial();
- if( !pMaterial )
- {
- Assert( 0 );
- return;
- }
-
- if ( pMaterial != m_pMaterial )
- {
-// Warning( "\t%s!=%s\n", pMaterial->GetName(), m_pMaterial->GetName() );
- return;
- }
-
- bool bFound;
- IMaterialVar *pMaterialVar = pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false );
- if ( !bFound )
- return;
-
- if( Q_strcmp( pControl->GetMaterialVariableValue(), "" ) )
- {
-// const char *pMaterialName = m_pMaterial->GetName();
-// const char *pMaterialVarName = pMaterialVar->GetName();
-// const char *pMaterialVarValue = pControl->GetMaterialVariableValue();
-// if( debug_materialmodifycontrol_client.GetBool()
-// && Q_stristr( m_pMaterial->GetName(), "faceandhair" )
-// && Q_stristr( pMaterialVar->GetName(), "self" )
-// )
-// {
-// static int count = 0;
-// DevMsg( 1, "CMaterialModifyProxy::OnBindSetVar \"%s\" %s=%s %d pControl=0x%p\n",
-// m_pMaterial->GetName(), pMaterialVar->GetName(), pControl->GetMaterialVariableValue(), count++, pControl );
-// }
- pMaterialVar->SetValueAutodetectType( pControl->GetMaterialVariableValue() );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Does the dirty deed
-//-----------------------------------------------------------------------------
-void CMaterialModifyProxy::OnBindAnimatedTexture( C_MaterialModifyControl *pControl )
-{
- assert ( m_AnimatedTextureVar );
- if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
- return;
-
- ITexture *pTexture;
- pTexture = m_AnimatedTextureVar->GetTextureValue();
-
- if ( !pControl )
- return;
-
- if ( pControl->HasNewAnimationCommands() )
- {
- // Read the data from the modify entity
- materialanimcommands_t sCommands;
- pControl->GetAnimationCommands( &sCommands );
-
- m_iFrameStart = sCommands.iFrameStart;
- m_iFrameEnd = sCommands.iFrameEnd;
- m_bCustomWrap = sCommands.bWrap;
- m_flCustomFramerate = sCommands.flFrameRate;
- m_bReachedEnd = false;
-
- m_flStartTime = gpGlobals->curtime;
-
- pControl->ClearAnimationCommands();
- }
-
- // Init all the vars based on whether we're using the base material settings,
- // or the custom ones from the entity input.
- int numFrames;
- bool bWrapAnimation;
- float flFrameRate;
- int iLastFrame;
-
- // Do we have a custom frame section from the server?
- if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
- {
- if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET )
- {
- m_iFrameEnd = pTexture->GetNumAnimationFrames();
- }
-
- numFrames = (m_iFrameEnd - m_iFrameStart) + 1;
- bWrapAnimation = m_bCustomWrap;
- flFrameRate = m_flCustomFramerate;
- iLastFrame = (m_iFrameEnd - 1);
- }
- else
- {
- numFrames = pTexture->GetNumAnimationFrames();
- bWrapAnimation = m_WrapAnimation;
- flFrameRate = m_FrameRate;
- iLastFrame = (numFrames - 1);
- }
-
- // Have we already reached the end? If so, stay there.
- if ( m_bReachedEnd && !bWrapAnimation )
- {
- m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame );
- return;
- }
-
- // NOTE: Must not use relative time based methods here
- // because the bind proxy can be called many times per frame.
- // Prevent multiple Wrap callbacks to be sent for no wrap mode
- float startTime;
- if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
- {
- startTime = m_flStartTime;
- }
- else
- {
- startTime = GetAnimationStartTime(pControl);
- }
- float deltaTime = gpGlobals->curtime - startTime;
- float prevTime = deltaTime - gpGlobals->frametime;
-
- // Clamp..
- if (deltaTime < 0.0f)
- deltaTime = 0.0f;
- if (prevTime < 0.0f)
- prevTime = 0.0f;
-
- float frame = flFrameRate * deltaTime;
- float prevFrame = flFrameRate * prevTime;
-
- int intFrame = ((int)frame) % numFrames;
- int intPrevFrame = ((int)prevFrame) % numFrames;
-
- if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
- {
- intFrame += m_iFrameStart;
- intPrevFrame += m_iFrameStart;
- }
-
- // Report wrap situation...
- if (intPrevFrame > intFrame)
- {
- m_bReachedEnd = true;
-
- if (bWrapAnimation)
- {
- AnimationWrapped( pControl );
- }
- else
- {
- // Only sent the wrapped message once.
- // when we're in non-wrapping mode
- if (prevFrame < numFrames)
- AnimationWrapped( pControl );
- intFrame = numFrames - 1;
- }
- }
-
- m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-float CMaterialModifyProxy::GetAnimationStartTime( void* pArg )
-{
- IClientRenderable *pRend = (IClientRenderable *)pArg;
- if (!pRend)
- return 0.0f;
-
- C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
- if (pEntity)
- {
- return pEntity->GetTextureAnimationStartTime();
- }
- return 0.0f;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CMaterialModifyProxy::AnimationWrapped( void* pArg )
-{
- IClientRenderable *pRend = (IClientRenderable *)pArg;
- if (!pRend)
- return;
-
- C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
- if (pEntity)
- {
- pEntity->TextureAnimationWrapped();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Does the dirty deed
-//-----------------------------------------------------------------------------
-void CMaterialModifyProxy::OnBindFloatLerp( C_MaterialModifyControl *pControl )
-{
- if ( !pControl )
- return;
-
- if ( pControl->HasNewAnimationCommands() )
- {
- pControl->SetAnimationStartTime( gpGlobals->curtime );
- pControl->ClearAnimationCommands();
- }
-
- // Read the data from the modify entity
- materialfloatlerpcommands_t sCommands;
- pControl->GetFloatLerpCommands( &sCommands );
-
- m_flStartValue = sCommands.flStartValue;
- m_flEndValue = sCommands.flEndValue;
- m_flTransitionTime = sCommands.flTransitionTime;
- m_flStartTime = pControl->GetAnimationStartTime();
- bool bFound;
- m_pMaterialVar = m_pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false );
-
- if( bFound )
- {
- float currentValue;
- if( m_flTransitionTime > 0.0f )
- {
- currentValue = m_flStartValue + ( m_flEndValue - m_flStartValue ) * clamp( ( ( gpGlobals->curtime - m_flStartTime ) / m_flTransitionTime ), 0.0f, 1.0f );
- }
- else
- {
- currentValue = m_flEndValue;
- }
-
- if( debug_materialmodifycontrol_client.GetBool() && Q_stristr( m_pMaterial->GetName(), "faceandhair" ) && Q_stristr( m_pMaterialVar->GetName(), "warp" ) )
- {
- static int count = 0;
- DevMsg( 1, "CMaterialFloatLerpProxy::OnBind \"%s\" %s=%f %d\n", m_pMaterial->GetName(), m_pMaterialVar->GetName(), currentValue, count++ );
- }
- m_pMaterialVar->SetFloatValue( currentValue );
- }
-}
-
-//=============================================================================
-//
-// MATERIALMODIFYANIMATED PROXY
-//
-class CMaterialModifyAnimatedProxy : public CBaseAnimatedTextureProxy
-{
-public:
- CMaterialModifyAnimatedProxy() {};
- virtual ~CMaterialModifyAnimatedProxy() {};
- virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
- virtual void OnBind( void *pEntity );
-
- virtual float GetAnimationStartTime( void* pBaseEntity );
- virtual void AnimationWrapped( void* pC_BaseEntity );
-
-private:
- IMaterial *m_pMaterial;
- int m_iFrameStart;
- int m_iFrameEnd;
- bool m_bReachedEnd;
- float m_flStartTime;
- bool m_bCustomWrap;
- float m_flCustomFramerate;
-};
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool CMaterialModifyAnimatedProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
-{
- m_pMaterial = pMaterial;
- m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET;
- m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET;
- m_bReachedEnd = false;
- return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
-}
-
-//-----------------------------------------------------------------------------
-// Does the dirty deed
-//-----------------------------------------------------------------------------
-void CMaterialModifyAnimatedProxy::OnBind( void *pEntity )
-{
- assert ( m_AnimatedTextureVar );
- if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
- return;
-
- ITexture *pTexture;
- pTexture = m_AnimatedTextureVar->GetTextureValue();
-
- // Get the modified material vars from the entity input
- IClientRenderable *pRend = (IClientRenderable *)pEntity;
- if ( pRend )
- {
- C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity();
- if ( pBaseEntity )
- {
- for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
- {
- C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild );
- if ( !pControl )
- continue;
-
- if ( !pControl->HasNewAnimationCommands() )
- continue;
-
- // Read the data from the modify entity
- materialanimcommands_t sCommands;
- pControl->GetAnimationCommands( &sCommands );
-
- m_iFrameStart = sCommands.iFrameStart;
- m_iFrameEnd = sCommands.iFrameEnd;
- m_bCustomWrap = sCommands.bWrap;
- m_flCustomFramerate = sCommands.flFrameRate;
- m_bReachedEnd = false;
-
- m_flStartTime = gpGlobals->curtime;
-
- pControl->ClearAnimationCommands();
- }
- }
- }
-
- // Init all the vars based on whether we're using the base material settings,
- // or the custom ones from the entity input.
- int numFrames;
- bool bWrapAnimation;
- float flFrameRate;
- int iLastFrame;
-
- // Do we have a custom frame section from the server?
- if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
- {
- if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET )
- {
- m_iFrameEnd = pTexture->GetNumAnimationFrames();
- }
-
- numFrames = (m_iFrameEnd - m_iFrameStart) + 1;
- bWrapAnimation = m_bCustomWrap;
- flFrameRate = m_flCustomFramerate;
- iLastFrame = (m_iFrameEnd - 1);
- }
- else
- {
- numFrames = pTexture->GetNumAnimationFrames();
- bWrapAnimation = m_WrapAnimation;
- flFrameRate = m_FrameRate;
- iLastFrame = (numFrames - 1);
- }
-
- // Have we already reached the end? If so, stay there.
- if ( m_bReachedEnd && !bWrapAnimation )
- {
- m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame );
- return;
- }
-
- // NOTE: Must not use relative time based methods here
- // because the bind proxy can be called many times per frame.
- // Prevent multiple Wrap callbacks to be sent for no wrap mode
- float startTime;
- if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
- {
- startTime = m_flStartTime;
- }
- else
- {
- startTime = GetAnimationStartTime(pEntity);
- }
- float deltaTime = gpGlobals->curtime - startTime;
- float prevTime = deltaTime - gpGlobals->frametime;
-
- // Clamp..
- if (deltaTime < 0.0f)
- deltaTime = 0.0f;
- if (prevTime < 0.0f)
- prevTime = 0.0f;
-
- float frame = flFrameRate * deltaTime;
- float prevFrame = flFrameRate * prevTime;
-
- int intFrame = ((int)frame) % numFrames;
- int intPrevFrame = ((int)prevFrame) % numFrames;
-
- if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
- {
- intFrame += m_iFrameStart;
- intPrevFrame += m_iFrameStart;
- }
-
- // Report wrap situation...
- if (intPrevFrame > intFrame)
- {
- m_bReachedEnd = true;
-
- if (bWrapAnimation)
- {
- AnimationWrapped( pEntity );
- }
- else
- {
- // Only sent the wrapped message once.
- // when we're in non-wrapping mode
- if (prevFrame < numFrames)
- AnimationWrapped( pEntity );
- intFrame = numFrames - 1;
- }
- }
-
- m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
-
- if ( ToolsEnabled() )
- {
- ToolFramework_RecordMaterialParams( GetMaterial() );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-float CMaterialModifyAnimatedProxy::GetAnimationStartTime( void* pArg )
-{
- IClientRenderable *pRend = (IClientRenderable *)pArg;
- if (!pRend)
- return 0.0f;
-
- C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
- if (pEntity)
- {
- return pEntity->GetTextureAnimationStartTime();
- }
- return 0.0f;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CMaterialModifyAnimatedProxy::AnimationWrapped( void* pArg )
-{
- IClientRenderable *pRend = (IClientRenderable *)pArg;
- if (!pRend)
- return;
-
- C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
- if (pEntity)
- {
- pEntity->TextureAnimationWrapped();
- }
-}
-
-
-EXPOSE_INTERFACE( CMaterialModifyProxy, IMaterialProxy, "MaterialModify" IMATERIAL_PROXY_INTERFACE_VERSION );
-EXPOSE_INTERFACE( CMaterialModifyAnimatedProxy, IMaterialProxy, "MaterialModifyAnimated" IMATERIAL_PROXY_INTERFACE_VERSION );
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Material Modify control entity. +// +//=============================================================================// + +#include "cbase.h" +#include "proxyentity.h" +#include "materialsystem/imaterial.h" +#include "materialsystem/imaterialvar.h" +#include "materialsystem/itexture.h" +#include "iviewrender.h" +#include "texture_group_names.h" +#include "baseanimatedtextureproxy.h" +#include "toolframework_client.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define MATERIAL_MODIFY_STRING_SIZE 255 +#define MATERIAL_MODIFY_ANIMATION_UNSET -1 + +// Must match MaterialModifyControl.cpp +enum MaterialModifyMode_t +{ + MATERIAL_MODIFY_MODE_NONE = 0, + MATERIAL_MODIFY_MODE_SETVAR = 1, + MATERIAL_MODIFY_MODE_ANIM_SEQUENCE = 2, + MATERIAL_MODIFY_MODE_FLOAT_LERP = 3, +}; + +// forward declarations +void ToolFramework_RecordMaterialParams( IMaterial *pMaterial ); + +ConVar debug_materialmodifycontrol_client( "debug_materialmodifycontrol_client", "0" ); + +struct materialanimcommands_t +{ + int iFrameStart; + int iFrameEnd; + bool bWrap; + float flFrameRate; +}; + +struct materialfloatlerpcommands_t +{ + int flStartValue; + int flEndValue; + float flTransitionTime; +}; + +//------------------------------------------------------------------------------ +// FIXME: This really should inherit from something more lightweight +//------------------------------------------------------------------------------ + +class C_MaterialModifyControl : public C_BaseEntity +{ +public: + + DECLARE_CLASS( C_MaterialModifyControl, C_BaseEntity ); + + C_MaterialModifyControl(); + + void OnPreDataChanged( DataUpdateType_t updateType ); + void OnDataChanged( DataUpdateType_t updateType ); + bool ShouldDraw(); + + IMaterial *GetMaterial( void ) { return m_pMaterial; } + const char *GetMaterialVariableName( void ) { return m_szMaterialVar; } + const char *GetMaterialVariableValue( void ) { return m_szMaterialVarValue; } + + DECLARE_CLIENTCLASS(); + + // Animated texture and Float Lerp usage + bool HasNewAnimationCommands( void ) { return m_bHasNewAnimationCommands; } + void ClearAnimationCommands( void ) { m_bHasNewAnimationCommands = false; } + + // Animated texture usage + void GetAnimationCommands( materialanimcommands_t *pCommands ); + + // FloatLerp usage + void GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands ); + + void SetAnimationStartTime( float flTime ) + { + m_flAnimationStartTime = flTime; + } + float GetAnimationStartTime( void ) const + { + return m_flAnimationStartTime; + } + + MaterialModifyMode_t GetModifyMode( void ) const + { + return ( MaterialModifyMode_t)m_nModifyMode; + } +private: + + char m_szMaterialName[MATERIAL_MODIFY_STRING_SIZE]; + char m_szMaterialVar[MATERIAL_MODIFY_STRING_SIZE]; + char m_szMaterialVarValue[MATERIAL_MODIFY_STRING_SIZE]; + IMaterial *m_pMaterial; + + bool m_bHasNewAnimationCommands; + + // Animation commands from the server + int m_iFrameStart; + int m_iFrameEnd; + bool m_bWrap; + float m_flFramerate; + bool m_bNewAnimCommandsSemaphore; + bool m_bOldAnimCommandsSemaphore; + + // Float lerp commands from the server + float m_flFloatLerpStartValue; + float m_flFloatLerpEndValue; + float m_flFloatLerpTransitionTime; + bool m_bFloatLerpWrap; + float m_flAnimationStartTime; + + int m_nModifyMode; +}; + +IMPLEMENT_CLIENTCLASS_DT(C_MaterialModifyControl, DT_MaterialModifyControl, CMaterialModifyControl) + RecvPropString( RECVINFO( m_szMaterialName ) ), + RecvPropString( RECVINFO( m_szMaterialVar ) ), + RecvPropString( RECVINFO( m_szMaterialVarValue ) ), + RecvPropInt( RECVINFO(m_iFrameStart) ), + RecvPropInt( RECVINFO(m_iFrameEnd) ), + RecvPropInt( RECVINFO(m_bWrap) ), + RecvPropFloat( RECVINFO(m_flFramerate) ), + RecvPropInt( RECVINFO(m_bNewAnimCommandsSemaphore) ), + RecvPropFloat( RECVINFO(m_flFloatLerpStartValue) ), + RecvPropFloat( RECVINFO(m_flFloatLerpEndValue) ), + RecvPropFloat( RECVINFO(m_flFloatLerpTransitionTime) ), + RecvPropInt( RECVINFO(m_bFloatLerpWrap) ), + RecvPropInt( RECVINFO(m_nModifyMode) ), +END_RECV_TABLE() + +//------------------------------------------------------------------------------ +// Purpose: +//------------------------------------------------------------------------------ +C_MaterialModifyControl::C_MaterialModifyControl() +{ + m_pMaterial = NULL; + m_bOldAnimCommandsSemaphore = false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_MaterialModifyControl::OnPreDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnPreDataChanged( updateType ); + + m_bOldAnimCommandsSemaphore = m_bNewAnimCommandsSemaphore; +} + +//------------------------------------------------------------------------------ +// Purpose: +//------------------------------------------------------------------------------ +void C_MaterialModifyControl::OnDataChanged( DataUpdateType_t updateType ) +{ + if( updateType == DATA_UPDATE_CREATED ) + { + m_pMaterial = materials->FindMaterial( m_szMaterialName, TEXTURE_GROUP_OTHER ); + + // Clear out our variables + m_bHasNewAnimationCommands = true; + } + + // Detect changes in the anim commands + if ( m_bNewAnimCommandsSemaphore != m_bOldAnimCommandsSemaphore ) + { + m_bHasNewAnimationCommands = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_MaterialModifyControl::GetAnimationCommands( materialanimcommands_t *pCommands ) +{ + pCommands->iFrameStart = m_iFrameStart; + pCommands->iFrameEnd = m_iFrameEnd; + pCommands->bWrap = m_bWrap; + pCommands->flFrameRate = m_flFramerate; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_MaterialModifyControl::GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands ) +{ + pCommands->flStartValue = m_flFloatLerpStartValue; + pCommands->flEndValue = m_flFloatLerpEndValue; + pCommands->flTransitionTime = m_flFloatLerpTransitionTime; +} + +//------------------------------------------------------------------------------ +// Purpose: We don't draw. +//------------------------------------------------------------------------------ +bool C_MaterialModifyControl::ShouldDraw() +{ + return false; +} + +//============================================================================= +// +// THE MATERIALMODIFYPROXY ITSELF +// +class CMaterialModifyProxy : public CBaseAnimatedTextureProxy +{ +public: + CMaterialModifyProxy(); + virtual ~CMaterialModifyProxy(); + virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); + virtual void OnBind( void *pEntity ); + virtual IMaterial *GetMaterial(); + +private: + void OnBindSetVar( C_MaterialModifyControl *pControl ); + void OnBindAnimatedTexture( C_MaterialModifyControl *pControl ); + void OnBindFloatLerp( C_MaterialModifyControl *pControl ); + float GetAnimationStartTime( void* pArg ); + void AnimationWrapped( void* pArg ); + + IMaterial *m_pMaterial; + + // texture animation stuff + int m_iFrameStart; + int m_iFrameEnd; + bool m_bReachedEnd; + bool m_bCustomWrap; + float m_flCustomFramerate; + + // float lerp stuff + IMaterialVar *m_pMaterialVar; + int m_flStartValue; + int m_flEndValue; + float m_flStartTime; + float m_flTransitionTime; +}; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CMaterialModifyProxy::CMaterialModifyProxy() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CMaterialModifyProxy::~CMaterialModifyProxy() +{ +} + +bool CMaterialModifyProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) +{ + // set var stuff + m_pMaterial = pMaterial; + + // float lerp stuff + m_flStartValue = MATERIAL_MODIFY_ANIMATION_UNSET; + m_flEndValue = MATERIAL_MODIFY_ANIMATION_UNSET; + + // animated stuff +// m_pMaterial = pMaterial; +// m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET; +// m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET; +// m_bReachedEnd = false; +// return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues ); + + return true; +} + +void CMaterialModifyProxy::OnBind( void *pEntity ) +{ + // Get the modified material vars from the entity input + IClientRenderable *pRend = (IClientRenderable *)pEntity; + if ( pRend ) + { + C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity(); + + if ( pBaseEntity ) + { + if( debug_materialmodifycontrol_client.GetBool() ) + { +// DevMsg( 1, "%s\n", pBaseEntity->GetDebugName() ); + } + int numChildren = 0; + bool gotOne = false; + for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() ) + { + numChildren++; + C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild ); + if ( !pControl ) + continue; + + if( debug_materialmodifycontrol_client.GetBool() ) + { +// DevMsg( 1, "pControl: 0x%p\n", pControl ); + } + + switch( pControl->GetModifyMode() ) + { + case MATERIAL_MODIFY_MODE_NONE: + break; + case MATERIAL_MODIFY_MODE_SETVAR: + gotOne = true; + OnBindSetVar( pControl ); + break; + case MATERIAL_MODIFY_MODE_ANIM_SEQUENCE: + OnBindAnimatedTexture( pControl ); + break; + case MATERIAL_MODIFY_MODE_FLOAT_LERP: + OnBindFloatLerp( pControl ); + break; + default: + Assert( 0 ); + break; + } + } + if( gotOne ) + { +// DevMsg( 1, "numChildren: %d\n", numChildren ); + } + } + } + + if ( ToolsEnabled() ) + { + ToolFramework_RecordMaterialParams( GetMaterial() ); + } +} + +IMaterial *CMaterialModifyProxy::GetMaterial() +{ + return m_pMaterial; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMaterialModifyProxy::OnBindSetVar( C_MaterialModifyControl *pControl ) +{ + IMaterial *pMaterial = pControl->GetMaterial(); + if( !pMaterial ) + { + Assert( 0 ); + return; + } + + if ( pMaterial != m_pMaterial ) + { +// Warning( "\t%s!=%s\n", pMaterial->GetName(), m_pMaterial->GetName() ); + return; + } + + bool bFound; + IMaterialVar *pMaterialVar = pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false ); + if ( !bFound ) + return; + + if( Q_strcmp( pControl->GetMaterialVariableValue(), "" ) ) + { +// const char *pMaterialName = m_pMaterial->GetName(); +// const char *pMaterialVarName = pMaterialVar->GetName(); +// const char *pMaterialVarValue = pControl->GetMaterialVariableValue(); +// if( debug_materialmodifycontrol_client.GetBool() +// && Q_stristr( m_pMaterial->GetName(), "faceandhair" ) +// && Q_stristr( pMaterialVar->GetName(), "self" ) +// ) +// { +// static int count = 0; +// DevMsg( 1, "CMaterialModifyProxy::OnBindSetVar \"%s\" %s=%s %d pControl=0x%p\n", +// m_pMaterial->GetName(), pMaterialVar->GetName(), pControl->GetMaterialVariableValue(), count++, pControl ); +// } + pMaterialVar->SetValueAutodetectType( pControl->GetMaterialVariableValue() ); + } +} + + +//----------------------------------------------------------------------------- +// Does the dirty deed +//----------------------------------------------------------------------------- +void CMaterialModifyProxy::OnBindAnimatedTexture( C_MaterialModifyControl *pControl ) +{ + assert ( m_AnimatedTextureVar ); + if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE ) + return; + + ITexture *pTexture; + pTexture = m_AnimatedTextureVar->GetTextureValue(); + + if ( !pControl ) + return; + + if ( pControl->HasNewAnimationCommands() ) + { + // Read the data from the modify entity + materialanimcommands_t sCommands; + pControl->GetAnimationCommands( &sCommands ); + + m_iFrameStart = sCommands.iFrameStart; + m_iFrameEnd = sCommands.iFrameEnd; + m_bCustomWrap = sCommands.bWrap; + m_flCustomFramerate = sCommands.flFrameRate; + m_bReachedEnd = false; + + m_flStartTime = gpGlobals->curtime; + + pControl->ClearAnimationCommands(); + } + + // Init all the vars based on whether we're using the base material settings, + // or the custom ones from the entity input. + int numFrames; + bool bWrapAnimation; + float flFrameRate; + int iLastFrame; + + // Do we have a custom frame section from the server? + if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET ) + { + if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET ) + { + m_iFrameEnd = pTexture->GetNumAnimationFrames(); + } + + numFrames = (m_iFrameEnd - m_iFrameStart) + 1; + bWrapAnimation = m_bCustomWrap; + flFrameRate = m_flCustomFramerate; + iLastFrame = (m_iFrameEnd - 1); + } + else + { + numFrames = pTexture->GetNumAnimationFrames(); + bWrapAnimation = m_WrapAnimation; + flFrameRate = m_FrameRate; + iLastFrame = (numFrames - 1); + } + + // Have we already reached the end? If so, stay there. + if ( m_bReachedEnd && !bWrapAnimation ) + { + m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame ); + return; + } + + // NOTE: Must not use relative time based methods here + // because the bind proxy can be called many times per frame. + // Prevent multiple Wrap callbacks to be sent for no wrap mode + float startTime; + if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET ) + { + startTime = m_flStartTime; + } + else + { + startTime = GetAnimationStartTime(pControl); + } + float deltaTime = gpGlobals->curtime - startTime; + float prevTime = deltaTime - gpGlobals->frametime; + + // Clamp.. + if (deltaTime < 0.0f) + deltaTime = 0.0f; + if (prevTime < 0.0f) + prevTime = 0.0f; + + float frame = flFrameRate * deltaTime; + float prevFrame = flFrameRate * prevTime; + + int intFrame = ((int)frame) % numFrames; + int intPrevFrame = ((int)prevFrame) % numFrames; + + if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET ) + { + intFrame += m_iFrameStart; + intPrevFrame += m_iFrameStart; + } + + // Report wrap situation... + if (intPrevFrame > intFrame) + { + m_bReachedEnd = true; + + if (bWrapAnimation) + { + AnimationWrapped( pControl ); + } + else + { + // Only sent the wrapped message once. + // when we're in non-wrapping mode + if (prevFrame < numFrames) + AnimationWrapped( pControl ); + intFrame = numFrames - 1; + } + } + + m_AnimatedTextureFrameNumVar->SetIntValue( intFrame ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CMaterialModifyProxy::GetAnimationStartTime( void* pArg ) +{ + IClientRenderable *pRend = (IClientRenderable *)pArg; + if (!pRend) + return 0.0f; + + C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity(); + if (pEntity) + { + return pEntity->GetTextureAnimationStartTime(); + } + return 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMaterialModifyProxy::AnimationWrapped( void* pArg ) +{ + IClientRenderable *pRend = (IClientRenderable *)pArg; + if (!pRend) + return; + + C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity(); + if (pEntity) + { + pEntity->TextureAnimationWrapped(); + } +} + +//----------------------------------------------------------------------------- +// Does the dirty deed +//----------------------------------------------------------------------------- +void CMaterialModifyProxy::OnBindFloatLerp( C_MaterialModifyControl *pControl ) +{ + if ( !pControl ) + return; + + if ( pControl->HasNewAnimationCommands() ) + { + pControl->SetAnimationStartTime( gpGlobals->curtime ); + pControl->ClearAnimationCommands(); + } + + // Read the data from the modify entity + materialfloatlerpcommands_t sCommands; + pControl->GetFloatLerpCommands( &sCommands ); + + m_flStartValue = sCommands.flStartValue; + m_flEndValue = sCommands.flEndValue; + m_flTransitionTime = sCommands.flTransitionTime; + m_flStartTime = pControl->GetAnimationStartTime(); + bool bFound; + m_pMaterialVar = m_pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false ); + + if( bFound ) + { + float currentValue; + if( m_flTransitionTime > 0.0f ) + { + currentValue = m_flStartValue + ( m_flEndValue - m_flStartValue ) * clamp( ( ( gpGlobals->curtime - m_flStartTime ) / m_flTransitionTime ), 0.0f, 1.0f ); + } + else + { + currentValue = m_flEndValue; + } + + if( debug_materialmodifycontrol_client.GetBool() && Q_stristr( m_pMaterial->GetName(), "faceandhair" ) && Q_stristr( m_pMaterialVar->GetName(), "warp" ) ) + { + static int count = 0; + DevMsg( 1, "CMaterialFloatLerpProxy::OnBind \"%s\" %s=%f %d\n", m_pMaterial->GetName(), m_pMaterialVar->GetName(), currentValue, count++ ); + } + m_pMaterialVar->SetFloatValue( currentValue ); + } +} + +//============================================================================= +// +// MATERIALMODIFYANIMATED PROXY +// +class CMaterialModifyAnimatedProxy : public CBaseAnimatedTextureProxy +{ +public: + CMaterialModifyAnimatedProxy() {}; + virtual ~CMaterialModifyAnimatedProxy() {}; + virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); + virtual void OnBind( void *pEntity ); + + virtual float GetAnimationStartTime( void* pBaseEntity ); + virtual void AnimationWrapped( void* pC_BaseEntity ); + +private: + IMaterial *m_pMaterial; + int m_iFrameStart; + int m_iFrameEnd; + bool m_bReachedEnd; + float m_flStartTime; + bool m_bCustomWrap; + float m_flCustomFramerate; +}; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CMaterialModifyAnimatedProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) +{ + m_pMaterial = pMaterial; + m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET; + m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET; + m_bReachedEnd = false; + return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues ); +} + +//----------------------------------------------------------------------------- +// Does the dirty deed +//----------------------------------------------------------------------------- +void CMaterialModifyAnimatedProxy::OnBind( void *pEntity ) +{ + assert ( m_AnimatedTextureVar ); + if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE ) + return; + + ITexture *pTexture; + pTexture = m_AnimatedTextureVar->GetTextureValue(); + + // Get the modified material vars from the entity input + IClientRenderable *pRend = (IClientRenderable *)pEntity; + if ( pRend ) + { + C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity(); + if ( pBaseEntity ) + { + for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() ) + { + C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild ); + if ( !pControl ) + continue; + + if ( !pControl->HasNewAnimationCommands() ) + continue; + + // Read the data from the modify entity + materialanimcommands_t sCommands; + pControl->GetAnimationCommands( &sCommands ); + + m_iFrameStart = sCommands.iFrameStart; + m_iFrameEnd = sCommands.iFrameEnd; + m_bCustomWrap = sCommands.bWrap; + m_flCustomFramerate = sCommands.flFrameRate; + m_bReachedEnd = false; + + m_flStartTime = gpGlobals->curtime; + + pControl->ClearAnimationCommands(); + } + } + } + + // Init all the vars based on whether we're using the base material settings, + // or the custom ones from the entity input. + int numFrames; + bool bWrapAnimation; + float flFrameRate; + int iLastFrame; + + // Do we have a custom frame section from the server? + if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET ) + { + if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET ) + { + m_iFrameEnd = pTexture->GetNumAnimationFrames(); + } + + numFrames = (m_iFrameEnd - m_iFrameStart) + 1; + bWrapAnimation = m_bCustomWrap; + flFrameRate = m_flCustomFramerate; + iLastFrame = (m_iFrameEnd - 1); + } + else + { + numFrames = pTexture->GetNumAnimationFrames(); + bWrapAnimation = m_WrapAnimation; + flFrameRate = m_FrameRate; + iLastFrame = (numFrames - 1); + } + + // Have we already reached the end? If so, stay there. + if ( m_bReachedEnd && !bWrapAnimation ) + { + m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame ); + return; + } + + // NOTE: Must not use relative time based methods here + // because the bind proxy can be called many times per frame. + // Prevent multiple Wrap callbacks to be sent for no wrap mode + float startTime; + if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET ) + { + startTime = m_flStartTime; + } + else + { + startTime = GetAnimationStartTime(pEntity); + } + float deltaTime = gpGlobals->curtime - startTime; + float prevTime = deltaTime - gpGlobals->frametime; + + // Clamp.. + if (deltaTime < 0.0f) + deltaTime = 0.0f; + if (prevTime < 0.0f) + prevTime = 0.0f; + + float frame = flFrameRate * deltaTime; + float prevFrame = flFrameRate * prevTime; + + int intFrame = ((int)frame) % numFrames; + int intPrevFrame = ((int)prevFrame) % numFrames; + + if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET ) + { + intFrame += m_iFrameStart; + intPrevFrame += m_iFrameStart; + } + + // Report wrap situation... + if (intPrevFrame > intFrame) + { + m_bReachedEnd = true; + + if (bWrapAnimation) + { + AnimationWrapped( pEntity ); + } + else + { + // Only sent the wrapped message once. + // when we're in non-wrapping mode + if (prevFrame < numFrames) + AnimationWrapped( pEntity ); + intFrame = numFrames - 1; + } + } + + m_AnimatedTextureFrameNumVar->SetIntValue( intFrame ); + + if ( ToolsEnabled() ) + { + ToolFramework_RecordMaterialParams( GetMaterial() ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CMaterialModifyAnimatedProxy::GetAnimationStartTime( void* pArg ) +{ + IClientRenderable *pRend = (IClientRenderable *)pArg; + if (!pRend) + return 0.0f; + + C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity(); + if (pEntity) + { + return pEntity->GetTextureAnimationStartTime(); + } + return 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMaterialModifyAnimatedProxy::AnimationWrapped( void* pArg ) +{ + IClientRenderable *pRend = (IClientRenderable *)pArg; + if (!pRend) + return; + + C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity(); + if (pEntity) + { + pEntity->TextureAnimationWrapped(); + } +} + + +EXPOSE_INTERFACE( CMaterialModifyProxy, IMaterialProxy, "MaterialModify" IMATERIAL_PROXY_INTERFACE_VERSION ); +EXPOSE_INTERFACE( CMaterialModifyAnimatedProxy, IMaterialProxy, "MaterialModifyAnimated" IMATERIAL_PROXY_INTERFACE_VERSION ); |