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.

672 lines
17 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include <mxtk/mx.h>
  9. #include <stdio.h>
  10. #include "resource.h"
  11. #include "EventProperties.h"
  12. #include "mdlviewer.h"
  13. #include "choreoevent.h"
  14. #include "filesystem.h"
  15. #include "SoundEmitterSystem/isoundemittersystembase.h"
  16. #include "AddSoundEntry.h"
  17. #include "SoundLookup.h"
  18. #include "ifaceposersound.h"
  19. #include "MatSysWin.h"
  20. static CEventParams g_Params;
  21. class CEventPropertiesSpeakDialog : public CBaseEventPropertiesDialog
  22. {
  23. typedef CBaseEventPropertiesDialog BaseClass;
  24. public:
  25. CEventPropertiesSpeakDialog()
  26. {
  27. m_bShowAll = false;
  28. m_szLastFilter[ 0 ] = 0;
  29. m_Timer = 0;
  30. m_flLastFilterUpdateTime;
  31. }
  32. virtual void InitDialog( HWND hwndDlg );
  33. virtual BOOL HandleMessage( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
  34. virtual void SetTitle();
  35. virtual void ShowControlsForEventType( CEventParams *params );
  36. virtual void InitControlData( CEventParams *params );
  37. private:
  38. void PopulateFilterList( bool resetCurrent );
  39. void OnCheckFilterUpdate();
  40. void AddFilterToHistory( char const *filter );
  41. void OnSoundSelected( CEventParams *params );
  42. void PopulateSoundList( char const *current, HWND wnd );
  43. void PopulateVolumeLevels( HWND control, CEventParams *params );
  44. void FindWaveInSoundEntries( CUtlVector< int >& entryList, char const *search );
  45. void OnCheckChangedVolumeLevel( CEventParams *params );
  46. bool m_bShowAll;
  47. CUtlVector< CUtlSymbol > m_FilterHistory;
  48. CUtlSymbolTable m_Symbols;
  49. enum
  50. {
  51. TIMER_ID = 100,
  52. };
  53. UINT m_Timer;
  54. char m_szLastFilter[ 256 ];
  55. float m_flLastFilterUpdateTime;
  56. };
  57. void CEventPropertiesSpeakDialog::AddFilterToHistory( char const *filter )
  58. {
  59. CUtlSymbol sym = m_Symbols.AddString( filter );
  60. // Move it to front of list...
  61. m_FilterHistory.FindAndRemove( sym );
  62. m_FilterHistory.AddToHead( sym );
  63. PopulateFilterList( false );
  64. // Apply filter
  65. PopulateSoundList( g_Params.m_szParameters, GetControl( IDC_SOUNDLIST ) );
  66. }
  67. void CEventPropertiesSpeakDialog::PopulateFilterList( bool resetCurrent )
  68. {
  69. HWND control = GetControl( IDC_FILTER );
  70. char oldf[ 256 ];
  71. SendMessage( control, WM_GETTEXT, (WPARAM)sizeof( oldf ), (LPARAM)oldf );
  72. SendMessage( control, CB_RESETCONTENT, 0, 0 );
  73. int c = m_FilterHistory.Count();
  74. if ( c == 0 )
  75. return;
  76. for ( int i = 0; i < c; ++i )
  77. {
  78. char const *str = m_Symbols.String( m_FilterHistory[ i ] );
  79. SendMessage( control, CB_ADDSTRING, 0, (LPARAM)str );
  80. }
  81. char const *first = m_Symbols.String( m_FilterHistory[ 0 ] );
  82. if ( resetCurrent && first )
  83. {
  84. SendMessage( control, WM_SETTEXT , 0, (LPARAM)first );
  85. SendMessage( control, CB_SETEDITSEL , 0, MAKELPARAM( Q_strlen(first), -1 ) );
  86. }
  87. else
  88. {
  89. SendMessage( control, WM_SETTEXT , 0, (LPARAM)oldf );
  90. SendMessage( control, CB_SETEDITSEL , 0, MAKELPARAM( Q_strlen(oldf), -1 ) );
  91. }
  92. }
  93. void CEventPropertiesSpeakDialog::OnCheckFilterUpdate()
  94. {
  95. char curfilter[ 256 ];
  96. HWND control = GetControl( IDC_FILTER );
  97. SendMessage( control, WM_GETTEXT, (WPARAM)sizeof( curfilter), (LPARAM)curfilter );
  98. if ( Q_stricmp( curfilter, m_szLastFilter ) )
  99. {
  100. Q_strncpy( m_szLastFilter, curfilter, sizeof( m_szLastFilter ) );
  101. AddFilterToHistory( m_szLastFilter );
  102. }
  103. }
  104. void CEventPropertiesSpeakDialog::SetTitle()
  105. {
  106. SetDialogTitle( &g_Params, "Speak", "Speak Sound" );
  107. }
  108. void CEventPropertiesSpeakDialog::InitControlData( CEventParams *params )
  109. {
  110. BaseClass::InitControlData( params );
  111. m_flLastFilterUpdateTime = (float)mx::getTickCount() / 1000.0f;
  112. m_Timer = SetTimer( m_hDialog, TIMER_ID, 1, 0 );
  113. HWND choices1 = GetControl( IDC_SOUNDLIST );
  114. SendMessage( choices1, LB_RESETCONTENT, 0, 0 );
  115. HWND choices2 = GetControl( IDC_EVENTCHOICES2 );
  116. SendMessage( choices2, CB_RESETCONTENT, 0, 0 );
  117. SendMessage( choices2, WM_SETTEXT , 0, (LPARAM)params->m_szParameters2 );
  118. HWND attenuate = GetControl( IDC_CAPTION_ATTENUATION );
  119. SendMessage( attenuate, BM_SETCHECK, (WPARAM) params->m_bCloseCaptionNoAttenuate ? BST_CHECKED : BST_UNCHECKED, 0 );
  120. PopulateSoundList( params->m_szParameters, choices1 );
  121. OnSoundSelected( params );
  122. PopulateFilterList( true );
  123. }
  124. void CEventPropertiesSpeakDialog::InitDialog( HWND hwndDlg )
  125. {
  126. m_hDialog = hwndDlg;
  127. g_Params.PositionSelf( m_hDialog );
  128. // Set working title for dialog, etc.
  129. SetTitle();
  130. // Show/Hide dialog controls
  131. ShowControlsForEventType( &g_Params );
  132. InitControlData( &g_Params );
  133. UpdateTagRadioButtons( &g_Params );
  134. SetFocus( GetControl( IDC_EVENTNAME ) );
  135. }
  136. static CEventPropertiesSpeakDialog g_EventPropertiesSpeakDialog;
  137. void CEventPropertiesSpeakDialog::PopulateVolumeLevels( HWND control, CEventParams *params )
  138. {
  139. SendMessage( control, CB_RESETCONTENT, 0, 0 );
  140. // Assume uneditable
  141. SendMessage( control, CB_ADDSTRING, 0, (LPARAM)"VOL_NORM" );
  142. SendMessage( control, WM_SETTEXT , 0, (LPARAM)"VOL_NORM" );
  143. bool enabled = false;
  144. if ( !Q_stristr( params->m_szParameters, ".wav" ) )
  145. {
  146. // Look up the sound level from the soundemitter system
  147. int soundindex = soundemitter->GetSoundIndex( params->m_szParameters );
  148. if ( soundindex >= 0 )
  149. {
  150. // Look up the sound level from the soundemitter system
  151. CSoundParametersInternal *params = soundemitter->InternalGetParametersForSound( soundindex );
  152. if ( params )
  153. {
  154. // Found it
  155. SendMessage( control, WM_SETTEXT , 0, (LPARAM)params->VolumeToString() );
  156. //
  157. // See if the .txt file is writable
  158. char const *scriptfile = soundemitter->GetSourceFileForSound( soundindex );
  159. if ( scriptfile )
  160. {
  161. // See if it's writable
  162. if ( filesystem->FileExists( scriptfile ) &&
  163. filesystem->IsFileWritable( scriptfile ) )
  164. {
  165. enabled = true;
  166. }
  167. }
  168. }
  169. }
  170. }
  171. EnableWindow( control, enabled ? TRUE : FALSE );
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Purpose:
  175. // Input : wnd -
  176. // Output : static void
  177. //-----------------------------------------------------------------------------
  178. void CEventPropertiesSpeakDialog::PopulateSoundList( char const *current, HWND wnd )
  179. {
  180. extern bool NameLessFunc( const char *const& name1, const char *const& name2 );
  181. CUtlRBTree< char const *, int > m_SortedNames( 0, 0, NameLessFunc );
  182. int c = soundemitter->GetSoundCount();
  183. for ( int i = 0; i < c; i++ )
  184. {
  185. char const *name = soundemitter->GetSoundName( i );
  186. if ( name && name[ 0 ] )
  187. {
  188. bool add = true;
  189. if ( !m_bShowAll )
  190. {
  191. CSoundParameters params;
  192. if ( soundemitter->GetParametersForSound( name, params, GENDER_NONE ) )
  193. {
  194. if ( params.channel != CHAN_VOICE )
  195. {
  196. add = false;
  197. }
  198. }
  199. }
  200. // Apply filter
  201. if ( m_szLastFilter[ 0 ] != 0 )
  202. {
  203. if ( !Q_stristr( name, m_szLastFilter ) )
  204. {
  205. add = false;
  206. }
  207. }
  208. if ( add )
  209. {
  210. m_SortedNames.Insert( name );
  211. }
  212. }
  213. }
  214. SendMessage( wnd, WM_SETREDRAW , (WPARAM)FALSE, (LPARAM)0 );
  215. // Remove all
  216. SendMessage( wnd, LB_RESETCONTENT, 0, 0 );
  217. int selectslot = 0;
  218. int j = m_SortedNames.FirstInorder();
  219. while ( j != m_SortedNames.InvalidIndex() )
  220. {
  221. char const *name = m_SortedNames[ j ];
  222. if ( name && name[ 0 ] )
  223. {
  224. int temp = SendMessage( wnd, LB_ADDSTRING, 0, (LPARAM)name );
  225. if ( !Q_stricmp( name, current ) )
  226. {
  227. selectslot = temp;
  228. }
  229. }
  230. j = m_SortedNames.NextInorder( j );
  231. }
  232. SendMessage( wnd, LB_SETCURSEL, (WPARAM)selectslot, 0 );
  233. SendMessage( wnd, WM_SETREDRAW , (WPARAM)TRUE, (LPARAM)0 );
  234. }
  235. //-----------------------------------------------------------------------------
  236. // Purpose:
  237. // Input : wnd -
  238. // *params -
  239. // Output : static
  240. //-----------------------------------------------------------------------------
  241. void CEventPropertiesSpeakDialog::ShowControlsForEventType( CEventParams *params )
  242. {
  243. BaseClass::ShowControlsForEventType( params );
  244. }
  245. void CEventPropertiesSpeakDialog::FindWaveInSoundEntries( CUtlVector< int >& entryList, char const *search )
  246. {
  247. int c = soundemitter->GetSoundCount();
  248. for ( int i = 0; i < c; i++ )
  249. {
  250. CSoundParametersInternal *params = soundemitter->InternalGetParametersForSound( i );
  251. if ( !params )
  252. continue;
  253. int waveCount = params->NumSoundNames();
  254. for ( int wave = 0; wave < waveCount; wave++ )
  255. {
  256. char const *waveName = soundemitter->GetWaveName( params->GetSoundNames()[ wave ].symbol );
  257. if ( !Q_stricmp( waveName, search ) )
  258. {
  259. entryList.AddToTail( i );
  260. break;
  261. }
  262. }
  263. }
  264. }
  265. void CEventPropertiesSpeakDialog::OnCheckChangedVolumeLevel( CEventParams *params )
  266. {
  267. HWND control = GetControl( IDC_EVENTCHOICES2 );
  268. if ( !IsWindowEnabled( control ) )
  269. {
  270. return;
  271. }
  272. if ( Q_stristr( params->m_szParameters, ".wav" ) )
  273. {
  274. return;
  275. }
  276. int soundindex = soundemitter->GetSoundIndex( params->m_szParameters );
  277. if ( soundindex < 0 )
  278. return;
  279. // Look up the sound level from the soundemitter system
  280. CSoundParametersInternal *soundparams = soundemitter->InternalGetParametersForSound( soundindex );
  281. if ( !params )
  282. {
  283. return;
  284. }
  285. // See if it's writable, if not then bail
  286. char const *scriptfile = soundemitter->GetSourceFileForSound( soundindex );
  287. if ( !scriptfile ||
  288. !filesystem->FileExists( scriptfile ) ||
  289. !filesystem->IsFileWritable( scriptfile ) )
  290. {
  291. return;
  292. }
  293. // Copy the parameters
  294. CSoundParametersInternal newparams;
  295. newparams.CopyFrom( *soundparams );
  296. // Get the value from the control
  297. char newvolumelevel[ 256 ];
  298. SendMessage( control, WM_GETTEXT, (WPARAM)sizeof( newvolumelevel ), (LPARAM)newvolumelevel );
  299. newparams.VolumeFromString( newvolumelevel );
  300. // No change
  301. if ( newparams == *soundparams )
  302. {
  303. return;
  304. }
  305. soundemitter->UpdateSoundParameters( params->m_szParameters , newparams );
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose:
  309. // Input : hwndDlg -
  310. // uMsg -
  311. // wParam -
  312. // lParam -
  313. // Output : static BOOL CALLBACK
  314. //-----------------------------------------------------------------------------
  315. static BOOL CALLBACK EventPropertiesSpeakDialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  316. {
  317. return g_EventPropertiesSpeakDialog.HandleMessage( hwndDlg, uMsg, wParam, lParam );
  318. };
  319. void CEventPropertiesSpeakDialog::OnSoundSelected( CEventParams *params )
  320. {
  321. PopulateVolumeLevels( GetControl( IDC_EVENTCHOICES2 ), params );
  322. SendMessage( GetControl( IDC_SOUNDNAME ), WM_SETTEXT, 0, (LPARAM)params->m_szParameters );
  323. // Update script name and wavename fields
  324. HWND scriptname = GetControl( IDC_STATIC_SCRIPTFILE );
  325. HWND wavename = GetControl( IDC_STATIC_WAVEFILENAME );
  326. SendMessage( scriptname, WM_SETTEXT, (WPARAM)1, (LPARAM)"" );
  327. SendMessage( wavename, WM_SETTEXT, (WPARAM)1, (LPARAM)"" );
  328. int soundindex = soundemitter->GetSoundIndex( params->m_szParameters );
  329. if ( soundindex >= 0 )
  330. {
  331. char const *script = soundemitter->GetSourceFileForSound( soundindex );
  332. if ( script && script [ 0 ] )
  333. {
  334. SendMessage( scriptname, WM_SETTEXT, (WPARAM)Q_strlen( script ) + 1, (LPARAM)script );
  335. // Look up the sound level from the soundemitter system
  336. CSoundParametersInternal *params = soundemitter->InternalGetParametersForSound( soundindex );
  337. if ( params )
  338. {
  339. // Get wave name
  340. char const *w = soundemitter->GetWaveName( params->GetSoundNames()[ 0 ].symbol );
  341. if ( w && w[ 0 ] )
  342. {
  343. SendMessage( wavename, WM_SETTEXT, (WPARAM)Q_strlen( w ) + 1, (LPARAM)w );
  344. }
  345. }
  346. }
  347. }
  348. }
  349. BOOL CEventPropertiesSpeakDialog::HandleMessage( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  350. {
  351. m_hDialog = hwndDlg;
  352. bool handled = false;
  353. BOOL bret = InternalHandleMessage( &g_Params, hwndDlg, uMsg, wParam, lParam, handled );
  354. if ( handled )
  355. return bret;
  356. switch(uMsg)
  357. {
  358. case WM_PAINT:
  359. {
  360. PAINTSTRUCT ps;
  361. HDC hdc;
  362. hdc = BeginPaint(hwndDlg, &ps);
  363. DrawSpline( hdc, GetControl( IDC_STATIC_SPLINE ), g_Params.m_pEvent );
  364. EndPaint(hwndDlg, &ps);
  365. return FALSE;
  366. }
  367. break;
  368. case WM_VSCROLL:
  369. {
  370. RECT rcOut;
  371. GetSplineRect( GetControl( IDC_STATIC_SPLINE ), rcOut );
  372. InvalidateRect( hwndDlg, &rcOut, TRUE );
  373. UpdateWindow( hwndDlg );
  374. return FALSE;
  375. }
  376. break;
  377. case WM_INITDIALOG:
  378. {
  379. InitDialog( hwndDlg );
  380. }
  381. return FALSE;
  382. case WM_TIMER:
  383. {
  384. g_pMatSysWindow->Frame();
  385. float curtime = (float)mx::getTickCount() / 1000.0f;
  386. if ( curtime - m_flLastFilterUpdateTime > 0.5f )
  387. {
  388. m_flLastFilterUpdateTime = curtime;
  389. OnCheckFilterUpdate();
  390. }
  391. }
  392. return FALSE;
  393. case WM_COMMAND:
  394. switch (LOWORD(wParam))
  395. {
  396. case IDOK:
  397. {
  398. char sz[ 512 ];
  399. GetDlgItemText( m_hDialog, IDC_SOUNDNAME, sz, sizeof( sz ) );
  400. Q_FixSlashes( sz );
  401. // Strip off game directory stuff
  402. Q_strncpy( g_Params.m_szParameters, sz, sizeof( g_Params.m_szParameters ) );
  403. char *p = Q_strstr( sz, "\\sound\\" );
  404. if ( p )
  405. {
  406. Q_strncpy( g_Params.m_szParameters, p + strlen( "\\sound\\" ), sizeof( g_Params.m_szParameters ) );
  407. }
  408. OnCheckChangedVolumeLevel( &g_Params );
  409. GetDlgItemText( m_hDialog, IDC_EVENTNAME, g_Params.m_szName, sizeof( g_Params.m_szName ) );
  410. if ( !g_Params.m_szName[ 0 ] )
  411. {
  412. Q_strncpy( g_Params.m_szName, sz, sizeof( g_Params.m_szName ) );
  413. }
  414. char szTime[ 32 ];
  415. GetDlgItemText( m_hDialog, IDC_STARTTIME, szTime, sizeof( szTime ) );
  416. g_Params.m_flStartTime = atof( szTime );
  417. GetDlgItemText( m_hDialog, IDC_ENDTIME, szTime, sizeof( szTime ) );
  418. g_Params.m_flEndTime = atof( szTime );
  419. // Parse tokens from tags
  420. ParseTags( &g_Params );
  421. KillTimer( m_hDialog, m_Timer );
  422. EndDialog( hwndDlg, 1 );
  423. }
  424. break;
  425. case IDCANCEL:
  426. {
  427. KillTimer( m_hDialog, m_Timer );
  428. EndDialog( hwndDlg, 0 );
  429. }
  430. break;
  431. case IDC_CAPTION_ATTENUATION:
  432. {
  433. HWND control = GetControl( IDC_CAPTION_ATTENUATION );
  434. g_Params.m_bCloseCaptionNoAttenuate = SendMessage( control, BM_GETCHECK, 0, 0 ) == BST_CHECKED ? true : false;
  435. }
  436. break;
  437. case IDC_PLAY_SOUND:
  438. {
  439. // Get sound name from soundemitter
  440. sound->PlaySound(
  441. NULL,
  442. 1.0f,
  443. va( "sound/%s", FacePoser_TranslateSoundName( g_Params.m_szParameters ) ),
  444. NULL );
  445. }
  446. break;
  447. case IDC_OPENSOURCE:
  448. {
  449. // Look up the sound level from the soundemitter system
  450. int soundindex = soundemitter->GetSoundIndex( g_Params.m_szParameters );
  451. if ( soundindex >= 0 )
  452. {
  453. // Look up the sound level from the soundemitter system
  454. CSoundParametersInternal *params = soundemitter->InternalGetParametersForSound( soundindex );
  455. if ( params )
  456. {
  457. // See if the .txt file is writable
  458. char const *scriptfile = soundemitter->GetSourceFileForSound( soundindex );
  459. if ( scriptfile )
  460. {
  461. char relative_path[MAX_PATH];
  462. Q_snprintf( relative_path, MAX_PATH, "%s", scriptfile );
  463. char full_path[MAX_PATH];
  464. if ( filesystem->GetLocalPath( relative_path, full_path, MAX_PATH ) )
  465. {
  466. ShellExecute( NULL, "open", full_path, NULL, NULL, SW_SHOWNORMAL );
  467. }
  468. }
  469. }
  470. }
  471. }
  472. break;
  473. case IDC_SHOW_ALL_SOUNDS:
  474. {
  475. m_bShowAll = SendMessage( GetControl( IDC_SHOW_ALL_SOUNDS ), BM_GETCHECK, 0, 0 ) == BST_CHECKED ? true : false;
  476. PopulateSoundList( g_Params.m_szParameters, GetControl( IDC_EVENTCHOICES ) );
  477. }
  478. break;
  479. case IDC_CHECK_ENDTIME:
  480. {
  481. g_Params.m_bHasEndTime = SendMessage( GetControl( IDC_CHECK_ENDTIME ), BM_GETCHECK, 0, 0 ) == BST_CHECKED ? true : false;
  482. if ( !g_Params.m_bHasEndTime )
  483. {
  484. ShowWindow( GetControl( IDC_ENDTIME ), SW_HIDE );
  485. }
  486. else
  487. {
  488. ShowWindow( GetControl( IDC_ENDTIME ), SW_RESTORE );
  489. }
  490. }
  491. break;
  492. case IDC_CHECK_RESUMECONDITION:
  493. {
  494. g_Params.m_bResumeCondition = SendMessage( GetControl( IDC_CHECK_RESUMECONDITION ), BM_GETCHECK, 0, 0 ) == BST_CHECKED ? true : false;
  495. }
  496. break;
  497. case IDC_SOUNDLIST:
  498. {
  499. HWND control = (HWND)lParam;
  500. if ( control )
  501. {
  502. int cursel = SendMessage( control, LB_GETCURSEL, 0, 0 );
  503. if ( cursel != LB_ERR )
  504. {
  505. SendMessage( control, LB_GETTEXT, cursel, (LPARAM)g_Params.m_szParameters );
  506. OnSoundSelected( &g_Params );
  507. if ( HIWORD( wParam ) == LBN_DBLCLK )
  508. {
  509. // Get sound name from soundemitter
  510. sound->PlaySound(
  511. NULL,
  512. 1.0f,
  513. va( "sound/%s", FacePoser_TranslateSoundName( g_Params.m_szParameters ) ),
  514. NULL );
  515. }
  516. }
  517. }
  518. }
  519. break;
  520. case IDC_EVENTCHOICES2:
  521. {
  522. HWND control = (HWND)lParam;
  523. if ( control )
  524. {
  525. SendMessage( control, WM_GETTEXT, (WPARAM)sizeof( g_Params.m_szParameters2 ), (LPARAM)g_Params.m_szParameters2 );
  526. }
  527. }
  528. break;
  529. case IDC_ABSOLUTESTART:
  530. {
  531. g_Params.m_bUsesTag = false;
  532. UpdateTagRadioButtons( &g_Params );
  533. }
  534. break;
  535. case IDC_RELATIVESTART:
  536. {
  537. g_Params.m_bUsesTag = true;
  538. UpdateTagRadioButtons( &g_Params );
  539. }
  540. break;
  541. }
  542. return TRUE;
  543. }
  544. return FALSE;
  545. }
  546. //-----------------------------------------------------------------------------
  547. // Purpose:
  548. // Input : *view -
  549. // *actor -
  550. // Output : int
  551. //-----------------------------------------------------------------------------
  552. int EventProperties_Speak( CEventParams *params )
  553. {
  554. g_Params = *params;
  555. int retval = DialogBox( (HINSTANCE)GetModuleHandle( 0 ),
  556. MAKEINTRESOURCE( IDD_EVENTPROPERTIES_SPEAK ),
  557. (HWND)g_MDLViewer->getHandle(),
  558. (DLGPROC)EventPropertiesSpeakDialog );
  559. *params = g_Params;
  560. return retval;
  561. }