From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- sp/src/game/client/C_MaterialModifyControl.cpp | 1596 ++++++++++++------------ 1 file changed, 798 insertions(+), 798 deletions(-) (limited to 'sp/src/game/client/C_MaterialModifyControl.cpp') diff --git a/sp/src/game/client/C_MaterialModifyControl.cpp b/sp/src/game/client/C_MaterialModifyControl.cpp index 55ff2ec5..f038022e 100644 --- a/sp/src/game/client/C_MaterialModifyControl.cpp +++ b/sp/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( 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( 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( 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( 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 ); -- cgit v1.2.3