350 lines
12 KiB
C++
350 lines
12 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//===========================================================================//
|
|
// Client-side CBasePlayer
|
|
|
|
#ifndef C_STUDIOFLEX_H
|
|
#define C_STUDIOFLEX_H
|
|
#pragma once
|
|
|
|
#include "c_baseanimating.h"
|
|
#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;
|
|
|
|
enum {
|
|
PHONEME_CLASS_WEAK = 0,
|
|
PHONEME_CLASS_NORMAL,
|
|
PHONEME_CLASS_STRONG,
|
|
|
|
NUM_PHONEME_CLASSES
|
|
};
|
|
|
|
// 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;
|
|
};
|
|
|
|
bool FlexSettingLessFunc(const FS_LocalToGlobal_t &lhs,
|
|
const FS_LocalToGlobal_t &rhs);
|
|
|
|
class IHasLocalToGlobalFlexSettings {
|
|
public:
|
|
virtual void EnsureTranslations(const flexsettinghdr_t *pSettinghdr) = 0;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
class C_BaseFlex : public C_BaseAnimatingOverlay,
|
|
public IHasLocalToGlobalFlexSettings {
|
|
DECLARE_CLASS(C_BaseFlex, C_BaseAnimatingOverlay);
|
|
|
|
public:
|
|
DECLARE_CLIENTCLASS();
|
|
DECLARE_PREDICTABLE();
|
|
DECLARE_INTERPOLATION();
|
|
|
|
C_BaseFlex();
|
|
virtual ~C_BaseFlex();
|
|
|
|
virtual void Spawn();
|
|
|
|
virtual void InitPhonemeMappings();
|
|
|
|
void SetupMappings(char const *pchFileRoot);
|
|
|
|
virtual CStudioHdr *OnNewModel(void);
|
|
|
|
virtual void StandardBlendingRules(CStudioHdr *hdr, Vector pos[],
|
|
Quaternion q[], float currentTime,
|
|
int boneMask);
|
|
|
|
virtual void OnThreadedDrawSetup();
|
|
|
|
// model specific
|
|
virtual void BuildTransformations(CStudioHdr *pStudioHdr, Vector *pos,
|
|
Quaternion q[],
|
|
const matrix3x4_t &cameraTransform,
|
|
int boneMask, CBoneBitList &boneComputed);
|
|
static void LinkToGlobalFlexControllers(CStudioHdr *hdr);
|
|
virtual void SetupWeights(const matrix3x4_t *pBoneToWorld,
|
|
int nFlexWeightCount, float *pFlexWeights,
|
|
float *pFlexDelayedWeights);
|
|
virtual bool SetupGlobalWeights(const matrix3x4_t *pBoneToWorld,
|
|
int nFlexWeightCount, float *pFlexWeights,
|
|
float *pFlexDelayedWeights);
|
|
static void RunFlexDelay(int nFlexWeightCount, float *pFlexWeights,
|
|
float *pFlexDelayedWeights,
|
|
float &flFlexDelayTime);
|
|
virtual void SetupLocalWeights(const matrix3x4_t *pBoneToWorld,
|
|
int nFlexWeightCount, float *pFlexWeights,
|
|
float *pFlexDelayedWeights);
|
|
virtual bool UsesFlexDelayedWeights();
|
|
|
|
static void RunFlexRules(CStudioHdr *pStudioHdr, float *dest);
|
|
|
|
virtual Vector SetViewTarget(CStudioHdr *pStudioHdr);
|
|
|
|
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(const 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);
|
|
|
|
// 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
|
|
virtual void ProcessSceneEvents(bool bFlexEvents);
|
|
|
|
// 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
|
|
virtual bool ProcessSceneEvent(bool bFlexEvents, CSceneEventInfo *info,
|
|
CChoreoScene *scene, CChoreoEvent *event);
|
|
|
|
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);
|
|
|
|
// 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);
|
|
|
|
// IHasLocalToGlobalFlexSettings
|
|
virtual void EnsureTranslations(const flexsettinghdr_t *pSettinghdr);
|
|
|
|
// For handling scene files
|
|
void *FindSceneFile(const char *filename);
|
|
|
|
private:
|
|
bool RequestStartSequenceSceneEvent(CSceneEventInfo *info,
|
|
CChoreoScene *scene,
|
|
CChoreoEvent *event,
|
|
CChoreoActor *actor,
|
|
CBaseEntity *pTarget);
|
|
|
|
bool ProcessFlexAnimationSceneEvent(CSceneEventInfo *info,
|
|
CChoreoScene *scene,
|
|
CChoreoEvent *event);
|
|
bool ProcessFlexSettingSceneEvent(CSceneEventInfo *info,
|
|
CChoreoScene *scene, CChoreoEvent *event);
|
|
void AddFlexSetting(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:
|
|
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;
|
|
bool m_bSearchedForEyeFlexes;
|
|
int m_iMouthAttachment;
|
|
|
|
float m_flFlexDelayTime;
|
|
float *m_flFlexDelayedWeight;
|
|
int m_cFlexDelayedWeight;
|
|
|
|
// shared flex controllers
|
|
static int g_numflexcontrollers;
|
|
static char *g_flexcontroller[MAXSTUDIOFLEXCTRL *
|
|
4]; // room for global set of flexcontrollers
|
|
static float g_flexweight[MAXSTUDIOFLEXDESC];
|
|
|
|
protected:
|
|
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);
|
|
void AddVisemesForSentence(Emphasized_Phoneme *classes,
|
|
float emphasis_intensity, CSentence *sentence,
|
|
float t, float dt, bool juststarted);
|
|
void AddViseme(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
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
class CFlexSceneFileManager : CAutoGameSystem {
|
|
public:
|
|
CFlexSceneFileManager() : CAutoGameSystem("CFlexSceneFileManager") {}
|
|
|
|
virtual bool Init();
|
|
virtual void Shutdown();
|
|
|
|
void EnsureTranslations(IHasLocalToGlobalFlexSettings *instance,
|
|
const flexsettinghdr_t *pSettinghdr);
|
|
void *FindSceneFile(IHasLocalToGlobalFlexSettings *instance,
|
|
const char *filename, bool allowBlockingIO);
|
|
|
|
private:
|
|
void DeleteSceneFiles();
|
|
|
|
CUtlVector<CFlexSceneFile *> m_FileList;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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
|