Team Fortress 2 Source Code as on 22/4/2020
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.

1065 lines
22 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "workspacebrowser.h"
  8. #include "workspace.h"
  9. #include "project.h"
  10. #include <windows.h>
  11. #include "resource.h"
  12. #include "project.h"
  13. #include "vcdfile.h"
  14. #include "wavefile.h"
  15. #include "scene.h"
  16. #include "workspacemanager.h"
  17. #include "wavebrowser.h"
  18. #include "SoundEmitterSystem/isoundemittersystembase.h"
  19. #include "iscenemanagersound.h"
  20. #include "snd_wave_source.h"
  21. #include "cmdlib.h"
  22. #include "tabwindow.h"
  23. #include "inputproperties.h"
  24. #include "waveproperties.h"
  25. #include "drawhelper.h"
  26. #include "ifileloader.h"
  27. #include "MultipleRequest.h"
  28. #include "soundchars.h"
  29. enum
  30. {
  31. // Controls
  32. IDC_SB_LISTVIEW = 101,
  33. IDC_SB_FILETREE,
  34. // Messages
  35. IDC_SB_PLAY = 1000,
  36. IDC_SB_CHECKOUT,
  37. IDC_SB_CHECKIN,
  38. IDC_SB_PROPERTIES,
  39. IDC_SB_ENABLEVOICEDUCKING,
  40. IDC_SB_DISABLEVOICEDUCKING,
  41. IDC_SB_EXPORTSENTENCE,
  42. IDC_SB_IMPORTSENTENCE,
  43. IDC_SB_GETSENTENCE,
  44. };
  45. enum
  46. {
  47. COL_WAV = 0,
  48. COL_DUCKED,
  49. COL_SENTENCE
  50. };
  51. class CWaveList : public mxListView
  52. {
  53. public:
  54. CWaveList( mxWindow *parent, int id = 0 )
  55. : mxListView( parent, 0, 0, 0, 0, id )
  56. {
  57. // SendMessage ( (HWND)getHandle(), WM_SETFONT, (WPARAM) (HFONT) GetStockObject (ANSI_FIXED_FONT), MAKELPARAM (TRUE, 0));
  58. //HWND wnd = (HWND)getHandle();
  59. //DWORD style = GetWindowLong( wnd, GWL_STYLE );
  60. //style |= LVS_SORTASCENDING;
  61. //SetWindowLong( wnd, GWL_STYLE, style );
  62. //SceneManager_AddWindowStyle( this, LVS_SORTASCENDING );
  63. // Add column headers
  64. insertTextColumn( COL_WAV, 300, "WAV" );
  65. insertTextColumn( COL_DUCKED, 50, "Ducked" );
  66. insertTextColumn( COL_SENTENCE, 300, "Sentence Text" );
  67. }
  68. };
  69. class CWaveFileTree : public mxTreeView
  70. {
  71. public:
  72. CWaveFileTree( mxWindow *parent, int id = 0 ) : mxTreeView( parent, 0, 0, 0, 0, id ),
  73. m_Paths( 0, 0, FileTreeLessFunc )
  74. {
  75. }
  76. void Clear()
  77. {
  78. removeAll();
  79. m_Paths.RemoveAll();
  80. }
  81. void FindOrAddSubdirectory( char const *subdir )
  82. {
  83. FileTreePath fp;
  84. Q_strcpy( fp.path, subdir );
  85. if ( m_Paths.Find( fp ) != m_Paths.InvalidIndex() )
  86. return;
  87. m_Paths.Insert( fp );
  88. }
  89. mxTreeViewItem *FindOrAddChildItem( mxTreeViewItem *parent, char const *child )
  90. {
  91. mxTreeViewItem *p = getFirstChild( parent );
  92. if ( !p )
  93. {
  94. return add( parent, child );
  95. }
  96. while ( p )
  97. {
  98. if ( !Q_stricmp( getLabel( p ), child ) )
  99. return p;
  100. p = getNextChild( p );
  101. }
  102. return add( parent, child );
  103. }
  104. void _PopulateTree( int pathId, char const *path )
  105. {
  106. char sz[ 512 ];
  107. Q_strcpy( sz, path );
  108. char *p = sz;
  109. // Start at root
  110. mxTreeViewItem *cur = NULL;
  111. // Tokenize path
  112. while ( p && p[0] )
  113. {
  114. char *slash = Q_strstr( p, "/" );
  115. if ( !slash )
  116. {
  117. slash = Q_strstr( p, "\\" );
  118. }
  119. char *check = p;
  120. if ( slash )
  121. {
  122. *slash = 0;
  123. // see if a child of current already exists with this name
  124. p = slash + 1;
  125. }
  126. else
  127. {
  128. p = NULL;
  129. }
  130. Assert( check );
  131. cur = FindOrAddChildItem( cur, check );
  132. }
  133. setUserData( cur, (void *)pathId );
  134. }
  135. char const *GetSelectedPath( void )
  136. {
  137. mxTreeViewItem *tvi = getSelectedItem();
  138. int id = (int)getUserData( tvi );
  139. if ( id < 0 || id >= m_Paths.Count() )
  140. {
  141. Assert( 0 );
  142. return "";
  143. }
  144. return m_Paths[ id ].path;
  145. }
  146. void PopulateTree()
  147. {
  148. int i;
  149. for ( i = m_Paths.FirstInorder(); i != m_Paths.InvalidIndex(); i = m_Paths.NextInorder( i ) )
  150. {
  151. _PopulateTree( i, m_Paths[ i ].path );
  152. }
  153. mxTreeViewItem *p = getFirstChild( NULL );
  154. setOpen( p, true );
  155. }
  156. struct FileTreePath
  157. {
  158. char path[ MAX_PATH ];
  159. };
  160. static bool FileTreeLessFunc( const FileTreePath &lhs, const FileTreePath &rhs )
  161. {
  162. return Q_stricmp( lhs.path, rhs.path ) < 0;
  163. }
  164. CUtlRBTree< FileTreePath, int > m_Paths;
  165. };
  166. class CWaveOptionsWindow : public mxWindow
  167. {
  168. typedef mxWindow BaseClass;
  169. public:
  170. enum
  171. {
  172. IDC_PLAY_SOUND = 1000,
  173. IDC_STOP_SOUNDS,
  174. IDC_SEARCH,
  175. };
  176. CWaveOptionsWindow( CWaveBrowser *browser ) : BaseClass( browser, 0, 0, 0, 0 ), m_pBrowser( browser )
  177. {
  178. SceneManager_AddWindowStyle( this, WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
  179. m_szSearchString[0]=0;
  180. m_pPlay = new mxButton( this, 0, 0, 0, 0, "Play", IDC_PLAY_SOUND );
  181. m_pStopSounds = new mxButton( this, 0, 0, 0, 0, "Stop Sounds", IDC_STOP_SOUNDS );
  182. m_pSearch = new mxButton( this, 0, 0, 0, 0, "Search...", IDC_SEARCH );
  183. m_pSearchString = new mxLabel( this, 0, 0, 0, 0, "" );
  184. }
  185. bool PaintBackground( void )
  186. {
  187. redraw();
  188. return false;
  189. }
  190. virtual void redraw()
  191. {
  192. CDrawHelper drawHelper( this, GetSysColor( COLOR_BTNFACE ) );
  193. }
  194. virtual int handleEvent( mxEvent *event )
  195. {
  196. int iret = 0;
  197. switch ( event->event )
  198. {
  199. default:
  200. break;
  201. case mxEvent::Size:
  202. {
  203. iret = 1;
  204. int split = 120;
  205. int x = 1;
  206. m_pPlay->setBounds( x, 1, split, h2() - 2 );
  207. x += split + 10;
  208. m_pStopSounds->setBounds( x, 1, split, h2()-2 );
  209. x += split + 10;
  210. m_pSearch->setBounds( x, 1, split, h2() - 2 );
  211. x += split + 10;
  212. m_pSearchString->setBounds( x, 2, split * 2, h2() - 4 );
  213. x += split * 2 + 10;
  214. }
  215. break;
  216. case mxEvent::Action:
  217. {
  218. switch ( event->action )
  219. {
  220. case IDC_STOP_SOUNDS:
  221. {
  222. iret = 1;
  223. sound->StopAll();
  224. }
  225. break;
  226. case IDC_PLAY_SOUND:
  227. {
  228. iret = 1;
  229. m_pBrowser->OnPlay();
  230. }
  231. break;
  232. case IDC_SEARCH:
  233. {
  234. iret = 1;
  235. OnSearch();
  236. };
  237. break;
  238. default:
  239. break;
  240. }
  241. }
  242. break;
  243. }
  244. return iret;
  245. }
  246. char const *GetSearchString()
  247. {
  248. return m_szSearchString;
  249. }
  250. void OnSearch()
  251. {
  252. CInputParams params;
  253. memset( &params, 0, sizeof( params ) );
  254. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "Search" );
  255. Q_strcpy( params.m_szPrompt, "Find:" );
  256. Q_strcpy( params.m_szInputText, m_szSearchString );
  257. if ( !InputProperties( &params ) )
  258. return;
  259. Q_strcpy( m_szSearchString, params.m_szInputText );
  260. m_pSearchString->setLabel( va( "Search: '%s'", GetSearchString() ) );
  261. m_pBrowser->OnSearch();
  262. }
  263. private:
  264. mxButton *m_pStopSounds;
  265. mxButton *m_pPlay;
  266. mxButton *m_pSearch;
  267. mxLabel *m_pSearchString;
  268. CWaveBrowser *m_pBrowser;
  269. char m_szSearchString[ 256 ];
  270. };
  271. //-----------------------------------------------------------------------------
  272. // Purpose:
  273. // Input : *parent -
  274. //-----------------------------------------------------------------------------
  275. CWaveBrowser::CWaveBrowser( mxWindow *parent, CWorkspaceManager *manager, int id ) :
  276. BaseClass( parent, 0, 0, 0, 0, "Wave Browser", id )
  277. {
  278. m_pManager = manager;
  279. SceneManager_MakeToolWindow( this, false );
  280. m_pListView = new CWaveList( this, IDC_SB_LISTVIEW );
  281. m_pOptions = new CWaveOptionsWindow( this );
  282. m_pFileTree = new CWaveFileTree( this, IDC_SB_FILETREE );
  283. HIMAGELIST list = GetWorkspaceManager()->CreateImageList();
  284. // Associate the image list with the tree-view control.
  285. m_pListView->setImageList( (void *)list );
  286. LoadAllSounds();
  287. PopulateTree( NULL );
  288. }
  289. //-----------------------------------------------------------------------------
  290. // Purpose:
  291. //-----------------------------------------------------------------------------
  292. void CWaveBrowser::OnDelete()
  293. {
  294. RemoveAllSounds();
  295. }
  296. //-----------------------------------------------------------------------------
  297. // Purpose:
  298. // Input : *event -
  299. // Output : int
  300. //-----------------------------------------------------------------------------
  301. int CWaveBrowser::handleEvent( mxEvent *event )
  302. {
  303. int iret = 0;
  304. switch ( event->event )
  305. {
  306. default:
  307. break;
  308. case mxEvent::Action:
  309. {
  310. iret = 1;
  311. switch ( event->action )
  312. {
  313. default:
  314. {
  315. iret = 0;
  316. }
  317. break;
  318. case IDC_SB_LISTVIEW:
  319. {
  320. bool rightmouse = ( event->flags == mxEvent::RightClicked ) ? true : false;
  321. bool doubleclicked = ( event->flags == mxEvent::DoubleClicked ) ? true : false;
  322. if ( rightmouse )
  323. {
  324. ShowContextMenu();
  325. }
  326. else if ( doubleclicked )
  327. {
  328. if ( m_pListView->getNumSelected() == 1 )
  329. {
  330. int index = m_pListView->getNextSelectedItem( -1 );
  331. if ( index >= 0 )
  332. {
  333. CWaveFile *wav = (CWaveFile *)m_pListView->getUserData( index, 0 );
  334. if ( wav )
  335. {
  336. wav->Play();
  337. }
  338. }
  339. }
  340. }
  341. }
  342. break;
  343. case IDC_SB_FILETREE:
  344. {
  345. PopulateTree( m_pFileTree->GetSelectedPath() );
  346. }
  347. break;
  348. case IDC_SB_PLAY:
  349. {
  350. OnPlay();
  351. }
  352. break;
  353. case IDC_SB_GETSENTENCE:
  354. {
  355. OnGetSentence();
  356. }
  357. break;
  358. case IDC_SB_PROPERTIES:
  359. {
  360. OnWaveProperties();
  361. }
  362. break;
  363. case IDC_SB_CHECKOUT:
  364. {
  365. OnCheckout();
  366. }
  367. break;
  368. case IDC_SB_CHECKIN:
  369. {
  370. OnCheckin();
  371. }
  372. break;
  373. case IDC_SB_ENABLEVOICEDUCKING:
  374. {
  375. OnEnableVoiceDucking();
  376. }
  377. break;
  378. case IDC_SB_DISABLEVOICEDUCKING:
  379. {
  380. OnDisableVoiceDucking();
  381. }
  382. break;
  383. case IDC_SB_IMPORTSENTENCE:
  384. {
  385. OnImportSentence();
  386. }
  387. break;
  388. case IDC_SB_EXPORTSENTENCE:
  389. {
  390. OnExportSentence();
  391. }
  392. break;
  393. }
  394. }
  395. break;
  396. case mxEvent::Size:
  397. {
  398. int optionsh = 20;
  399. m_pOptions->setBounds( 0, 0, w2(), optionsh );
  400. int filetreewidth = 175;
  401. m_pFileTree->setBounds( 0, optionsh, filetreewidth, h2() - optionsh );
  402. m_pListView->setBounds( filetreewidth, optionsh, w2() - filetreewidth, h2() - optionsh );
  403. GetWorkspaceManager()->SetWorkspaceDirty();
  404. iret = 1;
  405. }
  406. break;
  407. case mxEvent::Close:
  408. {
  409. iret = 1;
  410. }
  411. break;
  412. }
  413. return iret;
  414. }
  415. static bool NameLessFunc( CWaveFile *const& name1, CWaveFile *const& name2 )
  416. {
  417. if ( Q_stricmp( name1->GetName(), name2->GetName() ) < 0 )
  418. return true;
  419. return false;
  420. }
  421. #define SOUND_PREFIX_LEN 6
  422. //-----------------------------------------------------------------------------
  423. // Finds all .wav files in a particular directory
  424. //-----------------------------------------------------------------------------
  425. bool CWaveBrowser::LoadWaveFilesInDirectory( CUtlDict< CWaveFile *, int >& soundlist, char const* pDirectoryName, int nDirectoryNameLen )
  426. {
  427. Assert( Q_strnicmp( pDirectoryName, "sound", 5 ) == 0 );
  428. char *pWildCard;
  429. pWildCard = ( char * )stackalloc( nDirectoryNameLen + 7 );
  430. Q_snprintf( pWildCard, nDirectoryNameLen + 7, "%s/*.wav", pDirectoryName );
  431. if ( !filesystem )
  432. {
  433. return false;
  434. }
  435. FileFindHandle_t findHandle;
  436. const char *pFileName = filesystem->FindFirst( pWildCard, &findHandle );
  437. while( pFileName )
  438. {
  439. if( !filesystem->FindIsDirectory( findHandle ) )
  440. {
  441. // Strip off the 'sound/' part of the name.
  442. char *pFileNameWithPath;
  443. int nAllocSize = nDirectoryNameLen + Q_strlen(pFileName) + 2;
  444. pFileNameWithPath = (char *)stackalloc( nAllocSize );
  445. Q_snprintf( pFileNameWithPath, nAllocSize, "%s/%s", &pDirectoryName[SOUND_PREFIX_LEN], pFileName );
  446. Q_strnlwr( pFileNameWithPath, nAllocSize );
  447. CWaveFile *wav = new CWaveFile( NULL, NULL, pFileNameWithPath );
  448. soundlist.Insert( pFileNameWithPath, wav );
  449. /*
  450. if ( !(soundlist.Count() % 500 ) )
  451. {
  452. Con_Printf( "CWaveBrowser: loaded %i sounds\n", soundlist.Count() );
  453. }
  454. */
  455. }
  456. pFileName = filesystem->FindNext( findHandle );
  457. }
  458. m_pFileTree->FindOrAddSubdirectory( &pDirectoryName[ SOUND_PREFIX_LEN ] );
  459. filesystem->FindClose( findHandle );
  460. return true;
  461. }
  462. bool CWaveBrowser::InitDirectoryRecursive( CUtlDict< CWaveFile *, int >& soundlist, char const* pDirectoryName )
  463. {
  464. // Compute directory name length
  465. int nDirectoryNameLen = Q_strlen( pDirectoryName );
  466. if (!LoadWaveFilesInDirectory( soundlist, pDirectoryName, nDirectoryNameLen ) )
  467. return false;
  468. char *pWildCard = ( char * )stackalloc( nDirectoryNameLen + 4 );
  469. strcpy(pWildCard, pDirectoryName);
  470. strcat(pWildCard, "/*.");
  471. int nPathStrLen = nDirectoryNameLen + 1;
  472. FileFindHandle_t findHandle;
  473. const char *pFileName = filesystem->FindFirst( pWildCard, &findHandle );
  474. while( pFileName )
  475. {
  476. if ((pFileName[0] != '.') || (pFileName[1] != '.' && pFileName[1] != 0))
  477. {
  478. if( filesystem->FindIsDirectory( findHandle ) )
  479. {
  480. int fileNameStrLen = Q_strlen( pFileName );
  481. char *pFileNameWithPath = ( char * )stackalloc( nPathStrLen + fileNameStrLen + 1 );
  482. memcpy( pFileNameWithPath, pWildCard, nPathStrLen );
  483. pFileNameWithPath[nPathStrLen] = '\0';
  484. strcat( pFileNameWithPath, pFileName );
  485. if (!InitDirectoryRecursive( soundlist, pFileNameWithPath ))
  486. return false;
  487. }
  488. }
  489. pFileName = filesystem->FindNext( findHandle );
  490. }
  491. return true;
  492. }
  493. void CWaveBrowser::LoadAllSounds()
  494. {
  495. RemoveAllSounds();
  496. InitDirectoryRecursive( m_AllSounds, "sound" );
  497. // InitDirectoryRecursive( m_AllSounds, "sound/npc" );
  498. int c = m_AllSounds.Count();
  499. CUtlVector< CWaveFile * > list;
  500. for ( int i = 0; i < c; i++ )
  501. {
  502. CWaveFile *wav = m_AllSounds[ i ];
  503. list.AddToTail( wav );
  504. }
  505. fileloader->AddWaveFilesToThread( list );
  506. m_pFileTree->PopulateTree();
  507. }
  508. void CWaveBrowser::RemoveAllSounds()
  509. {
  510. int c = m_AllSounds.Count();
  511. for ( int i = 0; i < c; i++ )
  512. {
  513. CWaveFile *wav = m_AllSounds[ i ];
  514. delete wav;
  515. }
  516. m_AllSounds.RemoveAll();
  517. m_Scripts.RemoveAll();
  518. m_CurrentSelection.RemoveAll();
  519. m_pFileTree->Clear();
  520. }
  521. //-----------------------------------------------------------------------------
  522. // Purpose:
  523. //-----------------------------------------------------------------------------
  524. void CWaveBrowser::PopulateTree( char const *subdirectory, bool textsearch /*= false*/ )
  525. {
  526. int i;
  527. CUtlRBTree< CWaveFile *, int > m_Sorted( 0, 0, NameLessFunc );
  528. bool check_load_sentence_data = false;
  529. char const *texttofind = NULL;
  530. if ( textsearch )
  531. {
  532. subdirectory = NULL;
  533. texttofind = GetSearchString();
  534. }
  535. int len = 0;
  536. if ( subdirectory )
  537. {
  538. len = Q_strlen( subdirectory );
  539. check_load_sentence_data = Q_strstr( subdirectory, "/" ) ? true : false;
  540. }
  541. int c = m_AllSounds.Count();
  542. for ( i = 0; i < c; i++ )
  543. {
  544. CWaveFile *wav = m_AllSounds[ i ];
  545. char const *name = wav->GetName();
  546. if ( subdirectory )
  547. {
  548. if ( Q_strnicmp( subdirectory, wav->GetName(), len ) )
  549. continue;
  550. }
  551. if ( textsearch && texttofind )
  552. {
  553. if ( !Q_stristr( name, texttofind ) )
  554. continue;
  555. }
  556. m_Sorted.Insert( wav );
  557. }
  558. char prevSelectedName[ 512 ];
  559. prevSelectedName[ 0 ] = 0;
  560. if ( m_pListView->getNumSelected() == 1 )
  561. {
  562. int selectedItem = m_pListView->getNextSelectedItem( 0 );
  563. if ( selectedItem >= 0 )
  564. {
  565. // Grab wave name of previously selected item
  566. Q_strcpy( prevSelectedName, m_pListView->getLabel( selectedItem, 0 ) );
  567. }
  568. }
  569. // Repopulate tree
  570. m_pListView->removeAll();
  571. int loadcount = 0;
  572. m_pListView->setDrawingEnabled( false );
  573. int selectedSlot = -1;
  574. for ( i = m_Sorted.FirstInorder(); i != m_Sorted.InvalidIndex(); i = m_Sorted.NextInorder( i ) )
  575. {
  576. CWaveFile *wav = m_Sorted[ i ];
  577. char const *name = wav->GetName();
  578. int slot = m_pListView->add( name );
  579. if ( !Q_stricmp( prevSelectedName, name ) )
  580. {
  581. selectedSlot = slot;
  582. }
  583. m_pListView->setImage( slot, COL_WAV, wav->GetIconIndex() );
  584. m_pListView->setUserData( slot, COL_WAV, (void *)wav );
  585. if ( wav->HasLoadedSentenceInfo() )
  586. {
  587. m_pListView->setLabel( slot, COL_DUCKED, wav->GetVoiceDuck() ? "yes" : "no" );
  588. m_pListView->setLabel( slot, COL_SENTENCE, wav->GetSentenceText() );
  589. }
  590. else
  591. {
  592. m_pListView->setLabel( slot, COL_SENTENCE, "(loading...)" );
  593. }
  594. ++loadcount;
  595. }
  596. m_pListView->setDrawingEnabled( true );
  597. if ( selectedSlot != -1 )
  598. {
  599. m_pListView->setSelected( selectedSlot, true );
  600. m_pListView->scrollToItem( selectedSlot );
  601. }
  602. // Con_Printf( "CWaveBrowser: selected %i sounds\n", loadcount );
  603. }
  604. CWorkspaceManager *CWaveBrowser::GetManager()
  605. {
  606. return m_pManager;
  607. }
  608. void CWaveBrowser::RepopulateTree()
  609. {
  610. PopulateTree( m_pFileTree->GetSelectedPath() );
  611. }
  612. void CWaveBrowser::BuildSelectionList( CUtlVector< CWaveFile * >& selected )
  613. {
  614. selected.RemoveAll();
  615. int idx = -1;
  616. do
  617. {
  618. idx = m_pListView->getNextSelectedItem( idx );
  619. if ( idx != -1 )
  620. {
  621. CWaveFile *wav = (CWaveFile *)m_pListView->getUserData( idx, 0 );
  622. if ( wav )
  623. {
  624. selected.AddToTail( wav );
  625. }
  626. }
  627. } while ( idx != -1 );
  628. }
  629. void CWaveBrowser::ShowContextMenu( void )
  630. {
  631. BuildSelectionList( m_CurrentSelection );
  632. if ( m_CurrentSelection.Count() <= 0 )
  633. return;
  634. POINT pt;
  635. GetCursorPos( &pt );
  636. ScreenToClient( (HWND)getHandle(), &pt );
  637. // New scene, edit comments
  638. mxPopupMenu *pop = new mxPopupMenu();
  639. if ( m_CurrentSelection.Count() == 1 )
  640. {
  641. pop->add ("&Play", IDC_SB_PLAY );
  642. pop->add( "Properties...", IDC_SB_PROPERTIES );
  643. pop->addSeparator();
  644. }
  645. else
  646. {
  647. pop->add( "Enable Voice Ducking", IDC_SB_ENABLEVOICEDUCKING );
  648. pop->add( "Disable Voice Ducking", IDC_SB_DISABLEVOICEDUCKING );
  649. pop->addSeparator();
  650. }
  651. pop->add( "Refresh sentence data", IDC_SB_GETSENTENCE );
  652. pop->add( "Import Sentence Data", IDC_SB_IMPORTSENTENCE );
  653. pop->add( "Export Sentence Data", IDC_SB_EXPORTSENTENCE );
  654. pop->addSeparator();
  655. pop->add( "Check out", IDC_SB_CHECKOUT );
  656. pop->add( "Check in", IDC_SB_CHECKIN );
  657. pop->popup( this, pt.x, pt.y );
  658. }
  659. void CWaveBrowser::OnPlay()
  660. {
  661. BuildSelectionList( m_CurrentSelection );
  662. if ( m_CurrentSelection.Count() == 1 )
  663. {
  664. CWaveFile *wav = m_CurrentSelection[ 0 ];
  665. if ( wav )
  666. {
  667. wav->Play();
  668. }
  669. }
  670. }
  671. void CWaveBrowser::OnCheckout()
  672. {
  673. BuildSelectionList( m_CurrentSelection );
  674. int c = m_CurrentSelection.Count();
  675. for ( int i = 0; i < c; i++ )
  676. {
  677. CWaveFile *wav = m_CurrentSelection[ i ];
  678. Assert( wav );
  679. wav->Checkout( false );
  680. }
  681. GetWorkspaceManager()->RefreshBrowsers();
  682. }
  683. void CWaveBrowser::OnCheckin()
  684. {
  685. BuildSelectionList( m_CurrentSelection );
  686. int c = m_CurrentSelection.Count();
  687. for ( int i = 0; i < c; i++ )
  688. {
  689. CWaveFile *wav = m_CurrentSelection[ i ];
  690. Assert( wav );
  691. wav->Checkin( false );
  692. }
  693. GetWorkspaceManager()->RefreshBrowsers();
  694. }
  695. void SplitFileName( char const *in, char *path, int maxpath, char *filename, int maxfilename );
  696. //-----------------------------------------------------------------------------
  697. // Purpose:
  698. // Input : *se -
  699. //-----------------------------------------------------------------------------
  700. void CWaveBrowser::JumpToItem( CWaveFile *wav )
  701. {
  702. char path[ 256 ];
  703. char filename[ 256 ];
  704. SplitFileName( wav->GetFileName(), path, sizeof( path ), filename, sizeof( filename ) );
  705. char *usepath = path + Q_strlen( "/sound/" );
  706. PopulateTree( usepath );
  707. int idx = 0;
  708. int c = m_pListView->getItemCount();
  709. for ( ; idx < c; idx++ )
  710. {
  711. CWaveFile *item = (CWaveFile *)m_pListView->getUserData( idx, 0 );
  712. if ( !Q_stricmp( item->GetFileName(), wav->GetFileName() ) )
  713. {
  714. break;
  715. }
  716. }
  717. if ( idx < c )
  718. {
  719. m_pListView->scrollToItem( idx );
  720. }
  721. }
  722. CWaveFile *CWaveBrowser::FindEntry( char const *wavname, bool jump /*= false*/ )
  723. {
  724. int idx = m_AllSounds.Find( PSkipSoundChars( wavname ) );
  725. if ( idx != m_AllSounds.InvalidIndex() )
  726. {
  727. CWaveFile *wav = m_AllSounds[ idx ];
  728. #if defined( _DEBUG )
  729. char const *name = wav->GetName();
  730. NOTE_UNUSED( name );
  731. #endif
  732. if ( jump )
  733. {
  734. JumpToItem( wav );
  735. }
  736. return wav;
  737. }
  738. return NULL;
  739. }
  740. void CWaveBrowser::OnWaveProperties()
  741. {
  742. BuildSelectionList( m_CurrentSelection );
  743. if ( m_CurrentSelection.Count() != 1 )
  744. {
  745. Con_Printf( "Can only apply properties to one item at a time (FOR NOW)\n" );
  746. return;
  747. }
  748. CWaveFile *entry = m_CurrentSelection[ 0 ];
  749. if ( !entry )
  750. return;
  751. CWaveParams params;
  752. memset( &params, 0, sizeof( params ) );
  753. Q_snprintf( params.m_szDialogTitle, sizeof( params.m_szDialogTitle ), "Wave Properties" );
  754. params.items.AddToTail( entry );
  755. if ( !WaveProperties( &params ) )
  756. return;
  757. }
  758. int CWaveBrowser::GetSoundCount() const
  759. {
  760. return m_AllSounds.Count();
  761. }
  762. CWaveFile *CWaveBrowser::GetSound( int index )
  763. {
  764. if ( index < 0 || index >= m_AllSounds.Count() )
  765. return NULL;
  766. return m_AllSounds[ index ];
  767. }
  768. void CWaveBrowser::OnSearch()
  769. {
  770. PopulateTree( GetSearchString(), true );
  771. }
  772. char const *CWaveBrowser::GetSearchString()
  773. {
  774. return m_pOptions->GetSearchString();
  775. }
  776. void CWaveBrowser::OnEnableVoiceDucking()
  777. {
  778. BuildSelectionList( m_CurrentSelection );
  779. int count = m_CurrentSelection.Count();
  780. if ( count < 1 )
  781. return;
  782. MultipleRequestChangeContext();
  783. for ( int i = 0; i < count; i++ )
  784. {
  785. CWaveFile *item = m_CurrentSelection[ i ];
  786. if ( !item->GetVoiceDuck() )
  787. {
  788. item->SetVoiceDuck( true );
  789. }
  790. }
  791. GetWorkspaceManager()->RefreshBrowsers();
  792. }
  793. void CWaveBrowser::OnDisableVoiceDucking()
  794. {
  795. BuildSelectionList( m_CurrentSelection );
  796. int count = m_CurrentSelection.Count();
  797. if ( count < 1 )
  798. return;
  799. MultipleRequestChangeContext();
  800. for ( int i = 0; i < count; i++ )
  801. {
  802. CWaveFile *item = m_CurrentSelection[ i ];
  803. if ( item->GetVoiceDuck() )
  804. {
  805. item->SetVoiceDuck( false );
  806. }
  807. }
  808. GetWorkspaceManager()->RefreshBrowsers();
  809. }
  810. void CWaveBrowser::OnImportSentence()
  811. {
  812. BuildSelectionList( m_CurrentSelection );
  813. int count = m_CurrentSelection.Count();
  814. if ( count < 1 )
  815. return;
  816. MultipleRequestChangeContext();
  817. for ( int i = 0; i < count; i++ )
  818. {
  819. CWaveFile *item = m_CurrentSelection[ i ];
  820. char relative[ 512 ];
  821. item->GetPhonemeExportFile( relative, sizeof( relative ) );
  822. if ( filesystem->FileExists( relative ) )
  823. {
  824. item->ImportValveDataChunk( relative );
  825. }
  826. }
  827. GetWorkspaceManager()->RefreshBrowsers();
  828. }
  829. void CWaveBrowser::OnExportSentence()
  830. {
  831. BuildSelectionList( m_CurrentSelection );
  832. int count = m_CurrentSelection.Count();
  833. if ( count < 1 )
  834. return;
  835. for ( int i = 0; i < count; i++ )
  836. {
  837. CWaveFile *item = m_CurrentSelection[ i ];
  838. char relative[ 512 ];
  839. item->GetPhonemeExportFile( relative, sizeof( relative ) );
  840. if ( filesystem->FileExists( relative ) )
  841. {
  842. filesystem->RemoveFile( relative );
  843. }
  844. item->ExportValveDataChunk( relative );
  845. }
  846. }
  847. void CWaveBrowser::OnGetSentence()
  848. {
  849. BuildSelectionList( m_CurrentSelection );
  850. if ( m_CurrentSelection.Count() < 1 )
  851. {
  852. Con_Printf( "No selection\n" );
  853. return;
  854. }
  855. int c = m_CurrentSelection.Count();
  856. for ( int i = c - 1; i >= 0 ; i-- )
  857. {
  858. CWaveFile *wav = m_CurrentSelection[ i ];
  859. if ( !wav->HasLoadedSentenceInfo() )
  860. {
  861. wav->EnsureSentence();
  862. }
  863. }
  864. // Repopulate things
  865. GetWorkspaceManager()->RefreshBrowsers();
  866. }