source-engine/public/sentence.h

303 lines
8.1 KiB
C
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= 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
//
// "<persist:2.0><clr:255,0,0,0>The <I>default<I> case"
// "<sameline>is the <U>entire<U> sentence shown at <B>start time<B>"
// Commands that aren't closed at end of phrase are automatically terminated
//
// Commands
// <linger:2.0> The line should persist for 2.0 seconds beyond m_flEndTime
// <sameline> Don't go to new line for next phrase on stack
// <clr:r,g,b,a> Push current color onto stack and start drawing with new
// color until we reach the next <clr> marker or a <clr> with no commands which
// means restore the previous color
// <U> Underline text (start/end)
// <I> Italics text (start/end)
// <B> Bold text (start/end)
// <position:where> Draw caption at special location ??? needed
// <cr> 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