You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
591 lines
16 KiB
591 lines
16 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#ifndef PHONEEDITOR_H |
|
#define PHONEEDITOR_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
#include <mxtk/mx.h> |
|
class CAudioSource; |
|
class CAudioMixer; |
|
class mxBitmapButton; |
|
class mxButton; |
|
|
|
#include "utlvector.h" |
|
#include "faceposertoolwindow.h" |
|
|
|
#define IDC_PHONEME_SCROLL 1001 |
|
#define IDC_PHONEME_PLAY_ORIG 1002 |
|
#define IDC_EDIT_PHONEME 1004 |
|
#define IDC_EDIT_INSERTPHONEMEBEFORE 1005 |
|
#define IDC_EDIT_INSERTPHONEMEAFTER 1006 |
|
#define IDC_EDIT_DELETEPHONEME 1007 |
|
|
|
#define IDC_PLAY_EDITED_SELECTION 1008 |
|
|
|
#define IDC_REDO_PHONEMEEXTRACTION 1009 |
|
#define IDC_REDO_PHONEMEEXTRACTION_SELECTION 1010 |
|
#define IDC_DESELECT 1011 |
|
#define IDC_PLAY_EDITED 1012 |
|
#define IDC_SAVE_LINGUISTIC 1013 |
|
#define IDC_CANCELPLAYBACK 1014 |
|
|
|
#define IDC_EDITWORDLIST 1015 |
|
#define IDC_SNAPWORDS 1016 |
|
#define IDC_SEPARATEWORDS 1017 |
|
#define IDC_LOADWAVEFILE 1018 |
|
#define IDC_SNAPPHONEMES 1019 |
|
#define IDC_SEPARATEPHONEMES 1020 |
|
|
|
#define IDC_COMMITEXTRACTED 1021 |
|
#define IDC_CLEAREXTRACTED 1022 |
|
|
|
#define IDC_ADDTAG 1023 |
|
#define IDC_DELETETAG 1024 |
|
|
|
#define IDC_CVUNDO 1025 |
|
#define IDC_CVREDO 1026 |
|
|
|
#define IDC_EDIT_DELETEWORD 1027 |
|
#define IDC_EDIT_WORD 1028 |
|
#define IDC_EDIT_INSERTWORDBEFORE 1029 |
|
#define IDC_EDIT_INSERTWORDAFTER 1030 |
|
#define IDC_EDIT_INSERTFIRSTPHONEMEOFWORD 1031 |
|
|
|
#define IDC_SELECT_WORDSRIGHT 1032 |
|
#define IDC_SELECT_WORDSLEFT 1033 |
|
#define IDC_SELECT_PHONEMESRIGHT 1034 |
|
#define IDC_SELECT_PHONEMESLEFT 1035 |
|
|
|
#define IDC_DESELECT_PHONEMESANDWORDS 1036 |
|
#define IDC_CLEANUP 1037 |
|
#define IDC_CLEARUNDO 1038 |
|
|
|
#define IDC_PLAYBUTTON 1039 |
|
|
|
#define IDC_MODE_TAB 1040 |
|
|
|
#define IDC_EMPHASIS_DELETE 1041 |
|
#define IDC_EMPHASIS_DESELECT 1042 |
|
#define IDC_EMPHASIS_SELECTALL 1043 |
|
|
|
#define IDC_PLAYBACKRATE 1044 |
|
|
|
#define IDC_REALIGNPHONEMES 1045 |
|
#define IDC_REALIGNWORDS 1046 |
|
|
|
// Support for multiple speech api's |
|
#define IDC_API_SAPI 1050 |
|
#define IDC_API_LIPSINC 1051 |
|
|
|
#define IDC_EXPORT_SENTENCE 1075 |
|
#define IDC_IMPORT_SENTENCE 1076 |
|
#define IDC_TOGGLE_VOICEDUCK 1077 |
|
|
|
#define IDC_PE_LANGUAGESTART 1100 |
|
// #define IDC_PE_LANGUAGEEND 1106 or so |
|
|
|
class IterateOutputRIFF; |
|
class IterateRIFF; |
|
class CChoreoWidgetDrawHelper; |
|
class CChoreoEvent; |
|
class CEventRelativeTag; |
|
class CChoreoView; |
|
class IPhonemeExtractor; |
|
class CPhonemeModeTab; |
|
class mxPopupMenu; |
|
|
|
#include "sentence.h" |
|
|
|
enum |
|
{ |
|
COLOR_PHONEME_BACKGROUND = 0, |
|
COLOR_PHONEME_TEXT, |
|
COLOR_PHONEME_LIGHTTEXT, |
|
COLOR_PHONEME_PLAYBACKTICK, |
|
COLOR_PHONEME_WAVDATA, |
|
COLOR_PHONEME_TIMELINE, |
|
COLOR_PHONEME_TIMELINE_MAJORTICK, |
|
COLOR_PHONEME_TIMELINE_MINORTICK, |
|
COLOR_PHONEME_EXTRACTION_RESULT_FAIL, |
|
COLOR_PHONEME_EXTRACTION_RESULT_SUCCESS, |
|
COLOR_PHONEME_EXTRACTION_RESULT_ERROR, |
|
COLOR_PHONEME_EXTRACTION_RESULT_OTHER, |
|
COLOR_PHONEME_TAG_BORDER, |
|
COLOR_PHONEME_TAG_BORDER_SELECTED, |
|
COLOR_PHONEME_TAG_FILLER_NORMAL, |
|
COLOR_PHONEME_TAG_SELECTED, |
|
COLOR_PHONEME_TAG_TEXT, |
|
COLOR_PHONEME_TAG_TEXT_SELECTED, |
|
COLOR_PHONEME_WAV_ENDPOINT, |
|
COLOR_PHONEME_AB, |
|
COLOR_PHONEME_AB_LINE, |
|
COLOR_PHONEME_AB_TEXT, |
|
|
|
COLOR_PHONEME_ACTIVE_BORDER, |
|
COLOR_PHONEME_SELECTED_BORDER, |
|
COLOR_PHONEME_TIMING_TAG, |
|
|
|
COLOR_PHONEME_EMPHASIS_BG, |
|
COLOR_PHONEME_EMPHASIS_BG_STRONG, |
|
COLOR_PHONEME_EMPHASIS_BG_WEAK, |
|
|
|
COLOR_PHONEME_EMPHASIS_BORDER, |
|
COLOR_PHONEME_EMPHASIS_LINECOLOR, |
|
COLOR_PHONEME_EMPHASIS_DOTCOLOR, |
|
COLOR_PHONEME_EMPHASIS_DOTCOLOR_SELECTED, |
|
COLOR_PHONEME_EMPHASIS_TEXT, |
|
COLOR_PHONEME_EMPHASIS_MIDLINE, |
|
|
|
NUM_COLORS, |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Shows WAV data and allows blanking it out and tweaking phoneme tags |
|
//----------------------------------------------------------------------------- |
|
class PhonemeEditor : public mxWindow, public IFacePoserToolWindow |
|
{ |
|
public: |
|
enum |
|
{ |
|
BOUNDARY_NONE = 0, |
|
BOUNDARY_PHONEME, |
|
BOUNDARY_WORD, |
|
}; |
|
|
|
typedef enum |
|
{ |
|
MODE_PHONEMES = 0, |
|
MODE_EMPHASIS |
|
} EditorMode; |
|
|
|
// Construction |
|
PhonemeEditor( mxWindow *parent ); |
|
~PhonemeEditor( void ); |
|
|
|
virtual void Think( float dt ); |
|
|
|
virtual void OnDelete(); |
|
virtual bool CanClose(); |
|
|
|
void ValidateSpeechAPIIndex(); |
|
|
|
virtual int handleEvent( mxEvent *event ); |
|
virtual void redraw( void ); |
|
virtual bool PaintBackground( void ); |
|
|
|
EditorMode GetMode( void ) const; |
|
void SetupPhonemeEditorColors( void ); |
|
COLORREF PEColor( int colornum ); |
|
void OnModeChanged( void ); |
|
|
|
// Change wave file being edited |
|
void SetCurrentWaveFile( const char *wavefile, bool force = false, CChoreoEvent *event = NULL ); |
|
|
|
// called when scene is unloaded in choreview or when event/channel/actor gets deleted |
|
// so we don't have dangling pointers to tags, events, scene |
|
void ClearEvent( void ); |
|
|
|
void Play(); |
|
|
|
private: |
|
void DrawWords( CChoreoWidgetDrawHelper& drawHelper, RECT& rcWorkSpace, CSentence &sentence, int type, bool showactive = true ); |
|
void DrawPhonemes( CChoreoWidgetDrawHelper& drawHelper, RECT& rcWorkSpace, CSentence &sentence, int type, bool showactive = true ); |
|
void DrawRelativeTags( CChoreoWidgetDrawHelper& drawHelper, RECT& rc ); |
|
|
|
void Emphasis_Redraw( CChoreoWidgetDrawHelper& drawHelper, RECT& rcWorkSpace ); |
|
void Emphasis_GetRect( RECT const & rcWorkSpace, RECT& rcEmphasis ); |
|
|
|
void Emphasis_Init( void ); |
|
CEmphasisSample *Emphasis_GetSampleUnderMouse( mxEvent *event ); |
|
void Emphasis_DeselectAll( void ); |
|
void Emphasis_SelectAll( void ); |
|
void Emphasis_Delete( void ); |
|
void Emphasis_AddSample( CEmphasisSample const& sample ); |
|
void Emphasis_CountSelected( void ); |
|
void Emphasis_ShowContextMenu( mxEvent *event ); |
|
void Emphasis_MouseDrag( int x, int y ); |
|
bool Emphasis_IsValid( void ); |
|
void Emphasis_SelectPoints( void ); |
|
|
|
// Data |
|
int m_nNumSelected; |
|
|
|
// Readjust slider |
|
void MoveTimeSliderToPos( int x ); |
|
|
|
// Handle scrollbar |
|
void SetTimeZoomScale( int scale ); |
|
float GetTimeZoomScale( void ); |
|
float GetPixelsPerSecond( void ); |
|
// Adjust scroll bars |
|
void RepositionHSlider( void ); |
|
|
|
// Edit commands |
|
void EditPhoneme( CPhonemeTag *pPhoneme, bool positionDialog = false ); |
|
void EditPhoneme( void ); |
|
void EditInsertPhonemeBefore( void ); |
|
void EditInsertPhonemeAfter( void ); |
|
void EditDeletePhoneme( void ); |
|
|
|
void SelectPhonemes( bool forward ); |
|
|
|
void EditInsertFirstPhonemeOfWord( void ); |
|
|
|
void EditWord( CWordTag *pWord, bool positionDialog = false ); |
|
void EditWord( void ); |
|
void EditInsertWordBefore( void ); |
|
void EditInsertWordAfter( void ); |
|
void EditDeleteWord( void ); |
|
|
|
void SelectWords( bool forward ); |
|
|
|
// Edit word list |
|
void EditWordList( void ); |
|
void SentenceFromString( CSentence& sentence, char const *str ); |
|
|
|
|
|
// Wav processing commands |
|
void RedoPhonemeExtraction( void ); |
|
// Redo extraction of selected words only |
|
void RedoPhonemeExtractionSelected( void ); |
|
void Deselect( void ); |
|
|
|
void PlayEditedWave( bool selection = false ); |
|
void CommitChanges( void ); |
|
|
|
// Context menu |
|
void ShowPhonemeMenu( CPhonemeTag *pho, int mx, int my ); |
|
void ShowWordMenu( CWordTag *word, int mx, int my ); |
|
|
|
void ShowContextMenu( int mx, int my ); |
|
void ShowContextMenu_Phonemes( int mx, int my ); |
|
void ShowContextMenu_Emphasis( int mx, int my ); |
|
|
|
// UI helpers |
|
void GetWorkspaceRect( RECT &rc ); |
|
|
|
|
|
bool IsMouseOverWordRow( int my ); |
|
bool IsMouseOverPhonemeRow( int my ); |
|
|
|
int IsMouseOverBoundary( mxEvent *event ); |
|
int GetWordUnderMouse( int mx, int my ); |
|
int ComputeHPixelsNeeded( void ); |
|
void DrawFocusRect( char *reason ); |
|
void StartDragging( int dragtype, int startx, int starty, HCURSOR cursor ); |
|
|
|
void FinishPhonemeMove( int startx, int endx ); |
|
void FinishPhonemeDrag( int startx, int endx ); |
|
void FinishWordMove( int startx, int endx ); |
|
void FinishWordDrag( int startx, int endx ); |
|
|
|
float GetTimeForPixel( int mx ); |
|
void GetScreenStartAndEndTime( float &starttime, float& endtime ); |
|
float GetTimePerPixel( void ); |
|
int GetSampleForMouse( int mx ); |
|
int GetPixelForSample( int sample ); |
|
|
|
bool FindSpanningPhonemes( float time, CPhonemeTag **pp1, CPhonemeTag **pp2 ); |
|
bool FindSpanningWords( float time, CWordTag **pp1, CWordTag **pp2 ); |
|
int FindWordForTime( float time ); |
|
CPhonemeTag *FindPhonemeForTime( float time ); |
|
void DeselectWords( void ); |
|
void SnapWords( void ); |
|
void SeparateWords( void ); |
|
|
|
void DeselectPhonemes( void ); |
|
void SnapPhonemes( void ); |
|
void SeparatePhonemes( void ); |
|
|
|
void CreateEvenWordDistribution( const char *wordlist ); |
|
|
|
// Dirty flag |
|
void SetDirty( bool dirty, bool clearundo = true ); |
|
bool GetDirty( void ); |
|
|
|
// FIXME: Do something else here |
|
void ResampleChunk( IterateOutputRIFF& store, void *format, int chunkname, char *buffer, int buffersize, int start_silence = 0, int end_silence = 0 ); |
|
|
|
// Mouse control over selected samples |
|
void SelectSamples( int start, int end ); |
|
void FinishSelect( int startx, int mx ); |
|
void FinishMoveSelection( int startx, int mx ); |
|
void FinishMoveSelectionStart( int startx, int mx ); |
|
void FinishMoveSelectionEnd( int startx, int mx ); |
|
|
|
bool IsMouseOverSamples( int mx, int my ); |
|
bool IsMouseOverSelection( int mx, int my ); |
|
bool IsMouseOverSelectionStartEdge( mxEvent *event ); |
|
bool IsMouseOverSelectionEndEdge( mxEvent *event ); |
|
|
|
bool IsMouseOverTag( int mx, int my ); |
|
void FinishEventTagDrag( int startx, int endx ); |
|
CEventRelativeTag *GetTagUnderMouse( int mx ); |
|
bool IsMouseOverTagRow( int my ); |
|
void ShowTagMenu( int mx, int my ); |
|
void AddTag( void ); |
|
void DeleteTag( void ); |
|
|
|
// After running liset/sapi, retrieve phoneme tag data from stream |
|
void RetrieveLinguisticData( void ); |
|
|
|
// Copy current phoneme chunk over existing data chunk of .wav file |
|
void SaveLinguisticData( void ); |
|
void StoreValveDataChunk( IterateOutputRIFF& store ); |
|
|
|
void ExportValveDataChunk( char const *tempfile ); |
|
void ImportValveDataChunk( char const *tempfile ); |
|
|
|
void OnImport(); |
|
void OnExport(); |
|
|
|
// Playback (returns true if sound had been playing) |
|
bool StopPlayback( void ); |
|
|
|
CPhonemeTag *GetPhonemeTagUnderMouse( int mx, int my ); |
|
CWordTag *GetWordTagUnderMouse( int mx, int my ); |
|
|
|
void ReadLinguisticTags( void ); |
|
|
|
void LoadWaveFile( void ); |
|
|
|
void GetPhonemeTrayTopBottom( RECT& rc ); |
|
void GetWordTrayTopBottom( RECT& rc ); |
|
|
|
void GetWordRect( const CWordTag *tag, RECT& rc ); |
|
void GetPhonemeRect( const CPhonemeTag *tag, RECT& rc ); |
|
int GetMouseForTime( float time ); |
|
|
|
void CommitExtracted( void ); |
|
void ClearExtracted( void ); |
|
|
|
const char * GetExtractionResultString( int resultCode ); |
|
|
|
void AddFocusRect( RECT& rc ); |
|
|
|
void CountSelected( void ); |
|
|
|
typedef void (PhonemeEditor::*PEWORDITERFUNC)( CWordTag *word, float fparam ); |
|
typedef void (PhonemeEditor::*PEPHONEMEITERFUNC)( CPhonemeTag *phoneme, CWordTag *word, float fparam ); |
|
|
|
void TraverseWords( PEWORDITERFUNC pfn, float fparam ); |
|
void TraversePhonemes( PEPHONEMEITERFUNC pfn, float fparam ); |
|
|
|
// Iteration functions |
|
void ITER_MoveSelectedWords( CWordTag *word, float amount ); |
|
void ITER_MoveSelectedPhonemes( CPhonemeTag *phoneme, CWordTag *word, float amount ); |
|
|
|
void ITER_ExtendSelectedPhonemeEndTimes( CPhonemeTag *phoneme, CWordTag *word, float amount ); |
|
void ITER_ExtendSelectedWordEndTimes( CWordTag *word, float amount ); |
|
|
|
void ITER_AddFocusRectSelectedWords( CWordTag *word, float amount ); |
|
void ITER_AddFocusRectSelectedPhonemes( CPhonemeTag *phoneme, CWordTag *word, float amount ); |
|
|
|
void ITER_CountSelectedWords( CWordTag *word, float amount ); |
|
void ITER_CountSelectedPhonemes( CPhonemeTag *phoneme, CWordTag *word, float amount ); |
|
|
|
void ITER_SelectSpanningWords( CWordTag *word, float amount ); |
|
|
|
// Undo/Redo |
|
void Undo( void ); |
|
void Redo( void ); |
|
void ClearUndo( void ); |
|
|
|
// Do push before changes |
|
void PushUndo( void ); |
|
// Do this push after changes, must match pushundo 1for1 |
|
void PushRedo( void ); |
|
|
|
void WipeUndo( void ); |
|
void WipeRedo( void ); |
|
|
|
CPhonemeTag *GetClickedPhoneme( void ); |
|
CWordTag *GetClickedWord( void ); |
|
void SetClickedPhoneme( int word, int phoneme ); |
|
|
|
void ShiftSelectedPhoneme( int direction ); |
|
void ExtendSelectedPhonemeEndTime( int direction ); |
|
void SelectNextPhoneme( int direction ); |
|
void SelectNextWord( int direction ); |
|
bool IsPhonemeSelected( CWordTag *word ); |
|
void ShiftSelectedWord( int direction ); |
|
void ExtendSelectedWordEndTime( int direction ); |
|
|
|
float GetTimeGapToNextWord( bool forward, CWordTag *currentWord, CWordTag **ppNextWord = NULL ); |
|
float GetTimeGapToNextPhoneme( bool forward, CPhonemeTag *currentPhoneme, CWordTag **ppword = NULL, CPhonemeTag **phoneme = NULL ); |
|
int IndexOfWord( CWordTag *word ); |
|
CPhonemeTag *GetSelectedPhoneme( void ); |
|
CWordTag *GetSelectedWord( void ); |
|
|
|
void OnMouseMove( mxEvent *event ); |
|
|
|
bool AreSelectedWordsContiguous( void ); |
|
bool AreSelectedPhonemesContiguous( void ); |
|
|
|
bool CreateCroppedWave( char const *filename, int startsample, int endsample ); |
|
void CleanupWordsAndPhonemes( bool prepareundo ); |
|
void RealignPhonemesToWords( bool prepareundo ); |
|
void RealignWordsToPhonemes( bool prepareundo ); |
|
void SortWords( bool prepareundo ); |
|
void SortPhonemes( bool prepareundo ); |
|
|
|
float ComputeMaxWordShift( bool forward, bool allowcrop ); |
|
float ComputeMaxPhonemeShift( bool forward, bool allowcrop ); |
|
|
|
int PixelsForDeltaTime( float dt ); |
|
|
|
void ClearDragLimit( void ); |
|
void SetDragLimit( int dragtype ); |
|
void LimitDrag( int& mousex ); |
|
|
|
void SelectExpression( CPhonemeTag *tag ); |
|
|
|
void OnSAPI( void ); |
|
void OnLipSinc( void ); |
|
|
|
bool CheckSpeechAPI( void ); |
|
char const *GetSpeechAPIName( void ); |
|
|
|
void LoadPhonemeConverters(); |
|
void UnloadPhonemeConverters(); |
|
|
|
bool IsMouseOverScrubHandle( mxEvent *event ); |
|
bool IsMouseOverScrubArea( mxEvent *event ); |
|
void GetScrubHandleRect( RECT& rcHandle, bool clipped = false ); |
|
void GetScrubAreaRect( RECT& rcArea ); |
|
void DrawScrubHandle(); |
|
|
|
void DrawScrubHandle( CChoreoWidgetDrawHelper& drawHelper ); |
|
void ScrubThink( float dt, bool scrubbing ); |
|
|
|
void SetScrubTime( float t ); |
|
void SetScrubTargetTime( float t ); |
|
|
|
float GetTimeForSample( int sample ); |
|
void ClampTimeToSelectionInterval( float& timeval ); |
|
void OnToggleVoiceDuck(); |
|
|
|
// Data |
|
private: |
|
// Type of mouse movement |
|
enum |
|
{ |
|
DRAGTYPE_NONE = 0, |
|
DRAGTYPE_PHONEME , |
|
DRAGTYPE_WORD, |
|
DRAGTYPE_SELECTSAMPLES, |
|
DRAGTYPE_MOVESELECTION, |
|
DRAGTYPE_MOVESELECTIONSTART, |
|
DRAGTYPE_MOVESELECTIONEND, |
|
DRAGTYPE_MOVEWORD, |
|
DRAGTYPE_MOVEPHONEME, |
|
DRAGTYPE_EVENTTAG_MOVE, |
|
DRAGTYPE_EMPHASIS_SELECT, |
|
DRAGTYPE_EMPHASIS_MOVE, |
|
DRAGTYPE_SCRUBBER |
|
}; |
|
|
|
float m_flScrub; |
|
float m_flScrubTarget; |
|
|
|
EditorMode m_CurrentMode; |
|
// Graph scale |
|
float m_flPixelsPerSecond; |
|
// Graph scale |
|
int m_nTimeZoom; |
|
int m_nTimeZoomStep; |
|
|
|
int m_nTickHeight; |
|
|
|
// Current wave file |
|
CAudioSource *m_pWaveFile; |
|
CAudioMixer *m_pMixer; |
|
CChoreoEvent *m_pEvent; |
|
int m_nClickX; |
|
|
|
struct CWorkFile |
|
{ |
|
public: |
|
char m_szWaveFile[ 256 ]; |
|
char m_szWorkingFile[ 256 ]; |
|
char m_szBasePath[ 256 ]; |
|
bool m_bDirty; |
|
}; |
|
CWorkFile m_WorkFile; |
|
|
|
mxScrollbar *m_pHorzScrollBar; |
|
// Current sb value |
|
int m_nLeftOffset; |
|
|
|
CPhonemeModeTab *m_pModeTab; |
|
|
|
mxSlider *m_pPlaybackRate; |
|
float m_flPlaybackRate; |
|
|
|
mxButton *m_btnRedoPhonemeExtraction; |
|
mxButton *m_btnSave; |
|
mxButton *m_btnLoad; |
|
|
|
mxButton *m_btnPlay; // selection or full depending |
|
|
|
// Mouse dragging |
|
HCURSOR m_hPrevCursor; |
|
|
|
int m_nStartX; |
|
int m_nStartY; |
|
int m_nLastX; |
|
int m_nLastY; |
|
int m_nDragType; |
|
struct CFocusRect |
|
{ |
|
RECT m_rcOrig; |
|
RECT m_rcFocus; |
|
}; |
|
CUtlVector < CFocusRect > m_FocusRects; |
|
|
|
int m_nClickedPhoneme; |
|
int m_nClickedWord; |
|
|
|
// Current set of tags |
|
CSentence m_Tags; |
|
|
|
CSentence m_TagsExt; |
|
|
|
int m_nSelection[ 2 ]; |
|
bool m_bSelectionActive; |
|
|
|
int m_nLastExtractionResult; |
|
|
|
int m_nSelectedPhonemeCount; |
|
int m_nSelectedWordCount; |
|
|
|
bool m_bWordsActive; |
|
|
|
struct PEUndo |
|
{ |
|
CSentence *undo; |
|
CSentence *redo; |
|
}; |
|
|
|
CUtlVector< PEUndo * > m_UndoStack; |
|
int m_nUndoLevel; |
|
bool m_bRedoPending; |
|
|
|
bool m_bLimitDrag; |
|
int m_nLeftLimit; |
|
int m_nRightLimit; |
|
|
|
IPhonemeExtractor *m_pPhonemeExtractor; |
|
float m_flScrubberTimeOffset; |
|
}; |
|
|
|
extern PhonemeEditor *g_pPhonemeEditor; |
|
|
|
#endif // PHONEEDITOR_H
|
|
|