aboutsummaryrefslogtreecommitdiff
path: root/mp/src/public/posedebugger.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/public/posedebugger.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/public/posedebugger.cpp')
-rw-r--r--mp/src/public/posedebugger.cpp1310
1 files changed, 655 insertions, 655 deletions
diff --git a/mp/src/public/posedebugger.cpp b/mp/src/public/posedebugger.cpp
index c0e72c3d..b8a7d1ed 100644
--- a/mp/src/public/posedebugger.cpp
+++ b/mp/src/public/posedebugger.cpp
@@ -1,655 +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 < MAX_EDICTS );
- if ( iEntNum < MAX_EDICTS )
- m_uiMaskShowModels.Set( iEntNum, bShow );
-}
-
-bool CPoseDebuggerImpl::IsModelShown( int iEntNum ) const
-{
- Assert( 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 );
+//========= 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 < MAX_EDICTS );
+ if ( iEntNum < MAX_EDICTS )
+ m_uiMaskShowModels.Set( iEntNum, bShow );
+}
+
+bool CPoseDebuggerImpl::IsModelShown( int iEntNum ) const
+{
+ Assert( 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 );