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.

200 lines
4.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "stdafx.h"
  7. #include "hammer.h"
  8. #include "ScenePreviewDlg.h"
  9. #include "choreoscene.h"
  10. #include "soundsystem.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include <tier0/memdbgon.h>
  13. #define WM_SCENEPREVIEW_IDLE (WM_USER+1)
  14. BEGIN_MESSAGE_MAP(CScenePreviewDlg, CDialog)
  15. //{{AFX_MSG_MAP(CScenePreviewDlg)
  16. ON_BN_CLICKED(IDCANCEL, OnCancel)
  17. //}}AFX_MSG_MAP
  18. END_MESSAGE_MAP()
  19. CScenePreviewDlg::CScenePreviewDlg( CChoreoScene *pScene, const char *pFilename, CWnd* pParent /*=NULL*/ )
  20. : CDialog(CScenePreviewDlg::IDD, pParent)
  21. {
  22. //{{AFX_DATA_INIT(CScenePreviewDlg)
  23. m_pScene = pScene;
  24. m_iLastEventPlayed = -2; // Don't do anything yet.
  25. m_hExitThreadEvent = NULL;
  26. m_hIdleEventHandledEvent = NULL;
  27. m_hIdleThread = NULL;
  28. V_strncpy( m_SceneFilename, pFilename, sizeof( m_SceneFilename ) );
  29. }
  30. CScenePreviewDlg::~CScenePreviewDlg()
  31. {
  32. EndThread();
  33. delete m_pScene;
  34. }
  35. void CScenePreviewDlg::EndThread()
  36. {
  37. if ( m_hIdleThread )
  38. {
  39. SetEvent( m_hExitThreadEvent );
  40. WaitForSingleObject( m_hIdleThread, INFINITE );
  41. CloseHandle( m_hIdleThread );
  42. CloseHandle( m_hExitThreadEvent );
  43. CloseHandle( m_hIdleEventHandledEvent );
  44. m_hIdleThread = m_hExitThreadEvent = m_hIdleEventHandledEvent = NULL;
  45. }
  46. }
  47. BOOL CScenePreviewDlg::OnInitDialog()
  48. {
  49. CDialog::OnInitDialog();
  50. // Setup the control showing the scene name.
  51. CString str;
  52. GetDlgItemText( IDC_SCENE_NAME, str );
  53. str = str + " " + m_SceneFilename;
  54. SetDlgItemText( IDC_SCENE_NAME, str );
  55. CString strNone;
  56. strNone.LoadString( IDS_NONE );
  57. SetDlgItemText( IDC_CURRENT_SOUND, strNone );
  58. SetDlgItemText( IDC_NEXT_SOUND, strNone );
  59. m_iLastEventPlayed = -1;
  60. m_flStartTime = Plat_FloatTime();
  61. // Start on the first event..
  62. for ( int i = 0; i < m_pScene->GetNumEvents(); i++ )
  63. {
  64. CChoreoEvent *e = m_pScene->GetEvent( i );
  65. if ( e && e->GetType() == CChoreoEvent::SPEAK )
  66. {
  67. m_flStartTime -= e->GetStartTime();
  68. break;
  69. }
  70. }
  71. // Create our idle thread.
  72. m_hExitThreadEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  73. m_hIdleEventHandledEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  74. m_hIdleThread = CreateThread( NULL, 0, &CScenePreviewDlg::StaticIdleThread, this, 0, NULL );
  75. return TRUE;
  76. }
  77. DWORD CScenePreviewDlg::StaticIdleThread( LPVOID pParameter )
  78. {
  79. return ((CScenePreviewDlg*)pParameter)->IdleThread();
  80. }
  81. DWORD CScenePreviewDlg::IdleThread()
  82. {
  83. HANDLE handles[2] = {m_hExitThreadEvent, m_hIdleEventHandledEvent};
  84. while ( 1 )
  85. {
  86. // Send the event to the window.
  87. PostMessage( WM_SCENEPREVIEW_IDLE, 0, 0 );
  88. DWORD ret = WaitForMultipleObjects( ARRAYSIZE( handles ), handles, false, INFINITE );
  89. if ( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT )
  90. return 0;
  91. Sleep( 100 ); // Only handle idle 10x/sec.
  92. }
  93. }
  94. void CScenePreviewDlg::OnIdle()
  95. {
  96. double flElapsed = Plat_FloatTime() - m_flStartTime;
  97. // Find the next sound to play.
  98. int iLastSound = -1;
  99. for ( int i = 0; i < m_pScene->GetNumEvents(); i++ )
  100. {
  101. CChoreoEvent *e = m_pScene->GetEvent( i );
  102. if ( !e || e->GetType() != CChoreoEvent::SPEAK )
  103. continue;
  104. if ( flElapsed > e->GetStartTime() )
  105. iLastSound = i;
  106. }
  107. // Is there another sound to play in here?
  108. if ( iLastSound >= 0 && iLastSound != m_iLastEventPlayed )
  109. {
  110. m_iLastEventPlayed = iLastSound;
  111. // Play the current sound.
  112. CChoreoEvent *pChoreoEvent = m_pScene->GetEvent( iLastSound );
  113. const char *pSoundName = pChoreoEvent->GetParameters();
  114. SoundType_t soundType;
  115. int nIndex;
  116. if ( g_Sounds.FindSoundByName( pSoundName, &soundType, &nIndex ) )
  117. {
  118. bool bRet = g_Sounds.Play( soundType, nIndex );
  119. CString curSound = pSoundName;
  120. if ( !bRet )
  121. {
  122. CString strErrorPlaying;
  123. strErrorPlaying.LoadString( IDS_ERROR_PLAYING );
  124. curSound += " " + strErrorPlaying;
  125. }
  126. SetDlgItemText( IDC_CURRENT_SOUND, curSound );
  127. }
  128. // Find the next sound event.
  129. CString str;
  130. str.LoadString( IDS_NONE );
  131. for ( int i=iLastSound+1; i < m_pScene->GetNumEvents(); i++ )
  132. {
  133. CChoreoEvent *e = m_pScene->GetEvent( i );
  134. if ( e && e->GetType() == CChoreoEvent::SPEAK )
  135. {
  136. str = e->GetParameters();
  137. break;
  138. }
  139. }
  140. SetDlgItemText( IDC_NEXT_SOUND, str );
  141. }
  142. }
  143. LRESULT CScenePreviewDlg::DefWindowProc( UINT message, WPARAM wParam, LPARAM lParam )
  144. {
  145. // We handle the enter key specifically because the default combo box behavior is to
  146. // reset the text and all this stuff we don't want.
  147. if ( message == WM_SCENEPREVIEW_IDLE )
  148. {
  149. OnIdle();
  150. SetEvent( m_hIdleEventHandledEvent );
  151. return 0;
  152. }
  153. return CDialog::DefWindowProc( message, wParam, lParam );
  154. }
  155. void CScenePreviewDlg::OnCancel(void)
  156. {
  157. g_Sounds.StopSound();
  158. EndThread();
  159. EndDialog( 0 );
  160. }