|
|
//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
// Client-side CBasePlayer
#ifndef C_STUDIOFLEX_H
#define C_STUDIOFLEX_H
#pragma once
#include "c_baseanimatingoverlay.h"
#include "sceneentity_shared.h"
#include "utlvector.h"
//-----------------------------------------------------------------------------
// Purpose: Item in list of loaded scene files
//-----------------------------------------------------------------------------
class CFlexSceneFile { public: enum { MAX_FLEX_FILENAME = 128, };
char filename[ MAX_FLEX_FILENAME ]; void *buffer; };
// For phoneme emphasis track
struct Emphasized_Phoneme; class CSentence;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_BaseFlex : public C_BaseAnimatingOverlay { DECLARE_CLASS( C_BaseFlex, C_BaseAnimatingOverlay ); public: DECLARE_CLIENTCLASS(); DECLARE_PREDICTABLE(); DECLARE_INTERPOLATION();
C_BaseFlex(); virtual ~C_BaseFlex();
virtual void Spawn();
virtual IClientModelRenderable* GetClientModelRenderable();
virtual void InitPhonemeMappings();
void SetupMappings( char const *pchFileRoot );
virtual CStudioHdr *OnNewModel( void );
virtual void StandardBlendingRules( CStudioHdr *hdr, BoneVector pos[], BoneQuaternionAligned q[], float currentTime, int boneMask );
virtual void OnThreadedDrawSetup();
// model specific
virtual void BuildTransformations( CStudioHdr *pStudioHdr, BoneVector *pos, BoneQuaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed ); virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights ); virtual bool UsesFlexDelayedWeights();
virtual bool GetSoundSpatialization( SpatializationInfo_t& info );
virtual void GetToolRecordingState( KeyValues *msg );
// Called at the lowest level to actually apply a flex animation
void AddFlexAnimation( CSceneEventInfo *info );
void SetFlexWeight( LocalFlexController_t index, float value ); float GetFlexWeight( LocalFlexController_t index );
// Look up flex controller index by global name
LocalFlexController_t FindFlexController( const char *szName );
public: Vector m_viewtarget; CInterpolatedVar< Vector > m_iv_viewtarget; // indexed by model local flexcontroller
float m_flexWeight[MAXSTUDIOFLEXCTRL]; CInterpolatedVarArray< float, MAXSTUDIOFLEXCTRL > m_iv_flexWeight;
int m_blinktoggle;
static int AddGlobalFlexController( char *szName ); static char const *GetGlobalFlexControllerName( int idx );
// bah, this should be unified with all prev/current stuff.
public:
// Keep track of what scenes are being played
void StartChoreoScene( CChoreoScene *scene ); void RemoveChoreoScene( CChoreoScene *scene );
// Start the specifics of an scene event
virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, C_BaseEntity *pTarget );
virtual bool ProcessSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
// Remove all playing events
void ClearSceneEvents( CChoreoScene *scene, bool canceled );
// Stop specifics of event
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
// Add the event to the queue for this actor
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, C_BaseEntity *pTarget = NULL, bool bClientSide = false, C_SceneEntity *pSceneEntity = NULL );
// Remove the event from the queue for this actor
void RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill );
// Checks to see if the event should be considered "completed"
bool CheckSceneEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event );
// Checks to see if a event should be considered "completed"
virtual bool CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event );
int FlexControllerLocalToGlobal( const flexsettinghdr_t *pSettinghdr, int key ); void EnsureTranslations( const flexsettinghdr_t *pSettinghdr );
// For handling scene files
const void *FindSceneFile( const char *filename );
static void InvalidateFlexCaches(); bool IsFlexCacheValid() const;
private: Vector SetViewTarget( CStudioHdr *pStudioHdr, const float *pGlobalFlexWeight ); void RunFlexRules( CStudioHdr *pStudioHdr, const float *pGlobalFlexWeight, float *dest );
// Manipulation of events for the object
// Should be called by think function to process all scene events
// The default implementation resets m_flexWeight array and calls
// AddSceneEvents
void ProcessSceneEvents( bool bFlexEvents, float *pGlobalFlexWeight );
// Assumes m_flexWeight array has been set up, this adds the actual currently playing
// expressions to the flex weights and adds other scene events as needed
bool ProcessSceneEvent( float *pGlobalFlexWeight, bool bFlexEvents, CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
bool RequestStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
bool ProcessFlexAnimationSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); bool ProcessFlexSettingSceneEvent( float *pGlobalFlexWeight, CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); void AddFlexSetting( float *pGlobalFlexWeight, const char *expr, float scale, const flexsettinghdr_t *pSettinghdr, bool newexpression );
// Array of active SceneEvents, in order oldest to newest
CUtlVector < CSceneEventInfo > m_SceneEvents; CUtlVector < CChoreoScene * > m_ActiveChoreoScenes;
bool HasSceneEvents() const;
private: // Mapping for each loaded scene file used by this actor
struct FS_LocalToGlobal_t { explicit FS_LocalToGlobal_t() : m_Key( 0 ), m_nCount( 0 ), m_Mapping( 0 ) { }
explicit FS_LocalToGlobal_t( const flexsettinghdr_t *key ) : m_Key( key ), m_nCount( 0 ), m_Mapping( 0 ) { }
void SetCount( int count ) { Assert( !m_Mapping ); Assert( count > 0 ); m_nCount = count; m_Mapping = new int[ m_nCount ]; Q_memset( m_Mapping, 0, m_nCount * sizeof( int ) ); }
FS_LocalToGlobal_t( const FS_LocalToGlobal_t& src ) { m_Key = src.m_Key; delete m_Mapping; m_Mapping = new int[ src.m_nCount ]; Q_memcpy( m_Mapping, src.m_Mapping, src.m_nCount * sizeof( int ) );
m_nCount = src.m_nCount; }
~FS_LocalToGlobal_t() { delete m_Mapping; m_nCount = 0; m_Mapping = 0; }
const flexsettinghdr_t *m_Key; int m_nCount; int *m_Mapping; };
static bool FlexSettingLessFunc( const FS_LocalToGlobal_t& lhs, const FS_LocalToGlobal_t& rhs ); CUtlRBTree< FS_LocalToGlobal_t, unsigned short > m_LocalToGlobal;
float m_blinktime; int m_prevblinktoggle;
int m_iBlink; LocalFlexController_t m_iEyeUpdown; LocalFlexController_t m_iEyeRightleft; int m_iMouthAttachment;
float *m_flFlexDelayedWeight;
int m_iMostRecentFlexCounter; Vector m_CachedViewTarget; CUtlVector< float > m_CachedFlexWeights; CUtlVector< float > m_CachedDelayedFlexWeights;
// shared flex controllers
static int g_numflexcontrollers; static char *g_flexcontroller[MAXSTUDIOFLEXCTRL*4]; // room for global set of flexcontrollers
static float s_pGlobalFlexWeight[MAXSTUDIOFLEXCTRL*4];
protected:
enum { PHONEME_CLASS_WEAK = 0, PHONEME_CLASS_NORMAL, PHONEME_CLASS_STRONG,
NUM_PHONEME_CLASSES };
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct Emphasized_Phoneme { // Global fields, setup at start
char classname[ 64 ]; bool required; // Global fields setup first time tracks played
bool basechecked; const flexsettinghdr_t *base; const flexsetting_t *exp;
// Local fields, processed for each sentence
bool valid; float amount; };
Emphasized_Phoneme m_PhonemeClasses[ NUM_PHONEME_CLASSES ];
private:
C_BaseFlex( const C_BaseFlex & ); // not defined, not accessible
const flexsetting_t *FindNamedSetting( const flexsettinghdr_t *pSettinghdr, const char *expr );
void ProcessVisemes( Emphasized_Phoneme *classes, float *pGlobalFlexWeight ); void AddVisemesForSentence( float *pGlobalFlexWeight, Emphasized_Phoneme *classes, float emphasis_intensity, CSentence *sentence, float t, float dt, bool juststarted ); void AddViseme( float *pGlobalFlexWeight, Emphasized_Phoneme *classes, float emphasis_intensity, int phoneme, float scale, bool newexpression ); bool SetupEmphasisBlend( Emphasized_Phoneme *classes, int phoneme ); void ComputeBlendedSetting( Emphasized_Phoneme *classes, float emphasis_intensity );
#ifdef HL2_CLIENT_DLL
public:
Vector m_vecLean; CInterpolatedVar< Vector > m_iv_vecLean; Vector m_vecShift; CInterpolatedVar< Vector > m_iv_vecShift; #endif
};
//-----------------------------------------------------------------------------
// Do we have active expressions?
//-----------------------------------------------------------------------------
inline bool C_BaseFlex::HasSceneEvents() const { return m_SceneEvents.Count() != 0; }
EXTERN_RECV_TABLE(DT_BaseFlex);
float *GetVisemeWeights( int phoneme );
#endif // C_STUDIOFLEX_H
|