From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/public/posedebugger.cpp | 1310 ++++++++++++++++++++-------------------- 1 file changed, 655 insertions(+), 655 deletions(-) (limited to 'mp/src/public/posedebugger.cpp') 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 ); -- cgit v1.2.3