//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef SENTENCE_H #define SENTENCE_H #ifdef _WIN32 #pragma once #endif // X360 optimizes out the extra memory needed by the editors in these types #ifndef _X360 #define PHONEME_EDITOR 1 #endif #include "utlvector.h" class CUtlBuffer; #define CACHED_SENTENCE_VERSION 1 #define CACHED_SENTENCE_VERSION_ALIGNED 4 //----------------------------------------------------------------------------- // Purpose: A sample point //----------------------------------------------------------------------------- // Can't do this due to backward compat issues //#ifdef _WIN32 //#pragma pack (1) //#endif struct CEmphasisSample { float time; float value; void SetSelected( bool isSelected ); #if PHONEME_EDITOR // Used by editors only bool selected; #endif }; class CBasePhonemeTag { public: CBasePhonemeTag(); CBasePhonemeTag( const CBasePhonemeTag& from ); CBasePhonemeTag &operator=( const CBasePhonemeTag &from ) { memcpy( this, &from, sizeof(*this) ); return *this; } float GetStartTime() const { return m_flStartTime; } void SetStartTime( float startTime ) { m_flStartTime = startTime; } void AddStartTime( float startTime ) { m_flStartTime += startTime; } float GetEndTime() const { return m_flEndTime; } void SetEndTime( float endTime ) { m_flEndTime = endTime; } void AddEndTime( float startTime ) { m_flEndTime += startTime; } int GetPhonemeCode() const { return m_nPhonemeCode; } void SetPhonemeCode( int phonemeCode ) { m_nPhonemeCode = phonemeCode; } private: float m_flStartTime; float m_flEndTime; unsigned short m_nPhonemeCode; }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CPhonemeTag : public CBasePhonemeTag { typedef CBasePhonemeTag BaseClass; public: CPhonemeTag( void ); CPhonemeTag( const char *phoneme ); CPhonemeTag( const CPhonemeTag& from ); ~CPhonemeTag( void ); void SetTag( const char *phoneme ); char const *GetTag() const; unsigned int ComputeDataCheckSum(); #if PHONEME_EDITOR bool m_bSelected; unsigned int m_uiStartByte; unsigned int m_uiEndByte; #endif void SetSelected( bool isSelected ); bool GetSelected() const; void SetStartAndEndBytes( unsigned int start, unsigned int end ); unsigned int GetStartByte() const; unsigned int GetEndByte() const; private: char *m_szPhoneme; }; //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class CWordTag { public: CWordTag( void ); CWordTag( const char *word ); CWordTag( const CWordTag& from ); ~CWordTag( void ); void SetWord( const char *word ); const char *GetWord() const; int IndexOfPhoneme( CPhonemeTag *tag ); unsigned int ComputeDataCheckSum(); float m_flStartTime; float m_flEndTime; CUtlVector < CPhonemeTag *> m_Phonemes; #if PHONEME_EDITOR bool m_bSelected; unsigned int m_uiStartByte; unsigned int m_uiEndByte; #endif void SetSelected( bool isSelected ); bool GetSelected() const; void SetStartAndEndBytes( unsigned int start, unsigned int end ); unsigned int GetStartByte() const; unsigned int GetEndByte() const; private: char *m_pszWord; }; // A sentence can be closed captioned // The default case is the entire sentence shown at start time // // "The default case" // "is the entire sentence shown at start time" // Commands that aren't closed at end of phrase are automatically terminated // // Commands // The line should persist for 2.0 seconds beyond m_flEndTime // Don't go to new line for next phrase on stack // Push current color onto stack and start drawing with new // color until we reach the next marker or a with no commands which // means restore the previous color // Underline text (start/end) // Italics text (start/end) // Bold text (start/end) // Draw caption at special location ??? needed // Go to new line // Close Captioning Support // The phonemes drive the mouth in english, but the CC text can // be one of several languages enum { CC_ENGLISH = 0, CC_FRENCH, CC_GERMAN, CC_ITALIAN, CC_KOREAN, CC_SCHINESE, // Simplified Chinese CC_SPANISH, CC_TCHINESE, // Traditional Chinese CC_JAPANESE, CC_RUSSIAN, CC_THAI, CC_PORTUGUESE, // etc etc CC_NUM_LANGUAGES }; //----------------------------------------------------------------------------- // Purpose: A sentence is a box of words, and words contain phonemes //----------------------------------------------------------------------------- class CSentence { public: static char const *NameForLanguage( int language ); static int LanguageForName( char const *name ); static void ColorForLanguage( int language, unsigned char& r, unsigned char& g, unsigned char& b ); // Construction CSentence( void ); ~CSentence( void ); // Assignment operator CSentence& operator =(const CSentence& src ); void Append( float starttime, const CSentence& src ); void SetText( const char *text ); const char *GetText( void ) const; void InitFromDataChunk( void *data, int size ); void InitFromBuffer( CUtlBuffer& buf ); void SaveToBuffer( CUtlBuffer& buf ); // This strips out all of the stuff used by the editor, leaving just one blank work, no sentence text, and just // the phonemes without the phoneme text...(same as the cacherestore version below) void MakeRuntimeOnly(); // This is a compressed save of just the data needed to drive phonemes in the engine (no word / sentence text, etc ) void CacheSaveToBuffer( CUtlBuffer& buf, int version ); void CacheRestoreFromBuffer( CUtlBuffer& buf ); // Add word/phoneme to sentence void AddPhonemeTag( CWordTag *word, CPhonemeTag *tag ); void AddWordTag( CWordTag *tag ); void Reset( void ); void ResetToBase( void ); void MarkNewPhraseBase( void ); int GetWordBase( void ); int CountPhonemes( void ); // For legacy loading, try to find a word that contains the time CWordTag *EstimateBestWord( float time ); CWordTag *GetWordForPhoneme( CPhonemeTag *phoneme ); void SetTextFromWords( void ); float GetIntensity( float time, float endtime ); void Resort( void ); CEmphasisSample *GetBoundedSample( int number, float endtime ); int GetNumSamples( void ); CEmphasisSample *GetSample( int index ); // Compute start and endtime based on all words void GetEstimatedTimes( float& start, float &end ); void SetVoiceDuck( bool shouldDuck ) { m_bShouldVoiceDuck = shouldDuck; } bool GetVoiceDuck() const { return m_bShouldVoiceDuck; } unsigned int ComputeDataCheckSum(); void SetDataCheckSum( unsigned int chk ); unsigned int GetDataCheckSum() const; int GetRuntimePhonemeCount() const; const CBasePhonemeTag *GetRuntimePhoneme( int i ) const; void ClearRuntimePhonemes(); void AddRuntimePhoneme( const CPhonemeTag *src ); void CreateEventWordDistribution( char const *pszText, float flSentenceDuration ); static int CountWords( char const *pszText ); static bool ShouldSplitWord( char in ); public: #if PHONEME_EDITOR char *m_szText; CUtlVector< CWordTag * > m_Words; #endif CUtlVector < CBasePhonemeTag *> m_RunTimePhonemes; #if PHONEME_EDITOR int m_nResetWordBase; #endif // Phoneme emphasis data CUtlVector< CEmphasisSample > m_EmphasisSamples; #if PHONEME_EDITOR unsigned int m_uCheckSum; #endif bool m_bIsValid : 8; bool m_bStoreCheckSum : 8; bool m_bShouldVoiceDuck : 8; bool m_bIsCached : 8; private: void ParseDataVersionOnePointZero( CUtlBuffer& buf ); void ParsePlaintext( CUtlBuffer& buf ); void ParseWords( CUtlBuffer& buf ); void ParseEmphasis( CUtlBuffer& buf ); void ParseOptions( CUtlBuffer& buf ); void ParseCloseCaption( CUtlBuffer& buf ); void ResetCloseCaptionAll( void ); friend class PhonemeEditor; }; //#ifdef _WIN32 //#pragma pack () //#endif #endif // SENTENCE_H