diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/hlfaceposer/wavebrowser.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/hlfaceposer/wavebrowser.cpp')
| -rw-r--r-- | utils/hlfaceposer/wavebrowser.cpp | 1182 |
1 files changed, 1182 insertions, 0 deletions
diff --git a/utils/hlfaceposer/wavebrowser.cpp b/utils/hlfaceposer/wavebrowser.cpp new file mode 100644 index 0000000..c961369 --- /dev/null +++ b/utils/hlfaceposer/wavebrowser.cpp @@ -0,0 +1,1182 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include "cbase.h" +#include <windows.h> +#include "resource.h" +#include "wavefile.h" +#include "wavebrowser.h" +#include "SoundEmitterSystem/isoundemittersystembase.h" +#include "ifaceposersound.h" +#include "snd_wave_source.h" +#include "filesystem.h" +#include "tabwindow.h" +#include "inputproperties.h" +#include "choreowidgetdrawhelper.h" +#include "ifileloader.h" +#include "tier2/riff.h" +#include "UtlBuffer.h" +#include "ChoreoEvent.h" + +CWaveBrowser *g_pWaveBrowser = NULL; + +//----------------------------------------------------------------------------- +// Purpose: Implements the RIFF i/o interface on stdio +//----------------------------------------------------------------------------- +class StdIOReadBinary : public IFileReadBinary +{ +public: + int open( const char *pFileName ) + { + return (int)filesystem->Open( pFileName, "rb" ); + } + + int read( void *pOutput, int size, int file ) + { + if ( !file ) + return 0; + + return filesystem->Read( pOutput, size, (FileHandle_t)file ); + } + + void seek( int file, int pos ) + { + if ( !file ) + return; + + filesystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD ); + } + + unsigned int tell( int file ) + { + if ( !file ) + return 0; + + return filesystem->Tell( (FileHandle_t)file ); + } + + unsigned int size( int file ) + { + if ( !file ) + return 0; + + return filesystem->Size( (FileHandle_t)file ); + } + + void close( int file ) + { + if ( !file ) + return; + + filesystem->Close( (FileHandle_t)file ); + } +}; + +class StdIOWriteBinary : public IFileWriteBinary +{ +public: + int create( const char *pFileName ) + { + return (int)filesystem->Open( pFileName, "wb" ); + } + + int write( void *pData, int size, int file ) + { + return filesystem->Write( pData, size, (FileHandle_t)file ); + } + + void close( int file ) + { + filesystem->Close( (FileHandle_t)file ); + } + + void seek( int file, int pos ) + { + filesystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD ); + } + + unsigned int tell( int file ) + { + return filesystem->Tell( (FileHandle_t)file ); + } +}; + +static StdIOReadBinary io_in; +static StdIOWriteBinary io_out; + +#define RIFF_WAVE MAKEID('W','A','V','E') +#define WAVE_FMT MAKEID('f','m','t',' ') +#define WAVE_DATA MAKEID('d','a','t','a') +#define WAVE_FACT MAKEID('f','a','c','t') +#define WAVE_CUE MAKEID('c','u','e',' ') + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &walk - +//----------------------------------------------------------------------------- +static void SceneManager_ParseSentence( CSentence& sentence, IterateRIFF &walk ) +{ + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + + buf.EnsureCapacity( walk.ChunkSize() ); + walk.ChunkRead( buf.Base() ); + buf.SeekPut( CUtlBuffer::SEEK_HEAD, walk.ChunkSize() ); + + sentence.InitFromDataChunk( buf.Base(), buf.TellPut() ); +} + +bool SceneManager_LoadSentenceFromWavFileUsingIO( char const *wavfile, CSentence& sentence, IFileReadBinary& io ) +{ + sentence.Reset(); + + InFileRIFF riff( wavfile, io ); + + // UNDONE: Don't use printf to handle errors + if ( riff.RIFFName() != RIFF_WAVE ) + { + return false; + } + + // set up the iterator for the whole file (root RIFF is a chunk) + IterateRIFF walk( riff, riff.RIFFSize() ); + + // This chunk must be first as it contains the wave's format + // break out when we've parsed it + bool found = false; + while ( walk.ChunkAvailable() && !found ) + { + switch( walk.ChunkName() ) + { + case WAVE_VALVEDATA: + { + found = true; + SceneManager_ParseSentence( sentence, walk ); + } + break; + } + walk.ChunkNext(); + } + + return true; +} + +bool SceneManager_LoadSentenceFromWavFile( char const *wavfile, CSentence& sentence ) +{ + return SceneManager_LoadSentenceFromWavFileUsingIO( wavfile, sentence, io_in ); +} + +enum +{ + // Controls + IDC_SB_LISTVIEW = 101, + IDC_SB_FILETREE, + + // Messages + IDC_SB_PLAY = 1000, +}; + +enum +{ + COL_WAV = 0, + COL_DUCKED, + COL_PHONEMES, + COL_SENTENCE +}; + +class CWaveList : public mxListView +{ +public: + CWaveList( mxWindow *parent, int id = 0 ) + : mxListView( parent, 0, 0, 0, 0, id ) + { + // Add column headers + insertTextColumn( COL_WAV, 300, "WAV" ); + insertTextColumn( COL_DUCKED, 50, "Ducked" ); + insertTextColumn( COL_PHONEMES, 120, "Words [ Phonemes ]" ); + insertTextColumn( COL_SENTENCE, 300, "Sentence Text" ); + } +}; + +class CWaveFileTree : public mxTreeView +{ +public: + CWaveFileTree( mxWindow *parent, int id = 0 ) : mxTreeView( parent, 0, 0, 0, 0, id ), + m_Paths( 0, 0, FileTreeLessFunc ) + { + } + + void Clear() + { + removeAll(); + m_Paths.RemoveAll(); + } + + void FindOrAddSubdirectory( char const *subdir ) + { + FileTreePath fp; + Q_strcpy( fp.path, subdir ); + + if ( m_Paths.Find( fp ) != m_Paths.InvalidIndex() ) + return; + + m_Paths.Insert( fp ); + } + + mxTreeViewItem *FindOrAddChildItem( mxTreeViewItem *parent, char const *child ) + { + mxTreeViewItem *p = getFirstChild( parent ); + if ( !p ) + { + return add( parent, child ); + } + + while ( p ) + { + if ( !Q_stricmp( getLabel( p ), child ) ) + return p; + + p = getNextChild( p ); + } + + return add( parent, child ); + } + + void _PopulateTree( int pathId, char const *path ) + { + char sz[ 512 ]; + Q_strcpy( sz, path ); + char *p = sz; + + // Start at root + mxTreeViewItem *cur = NULL; + + // Tokenize path + while ( p && p[0] ) + { + char *slash = Q_strstr( p, "/" ); + if ( !slash ) + { + slash = Q_strstr( p, "\\" ); + } + + char *check = p; + + if ( slash ) + { + *slash = 0; + + // see if a child of current already exists with this name + p = slash + 1; + } + else + { + p = NULL; + } + + Assert( check ); + + cur = FindOrAddChildItem( cur, check ); + } + + setUserData( cur, (void *)pathId ); + } + + char const *GetSelectedPath( void ) + { + mxTreeViewItem *tvi = getSelectedItem(); + unsigned int id = (unsigned int)getUserData( tvi ); + + if ( id < 0 || id >= m_Paths.Count() ) + { + Assert( 0 ); + return ""; + } + return m_Paths[ id ].path; + } + + void PopulateTree() + { + int i; + for ( i = m_Paths.FirstInorder(); i != m_Paths.InvalidIndex(); i = m_Paths.NextInorder( i ) ) + { + _PopulateTree( i, m_Paths[ i ].path ); + } + + mxTreeViewItem *p = getFirstChild( NULL ); + setOpen( p, true ); + } + + struct FileTreePath + { + char path[ MAX_PATH ]; + }; + + static bool FileTreeLessFunc( const FileTreePath &lhs, const FileTreePath &rhs ) + { + return Q_stricmp( lhs.path, rhs.path ) < 0; + } + + CUtlRBTree< FileTreePath, int > m_Paths; +}; +#pragma optimize( "", off ) +class CWaveOptionsWindow : public mxWindow +{ +typedef mxWindow BaseClass; +public: + enum + { + IDC_PLAYSOUND = 1000, + IDC_STOP_SOUNDS, + IDC_SEARCH, + IDC_CANCELSEARCH, + }; + + CWaveOptionsWindow( CWaveBrowser *browser ) : BaseClass( browser, 0, 0, 0, 0 ), m_pBrowser( browser ) + { + FacePoser_AddWindowStyle( this, WS_CLIPSIBLINGS | WS_CLIPCHILDREN ); + + m_szSearchString[0]=0; + + m_pPlay = new mxButton( this, 0, 0, 0, 0, "Play", IDC_PLAYSOUND ); + + m_pStopSounds = new mxButton( this, 0, 0, 0, 0, "Stop Sounds", IDC_STOP_SOUNDS ); + + m_pSearch = new mxLineEdit( this, 0, 0, 0, 0, "", IDC_SEARCH ); + + m_pCancelSearch = new mxButton( this, 0, 0, 0, 0, "Cancel", IDC_CANCELSEARCH ); + } + + bool PaintBackground( void ) + { + redraw(); + return false; + } + + + virtual void redraw() + { + CChoreoWidgetDrawHelper drawHelper( this, GetSysColor( COLOR_BTNFACE ) ); + } + virtual int handleEvent( mxEvent *event ) + { + int iret = 0; + switch ( event->event ) + { + default: + break; + case mxEvent::Size: + { + iret = 1; + + int split = 120; + + int x = 1; + + m_pPlay->setBounds( x, 1, split, h2() - 2 ); + + x += split + 10; + + m_pStopSounds->setBounds( x, 1, split, h2()-2 ); + + x += split + 10; + + m_pCancelSearch->setBounds( x, 1, split, h2() - 2 ); + + x += split + 10; + + m_pSearch->setBounds( x, 0, split * 3, h2() - 1 ); + + x += split * 3 + 10; + } + break; + case mxEvent::KeyDown: + switch ( event->action ) + { + default: + break; + case IDC_SEARCH: + { + if ( event->event == mxEvent::KeyDown ) + { + OnSearch(); + } + iret = 1; + }; + break; + } + break; + case mxEvent::Action: + { + switch ( event->action ) + { + case IDC_STOP_SOUNDS: + { + iret = 1; + sound->StopAll(); + } + break; + case IDC_SEARCH: + iret = 1; + break; + case IDC_PLAYSOUND: + { + iret = 1; + m_pBrowser->OnPlay(); + } + break; + case IDC_CANCELSEARCH: + { + iret = 1; + OnCancelSearch(); + } + break; + default: + break; + } + } + break; + } + + return iret; + } + + char const *GetSearchString() + { + return m_szSearchString; + } + + void OnSearch() + { + m_pSearch->getText( m_szSearchString, sizeof( m_szSearchString ) ); + + m_pBrowser->OnSearch(); + } + + void OnCancelSearch() + { + m_szSearchString[ 0 ] = 0; + m_pSearch->clear(); + + m_pBrowser->OnCancelSearch(); + } + +private: + + mxButton *m_pStopSounds; + mxButton *m_pPlay; + mxLineEdit *m_pSearch; + mxButton *m_pCancelSearch; + + CWaveBrowser *m_pBrowser; + + char m_szSearchString[ 256 ]; +}; + +#pragma optimize( "", on ) +//----------------------------------------------------------------------------- +// Purpose: +// Input : *parent - +//----------------------------------------------------------------------------- +CWaveBrowser::CWaveBrowser( mxWindow *parent ) + : IFacePoserToolWindow( "WaveBrowser", "Waves" ), mxWindow( parent, 0, 0, 0, 0 ) +{ + SetAutoProcess( false ); + + m_bTextSearch = false; + m_nPrevProcessed = -1; + + m_pListView = new CWaveList( this, IDC_SB_LISTVIEW ); + m_pOptions = new CWaveOptionsWindow( this ); + m_pFileTree = new CWaveFileTree( this, IDC_SB_FILETREE ); + + //HIMAGELIST list = CreateImageList(); + + // Associate the image list with the tree-view control. + //m_pListView->setImageList( (void *)list ); + + LoadAllSounds(); + + PopulateTree( NULL ); +} + +#define CX_ICON 16 +#define CY_ICON 16 + +HIMAGELIST CWaveBrowser::CreateImageList() +{ + HIMAGELIST list; + + list = ImageList_Create( CX_ICON, CY_ICON, + FALSE, NUM_IMAGES, 0 ); + + // Load the icon resources, and add the icons to the image list. + HICON hicon; + int slot; +#if defined( DBGFLAG_ASSERT ) + int c = 0; +#endif + + /* + hicon = LoadIcon( GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WORKSPACE)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + + hicon = LoadIcon( GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WORKSPACE_CHECKEDOUT)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + + hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_PROJECT)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + + hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_PROJECT_CHECKEDOUT)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + + hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SCENE)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + */ + +// hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SCENE_CHECKEDOUT)); +// slot = ImageList_AddIcon(list, hicon); +// Assert( slot == c++ ); +// DeleteObject( hicon ); + + /* + hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_VCD)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + + hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_VCD_CHECKEDOUT )); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + */ + + hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WAV)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + + /* + hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WAV_CHECKEDOUT)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + + hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SPEAK)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + + hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SPEAK_CHECKEDOUT)); + slot = ImageList_AddIcon(list, hicon); + Assert( slot == c++ ); + DeleteObject( hicon ); + */ + + return list; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWaveBrowser::OnDelete() +{ + RemoveAllSounds(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *event - +// Output : int +//----------------------------------------------------------------------------- +int CWaveBrowser::handleEvent( mxEvent *event ) +{ + int iret = 0; + + if ( HandleToolEvent( event ) ) + { + return iret; + } + + switch ( event->event ) + { + default: + break; + case mxEvent::Action: + { + iret = 1; + switch ( event->action ) + { + default: + { + iret = 0; + } + break; + case IDC_SB_LISTVIEW: + { + SetActiveTool( this ); + + bool rightmouse = ( event->flags == mxEvent::RightClicked ) ? true : false; + bool doubleclicked = ( event->flags == mxEvent::DoubleClicked ) ? true : false; + + if ( rightmouse ) + { + ShowContextMenu(); + } + else if ( doubleclicked ) + { + if ( m_pListView->getNumSelected() == 1 ) + { + int index = m_pListView->getNextSelectedItem( -1 ); + if ( index >= 0 ) + { + CWaveFile *wav = (CWaveFile *)m_pListView->getUserData( index, 0 ); + if ( wav ) + { + wav->Play(); + } + } + } + } + } + break; + case IDC_SB_FILETREE: + { + SetActiveTool( this ); + + PopulateTree( m_pFileTree->GetSelectedPath() ); + } + break; + case IDC_SB_PLAY: + { + OnPlay(); + } + break; + } + } + break; + case mxEvent::Size: + { + int optionsh = 20; + + m_pOptions->setBounds( 0, 0, w2(), optionsh ); + + int filetreewidth = 175; + + m_pFileTree->setBounds( 0, optionsh, filetreewidth, h2() - optionsh ); + m_pListView->setBounds( filetreewidth, optionsh, w2() - filetreewidth, h2() - optionsh ); + + iret = 1; + } + break; + case mxEvent::Close: + { + iret = 1; + } + break; + } + + return iret; +} + +static bool NameLessFunc( CWaveFile *const& name1, CWaveFile *const& name2 ) +{ + if ( Q_stricmp( name1->GetName(), name2->GetName() ) < 0 ) + return true; + return false; +} + +#define SOUND_PREFIX_LEN 6 +//----------------------------------------------------------------------------- +// Finds all .wav files in a particular directory +//----------------------------------------------------------------------------- +bool CWaveBrowser::LoadWaveFilesInDirectory( CUtlDict< CWaveFile *, int >& soundlist, char const* pDirectoryName, int nDirectoryNameLen ) +{ + Assert( Q_strnicmp( pDirectoryName, "sound", 5 ) == 0 ); + + char *pWildCard; + pWildCard = ( char * )stackalloc( nDirectoryNameLen + 7 ); + Q_snprintf( pWildCard, nDirectoryNameLen + 7, "%s/*.wav", pDirectoryName ); + + if ( !filesystem ) + { + return false; + } + + FileFindHandle_t findHandle; + const char *pFileName = filesystem->FindFirst( pWildCard, &findHandle ); + while( pFileName ) + { + if( !filesystem->FindIsDirectory( findHandle ) ) + { + // Strip off the 'sound/' part of the name. + char *pFileNameWithPath; + int nAllocSize = nDirectoryNameLen + Q_strlen(pFileName) + 2; + pFileNameWithPath = (char *)stackalloc( nAllocSize ); + Q_snprintf( pFileNameWithPath, nAllocSize, "%s/%s", &pDirectoryName[SOUND_PREFIX_LEN], pFileName ); + Q_strnlwr( pFileNameWithPath, nAllocSize ); + + CWaveFile *wav = new CWaveFile( pFileNameWithPath ); + soundlist.Insert( pFileNameWithPath, wav ); + + /* + if ( !(soundlist.Count() % 500 ) ) + { + Con_Printf( "CWaveBrowser: loaded %i sounds\n", soundlist.Count() ); + } + */ + } + pFileName = filesystem->FindNext( findHandle ); + } + + m_pFileTree->FindOrAddSubdirectory( &pDirectoryName[ SOUND_PREFIX_LEN ] ); + + filesystem->FindClose( findHandle ); + return true; +} + +bool CWaveBrowser::InitDirectoryRecursive( CUtlDict< CWaveFile *, int >& soundlist, char const* pDirectoryName ) +{ + // Compute directory name length + int nDirectoryNameLen = Q_strlen( pDirectoryName ); + + if (!LoadWaveFilesInDirectory( soundlist, pDirectoryName, nDirectoryNameLen ) ) + return false; + + char *pWildCard = ( char * )stackalloc( nDirectoryNameLen + 4 ); + strcpy(pWildCard, pDirectoryName); + strcat(pWildCard, "/*."); + int nPathStrLen = nDirectoryNameLen + 1; + + FileFindHandle_t findHandle; + const char *pFileName = filesystem->FindFirst( pWildCard, &findHandle ); + while( pFileName ) + { + if ((pFileName[0] != '.') || (pFileName[1] != '.' && pFileName[1] != 0)) + { + if( filesystem->FindIsDirectory( findHandle ) ) + { + int fileNameStrLen = Q_strlen( pFileName ); + char *pFileNameWithPath = ( char * )stackalloc( nPathStrLen + fileNameStrLen + 1 ); + memcpy( pFileNameWithPath, pWildCard, nPathStrLen ); + pFileNameWithPath[nPathStrLen] = '\0'; + strcat( pFileNameWithPath, pFileName ); + + if (!InitDirectoryRecursive( soundlist, pFileNameWithPath )) + return false; + } + } + pFileName = filesystem->FindNext( findHandle ); + } + + return true; +} + +void CWaveBrowser::LoadAllSounds() +{ + RemoveAllSounds(); + + Con_Printf( "Building list of all .wavs in sound/ folder\n" ); + + InitDirectoryRecursive( m_AllSounds, "sound" ); + + m_pFileTree->PopulateTree(); +} + +void CWaveBrowser::RemoveAllSounds() +{ + int c = m_AllSounds.Count(); + for ( int i = 0; i < c; i++ ) + { + CWaveFile *wav = m_AllSounds[ i ]; + delete wav; + } + + m_AllSounds.RemoveAll(); + m_Scripts.RemoveAll(); + m_CurrentSelection.RemoveAll(); + + m_pFileTree->Clear(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CWaveBrowser::PopulateTree( char const *subdirectory ) +{ + int i; + + CUtlRBTree< CWaveFile *, int > m_Sorted( 0, 0, NameLessFunc ); + + bool check_load_sentence_data = false; + + char const *texttofind = NULL; + + if ( m_bTextSearch ) + { + subdirectory = NULL; + texttofind = GetSearchString(); + } + + int len = 0; + if ( subdirectory ) + { + len = Q_strlen( subdirectory ); + check_load_sentence_data = ( Q_strstr( subdirectory, "/" ) || subdirectory[0] ) ? true : false; + } + + int c = m_AllSounds.Count(); + for ( i = 0; i < c; i++ ) + { + CWaveFile *wav = m_AllSounds[ i ]; + char const *name = wav->GetName(); + + if ( subdirectory ) + { + if ( Q_strnicmp( subdirectory, wav->GetName(), len ) ) + continue; + } + + if ( m_bTextSearch && texttofind ) + { + if ( !Q_stristr( name, texttofind ) ) + continue; + } + + m_Sorted.Insert( wav ); + } + + char prevSelectedName[ 512 ]; + prevSelectedName[ 0 ] = 0; + if ( m_pListView->getNumSelected() == 1 ) + { + int selectedItem = m_pListView->getNextSelectedItem( 0 ); + if ( selectedItem >= 0 ) + { + // Grab wave name of previously selected item + Q_strcpy( prevSelectedName, m_pListView->getLabel( selectedItem, 0 ) ); + } + } + +// Repopulate tree + m_pListView->removeAll(); + + int loadcount = 0; + + m_pListView->setDrawingEnabled( false ); + + int selectedSlot = -1; + + CUtlVector< CWaveFile * > list; + + + for ( i = m_Sorted.FirstInorder(); i != m_Sorted.InvalidIndex(); i = m_Sorted.NextInorder( i ) ) + { + CWaveFile *wav = m_Sorted[ i ]; + char const *name = wav->GetName(); + + int slot = m_pListView->add( name ); + + if ( !Q_stricmp( prevSelectedName, name ) ) + { + selectedSlot = slot; + } + + if ( ( check_load_sentence_data || m_bTextSearch ) && + !wav->HasLoadedSentenceInfo() && !wav->IsAsyncLoading() ) + { + wav->SetAsyncLoading( true ); + list.AddToTail( wav ); + } + + // m_pListView->setImage( slot, COL_WAV, wav->GetIconIndex() ); + m_pListView->setUserData( slot, COL_WAV, (void *)wav ); + + if ( wav->HasLoadedSentenceInfo() ) + { + m_pListView->setLabel( slot, COL_DUCKED, wav->GetVoiceDuck() ? "yes" : "no" ); + m_pListView->setLabel( slot, COL_PHONEMES, wav->GetPhonemeCount() || wav->GetWordCount() ? va( "%i [ %i ]", wav->GetWordCount(), wav->GetPhonemeCount() ) : "" ); + m_pListView->setLabel( slot, COL_SENTENCE, wav->GetSentenceText() ); + } + else + { + m_pListView->setLabel( slot, COL_SENTENCE, "(loading...)" ); + } + + ++loadcount; + } + + m_pListView->setDrawingEnabled( true ); + + if ( selectedSlot != -1 ) + { + m_pListView->setSelected( selectedSlot, true ); + m_pListView->scrollToItem( selectedSlot ); + } + + if ( list.Count() > 0 ) + { + fileloader->AddWaveFilesToThread( list ); + } + + // Con_Printf( "CWaveBrowser: selected %i sounds\n", loadcount ); +} + +void CWaveBrowser::RepopulateTree() +{ + PopulateTree( m_pFileTree->GetSelectedPath() ); +} + +void CWaveBrowser::BuildSelectionList( CUtlVector< CWaveFile * >& selected ) +{ + selected.RemoveAll(); + + int idx = -1; + do + { + idx = m_pListView->getNextSelectedItem( idx ); + if ( idx != -1 ) + { + CWaveFile *wav = (CWaveFile *)m_pListView->getUserData( idx, 0 ); + if ( wav ) + { + selected.AddToTail( wav ); + } + } + } while ( idx != -1 ); + +} + +void CWaveBrowser::ShowContextMenu( void ) +{ + SetActiveTool( this ); + + BuildSelectionList( m_CurrentSelection ); + if ( m_CurrentSelection.Count() <= 0 ) + return; + + POINT pt; + GetCursorPos( &pt ); + ScreenToClient( (HWND)getHandle(), &pt ); + + // New scene, edit comments + mxPopupMenu *pop = new mxPopupMenu(); + + if ( m_CurrentSelection.Count() == 1 ) + { + pop->add ("&Play", IDC_SB_PLAY ); +// pop->addSeparator(); + } + +// pop->add( "Import Sentence Data", IDC_SB_IMPORTSENTENCE ); +// pop->add( "Export Sentence Data", IDC_SB_EXPORTSENTENCE ); + + pop->popup( this, pt.x, pt.y ); +} + +void CWaveBrowser::OnPlay() +{ + SetActiveTool( this ); + + BuildSelectionList( m_CurrentSelection ); + if ( m_CurrentSelection.Count() == 1 ) + { + CWaveFile *wav = m_CurrentSelection[ 0 ]; + if ( wav ) + { + wav->Play(); + } + } +} + +static void SplitFileName( char const *in, char *path, int maxpath, char *filename, int maxfilename ) +{ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ext[_MAX_EXT]; + + _splitpath( in, drive, dir, fname, ext ); + + if ( dir[0] ) + { + Q_snprintf( path, maxpath, "\\%s", dir ); + } + else + { + path[0] = 0; + } + Q_snprintf( filename, maxfilename, "%s%s", fname, ext ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *se - +//----------------------------------------------------------------------------- +void CWaveBrowser::JumpToItem( CWaveFile *wav ) +{ + + SetActiveTool( this ); + + char path[ 256 ]; + char filename[ 256 ]; + + SplitFileName( wav->GetFileName(), path, sizeof( path ), filename, sizeof( filename ) ); + + char *usepath = path + Q_strlen( "/sound/" ); + PopulateTree( usepath ); + + int idx = 0; + int c = m_pListView->getItemCount(); + for ( ; idx < c; idx++ ) + { + CWaveFile *item = (CWaveFile *)m_pListView->getUserData( idx, 0 ); + if ( !Q_stricmp( item->GetFileName(), wav->GetFileName() ) ) + { + break; + } + } + + if ( idx < c ) + { + m_pListView->scrollToItem( idx ); + } +} + +CWaveFile *CWaveBrowser::FindEntry( char const *wavname, bool jump /*= false*/ ) +{ + int idx = m_AllSounds.Find( wavname ); + if ( idx != m_AllSounds.InvalidIndex() ) + { + CWaveFile *wav = m_AllSounds[ idx ]; + if ( jump ) + { + JumpToItem( wav ); + } + + return wav; + } + + return NULL; +} + +int CWaveBrowser::GetSoundCount() const +{ + return m_AllSounds.Count(); +} + +CWaveFile *CWaveBrowser::GetSound( int index ) +{ + if ( index < 0 || index >= (int)m_AllSounds.Count() ) + return NULL; + + return m_AllSounds[ index ]; +} + + +void CWaveBrowser::OnSearch() +{ + SetActiveTool( this ); + + m_bTextSearch = true; + + PopulateTree( GetSearchString()); +} + +void CWaveBrowser::OnCancelSearch() +{ + SetActiveTool( this ); + + m_bTextSearch = false; + + PopulateTree( m_pFileTree->GetSelectedPath() ); +} + +char const *CWaveBrowser::GetSearchString() +{ + return m_pOptions->GetSearchString(); +} + +void CWaveBrowser::Think( float dt ) +{ + int pending = fileloader->GetPendingLoadCount(); + if ( pending != m_nPrevProcessed ) + { + m_nPrevProcessed = pending; + + // Put into suffix of window title + if ( pending == 0 ) + { + SetSuffix( "" ); + } + else + { + SetSuffix( va( " - %i", pending ) ); + } + } + + int c = fileloader->ProcessCompleted(); + if ( c > 0 ) + { + RepopulateTree(); + } +} + +void CWaveBrowser::SetEvent( CChoreoEvent *event ) +{ + if ( event->GetType() != CChoreoEvent::SPEAK ) + return; + + SetCurrent( FacePoser_TranslateSoundName( event->GetParameters() ) ); +} + +void CWaveBrowser::SetCurrent( char const *filename ) +{ +// Get sound name and look up .wav from it + char const *p = filename; + if ( p && + ( !Q_strnicmp( p, "sound/", 6 ) || !Q_strnicmp( p, "sound\\", 6 ) ) ) + { + p += 6; + } + + char fn[ 512 ]; + Q_strncpy( fn, p, sizeof( fn ) ); + Q_FixSlashes( fn ); + + int i; + int c = m_pListView->getItemCount(); + + for ( i = 0; i < c; ++i ) + { + CWaveFile *wav = reinterpret_cast< CWaveFile * >( m_pListView->getUserData( i, COL_WAV ) ); + if ( !wav ) + continue; + + char fixed[ 512 ]; + Q_strncpy( fixed, wav->GetName(), sizeof( fixed ) ); + Q_FixSlashes( fixed ); + + if ( !Q_stricmp( fixed, fn ) ) + { + m_pListView->scrollToItem( i ); + m_pListView->setSelected( i, true ); + } + else + { + m_pListView->setSelected( i, false ); + } + } +} |