|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Helper methods + classes for file access
//
//===========================================================================//
#include "tier3/choreoutils.h"
#include "tier3/tier3.h"
#include "SoundEmitterSystem/isoundemittersystembase.h"
#include "studio.h"
#include "../game/shared/choreoscene.h"
#include "../game/shared/choreoevent.h"
#include "tier1/KeyValues.h"
#include "bone_setup.h"
#include "soundchars.h"
//-----------------------------------------------------------------------------
// Find sequence by name
//-----------------------------------------------------------------------------
static int LookupSequence( CStudioHdr *pStudioHdr, const char *pSequenceName ) { for ( int i = 0; i < pStudioHdr->GetNumSeq(); i++ ) { if ( !Q_stricmp( pSequenceName, pStudioHdr->pSeqdesc( i ).pszLabel() ) ) return i; } return -1; }
//-----------------------------------------------------------------------------
// Returns sequence flags
//-----------------------------------------------------------------------------
static int GetSequenceFlags( CStudioHdr *pStudioHdr, int nSequence ) { if ( !pStudioHdr || nSequence < 0 || nSequence >= pStudioHdr->GetNumSeq() ) return 0; mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( nSequence ); return seqdesc.flags; }
//-----------------------------------------------------------------------------
// Does a sequence loop?
//-----------------------------------------------------------------------------
static bool DoesSequenceLoop( CStudioHdr *pStudioHdr, int nSequence ) { int nFlags = GetSequenceFlags( pStudioHdr, nSequence ); bool bLooping = ( nFlags & STUDIO_LOOPING ) ? true : false; return bLooping; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool AutoAddGestureKeys( CChoreoEvent *e, CStudioHdr *pStudioHdr, float *pPoseParameters, bool bCheckOnly ) { int iSequence = LookupSequence( pStudioHdr, e->GetParameters() ); if ( iSequence < 0 ) return false;
KeyValues *pSeqKeyValues = new KeyValues( "" ); if ( !pSeqKeyValues->LoadFromBuffer( pStudioHdr->pszName(), Studio_GetKeyValueText( pStudioHdr, iSequence ) ) ) { pSeqKeyValues->deleteThis(); return false; }
// Do we have a build point section?
KeyValues *pKVAllFaceposer = pSeqKeyValues->FindKey("faceposer"); if ( !pKVAllFaceposer ) { pSeqKeyValues->deleteThis(); return false; }
int nMaxFrame = Studio_MaxFrame( pStudioHdr, iSequence, pPoseParameters ) - 1;
// Start grabbing the sounds and slotting them in
KeyValues *pkvFaceposer; char szStartLoop[CEventAbsoluteTag::MAX_EVENTTAG_LENGTH] = { "loop" }; char szEndLoop[CEventAbsoluteTag::MAX_EVENTTAG_LENGTH] = { "end" }; char szEntry[CEventAbsoluteTag::MAX_EVENTTAG_LENGTH] = { "apex" }; char szExit[CEventAbsoluteTag::MAX_EVENTTAG_LENGTH] = { "end" };
for ( pkvFaceposer = pKVAllFaceposer->GetFirstSubKey(); pkvFaceposer; pkvFaceposer = pkvFaceposer->GetNextKey() ) { if ( !Q_stricmp( pkvFaceposer->GetName(), "startloop" ) ) { Q_strncpy( szStartLoop, pkvFaceposer->GetString(), sizeof(szStartLoop) ); continue; } if ( !Q_stricmp( pkvFaceposer->GetName(), "endloop" ) ) { Q_strncpy( szEndLoop, pkvFaceposer->GetString(), sizeof(szEndLoop) ); continue; } if ( !Q_stricmp( pkvFaceposer->GetName(), "entrytag" ) ) { Q_strncpy( szEntry, pkvFaceposer->GetString(), sizeof(szEntry) ); continue; } if ( !Q_stricmp( pkvFaceposer->GetName(), "exittag" ) ) { Q_strncpy( szExit, pkvFaceposer->GetString(), sizeof(szExit) ); continue; } if ( !Q_stricmp( pkvFaceposer->GetName(), "tags" ) ) { if ( nMaxFrame <= 0 ) continue;
KeyValues *pkvTags; for ( pkvTags = pkvFaceposer->GetFirstSubKey(); pkvTags; pkvTags = pkvTags->GetNextKey() ) { float flPercentage = (float)pkvTags->GetInt() / nMaxFrame;
CEventAbsoluteTag *ptag = e->FindAbsoluteTag( CChoreoEvent::ORIGINAL, pkvTags->GetName() ); if (ptag) { // reposition tag
ptag->SetPercentage( flPercentage ); } else { e->AddAbsoluteTag( CChoreoEvent::ORIGINAL, pkvTags->GetName(), flPercentage ); e->AddAbsoluteTag( CChoreoEvent::PLAYBACK, pkvTags->GetName(), flPercentage ); } // lock the original tags so they can't be edited
ptag = e->FindAbsoluteTag( CChoreoEvent::ORIGINAL, pkvTags->GetName() ); Assert( ptag ); ptag->SetLocked( true ); } e->VerifyTagOrder(); e->PreventTagOverlap(); continue; } }
// FIXME: lookup linear tags in sequence data
{ CEventAbsoluteTag *ptag; ptag = e->FindAbsoluteTag( CChoreoEvent::ORIGINAL, szStartLoop ); if (ptag) { ptag->SetLinear( true ); } ptag = e->FindAbsoluteTag( CChoreoEvent::PLAYBACK, szStartLoop ); if (ptag) { ptag->SetLinear( true ); } ptag = e->FindAbsoluteTag( CChoreoEvent::ORIGINAL, szEndLoop ); if (ptag) { ptag->SetLinear( true ); } ptag = e->FindAbsoluteTag( CChoreoEvent::PLAYBACK, szEndLoop ); if (ptag) { ptag->SetLinear( true ); }
ptag = e->FindAbsoluteTag( CChoreoEvent::ORIGINAL, szEntry ); if (ptag) { ptag->SetEntry( true ); } ptag = e->FindAbsoluteTag( CChoreoEvent::PLAYBACK, szEntry ); if (ptag) { ptag->SetEntry( true ); } ptag = e->FindAbsoluteTag( CChoreoEvent::ORIGINAL, szExit ); if (ptag) { ptag->SetExit( true ); } ptag = e->FindAbsoluteTag( CChoreoEvent::PLAYBACK, szExit ); if (ptag) { ptag->SetExit( true ); } }
pSeqKeyValues->deleteThis(); return true; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool UpdateGestureLength( CChoreoEvent *e, CStudioHdr *pStudioHdr, float *pPoseParameters, bool bCheckOnly ) { Assert( e ); if ( !e ) return false;
if ( e->GetType() != CChoreoEvent::GESTURE ) return false;
int iSequence = LookupSequence( pStudioHdr, e->GetParameters() ); if ( iSequence < 0 ) return false;
bool bChanged = false; float flSeqDuration = Studio_Duration( pStudioHdr, iSequence, pPoseParameters ); float flCurDuration; e->GetGestureSequenceDuration( flCurDuration ); if ( flSeqDuration != 0.0f && flSeqDuration != flCurDuration ) { bChanged = true; if ( !bCheckOnly ) { e->SetGestureSequenceDuration( flSeqDuration ); } }
return bChanged; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool UpdateSequenceLength( CChoreoEvent *e, CStudioHdr *pStudioHdr, float *pPoseParameters, bool bCheckOnly, bool bVerbose ) { Assert( e ); if ( !e ) return false;
if ( e->GetType() != CChoreoEvent::SEQUENCE ) { if ( bVerbose ) { ConMsg( "UpdateSequenceLength: called on non-SEQUENCE event %s\n", e->GetName() ); } return false; }
int iSequence = LookupSequence( pStudioHdr, e->GetParameters() ); if ( iSequence < 0 ) return false;
bool bChanged = false; bool bLooping = DoesSequenceLoop( pStudioHdr, iSequence ); float flSeqDuration = Studio_Duration( pStudioHdr, iSequence, pPoseParameters );
if ( bLooping ) { if ( e->IsFixedLength() ) { if ( bCheckOnly ) return true; if ( bVerbose ) { ConMsg( "UpdateSequenceLength: %s is looping, removing fixed length flag\n", e->GetName() ); } bChanged = true; } e->SetFixedLength( false );
if ( !e->HasEndTime() ) { if ( bCheckOnly ) return true;
if ( bVerbose ) { ConMsg( "CheckSequenceLength: %s is looping, setting default end time\n", e->GetName() ); } e->SetEndTime( e->GetStartTime() + flSeqDuration ); bChanged = true; }
return bChanged; }
if ( !e->IsFixedLength() ) { if ( bCheckOnly ) return true;
if ( bVerbose ) { ConMsg( "CheckSequenceLength: %s is fixed length, removing looping flag\n", e->GetName() ); } bChanged = true; } e->SetFixedLength( true );
if ( e->HasEndTime() ) { float dt = e->GetDuration(); if ( fabs( dt - flSeqDuration ) > 0.01f ) { if ( bCheckOnly ) return true; if ( bVerbose ) { ConMsg( "CheckSequenceLength: %s has wrong duration, changing length from %f to %f seconds\n", e->GetName(), dt, flSeqDuration ); } bChanged = true; } } else { if ( bCheckOnly ) return true; if ( bVerbose ) { ConMsg( "CheckSequenceLength: %s has wrong duration, changing length to %f seconds\n", e->GetName(), flSeqDuration ); } bChanged = true; }
if ( !bCheckOnly ) { e->SetEndTime( e->GetStartTime() + flSeqDuration ); }
return bChanged; }
//-----------------------------------------------------------------------------
// Finds sound files associated with events
//-----------------------------------------------------------------------------
const char *GetSoundForEvent( CChoreoEvent *pEvent, CStudioHdr *pStudioHdr ) { const char *pSoundName = pEvent->GetParameters(); if ( Q_stristr( pSoundName, ".wav" ) ) return PSkipSoundChars( pSoundName );
const char *pFileName = g_pSoundEmitterSystem->GetWavFileForSound( pSoundName, ( pStudioHdr && pStudioHdr->IsValid() ) ? pStudioHdr->pszName() : NULL ); return PSkipSoundChars( pFileName ); }
|