csgo-2018-source/movieobjects/dmeflexrules.cpp
2021-07-24 21:11:47 -07:00

444 lines
12 KiB
C++

//====== Copyright © 1996-2009, Valve Corporation, All rights reserved. =======
//
// DmeEyeball
//
//=============================================================================
// Standard includes
#include <ctype.h>
// Valve includes
#include "datamodel/dmelementfactoryhelper.h"
#include "movieobjects/dmecombinationoperator.h"
#include "movieobjects/dmeexpressionoperator.h"
#include "movieobjects/dmeflexrules.h"
// Last include
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeFlexRuleBase, CDmeFlexRuleBase );
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleBase::OnConstruction()
{
m_flResult.Init( this, "result" );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleBase::OnDestruction()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleBase::GetInputAttributes ( CUtlVector< CDmAttribute * > &attrs )
{
BaseClass::GetInputAttributes( attrs );
CDmeFlexRules *pDmeFlexRules = GetFlexRules();
if ( pDmeFlexRules )
{
attrs.AddToTail( pDmeFlexRules->m_vDeltaStateWeights.GetAttribute() );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleBase::GetOutputAttributes( CUtlVector< CDmAttribute * > &attrs )
{
BaseClass::GetOutputAttributes( attrs );
attrs.AddToTail( m_flResult.GetAttribute() );
}
//-----------------------------------------------------------------------------
// Returns the first DmeExpressionRules element that refers to this element
//-----------------------------------------------------------------------------
CDmeFlexRules *CDmeFlexRuleBase::GetFlexRules() const
{
return FindReferringElement< CDmeFlexRules >( this, "deltaStates" );
}
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeFlexRulePassThrough, CDmeFlexRulePassThrough );
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRulePassThrough::OnConstruction()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRulePassThrough::OnDestruction()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRulePassThrough::Operate()
{
CDmeFlexRules *pDmeFlexRules = GetFlexRules();
if ( !pDmeFlexRules )
return;
const float flResult = pDmeFlexRules->GetDeltaStateWeight( GetName() );
m_flResult.Set( flResult );
}
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeFlexRuleExpression, CDmeFlexRuleExpression );
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleExpression::OnConstruction()
{
m_expr.Init( this, "expr" );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleExpression::OnDestruction()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleExpression::Operate()
{
CDmeFlexRules *pDmeFlexRules = GetFlexRules();
if ( pDmeFlexRules )
{
for ( int i = 0; i < m_calc.VariableCount(); ++i )
{
m_calc.SetVariable( i, pDmeFlexRules->GetDeltaStateWeight( m_calc.VariableName( i ) ) );
}
}
float flVal = 0.0f;
if ( m_calc.Evaluate( flVal ) )
{
m_flResult.Set( flVal );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleExpression::Resolve()
{
if ( m_expr.IsDirty() )
{
m_calc.SetExpression( m_expr.Get() );
m_calc.BuildVariableListFromExpression();
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CDmeFlexRuleExpression::SetExpression( const char *pszExpression )
{
if ( !pszExpression || *pszExpression == '\0' )
return false;
bool bReturn = false;
CUtlVector< char *, CUtlMemory< char *, int > > pathStrings;
V_SplitString( pszExpression, "=", pathStrings );
if ( pathStrings.Count() == 2 )
{
char *pszLhs = pathStrings[0];
while ( V_isspace( *pszLhs ) )
{
++pszLhs;
}
for ( char *pszChar = pszLhs + V_strlen( pszLhs ) - 1; V_isspace( *pszChar ) && pszChar >= pszLhs; --pszChar )
{
*pszChar = '\0';
}
char *pszRhs = pathStrings[1];
while ( V_isspace( *pszRhs ) )
{
++pszRhs;
}
for ( char *pszChar = pszRhs + V_strlen( pszRhs ) - 1; V_isspace( *pszChar ) && pszChar >= pszRhs; --pszChar )
{
*pszChar = '\0';
}
m_expr = pszRhs;
Resolve();
// It's assumed the name of the node is the same as the variable on the left hand side of the expression
Assert( !V_strcmp( pszLhs, GetName() ) );
}
pathStrings.PurgeAndDeleteElements();
return bReturn;
}
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeFlexRuleLocalVar, CDmeFlexRuleLocalVar );
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleLocalVar::OnConstruction()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRuleLocalVar::OnDestruction()
{
}
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeFlexRules, CDmeFlexRules );
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRules::OnConstruction()
{
// Required to drive this node from a DmeCombinationOperator
m_eDeltaStates.Init( this, "deltaStates" );
m_vDeltaStateWeights.Init( this, "deltaStateWeights" );
m_eTarget.Init( this, "target" );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRules::OnDestruction()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRules::Operate()
{
if ( m_deltaToTargetMap.Count() <= 0 )
{
Resolve();
}
const int nDeltaCount = MIN( m_eDeltaStates.Count(), m_deltaToTargetMap.Count() );
CDmrArray< Vector2D > targetWeights( m_eTarget, "deltaStateWeights" );
const int nTargetWeightCount = targetWeights.Count();
for ( int i = 0; i < nDeltaCount; ++i )
{
const int nTargetIndex = m_deltaToTargetMap[i];
if ( nTargetIndex < 0 || nTargetIndex >= nTargetWeightCount )
continue;
CDmeFlexRuleBase *pDmeFlexRuleBase = m_eDeltaStates[i];
if ( !pDmeFlexRuleBase )
continue;
const CDmAttribute *pDmResultAttr = pDmeFlexRuleBase->ResultAttr();
if ( !pDmResultAttr )
continue;
const float flVal = pDmResultAttr->GetValue< float >();
targetWeights.Set( nTargetIndex, Vector2D( flVal, flVal ) ); // FlexRules ignore the built in stereo
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRules::Resolve()
{
if ( m_deltaToTargetMap.Count() <= 0 || m_eTarget.IsDirty() || m_eDeltaStates.IsDirty() )
{
m_deltaToTargetMap.SetCountNonDestructively( m_eDeltaStates.Count() );
const CDmrElementArrayConst< CDmElement > targetStates( m_eTarget, "deltaStates" );
for ( int i = 0; i < m_eDeltaStates.Count(); ++i )
{
m_deltaToTargetMap[i] = -1;
CDmeFlexRuleBase *pDmeFlexRuleBase = m_eDeltaStates[i];
if ( !pDmeFlexRuleBase )
continue;
for ( int j = 0; j < targetStates.Count(); ++j )
{
if ( !V_strcmp( targetStates[j]->GetName(), pDmeFlexRuleBase->GetName() ) )
{
m_deltaToTargetMap[i] = j;
break;
}
}
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRules::GetInputAttributes( CUtlVector< CDmAttribute * > &attrs )
{
attrs.AddToTail( m_eDeltaStates.GetAttribute() );
attrs.AddToTail( m_vDeltaStateWeights.GetAttribute() );
for ( int i = 0; i < m_eDeltaStates.Count(); ++i )
{
m_eDeltaStates[i]->GetOutputAttributes( attrs );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRules::GetOutputAttributes( CUtlVector< CDmAttribute * > &attrs )
{
CDmrArray<Vector2D> targetWeights( m_eTarget, "deltaStateWeights" );
if ( targetWeights.IsValid() )
{
attrs.AddToTail( targetWeights.GetAttribute() );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRules::AddFlexRule( CDmeFlexRuleBase *pDmeFlexRule )
{
if ( !pDmeFlexRule )
return;
m_eDeltaStates.AddToTail( pDmeFlexRule );
m_vDeltaStateWeights.AddToTail();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRules::RemoveAllRules()
{
m_eDeltaStates.RemoveAll();
m_vDeltaStateWeights.RemoveAll();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDmeFlexRules::SetTarget( CDmElement *pDmElement )
{
if ( !pDmElement )
return;
m_eTarget = pDmElement;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDmeFlexRules::GetDeltaStateIndex( const char *pszDeltaName ) const
{
for ( int i = 0; i < m_eDeltaStates.Count(); ++i )
{
if ( !V_strcmp( pszDeltaName, m_eDeltaStates[i]->GetName() ) )
return i;
}
return -1;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
float CDmeFlexRules::GetDeltaStateWeight( const char *pszDeltaName ) const
{
const int nDeltaStateIndex = GetDeltaStateIndex( pszDeltaName );
if ( nDeltaStateIndex < 0 || nDeltaStateIndex >= m_vDeltaStateWeights.Count() )
return 0.0f;
return m_vDeltaStateWeights[nDeltaStateIndex].x; // Weights are stereo...
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CDmeCombinationOperator *CDmeFlexRules::GetComboOp() const
{
return FindReferringElement< CDmeCombinationOperator >( this, m_vDeltaStateWeights.GetAttribute()->GetName() );
}