1
This commit is contained in:
655
public/posedebugger.cpp
Normal file
655
public/posedebugger.cpp
Normal file
@ -0,0 +1,655 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "tier0/tslist.h"
|
||||
#include "tier1/utlmap.h"
|
||||
#include "tier1/convar.h"
|
||||
|
||||
#include "bone_setup.h"
|
||||
|
||||
#include "con_nprint.h"
|
||||
#include "cdll_int.h"
|
||||
#include "globalvars_base.h"
|
||||
|
||||
#include "posedebugger.h"
|
||||
|
||||
#include "iclientnetworkable.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
extern IVEngineClient *engine;
|
||||
extern CGlobalVarsBase *gpGlobals;
|
||||
|
||||
static ConVar ui_posedebug_fade_in_time( "ui_posedebug_fade_in_time", "0.2",
|
||||
FCVAR_CHEAT | FCVAR_DONTRECORD,
|
||||
"Time during which a new pose activity layer is shown in green in +posedebug UI" );
|
||||
static ConVar ui_posedebug_fade_out_time( "ui_posedebug_fade_out_time", "0.8",
|
||||
FCVAR_CHEAT | FCVAR_DONTRECORD,
|
||||
"Time to keep a no longer active pose activity layer in red until removing it from +posedebug UI" );
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CPoseDebuggerStub : IPoseDebugger
|
||||
// empty interface implementation
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CPoseDebuggerStub : public IPoseDebugger
|
||||
{
|
||||
public:
|
||||
virtual void StartBlending( IClientNetworkable *pEntity, const CStudioHdr *pStudioHdr ) { }
|
||||
virtual void AccumulatePose(
|
||||
const CStudioHdr *pStudioHdr,
|
||||
CIKContext *pIKContext,
|
||||
Vector pos[],
|
||||
Quaternion q[],
|
||||
int sequence,
|
||||
float cycle,
|
||||
const float poseParameter[],
|
||||
int boneMask,
|
||||
float flWeight,
|
||||
float flTime
|
||||
) { }
|
||||
};
|
||||
|
||||
static CPoseDebuggerStub s_PoseDebuggerStub;
|
||||
IPoseDebugger *g_pPoseDebugger = &s_PoseDebuggerStub;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CPoseDebuggerImpl : IPoseDebugger
|
||||
// Purpose: Main implementation of the pose debugger
|
||||
// Declaration
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ModelPoseDebugInfo
|
||||
{
|
||||
public:
|
||||
ModelPoseDebugInfo() : m_iEntNum( 0 ), m_iCurrentText( 0 ) { }
|
||||
|
||||
|
||||
public:
|
||||
// Entity number
|
||||
int m_iEntNum;
|
||||
|
||||
// Currently processed text
|
||||
int m_iCurrentText;
|
||||
|
||||
// Info Text Flags
|
||||
enum InfoTextFlags
|
||||
{
|
||||
F_SEEN_THIS_FRAME = 1 << 0,
|
||||
F_SEEN_LAST_FRAME = 1 << 1,
|
||||
};
|
||||
|
||||
struct InfoText
|
||||
{
|
||||
InfoText() { memset( this, 0, sizeof( *this ) ); }
|
||||
|
||||
// Flags
|
||||
uint32 m_uiFlags;
|
||||
|
||||
// Time seen
|
||||
float m_flTimeToLive, m_flTimeAlive;
|
||||
|
||||
// Activity/label
|
||||
int m_iActivity;
|
||||
char m_chActivity[100];
|
||||
char m_chLabel[100];
|
||||
|
||||
// Text
|
||||
char m_chTextLines[4][256];
|
||||
enum
|
||||
{
|
||||
MAX_TEXT_LINES = 4
|
||||
};
|
||||
};
|
||||
|
||||
CCopyableUtlVector< InfoText > m_arrTxt;
|
||||
|
||||
|
||||
public:
|
||||
// Add an info text
|
||||
void AddInfoText( InfoText *x, ModelPoseDebugInfo *pOld );
|
||||
|
||||
// Lookup an info text
|
||||
InfoText *LookupInfoText( InfoText *x );
|
||||
|
||||
// Print pending info text
|
||||
void PrintPendingInfoText( int &rnPosPrint );
|
||||
};
|
||||
|
||||
void ModelPoseDebugInfo::AddInfoText( InfoText *x, ModelPoseDebugInfo *pOld )
|
||||
{
|
||||
if ( x )
|
||||
{
|
||||
// Try to set the proper flags on the info text
|
||||
x->m_uiFlags &= ~F_SEEN_LAST_FRAME;
|
||||
x->m_uiFlags |= F_SEEN_THIS_FRAME;
|
||||
}
|
||||
|
||||
// If we have smth to compare against
|
||||
if ( pOld )
|
||||
{
|
||||
// Search for the same activity/label in the other model pose debug info
|
||||
ModelPoseDebugInfo &o = *pOld;
|
||||
int k = o.m_iCurrentText;
|
||||
if ( x )
|
||||
{
|
||||
for ( ; k < o.m_arrTxt.Count(); ++ k )
|
||||
{
|
||||
InfoText &txt = o.m_arrTxt[k];
|
||||
if ( ( txt.m_uiFlags & F_SEEN_THIS_FRAME ) &&
|
||||
!stricmp( x->m_chActivity, txt.m_chActivity ) &&
|
||||
!stricmp( x->m_chLabel, txt.m_chLabel ) &&
|
||||
( x->m_iActivity == txt.m_iActivity ) )
|
||||
{
|
||||
x->m_flTimeAlive = txt.m_flTimeAlive;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
k = o.m_arrTxt.Count();
|
||||
}
|
||||
|
||||
// Range of finished activities
|
||||
int iFinishedRange[2] = { o.m_iCurrentText, k };
|
||||
|
||||
// Check whether this is a new message
|
||||
if ( k == o.m_arrTxt.Count() )
|
||||
{
|
||||
if ( !x )
|
||||
{
|
||||
o.m_iCurrentText = k;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't update the current when insertion happens and don't have finished commands
|
||||
iFinishedRange[1] = iFinishedRange[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
o.m_iCurrentText = k + 1;
|
||||
if ( x )
|
||||
{
|
||||
x->m_uiFlags |= F_SEEN_LAST_FRAME;
|
||||
x->m_flTimeAlive += gpGlobals->frametime;
|
||||
}
|
||||
}
|
||||
|
||||
// Everything before finished
|
||||
for ( int iFinished = iFinishedRange[0]; iFinished < iFinishedRange[1]; ++ iFinished )
|
||||
{
|
||||
InfoText &txtFinished = o.m_arrTxt[ iFinished ];
|
||||
|
||||
if ( txtFinished.m_uiFlags & F_SEEN_THIS_FRAME )
|
||||
txtFinished.m_uiFlags |= F_SEEN_LAST_FRAME;
|
||||
|
||||
txtFinished.m_uiFlags &= ~F_SEEN_THIS_FRAME;
|
||||
|
||||
txtFinished.m_flTimeToLive -= gpGlobals->frametime;
|
||||
txtFinished.m_flTimeAlive += gpGlobals->frametime;
|
||||
|
||||
if ( txtFinished.m_flTimeToLive >= 0.0f )
|
||||
m_arrTxt.AddToTail( txtFinished );
|
||||
}
|
||||
}
|
||||
|
||||
if ( x )
|
||||
{
|
||||
// Now add it to the array
|
||||
x->m_flTimeToLive = ui_posedebug_fade_out_time.GetFloat();
|
||||
m_arrTxt.AddToTail( *x );
|
||||
}
|
||||
}
|
||||
|
||||
ModelPoseDebugInfo::InfoText * ModelPoseDebugInfo::LookupInfoText( InfoText *x )
|
||||
{
|
||||
int k = m_iCurrentText;
|
||||
if ( x )
|
||||
{
|
||||
for ( ; k < m_arrTxt.Count(); ++ k )
|
||||
{
|
||||
InfoText &txt = m_arrTxt[k];
|
||||
if ( ( txt.m_uiFlags & F_SEEN_THIS_FRAME ) &&
|
||||
!stricmp( x->m_chActivity, txt.m_chActivity ) &&
|
||||
!stricmp( x->m_chLabel, txt.m_chLabel ) &&
|
||||
( x->m_iActivity == txt.m_iActivity ) )
|
||||
{
|
||||
return &txt;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ModelPoseDebugInfo::PrintPendingInfoText( int &rnPosPrint )
|
||||
{
|
||||
con_nprint_s nxPrn = { 0 };
|
||||
nxPrn.time_to_live = -1;
|
||||
nxPrn.color[0] = 1.0f, nxPrn.color[1] = 1.0f, nxPrn.color[2] = 1.0f;
|
||||
nxPrn.fixed_width_font = true;
|
||||
|
||||
float const flFadeInTime = ui_posedebug_fade_in_time.GetFloat();
|
||||
float const flFadeOutTime = ui_posedebug_fade_out_time.GetFloat();
|
||||
|
||||
// Now print all the accumulated spew
|
||||
for ( int k = m_iCurrentText; k < m_arrTxt.Count(); ++ k )
|
||||
{
|
||||
InfoText &prntxt = m_arrTxt[k];
|
||||
|
||||
switch( prntxt.m_uiFlags & ( F_SEEN_LAST_FRAME | F_SEEN_THIS_FRAME ) )
|
||||
{
|
||||
case ( F_SEEN_LAST_FRAME | F_SEEN_THIS_FRAME ) :
|
||||
nxPrn.color[0] = 1.f;
|
||||
nxPrn.color[1] = 1.f;
|
||||
nxPrn.color[2] = 1.f;
|
||||
if ( prntxt.m_flTimeAlive > flFadeInTime )
|
||||
break;
|
||||
else
|
||||
NULL; // Fall-through to keep showing in green
|
||||
case F_SEEN_THIS_FRAME :
|
||||
if ( flFadeInTime > 0.f )
|
||||
{
|
||||
nxPrn.color[0] = 1.f * prntxt.m_flTimeAlive / flFadeInTime;
|
||||
nxPrn.color[1] = 1.f;
|
||||
nxPrn.color[2] = 1.f * prntxt.m_flTimeAlive / flFadeInTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
nxPrn.color[0] = ( prntxt.m_flTimeAlive > 0.0f ) ? 1.f : 0.f;
|
||||
nxPrn.color[1] = 1.f;
|
||||
nxPrn.color[2] = ( prntxt.m_flTimeAlive > 0.0f ) ? 1.f : 0.f;
|
||||
}
|
||||
break;
|
||||
case F_SEEN_LAST_FRAME :
|
||||
case 0:
|
||||
if ( flFadeOutTime > 0.f )
|
||||
nxPrn.color[0] = 1.f * prntxt.m_flTimeToLive / flFadeOutTime;
|
||||
else
|
||||
nxPrn.color[0] = ( prntxt.m_flTimeToLive > 0.0f ) ? 1.f : 0.f;
|
||||
nxPrn.color[1] = 0.f;
|
||||
nxPrn.color[2] = 0.f;
|
||||
break;
|
||||
}
|
||||
|
||||
nxPrn.index = ( rnPosPrint += 1 );
|
||||
engine->Con_NXPrintf( &nxPrn, "%s", prntxt.m_chTextLines[0] );
|
||||
|
||||
for ( int iLine = 1; iLine < ModelPoseDebugInfo::InfoText::MAX_TEXT_LINES; ++ iLine)
|
||||
{
|
||||
if ( !prntxt.m_chTextLines[iLine][0] )
|
||||
break;
|
||||
|
||||
nxPrn.index = ( rnPosPrint += 1 );
|
||||
engine->Con_NXPrintf( &nxPrn, "%s", prntxt.m_chTextLines[iLine] );
|
||||
}
|
||||
}
|
||||
|
||||
m_iCurrentText = m_arrTxt.Count();
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CPoseDebuggerImpl : public IPoseDebugger
|
||||
{
|
||||
public:
|
||||
CPoseDebuggerImpl();
|
||||
~CPoseDebuggerImpl();
|
||||
|
||||
public:
|
||||
void ShowAllModels( bool bShow );
|
||||
void ShowModel( int iEntNum, bool bShow );
|
||||
bool IsModelShown( int iEntNum ) const;
|
||||
|
||||
public:
|
||||
virtual void StartBlending( IClientNetworkable *pEntity, const CStudioHdr *pStudioHdr );
|
||||
virtual void AccumulatePose(
|
||||
const CStudioHdr *pStudioHdr,
|
||||
CIKContext *pIKContext,
|
||||
Vector pos[],
|
||||
Quaternion q[],
|
||||
int sequence,
|
||||
float cycle,
|
||||
const float poseParameter[],
|
||||
int boneMask,
|
||||
float flWeight,
|
||||
float flTime
|
||||
);
|
||||
|
||||
protected:
|
||||
typedef CUtlMap< CStudioHdr const *, ModelPoseDebugInfo > MapModel;
|
||||
MapModel m_mapModel, m_mapModelOld;
|
||||
int m_nPosPrint;
|
||||
|
||||
CBitVec< MAX_EDICTS > m_uiMaskShowModels;
|
||||
|
||||
CStudioHdr const *m_pLastModel;
|
||||
};
|
||||
|
||||
static CPoseDebuggerImpl s_PoseDebuggerImpl;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CPoseDebuggerImpl
|
||||
// Implementation
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CPoseDebuggerImpl::CPoseDebuggerImpl() :
|
||||
m_mapModel( DefLessFunc( CStudioHdr const * ) ),
|
||||
m_mapModelOld( DefLessFunc( CStudioHdr const * ) ),
|
||||
m_nPosPrint( 0 ),
|
||||
m_pLastModel( NULL )
|
||||
{
|
||||
m_uiMaskShowModels.SetAll();
|
||||
}
|
||||
|
||||
CPoseDebuggerImpl::~CPoseDebuggerImpl()
|
||||
{
|
||||
// g_pPoseDebugger = &s_PoseDebuggerStub;
|
||||
}
|
||||
|
||||
void CPoseDebuggerImpl::ShowAllModels( bool bShow )
|
||||
{
|
||||
bShow ? m_uiMaskShowModels.SetAll() : m_uiMaskShowModels.ClearAll();
|
||||
}
|
||||
|
||||
void CPoseDebuggerImpl::ShowModel( int iEntNum, bool bShow )
|
||||
{
|
||||
Assert( iEntNum >= 0 && iEntNum < MAX_EDICTS );
|
||||
if ( iEntNum >= 0 && iEntNum < MAX_EDICTS )
|
||||
m_uiMaskShowModels.Set( iEntNum, bShow );
|
||||
}
|
||||
|
||||
bool CPoseDebuggerImpl::IsModelShown( int iEntNum ) const
|
||||
{
|
||||
Assert( iEntNum >= 0 && iEntNum < MAX_EDICTS );
|
||||
if ( iEntNum >= 0 && iEntNum < MAX_EDICTS )
|
||||
return m_uiMaskShowModels.IsBitSet( iEntNum );
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPoseDebuggerImpl::StartBlending( IClientNetworkable *pEntity, const CStudioHdr *pStudioHdr )
|
||||
{
|
||||
// virtualmodel_t const *pVMdl = pStudioHdr->GetVirtualModel();
|
||||
// if ( !pVMdl )
|
||||
// return;
|
||||
|
||||
// If we are starting a new model then finalize the previous one
|
||||
if ( pStudioHdr != m_pLastModel && m_pLastModel )
|
||||
{
|
||||
MapModel::IndexType_t idx = m_mapModel.Find( m_pLastModel );
|
||||
if ( idx != m_mapModel.InvalidIndex() )
|
||||
{
|
||||
ModelPoseDebugInfo &mpi = m_mapModel.Element( idx );
|
||||
ModelPoseDebugInfo *pMpiOld = NULL;
|
||||
MapModel::IndexType_t idxMapModelOld = m_mapModelOld.Find( m_pLastModel );
|
||||
if ( idxMapModelOld != m_mapModelOld.InvalidIndex() )
|
||||
{
|
||||
pMpiOld = &m_mapModelOld.Element( idxMapModelOld );
|
||||
}
|
||||
mpi.AddInfoText( NULL, pMpiOld );
|
||||
mpi.PrintPendingInfoText( m_nPosPrint );
|
||||
}
|
||||
}
|
||||
m_pLastModel = pStudioHdr;
|
||||
|
||||
// Go ahead with the new model
|
||||
studiohdr_t const *pRMdl = pStudioHdr->GetRenderHdr();
|
||||
if ( !pRMdl ||
|
||||
!pRMdl->numincludemodels )
|
||||
return;
|
||||
|
||||
// Entity number
|
||||
int iEntNum = pEntity->entindex();
|
||||
if ( !IsModelShown( iEntNum ) )
|
||||
return;
|
||||
|
||||
// Check if we saw the model
|
||||
if ( m_mapModel.Find( pStudioHdr ) != m_mapModel.InvalidIndex() )
|
||||
{
|
||||
// Initialize the printing position
|
||||
m_nPosPrint = 9;
|
||||
|
||||
// Swap the maps
|
||||
m_mapModelOld.RemoveAll();
|
||||
m_mapModelOld.Swap( m_mapModel );
|
||||
|
||||
// Zero out the text on the old map
|
||||
for ( int k = m_mapModelOld.FirstInorder();
|
||||
k != m_mapModelOld.InvalidIndex();
|
||||
k = m_mapModelOld.NextInorder( k ) )
|
||||
{
|
||||
ModelPoseDebugInfo &mpi = m_mapModelOld[k];
|
||||
mpi.m_iCurrentText = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Next model
|
||||
m_nPosPrint += 3;
|
||||
}
|
||||
|
||||
ModelPoseDebugInfo mpi;
|
||||
mpi.m_iEntNum = iEntNum;
|
||||
m_mapModel.Insert( pStudioHdr, mpi );
|
||||
|
||||
con_nprint_s nxPrn = { 0 };
|
||||
nxPrn.index = m_nPosPrint;
|
||||
nxPrn.time_to_live = -1;
|
||||
nxPrn.color[0] = 0.9f, nxPrn.color[1] = 1.0f, nxPrn.color[2] = 0.9f;
|
||||
nxPrn.fixed_width_font = false;
|
||||
|
||||
engine->Con_NXPrintf( &nxPrn, "[ %2d ] Model: %s", iEntNum, pRMdl->pszName() );
|
||||
m_nPosPrint += 3;
|
||||
}
|
||||
|
||||
void CPoseDebuggerImpl::AccumulatePose( const CStudioHdr *pStudioHdr, CIKContext *pIKContext,
|
||||
Vector pos[], Quaternion q[], int sequence, float cycle,
|
||||
const float poseParameter[], int boneMask,
|
||||
float flWeight, float flTime )
|
||||
{
|
||||
// virtualmodel_t const *pVMdl = pStudioHdr->GetVirtualModel();
|
||||
// if ( !pVMdl )
|
||||
// return;
|
||||
|
||||
studiohdr_t const *pRMdl = pStudioHdr->GetRenderHdr();
|
||||
if ( !pRMdl ||
|
||||
!pRMdl->numincludemodels )
|
||||
return;
|
||||
|
||||
MapModel::IndexType_t idxMapModel = m_mapModel.Find( pStudioHdr );
|
||||
if ( idxMapModel == m_mapModel.InvalidIndex() )
|
||||
return;
|
||||
|
||||
ModelPoseDebugInfo &mpi = m_mapModel.Element( idxMapModel );
|
||||
if ( !IsModelShown( mpi.m_iEntNum ) )
|
||||
return;
|
||||
|
||||
ModelPoseDebugInfo *pMpiOld = NULL;
|
||||
MapModel::IndexType_t idxMapModelOld = m_mapModelOld.Find( pStudioHdr );
|
||||
if ( idxMapModelOld != m_mapModelOld.InvalidIndex() )
|
||||
{
|
||||
pMpiOld = &m_mapModelOld.Element( idxMapModelOld );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Actual processing
|
||||
//
|
||||
|
||||
mstudioseqdesc_t &seqdesc = ((CStudioHdr *)pStudioHdr)->pSeqdesc( sequence );
|
||||
|
||||
if ( sequence >= pStudioHdr->GetNumSeq() )
|
||||
{
|
||||
sequence = 0;
|
||||
seqdesc = ((CStudioHdr *)pStudioHdr)->pSeqdesc( sequence );
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
widthActivity = 35,
|
||||
widthLayer = 35,
|
||||
widthIks = 60,
|
||||
widthPercent = 6,
|
||||
};
|
||||
|
||||
// Prepare the text
|
||||
char chBuffer[256];
|
||||
ModelPoseDebugInfo::InfoText txt;
|
||||
int numLines = 0;
|
||||
|
||||
txt.m_iActivity = seqdesc.activity;
|
||||
sprintf( txt.m_chActivity, "%s", seqdesc.pszActivityName() );
|
||||
sprintf( txt.m_chLabel, "%s", seqdesc.pszLabel() );
|
||||
|
||||
if ( !txt.m_chActivity[0] )
|
||||
{
|
||||
// Try to find the last seen activity and re-use it
|
||||
for ( int iLast = mpi.m_arrTxt.Count(); iLast --> 0; )
|
||||
{
|
||||
ModelPoseDebugInfo::InfoText &lastSeenTxt = mpi.m_arrTxt[iLast];
|
||||
if ( lastSeenTxt.m_uiFlags & ModelPoseDebugInfo::F_SEEN_THIS_FRAME &&
|
||||
lastSeenTxt.m_chActivity[0] )
|
||||
{
|
||||
sprintf( txt.m_chActivity, "%s", lastSeenTxt.m_chActivity );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The layer information
|
||||
ModelPoseDebugInfo::InfoText *pOldTxt = pMpiOld ? pMpiOld->LookupInfoText( &txt ) : NULL;
|
||||
sprintf( txt.m_chTextLines[numLines],
|
||||
"%-*s %-*s %*.2f %*.1f/%-*d %*.0f%% ",
|
||||
widthActivity,
|
||||
seqdesc.pszActivityName(),
|
||||
widthLayer,
|
||||
seqdesc.pszLabel(),
|
||||
7,
|
||||
pOldTxt ? pOldTxt->m_flTimeAlive : 0.f,
|
||||
5,
|
||||
cycle * ( ((CStudioHdr *)pStudioHdr)->pAnimdesc( seqdesc.anim( 0, 0 ) ).numframes - 1 ),
|
||||
3,
|
||||
((CStudioHdr *)pStudioHdr)->pAnimdesc( seqdesc.anim( 0, 0 ) ).numframes,
|
||||
widthPercent,
|
||||
flWeight * 100.0f
|
||||
);
|
||||
++ numLines;
|
||||
|
||||
if ( seqdesc.numiklocks )
|
||||
{
|
||||
sprintf( chBuffer,
|
||||
"iklocks : %-2d : ",
|
||||
seqdesc.numiklocks );
|
||||
|
||||
for ( int k = 0; k < seqdesc.numiklocks; ++ k )
|
||||
{
|
||||
mstudioiklock_t *plock = seqdesc.pIKLock( k );
|
||||
mstudioikchain_t *pchain = pStudioHdr->pIKChain( plock->chain );
|
||||
|
||||
sprintf( chBuffer + strlen( chBuffer ), "%s ", pchain->pszName() );
|
||||
// plock->flPosWeight;
|
||||
// plock->flLocalQWeight;
|
||||
}
|
||||
|
||||
sprintf( txt.m_chTextLines[numLines],
|
||||
"%-*s",
|
||||
widthIks,
|
||||
chBuffer
|
||||
);
|
||||
++ numLines;
|
||||
}
|
||||
|
||||
if ( seqdesc.numikrules )
|
||||
{
|
||||
sprintf( chBuffer, "ikrules : %-2d",
|
||||
seqdesc.numikrules );
|
||||
|
||||
sprintf( txt.m_chTextLines[numLines],
|
||||
"%-*s",
|
||||
widthIks,
|
||||
chBuffer
|
||||
);
|
||||
++ numLines;
|
||||
}
|
||||
|
||||
|
||||
// Now add the accumulated text into the container
|
||||
mpi.AddInfoText( &txt, pMpiOld );
|
||||
mpi.PrintPendingInfoText( m_nPosPrint );
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Con-commands
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void IN_PoseDebuggerStart( const CCommand &args )
|
||||
{
|
||||
if ( args.ArgC() <= 1 )
|
||||
{
|
||||
// No args, enable all
|
||||
s_PoseDebuggerImpl.ShowAllModels( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If explicitly showing the pose debugger when it was disabled
|
||||
if ( g_pPoseDebugger != &s_PoseDebuggerImpl )
|
||||
{
|
||||
s_PoseDebuggerImpl.ShowAllModels( false );
|
||||
}
|
||||
|
||||
// Show only specific models
|
||||
for ( int k = 1; k < args.ArgC(); ++ k )
|
||||
{
|
||||
int iEntNum = atoi( args.Arg( k ) );
|
||||
s_PoseDebuggerImpl.ShowModel( iEntNum, true );
|
||||
}
|
||||
}
|
||||
|
||||
g_pPoseDebugger = &s_PoseDebuggerImpl;
|
||||
}
|
||||
|
||||
static void IN_PoseDebuggerEnd( const CCommand &args )
|
||||
{
|
||||
if ( args.ArgC() <= 1 )
|
||||
{
|
||||
// No args, disable all
|
||||
s_PoseDebuggerImpl.ShowAllModels( false );
|
||||
|
||||
// Set the stub pointer
|
||||
g_pPoseDebugger = &s_PoseDebuggerStub;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide only specific models
|
||||
for ( int k = 1; k < args.ArgC(); ++ k )
|
||||
{
|
||||
int iEntNum = atoi( args.Arg( k ) );
|
||||
s_PoseDebuggerImpl.ShowModel( iEntNum, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand posedebuggerstart( "+posedebug", IN_PoseDebuggerStart, "Turn on pose debugger or add ents to pose debugger UI", FCVAR_CHEAT );
|
||||
static ConCommand posedebuggerend ( "-posedebug", IN_PoseDebuggerEnd, "Turn off pose debugger or hide ents from pose debugger UI", FCVAR_CHEAT );
|
Reference in New Issue
Block a user