1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2024-12-23 01:59:43 +08:00
hl2sdk/public/studio.cpp

1312 lines
32 KiB
C++

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "studio.h"
#include "datacache/idatacache.h"
#include "datacache/imdlcache.h"
#include "convar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
mstudioanimdesc_t &studiohdr_t::pAnimdesc( int i ) const
{
if (numincludemodels == 0)
{
return *pLocalAnimdesc( i );
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_anim[i].group ];
const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
Assert( pStudioHdr );
return *pStudioHdr->pLocalAnimdesc( pVModel->m_anim[i].index );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
mstudioanim_t *mstudioanimdesc_t::pAnim( void ) const
{
if (animblock == 0)
{
return (mstudioanim_t *)(((byte *)this) + animindex);
}
else
{
byte *pAnimBlocks = pStudiohdr()->GetAnimBlock( animblock );
if ( pAnimBlocks )
{
return (mstudioanim_t *)(pAnimBlocks + animindex);
}
}
return NULL;
}
mstudioikrule_t *mstudioanimdesc_t::pIKRule( int i ) const
{
if (ikruleindex)
{
return (mstudioikrule_t *)(((byte *)this) + ikruleindex) + i;
}
else if (animblockikruleindex)
{
if (animblock == 0)
{
return (mstudioikrule_t *)(((byte *)this) + animblockikruleindex) + i;
}
else
{
byte *pAnimBlocks = pStudiohdr()->GetAnimBlock( animblock );
if ( pAnimBlocks )
{
return (mstudioikrule_t *)(pAnimBlocks + animblockikruleindex) + i;
}
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool studiohdr_t::SequencesAvailable() const
{
if (numincludemodels == 0)
{
return true;
}
return ( GetVirtualModel() != NULL );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::GetNumSeq( void ) const
{
if (numincludemodels == 0)
{
return numlocalseq;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
return pVModel->m_seq.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
mstudioseqdesc_t &studiohdr_t::pSeqdesc( int i ) const
{
if (numincludemodels == 0)
{
return *pLocalSeqdesc( i );
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
if ( !pVModel )
{
return *pLocalSeqdesc( i );
}
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[i].group ];
const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
Assert( pStudioHdr );
return *pStudioHdr->pLocalSeqdesc( pVModel->m_seq[i].index );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::iRelativeAnim( int baseseq, int relanim ) const
{
if (numincludemodels == 0)
{
return relanim;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[baseseq].group ];
return pGroup->masterAnim[ relanim ];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::iRelativeSeq( int baseseq, int relseq ) const
{
if (numincludemodels == 0)
{
return relseq;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[baseseq].group ];
return pGroup->masterSeq[ relseq ];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::GetNumPoseParameters( void ) const
{
if (numincludemodels == 0)
{
return numlocalposeparameters;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
return pVModel->m_pose.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const mstudioposeparamdesc_t &studiohdr_t::pPoseParameter( int i ) const
{
if (numincludemodels == 0)
{
return *pLocalPoseParameter( i );
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
if ( pVModel->m_pose[i].group == 0)
return *pLocalPoseParameter( pVModel->m_pose[i].index );
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_pose[i].group ];
const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
Assert( pStudioHdr );
return *pStudioHdr->pLocalPoseParameter( pVModel->m_pose[i].index );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::GetSharedPoseParameter( int iSequence, int iLocalPose ) const
{
if (numincludemodels == 0)
{
return iLocalPose;
}
if (iLocalPose == -1)
return iLocalPose;
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ];
return pGroup->masterPose[iLocalPose];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::EntryNode( int iSequence ) const
{
mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
if (numincludemodels == 0 || seqdesc.localentrynode == 0)
{
return seqdesc.localentrynode;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ];
return pGroup->masterNode[seqdesc.localentrynode-1]+1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::ExitNode( int iSequence ) const
{
mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
if (numincludemodels == 0 || seqdesc.localexitnode == 0)
{
return seqdesc.localexitnode;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ];
return pGroup->masterNode[seqdesc.localexitnode-1]+1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::GetNumAttachments( void ) const
{
if (numincludemodels == 0)
{
return numlocalattachments;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
return pVModel->m_attachment.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const mstudioattachment_t &studiohdr_t::pAttachment( int i ) const
{
if (numincludemodels == 0)
{
return *pLocalAttachment( i );
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[i].group ];
const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
Assert( pStudioHdr );
return *pStudioHdr->pLocalAttachment( pVModel->m_attachment[i].index );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::GetAttachmentBone( int i ) const
{
const mstudioattachment_t &attachment = pAttachment( i );
// remap bone
virtualmodel_t *pVModel = GetVirtualModel();
if (pVModel)
{
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[i].group ];
int iBone = pGroup->masterBone[attachment.localbone];
if (iBone == -1)
return 0;
return iBone;
}
return attachment.localbone;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void studiohdr_t::SetAttachmentBone( int iAttachment, int iBone )
{
mstudioattachment_t &attachment = (mstudioattachment_t &)pAttachment( iAttachment );
// remap bone
virtualmodel_t *pVModel = GetVirtualModel();
if (pVModel)
{
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[iAttachment].group ];
iBone = pGroup->boneMap[iBone];
}
attachment.localbone = iBone;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
char *studiohdr_t::pszNodeName( int iNode ) const
{
if (numincludemodels == 0)
{
return pszLocalNodeName( iNode );
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
if ( pVModel->m_node.Count() <= iNode-1 )
return "Invalid node";
return pVModel->m_group[ pVModel->m_node[iNode-1].group ].GetStudioHdr()->pszLocalNodeName( pVModel->m_node[iNode-1].index );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::GetTransition( int iFrom, int iTo ) const
{
if (numincludemodels == 0)
{
return *pLocalTransition( (iFrom-1)*numlocalnodes + (iTo - 1) );
}
return iTo;
/*
FIXME: not connected
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
return pVModel->m_transition.Element( iFrom ).Element( iTo );
*/
}
int studiohdr_t::GetActivityListVersion( void ) const
{
if (numincludemodels == 0)
{
return activitylistversion;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
int version = activitylistversion;
int i;
for (i = 1; i < pVModel->m_group.Count(); i++)
{
virtualgroup_t *pGroup = &pVModel->m_group[ i ];
const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
Assert( pStudioHdr );
version = MIN( version, pStudioHdr->activitylistversion );
}
return version;
}
void studiohdr_t::SetActivityListVersion( int version ) const
{
activitylistversion = version;
if (numincludemodels == 0)
{
return;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
int i;
for (i = 1; i < pVModel->m_group.Count(); i++)
{
virtualgroup_t *pGroup = &pVModel->m_group[ i ];
const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
Assert( pStudioHdr );
pStudioHdr->SetActivityListVersion( version );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int studiohdr_t::GetNumIKAutoplayLocks( void ) const
{
if (numincludemodels == 0)
{
return numlocalikautoplaylocks;
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
return pVModel->m_iklock.Count();
}
const mstudioiklock_t &studiohdr_t::pIKAutoplayLock( int i ) const
{
if (numincludemodels == 0)
{
return *pLocalIKAutoplayLock( i );
}
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_iklock[i].group ];
const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr();
Assert( pStudioHdr );
return *pStudioHdr->pLocalIKAutoplayLock( pVModel->m_iklock[i].index );
}
int studiohdr_t::CountAutoplaySequences() const
{
int count = 0;
for (int i = 0; i < GetNumSeq(); i++)
{
mstudioseqdesc_t &seqdesc = pSeqdesc( i );
if (seqdesc.flags & STUDIO_AUTOPLAY)
{
count++;
}
}
return count;
}
int studiohdr_t::CopyAutoplaySequences( unsigned short *pOut, int outCount ) const
{
int outIndex = 0;
for (int i = 0; i < GetNumSeq() && outIndex < outCount; i++)
{
mstudioseqdesc_t &seqdesc = pSeqdesc( i );
if (seqdesc.flags & STUDIO_AUTOPLAY)
{
pOut[outIndex] = i;
outIndex++;
}
}
return outIndex;
}
//-----------------------------------------------------------------------------
// Purpose: maps local sequence bone to global bone
//-----------------------------------------------------------------------------
int studiohdr_t::RemapSeqBone( int iSequence, int iLocalBone ) const
{
// remap bone
virtualmodel_t *pVModel = GetVirtualModel();
if (pVModel)
{
const virtualgroup_t *pSeqGroup = pVModel->pSeqGroup( iSequence );
return pSeqGroup->masterBone[iLocalBone];
}
return iLocalBone;
}
int studiohdr_t::RemapAnimBone( int iAnim, int iLocalBone ) const
{
// remap bone
virtualmodel_t *pVModel = GetVirtualModel();
if (pVModel)
{
const virtualgroup_t *pAnimGroup = pVModel->pAnimGroup( iAnim );
return pAnimGroup->masterBone[iLocalBone];
}
return iLocalBone;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStudioHdr::CStudioHdr( void )
{
// set pointer to bogus value
m_nFrameUnlockCounter = 0;
m_pFrameUnlockCounter = &m_nFrameUnlockCounter;
Init( NULL );
}
CStudioHdr::CStudioHdr( IMDLCache *modelcache )
{
SetModelCache( modelcache );
Init( NULL );
}
CStudioHdr::CStudioHdr( const studiohdr_t *pStudioHdr, IMDLCache *modelcache )
{
SetModelCache( modelcache );
Init( pStudioHdr );
}
void CStudioHdr::SetModelCache( IMDLCache *modelcache )
{
m_pFrameUnlockCounter = modelcache->GetFrameUnlockCounterPtr( MDLCACHE_STUDIOHDR );
}
// extern IDataCache *g_pDataCache;
void CStudioHdr::Init( const studiohdr_t *pStudioHdr )
{
m_pStudioHdr = pStudioHdr;
m_pVModel = NULL;
m_pStudioHdrCache.RemoveAll();
if (m_pStudioHdr == NULL)
{
// make sure the tag says it's not ready
m_nFrameUnlockCounter = *m_pFrameUnlockCounter - 1;
return;
}
m_nFrameUnlockCounter = *m_pFrameUnlockCounter;
if (m_pStudioHdr->numincludemodels == 0)
{
return;
}
ResetVModel( m_pStudioHdr->GetVirtualModel() );
return;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CStudioHdr::SequencesAvailable() const
{
if (m_pStudioHdr->numincludemodels == 0)
{
return true;
}
if (m_pVModel == NULL)
{
// repoll m_pVModel
ResetVModel( m_pStudioHdr->GetVirtualModel() );
}
return ( m_pVModel != NULL );
}
void CStudioHdr::ResetVModel( const virtualmodel_t *pVModel ) const
{
m_pVModel = (virtualmodel_t *)pVModel;
if (m_pVModel != NULL)
{
m_pStudioHdrCache.SetCount( m_pVModel->m_group.Count() );
int i;
for (i = 0; i < m_pStudioHdrCache.Count(); i++)
{
m_pStudioHdrCache[ i ] = NULL;
}
}
}
const studiohdr_t *CStudioHdr::GroupStudioHdr( int i ) const
{
const studiohdr_t *pStudioHdr = m_pStudioHdrCache[ i ];
if (pStudioHdr == NULL)
{
virtualgroup_t *pGroup = &m_pVModel->m_group[ i ];
pStudioHdr = pGroup->GetStudioHdr();
m_pStudioHdrCache[ i ] = pStudioHdr;
}
Assert( pStudioHdr );
return pStudioHdr;
}
const studiohdr_t *CStudioHdr::pSeqStudioHdr( int sequence ) const
{
if (m_pVModel == NULL)
{
return m_pStudioHdr;
}
const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_seq[sequence].group );
return pStudioHdr;
}
const studiohdr_t *CStudioHdr::pAnimStudioHdr( int animation ) const
{
if (m_pVModel == NULL)
{
return m_pStudioHdr;
}
const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_anim[animation].group );
return pStudioHdr;
}
mstudioanimdesc_t &CStudioHdr::pAnimdesc( int i ) const
{
if (m_pVModel == NULL)
{
return *m_pStudioHdr->pLocalAnimdesc( i );
}
const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_anim[i].group );
return *pStudioHdr->pLocalAnimdesc( m_pVModel->m_anim[i].index );
}
#if 0
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
mstudioanim_t *mstudioanimdesc_t::pAnim( void ) const
{
if (animblock == 0)
{
return (mstudioanim_t *)(((byte *)this) + animindex);
}
else
{
byte *pAnimBlocks = pStudiohdr()->GetAnimBlock( animblock );
if ( !pAnimBlocks )
{
Error( "Error loading .ani file info block for '%s'\n",
pStudiohdr()->name );
}
return (mstudioanim_t *)(pAnimBlocks + animindex);
}
return NULL;
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::GetNumSeq( void ) const
{
if (m_pVModel == NULL)
{
return m_pStudioHdr->numlocalseq;
}
return m_pVModel->m_seq.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
mstudioseqdesc_t &CStudioHdr::pSeqdesc( int i ) const
{
Assert( i >= 0 && i < GetNumSeq() );
if (m_pVModel == NULL)
{
return *m_pStudioHdr->pLocalSeqdesc( i );
}
const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_seq[i].group );
return *pStudioHdr->pLocalSeqdesc( m_pVModel->m_seq[i].index );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::iRelativeAnim( int baseseq, int relanim ) const
{
if (m_pVModel == NULL)
{
return relanim;
}
virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[baseseq].group ];
return pGroup->masterAnim[ relanim ];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::iRelativeSeq( int baseseq, int relseq ) const
{
if (m_pVModel == NULL)
{
return relseq;
}
Assert( m_pVModel );
virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[baseseq].group ];
return pGroup->masterSeq[ relseq ];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::GetNumPoseParameters( void ) const
{
if (m_pVModel == NULL)
{
return m_pStudioHdr->numlocalposeparameters;
}
Assert( m_pVModel );
return m_pVModel->m_pose.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const mstudioposeparamdesc_t &CStudioHdr::pPoseParameter( int i ) const
{
if (m_pVModel == NULL)
{
return *m_pStudioHdr->pLocalPoseParameter( i );
}
if ( m_pVModel->m_pose[i].group == 0)
return *m_pStudioHdr->pLocalPoseParameter( m_pVModel->m_pose[i].index );
const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_pose[i].group );
return *pStudioHdr->pLocalPoseParameter( m_pVModel->m_pose[i].index );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::GetSharedPoseParameter( int iSequence, int iLocalPose ) const
{
if (m_pVModel == NULL)
{
return iLocalPose;
}
if (iLocalPose == -1)
return iLocalPose;
Assert( m_pVModel );
virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ];
return pGroup->masterPose[iLocalPose];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::EntryNode( int iSequence ) const
{
mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
if (m_pVModel == NULL || seqdesc.localentrynode == 0)
{
return seqdesc.localentrynode;
}
Assert( m_pVModel );
virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ];
return pGroup->masterNode[seqdesc.localentrynode-1]+1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::ExitNode( int iSequence ) const
{
mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence );
if (m_pVModel == NULL || seqdesc.localexitnode == 0)
{
return seqdesc.localexitnode;
}
Assert( m_pVModel );
virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ];
return pGroup->masterNode[seqdesc.localexitnode-1]+1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::GetNumAttachments( void ) const
{
if (m_pVModel == NULL)
{
return m_pStudioHdr->numlocalattachments;
}
Assert( m_pVModel );
return m_pVModel->m_attachment.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const mstudioattachment_t &CStudioHdr::pAttachment( int i ) const
{
if (m_pVModel == NULL)
{
return *m_pStudioHdr->pLocalAttachment( i );
}
Assert( m_pVModel );
const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_attachment[i].group );
return *pStudioHdr->pLocalAttachment( m_pVModel->m_attachment[i].index );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::GetAttachmentBone( int i ) const
{
if (m_pVModel == 0)
{
return m_pStudioHdr->pLocalAttachment( i )->localbone;
}
virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_attachment[i].group ];
const mstudioattachment_t &attachment = pAttachment( i );
int iBone = pGroup->masterBone[attachment.localbone];
if (iBone == -1)
return 0;
return iBone;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CStudioHdr::SetAttachmentBone( int iAttachment, int iBone )
{
mstudioattachment_t &attachment = (mstudioattachment_t &)m_pStudioHdr->pAttachment( iAttachment );
// remap bone
if (m_pVModel)
{
virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_attachment[iAttachment].group ];
iBone = pGroup->boneMap[iBone];
}
attachment.localbone = iBone;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
char *CStudioHdr::pszNodeName( int iNode ) const
{
if (m_pVModel == NULL)
{
return m_pStudioHdr->pszLocalNodeName( iNode );
}
if ( m_pVModel->m_node.Count() <= iNode-1 )
return "Invalid node";
const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_node[iNode-1].group );
return pStudioHdr->pszLocalNodeName( m_pVModel->m_node[iNode-1].index );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::GetTransition( int iFrom, int iTo ) const
{
if (m_pVModel == NULL)
{
return *m_pStudioHdr->pLocalTransition( (iFrom-1)*m_pStudioHdr->numlocalnodes + (iTo - 1) );
}
return iTo;
/*
FIXME: not connected
virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel();
Assert( pVModel );
return pVModel->m_transition.Element( iFrom ).Element( iTo );
*/
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::GetActivityListVersion( void ) const
{
if (m_pVModel == NULL)
{
return m_pStudioHdr->activitylistversion;
}
int version = m_pStudioHdr->activitylistversion;
int i;
for (i = 1; i < m_pVModel->m_group.Count(); i++)
{
const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
Assert( pStudioHdr );
version = MIN( version, pStudioHdr->activitylistversion );
}
return version;
}
void CStudioHdr::SetActivityListVersion( int version )
{
m_pStudioHdr->activitylistversion = version;
if (m_pVModel == NULL)
{
return;
}
int i;
for (i = 1; i < m_pVModel->m_group.Count(); i++)
{
const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
Assert( pStudioHdr );
pStudioHdr->SetActivityListVersion( version );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::GetEventListVersion( void ) const
{
if (m_pVModel == NULL)
{
return m_pStudioHdr->eventsindexed;
}
int version = m_pStudioHdr->eventsindexed;
int i;
for (i = 1; i < m_pVModel->m_group.Count(); i++)
{
const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
Assert( pStudioHdr );
version = MIN( version, pStudioHdr->eventsindexed );
}
return version;
}
void CStudioHdr::SetEventListVersion( int version )
{
m_pStudioHdr->eventsindexed = version;
if (m_pVModel == NULL)
{
return;
}
int i;
for (i = 1; i < m_pVModel->m_group.Count(); i++)
{
const studiohdr_t *pStudioHdr = GroupStudioHdr( i );
Assert( pStudioHdr );
pStudioHdr->eventsindexed = version;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CStudioHdr::GetNumIKAutoplayLocks( void ) const
{
if (m_pVModel == NULL)
{
return m_pStudioHdr->numlocalikautoplaylocks;
}
return m_pVModel->m_iklock.Count();
}
const mstudioiklock_t &CStudioHdr::pIKAutoplayLock( int i ) const
{
if (m_pVModel == NULL)
{
return *m_pStudioHdr->pLocalIKAutoplayLock( i );
}
const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_iklock[i].group );
Assert( pStudioHdr );
return *pStudioHdr->pLocalIKAutoplayLock( m_pVModel->m_iklock[i].index );
}
#if 0
int CStudioHdr::CountAutoplaySequences() const
{
int count = 0;
for (int i = 0; i < GetNumSeq(); i++)
{
mstudioseqdesc_t &seqdesc = pSeqdesc( i );
if (seqdesc.flags & STUDIO_AUTOPLAY)
{
count++;
}
}
return count;
}
int CStudioHdr::CopyAutoplaySequences( unsigned short *pOut, int outCount ) const
{
int outIndex = 0;
for (int i = 0; i < GetNumSeq() && outIndex < outCount; i++)
{
mstudioseqdesc_t &seqdesc = pSeqdesc( i );
if (seqdesc.flags & STUDIO_AUTOPLAY)
{
pOut[outIndex] = i;
outIndex++;
}
}
return outIndex;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: maps local sequence bone to global bone
//-----------------------------------------------------------------------------
int CStudioHdr::RemapSeqBone( int iSequence, int iLocalBone ) const
{
// remap bone
if (m_pVModel)
{
const virtualgroup_t *pSeqGroup = m_pVModel->pSeqGroup( iSequence );
return pSeqGroup->masterBone[iLocalBone];
}
return iLocalBone;
}
int CStudioHdr::RemapAnimBone( int iAnim, int iLocalBone ) const
{
// remap bone
if (m_pVModel)
{
const virtualgroup_t *pAnimGroup = m_pVModel->pAnimGroup( iAnim );
return pAnimGroup->masterBone[iLocalBone];
}
return iLocalBone;
}
// JasonM hack
//ConVar flex_maxrule( "flex_maxrule", "0" );
//-----------------------------------------------------------------------------
// Purpose: run the interpreted FAC's expressions, converting flex_controller
// values into FAC weights
//-----------------------------------------------------------------------------
void CStudioHdr::RunFlexRules( const float *src, float *dest )
{
int i, j;
// FIXME: this shouldn't be needed, flex without rules should be stripped in studiomdl
for (i = 0; i < numflexdesc(); i++)
{
dest[i] = 0;
}
for (i = 0; i < numflexrules(); i++)
{
float stack[32];
int k = 0;
mstudioflexrule_t *prule = pFlexRule( i );
mstudioflexop_t *pops = prule->iFlexOp( 0 );
/*
// JasonM hack for flex perf testing...
int nFlexRulesToRun = 0; // 0 means run them all
const char *pszExpression = flex_maxrule.GetString();
if ( pszExpression )
{
nFlexRulesToRun = atoi(pszExpression); // 0 will be returned if not a numeric string
}
// end JasonM hack
//*/
// debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), i + 1, 0, "%2d:%d\n", i, prule->flex );
for (j = 0; j < prule->numops; j++)
{
switch (pops->op)
{
case STUDIO_ADD: stack[k-2] = stack[k-2] + stack[k-1]; k--; break;
case STUDIO_SUB: stack[k-2] = stack[k-2] - stack[k-1]; k--; break;
case STUDIO_MUL: stack[k-2] = stack[k-2] * stack[k-1]; k--; break;
case STUDIO_DIV:
if (stack[k-1] > 0.0001)
{
stack[k-2] = stack[k-2] / stack[k-1];
}
else
{
stack[k-2] = 0;
}
k--;
break;
case STUDIO_NEG: stack[k-1] = -stack[k-1]; break;
case STUDIO_MAX: stack[k-2] = MAX( stack[k-2], stack[k-1] ); k--; break;
case STUDIO_MIN: stack[k-2] = MIN( stack[k-2], stack[k-1] ); k--; break;
case STUDIO_CONST: stack[k] = pops->d.value; k++; break;
case STUDIO_FETCH1:
{
int m = pFlexcontroller(pops->d.index)->link;
stack[k] = src[m];
k++;
break;
}
case STUDIO_FETCH2: stack[k] = dest[pops->d.index]; k++; break;
}
pops++;
}
dest[prule->flex] = stack[0];
/*
// JasonM hack
if ( nFlexRulesToRun == 0) // 0 means run all rules correctly
{
dest[prule->flex] = stack[0];
}
else // run only up to nFlexRulesToRun correctly...zero out the rest
{
if ( j < nFlexRulesToRun )
dest[prule->flex] = stack[0];
else
dest[prule->flex] = 0.0f;
}
dest[prule->flex] = 1.0f;
//*/
// end JasonM hack
}
}