2020-04-22 18:56:21 +02:00
|
|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
//
|
|
|
|
// $NoKeywords: $
|
|
|
|
//=============================================================================//
|
|
|
|
|
|
|
|
#include "cbase.h"
|
|
|
|
#include "c_baseanimatingoverlay.h"
|
|
|
|
#include "bone_setup.h"
|
2024-07-10 16:10:00 +02:00
|
|
|
#include "interpolatedvar.h"
|
2024-04-03 05:14:06 +02:00
|
|
|
#include "studio.h"
|
2020-04-22 18:56:21 +02:00
|
|
|
#include "tier0/vprof.h"
|
|
|
|
#include "engine/ivdebugoverlay.h"
|
|
|
|
#include "datacache/imdlcache.h"
|
|
|
|
#include "eventlist.h"
|
|
|
|
|
|
|
|
#include "dt_utlvector_recv.h"
|
|
|
|
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
|
|
#include "tier0/memdbgon.h"
|
|
|
|
|
|
|
|
extern ConVar r_sequence_debug;
|
|
|
|
|
|
|
|
C_BaseAnimatingOverlay::C_BaseAnimatingOverlay()
|
|
|
|
{
|
|
|
|
// FIXME: where does this initialization go now?
|
|
|
|
//for ( int i=0; i < MAX_OVERLAYS; i++ )
|
|
|
|
//{
|
|
|
|
// memset( &m_Layer[i], 0, sizeof(m_Layer[0]) );
|
|
|
|
// m_Layer[i].m_nOrder = MAX_OVERLAYS;
|
|
|
|
//}
|
|
|
|
|
|
|
|
// FIXME: where does this initialization go now?
|
|
|
|
// AddVar( m_Layer, &m_iv_AnimOverlay, LATCH_ANIMATION_VAR );
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef CBaseAnimatingOverlay
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_RECV_TABLE_NOBASE(CAnimationLayer, DT_Animationlayer)
|
|
|
|
RecvPropInt( RECVINFO_NAME(m_nSequence, m_nSequence)),
|
|
|
|
RecvPropFloat( RECVINFO_NAME(m_flCycle, m_flCycle)),
|
|
|
|
RecvPropFloat( RECVINFO_NAME(m_flPrevCycle, m_flPrevCycle)),
|
|
|
|
RecvPropFloat( RECVINFO_NAME(m_flWeight, m_flWeight)),
|
|
|
|
RecvPropInt( RECVINFO_NAME(m_nOrder, m_nOrder))
|
|
|
|
END_RECV_TABLE()
|
|
|
|
|
|
|
|
const char *s_m_iv_AnimOverlayNames[C_BaseAnimatingOverlay::MAX_OVERLAYS] =
|
|
|
|
{
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay00",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay01",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay02",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay03",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay04",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay05",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay06",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay07",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay08",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay09",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay10",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay11",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay12",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay13",
|
|
|
|
"C_BaseAnimatingOverlay::m_iv_AnimOverlay14"
|
|
|
|
};
|
|
|
|
|
|
|
|
void ResizeAnimationLayerCallback( void *pStruct, int offsetToUtlVector, int len )
|
|
|
|
{
|
|
|
|
C_BaseAnimatingOverlay *pEnt = (C_BaseAnimatingOverlay*)pStruct;
|
|
|
|
CUtlVector < C_AnimationLayer > *pVec = &pEnt->m_AnimOverlay;
|
|
|
|
CUtlVector< CInterpolatedVar< C_AnimationLayer > > *pVecIV = &pEnt->m_iv_AnimOverlay;
|
|
|
|
|
|
|
|
Assert( (char*)pVec - (char*)pEnt == offsetToUtlVector );
|
|
|
|
Assert( pVec->Count() == pVecIV->Count() );
|
|
|
|
Assert( pVec->Count() <= C_BaseAnimatingOverlay::MAX_OVERLAYS );
|
|
|
|
|
|
|
|
int diff = len - pVec->Count();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( diff == 0 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// remove all entries
|
|
|
|
for ( int i=0; i < pVec->Count(); i++ )
|
|
|
|
{
|
2024-07-12 03:59:34 +02:00
|
|
|
// pEnt->RemoveVar( &pVec->Element( i ) );
|
2020-04-22 18:56:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// adjust vector sizes
|
|
|
|
if ( diff > 0 )
|
|
|
|
{
|
|
|
|
pVec->AddMultipleToTail( diff );
|
|
|
|
pVecIV->AddMultipleToTail( diff );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pVec->RemoveMultiple( len, -diff );
|
|
|
|
pVecIV->RemoveMultiple( len, -diff );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rebind all the variables in the ent's list.
|
|
|
|
for ( int i=0; i < len; i++ )
|
|
|
|
{
|
|
|
|
IInterpolatedVar *pWatcher = &pVecIV->Element( i );
|
|
|
|
pWatcher->SetDebugName( s_m_iv_AnimOverlayNames[i] );
|
2024-07-12 03:59:34 +02:00
|
|
|
// pEnt->AddVar( &pVec->Element( i ), pWatcher, LATCH_ANIMATION_VAR );
|
2020-04-22 18:56:21 +02:00
|
|
|
}
|
|
|
|
// FIXME: need to set historical values of nOrder in pVecIV to MAX_OVERLAY
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
BEGIN_RECV_TABLE_NOBASE( C_BaseAnimatingOverlay, DT_OverlayVars )
|
|
|
|
RecvPropUtlVector(
|
2024-07-10 16:10:00 +02:00
|
|
|
RECVINFO_UTLVECTOR( m_AnimOverlay ),
|
2020-04-22 18:56:21 +02:00
|
|
|
C_BaseAnimatingOverlay::MAX_OVERLAYS,
|
|
|
|
RecvPropDataTable(NULL, 0, 0, &REFERENCE_RECV_TABLE( DT_Animationlayer ) ) )
|
|
|
|
END_RECV_TABLE()
|
|
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_CLIENTCLASS_DT( C_BaseAnimatingOverlay, DT_BaseAnimatingOverlay, CBaseAnimatingOverlay )
|
|
|
|
RecvPropDataTable( "overlay_vars", 0, 0, &REFERENCE_RECV_TABLE( DT_OverlayVars ) )
|
|
|
|
END_RECV_TABLE()
|
|
|
|
|
|
|
|
BEGIN_PREDICTION_DATA( C_BaseAnimatingOverlay )
|
|
|
|
|
|
|
|
/*
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_nSequence, FIELD_INTEGER ),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_flCycle, FIELD_FLOAT ),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_flPlaybackRate, FIELD_FLOAT),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_flWeight, FIELD_FLOAT),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_nSequence, FIELD_INTEGER ),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_flCycle, FIELD_FLOAT ),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_flPlaybackRate, FIELD_FLOAT),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_flWeight, FIELD_FLOAT),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_nSequence, FIELD_INTEGER ),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_flCycle, FIELD_FLOAT ),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_flPlaybackRate, FIELD_FLOAT),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_flWeight, FIELD_FLOAT),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_nSequence, FIELD_INTEGER ),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_flCycle, FIELD_FLOAT ),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_flPlaybackRate, FIELD_FLOAT),
|
|
|
|
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_flWeight, FIELD_FLOAT),
|
|
|
|
*/
|
|
|
|
|
|
|
|
END_PREDICTION_DATA()
|
|
|
|
|
|
|
|
C_AnimationLayer* C_BaseAnimatingOverlay::GetAnimOverlay( int i )
|
|
|
|
{
|
|
|
|
Assert( i >= 0 && i < MAX_OVERLAYS );
|
|
|
|
return &m_AnimOverlay[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void C_BaseAnimatingOverlay::SetNumAnimOverlays( int num )
|
|
|
|
{
|
|
|
|
if ( m_AnimOverlay.Count() < num )
|
|
|
|
{
|
|
|
|
m_AnimOverlay.AddMultipleToTail( num - m_AnimOverlay.Count() );
|
|
|
|
}
|
|
|
|
else if ( m_AnimOverlay.Count() > num )
|
|
|
|
{
|
|
|
|
m_AnimOverlay.RemoveMultiple( num, m_AnimOverlay.Count() - num );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int C_BaseAnimatingOverlay::GetNumAnimOverlays() const
|
|
|
|
{
|
|
|
|
return m_AnimOverlay.Count();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void C_BaseAnimatingOverlay::GetRenderBounds( Vector& theMins, Vector& theMaxs )
|
|
|
|
{
|
|
|
|
BaseClass::GetRenderBounds( theMins, theMaxs );
|
|
|
|
|
|
|
|
if ( !IsRagdoll() )
|
|
|
|
{
|
|
|
|
CStudioHdr *pStudioHdr = GetModelPtr();
|
|
|
|
if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
int nSequences = pStudioHdr->GetNumSeq();
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
|
|
|
{
|
|
|
|
if (m_AnimOverlay[i].m_flWeight > 0.0)
|
|
|
|
{
|
|
|
|
if ( m_AnimOverlay[i].m_nSequence >= nSequences )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_AnimOverlay[i].m_nSequence );
|
|
|
|
VectorMin( seqdesc.bbmin, theMins, theMins );
|
|
|
|
VectorMax( seqdesc.bbmax, theMaxs, theMaxs );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void C_BaseAnimatingOverlay::AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime )
|
|
|
|
{
|
2024-07-10 16:10:00 +02:00
|
|
|
BaseClass::AccumulateLayers(boneSetup, pos, q, currentTime);
|
2020-04-22 18:56:21 +02:00
|
|
|
|
2024-07-10 16:10:00 +02:00
|
|
|
// sort the layers
|
|
|
|
int layer[MAX_OVERLAYS] = {};
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
2024-07-12 03:59:34 +02:00
|
|
|
{
|
2020-04-22 18:56:21 +02:00
|
|
|
layer[i] = MAX_OVERLAYS;
|
|
|
|
}
|
|
|
|
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
|
|
|
{
|
2024-07-10 16:10:00 +02:00
|
|
|
CAnimationLayer &pLayer = m_AnimOverlay[i];
|
|
|
|
if( (pLayer.m_flWeight > 0) && pLayer.IsActive() && pLayer.m_nOrder >= 0 && pLayer.m_nOrder < m_AnimOverlay.Count())
|
2020-04-22 18:56:21 +02:00
|
|
|
{
|
2024-07-10 16:10:00 +02:00
|
|
|
layer[pLayer.m_nOrder] = i;
|
2020-04-22 18:56:21 +02:00
|
|
|
}
|
2024-07-12 03:59:34 +02:00
|
|
|
}
|
2024-07-10 16:10:00 +02:00
|
|
|
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
2020-04-22 18:56:21 +02:00
|
|
|
{
|
2024-07-10 16:10:00 +02:00
|
|
|
if (layer[i] >= 0 && layer[i] < m_AnimOverlay.Count())
|
2020-04-22 18:56:21 +02:00
|
|
|
{
|
2024-07-10 16:10:00 +02:00
|
|
|
CAnimationLayer &pLayer = m_AnimOverlay[layer[i]];
|
|
|
|
// UNDONE: Is it correct to use overlay weight for IK too?
|
|
|
|
boneSetup.AccumulatePose( pos, q, pLayer.m_nSequence, pLayer.m_flCycle, pLayer.m_flWeight, currentTime, m_pIk );
|
2020-04-22 18:56:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void C_BaseAnimatingOverlay::DoAnimationEvents( CStudioHdr *pStudioHdr )
|
|
|
|
{
|
|
|
|
if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
MDLCACHE_CRITICAL_SECTION();
|
|
|
|
|
|
|
|
int nSequences = pStudioHdr->GetNumSeq();
|
|
|
|
|
|
|
|
BaseClass::DoAnimationEvents( pStudioHdr );
|
|
|
|
|
|
|
|
bool watch = false; // Q_strstr( hdr->name, "rifle" ) ? true : false;
|
|
|
|
|
|
|
|
int j;
|
|
|
|
for (j = 0; j < m_AnimOverlay.Count(); j++)
|
|
|
|
{
|
|
|
|
if ( m_AnimOverlay[j].m_nSequence >= nSequences )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_AnimOverlay[j].m_nSequence );
|
|
|
|
if ( seqdesc.numevents == 0 )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// stalled?
|
|
|
|
if (m_AnimOverlay[j].m_flCycle == m_flOverlayPrevEventCycle[j])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bool bLoopingSequence = IsSequenceLooping( m_AnimOverlay[j].m_nSequence );
|
|
|
|
|
|
|
|
bool bLooped = false;
|
|
|
|
|
|
|
|
//in client code, m_flOverlayPrevEventCycle is set to -1 when we first start an overlay, looping or not
|
|
|
|
if ( bLoopingSequence &&
|
|
|
|
m_flOverlayPrevEventCycle[j] > 0.0f &&
|
|
|
|
m_AnimOverlay[j].m_flCycle <= m_flOverlayPrevEventCycle[j] )
|
|
|
|
{
|
|
|
|
if (m_flOverlayPrevEventCycle[j] - m_AnimOverlay[j].m_flCycle > 0.5)
|
|
|
|
{
|
|
|
|
bLooped = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// things have backed up, which is bad since it'll probably result in a hitch in the animation playback
|
|
|
|
// but, don't play events again for the same time slice
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mstudioevent_t *pevent = seqdesc.pEvent( 0 );
|
|
|
|
|
|
|
|
// This makes sure events that occur at the end of a sequence occur are
|
|
|
|
// sent before events that occur at the beginning of a sequence.
|
|
|
|
if (bLooped)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < (int)seqdesc.numevents; i++)
|
|
|
|
{
|
|
|
|
// ignore all non-client-side events
|
|
|
|
if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM )
|
|
|
|
{
|
|
|
|
if ( !( pevent[i].type & AE_TYPE_CLIENT ) )
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ( pevent[i].event < 5000 ) //Adrian - Support the old event system
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ( pevent[i].cycle <= m_flOverlayPrevEventCycle[j] )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ( watch )
|
|
|
|
{
|
|
|
|
Msg( "%i FE %i Looped cycle %f, prev %f ev %f (time %.3f)\n",
|
|
|
|
gpGlobals->tickcount,
|
|
|
|
pevent[i].event,
|
|
|
|
pevent[i].cycle,
|
|
|
|
m_flOverlayPrevEventCycle[j],
|
|
|
|
(float)m_AnimOverlay[j].m_flCycle,
|
|
|
|
gpGlobals->curtime );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Necessary to get the next loop working
|
|
|
|
m_flOverlayPrevEventCycle[j] = -0.01;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)seqdesc.numevents; i++)
|
|
|
|
{
|
|
|
|
if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM )
|
|
|
|
{
|
|
|
|
if ( !( pevent[i].type & AE_TYPE_CLIENT ) )
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ( pevent[i].event < 5000 ) //Adrian - Support the old event system
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ( (pevent[i].cycle > m_flOverlayPrevEventCycle[j] && pevent[i].cycle <= m_AnimOverlay[j].m_flCycle) )
|
|
|
|
{
|
|
|
|
if ( watch )
|
|
|
|
{
|
|
|
|
Msg( "%i (seq: %d) FE %i Normal cycle %f, prev %f ev %f (time %.3f)\n",
|
|
|
|
gpGlobals->tickcount,
|
|
|
|
m_AnimOverlay[j].m_nSequence.GetRaw(),
|
|
|
|
pevent[i].event,
|
|
|
|
pevent[i].cycle,
|
|
|
|
m_flOverlayPrevEventCycle[j],
|
|
|
|
(float)m_AnimOverlay[j].m_flCycle,
|
|
|
|
gpGlobals->curtime );
|
|
|
|
}
|
|
|
|
|
|
|
|
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_flOverlayPrevEventCycle[j] = m_AnimOverlay[j].m_flCycle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose:
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CStudioHdr *C_BaseAnimatingOverlay::OnNewModel()
|
|
|
|
{
|
|
|
|
CStudioHdr *hdr = BaseClass::OnNewModel();
|
|
|
|
|
|
|
|
// Clear out animation layers
|
|
|
|
for ( int i=0; i < m_AnimOverlay.Count(); i++ )
|
|
|
|
{
|
|
|
|
m_AnimOverlay[i].Reset();
|
|
|
|
m_AnimOverlay[i].m_nOrder = MAX_OVERLAYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hdr;
|
|
|
|
}
|
2024-04-03 05:14:06 +02:00
|
|
|
|
|
|
|
void C_BaseAnimatingOverlay::GetSkeleton( CStudioHdr* pStudioHdr, Vector pos[], Quaternion q[], int boneMask, float currentTime )
|
|
|
|
{
|
|
|
|
if(!pStudioHdr)
|
|
|
|
{
|
|
|
|
Assert(!"C_BaseAnimating::GetSkeleton() without a model");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pStudioHdr->SequencesAvailable())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float poseparameters[MAXSTUDIOPOSEPARAM];
|
|
|
|
GetPoseParameters(pStudioHdr, poseparameters);
|
|
|
|
|
|
|
|
IBoneSetup boneSetup( pStudioHdr, boneMask, poseparameters );
|
|
|
|
boneSetup.InitPose( pos, q );
|
|
|
|
|
|
|
|
boneSetup.AccumulatePose( pos, q, GetSequence(), GetCycle(), 1.0, currentTime, m_pIk );
|
|
|
|
|
|
|
|
// sort the layers
|
|
|
|
int layer[MAX_OVERLAYS] = {};
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
|
|
|
{
|
|
|
|
layer[i] = MAX_OVERLAYS;
|
|
|
|
}
|
|
|
|
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
|
|
|
{
|
|
|
|
CAnimationLayer &pLayer = m_AnimOverlay[i];
|
|
|
|
if( (pLayer.m_flWeight > 0) && pLayer.IsActive() && pLayer.m_nOrder >= 0 && pLayer.m_nOrder < m_AnimOverlay.Count())
|
|
|
|
{
|
|
|
|
layer[pLayer.m_nOrder] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
|
|
|
{
|
|
|
|
if (layer[i] >= 0 && layer[i] < m_AnimOverlay.Count())
|
|
|
|
{
|
|
|
|
CAnimationLayer &pLayer = m_AnimOverlay[layer[i]];
|
|
|
|
// UNDONE: Is it correct to use overlay weight for IK too?
|
|
|
|
boneSetup.AccumulatePose( pos, q, pLayer.m_nSequence, pLayer.m_flCycle, pLayer.m_flWeight, currentTime, m_pIk );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( m_pIk )
|
|
|
|
{
|
|
|
|
CIKContext auto_ik;
|
|
|
|
auto_ik.Init( pStudioHdr, GetRenderAngles(), GetRenderOrigin(), currentTime, 0, boneMask );
|
|
|
|
boneSetup.CalcAutoplaySequences( pos, q, currentTime, &auto_ik );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
boneSetup.CalcAutoplaySequences(pos, q, currentTime, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
float controllers[MAXSTUDIOBONECTRLS];
|
|
|
|
GetBoneControllers(controllers);
|
|
|
|
|
|
|
|
boneSetup.CalcBoneAdj( pos, q, controllers );
|
|
|
|
}
|