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.

457 lines
9.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: VGUI panel which can play back video, in-engine
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include <vgui/IVGui.h>
  8. #include "vgui/IInput.h"
  9. #include <vgui/ISurface.h>
  10. #include "ienginevgui.h"
  11. #include "iclientmode.h"
  12. #include "vgui_video_player.h"
  13. #include "engine/IEngineSound.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. VideoPlayerPanel::VideoPlayerPanel( vgui::Panel *parent, const char *panelName, int nXpos, int nYpos, int nWidth, int nHeight, const char *pVideoFile ) :
  17. BaseClass( parent, panelName ),
  18. m_VideoMaterial( NULL ),
  19. m_VideoFileName( NULL ),
  20. m_VideoLoaded( false ),
  21. m_VideoPlaying( false )
  22. {
  23. Assert( g_pVideo != NULL );
  24. // init all the video realted member vars
  25. ClearVideo();
  26. SetVisible( false );
  27. SetKeyBoardInputEnabled( false );
  28. SetMouseInputEnabled( false );
  29. SetProportional( false );
  30. SetPaintBackgroundEnabled( false );
  31. SetPaintBorderEnabled( false );
  32. // Set us up
  33. SetTall( nHeight );
  34. SetWide( nWidth );
  35. SetPos( nXpos, nYpos );
  36. // use defaults for scheme and control settings for now
  37. // SetScheme( vgui::scheme()->LoadSchemeFromFile( "resource/VideoPlayerPanelScheme.res", "VideoPlayerPanelScheme"));
  38. //LoadControlSettings("resource/UI/VideoPlayerPanel.res");
  39. // Assign video file if supplied
  40. SetVideo( pVideoFile );
  41. SetVisible( true );
  42. }
  43. //-----------------------------------------------------------------------------
  44. // Properly shutdown out materials
  45. //-----------------------------------------------------------------------------
  46. VideoPlayerPanel::~VideoPlayerPanel( void )
  47. {
  48. SetParent( (vgui::Panel *) NULL );
  49. StopVideo();
  50. ClearVideo();
  51. }
  52. bool VideoPlayerPanel::SetVideo( const char *pVideoFile )
  53. {
  54. ClearVideo();
  55. // clearing the video?
  56. if ( pVideoFile == NULL || pVideoFile[0] == 0x00 )
  57. {
  58. return true;
  59. }
  60. // create the material
  61. m_VideoMaterial = g_pVideo->CreateVideoMaterial( "VideoPlayerMaterial", pVideoFile, "GAME",
  62. VideoPlaybackFlags::DEFAULT_MATERIAL_OPTIONS,
  63. VideoSystem::DETERMINE_FROM_FILE_EXTENSION, true );
  64. if ( m_VideoMaterial == NULL )
  65. {
  66. return false;
  67. }
  68. // save filename
  69. int sLen = V_strlen( pVideoFile ) + 1;
  70. m_VideoFileName = new char[ sLen ];
  71. V_strncpy( m_VideoFileName, pVideoFile, sLen );
  72. // compute Playback dimensions
  73. int nWidth, nHeight;
  74. m_VideoMaterial->GetVideoImageSize( &nWidth, &nHeight );
  75. m_VideoMaterial->GetVideoTexCoordRange( &m_flU, &m_flV );
  76. float flFrameRatio = ( (float) GetWide() / (float) GetTall() );
  77. float flVideoRatio = ( (float) nWidth / (float) nHeight );
  78. if ( flVideoRatio > flFrameRatio )
  79. {
  80. m_nPlaybackWidth = GetWide();
  81. m_nPlaybackHeight = ( GetWide() / flVideoRatio );
  82. m_letterBox = 1;
  83. }
  84. else if ( flVideoRatio < flFrameRatio )
  85. {
  86. m_nPlaybackWidth = ( GetTall() * flVideoRatio );
  87. m_nPlaybackHeight = GetTall();
  88. m_letterBox = 2;
  89. }
  90. else
  91. {
  92. m_nPlaybackWidth = GetWide();
  93. m_nPlaybackHeight = GetTall();
  94. m_letterBox = 0;
  95. }
  96. m_pMaterial = m_VideoMaterial->GetMaterial();
  97. m_VideoDuration = m_VideoMaterial->GetVideoDuration();
  98. m_VideoLoaded = true;
  99. return true;
  100. }
  101. void VideoPlayerPanel::ClearVideo()
  102. {
  103. if ( m_VideoPlaying )
  104. {
  105. StopVideo();
  106. }
  107. // Shut down this video, destroy the video material
  108. if ( g_pVideo != NULL && m_VideoMaterial != NULL )
  109. {
  110. g_pVideo->DestroyVideoMaterial( m_VideoMaterial );
  111. m_VideoMaterial = NULL;
  112. }
  113. if ( m_VideoFileName != NULL )
  114. {
  115. delete[] m_VideoFileName;
  116. m_VideoFileName = NULL;
  117. }
  118. m_pMaterial = NULL;
  119. m_VideoLoaded = false;
  120. m_VideoPlaying = false;
  121. m_VideoPaused = false;
  122. m_nPlaybackHeight = 0;
  123. m_nPlaybackWidth = 0;
  124. m_letterBox = 0;
  125. m_flU = 0.0f;
  126. m_flV = 0.0f;
  127. m_VideoDuration = 0.0f;
  128. }
  129. //-----------------------------------------------------------------------------
  130. // Purpose:
  131. //-----------------------------------------------------------------------------
  132. void VideoPlayerPanel::Activate( void )
  133. {
  134. MoveToFront();
  135. RequestFocus();
  136. SetVisible( true );
  137. SetEnabled( true );
  138. vgui::surface()->SetMinimized( GetVPanel(), false );
  139. }
  140. //-----------------------------------------------------------------------------
  141. // Purpose:
  142. //-----------------------------------------------------------------------------
  143. void VideoPlayerPanel::OnClose( void )
  144. {
  145. StopVideo();
  146. // enginesound->NotifyEndMoviePlayback();
  147. vgui::surface()->RestrictPaintToSinglePanel( NULL );
  148. SetVisible( false );
  149. MarkForDeletion();
  150. }
  151. //-----------------------------------------------------------------------------
  152. // Purpose: Update and draw the frame
  153. //-----------------------------------------------------------------------------
  154. void VideoPlayerPanel::Paint( void )
  155. {
  156. BaseClass::Paint();
  157. // Get our dimensions
  158. int xpos = 0;
  159. int ypos = 0;
  160. vgui::ipanel()->GetAbsPos( GetVPanel(), xpos, ypos );
  161. // GetPanelPos( xpos, ypos );
  162. int width = GetWide();
  163. int height = GetTall();
  164. // Are we playing the video? Do we even have a video?
  165. if ( !m_VideoLoaded || !m_VideoPlaying )
  166. {
  167. vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
  168. vgui::surface()->DrawFilledRect( 0, 0, width, height );
  169. return;
  170. }
  171. if ( m_VideoMaterial == NULL )
  172. return;
  173. if ( m_VideoMaterial->Update() == false )
  174. {
  175. StopVideo();
  176. return;
  177. }
  178. // Black out the letterbox ares if we have them
  179. if ( m_letterBox != 0 )
  180. {
  181. vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
  182. if ( m_letterBox == 1 ) // bars on top, bottom
  183. {
  184. int excess = ( height - m_nPlaybackHeight );
  185. int top = excess /2;
  186. int bot = excess - top;
  187. vgui::surface()->DrawFilledRect( 0, 0, width, top );
  188. vgui::surface()->DrawFilledRect( 0, height - bot, width, height );
  189. }
  190. if ( m_letterBox == 2 ) // bars on left, right
  191. {
  192. int excess = ( width - m_nPlaybackWidth );
  193. int left = excess /2;
  194. int right = excess - left;
  195. vgui::surface()->DrawFilledRect( 0, 0, left, height );
  196. vgui::surface()->DrawFilledRect( width-right, 0, width, height );
  197. }
  198. }
  199. // Draw the polys to draw this out
  200. CMatRenderContextPtr pRenderContext( materials );
  201. pRenderContext->MatrixMode( MATERIAL_VIEW );
  202. pRenderContext->PushMatrix();
  203. pRenderContext->LoadIdentity();
  204. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  205. pRenderContext->PushMatrix();
  206. pRenderContext->LoadIdentity();
  207. pRenderContext->Bind( m_pMaterial, NULL );
  208. CMeshBuilder meshBuilder;
  209. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  210. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  211. float flLeftX = xpos;
  212. float flRightX = xpos + ( m_nPlaybackWidth-1 );
  213. float flTopY = ypos;
  214. float flBottomY = ypos + ( m_nPlaybackHeight-1 );
  215. // Map our UVs to cut out just the portion of the video we're interested in
  216. float flLeftU = 0.0f;
  217. float flTopV = 0.0f;
  218. // We need to subtract off a pixel to make sure we don't bleed
  219. float flRightU = m_flU - ( 1.0f / (float) m_nPlaybackWidth );
  220. float flBottomV = m_flV - ( 1.0f / (float) m_nPlaybackHeight );
  221. // Get the current viewport size
  222. int vx, vy, vw, vh;
  223. pRenderContext->GetViewport( vx, vy, vw, vh );
  224. // map from screen pixel coords to -1..1
  225. flRightX = FLerp( -1, 1, 0, vw, flRightX );
  226. flLeftX = FLerp( -1, 1, 0, vw, flLeftX );
  227. flTopY = FLerp( 1, -1, 0, vh ,flTopY );
  228. flBottomY = FLerp( 1, -1, 0, vh, flBottomY );
  229. float alpha = ((float)GetFgColor()[3]/255.0f);
  230. for ( int corner=0; corner<4; corner++ )
  231. {
  232. bool bLeft = (corner==0) || (corner==3);
  233. meshBuilder.Position3f( (bLeft) ? flLeftX : flRightX, (corner & 2) ? flBottomY : flTopY, 0.0f );
  234. meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
  235. meshBuilder.TexCoord2f( 0, (bLeft) ? flLeftU : flRightU, (corner & 2) ? flBottomV : flTopV );
  236. meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
  237. meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
  238. meshBuilder.Color4f( 1.0f, 1.0f, 1.0f, alpha );
  239. meshBuilder.AdvanceVertex();
  240. }
  241. meshBuilder.End();
  242. pMesh->Draw();
  243. pRenderContext->MatrixMode( MATERIAL_VIEW );
  244. pRenderContext->PopMatrix();
  245. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  246. pRenderContext->PopMatrix();
  247. }
  248. bool VideoPlayerPanel::StartVideo()
  249. {
  250. if ( !m_VideoLoaded )
  251. return false;
  252. // already playing?
  253. if ( m_VideoPlaying )
  254. {
  255. // paused?
  256. if ( m_VideoPaused )
  257. {
  258. return UnpauseVideo();
  259. }
  260. return true;
  261. }
  262. m_VideoPlaying = m_VideoMaterial->StartVideo();
  263. return m_VideoPlaying;
  264. }
  265. bool VideoPlayerPanel::StopVideo()
  266. {
  267. if ( !m_VideoLoaded || !m_VideoPlaying )
  268. return false;
  269. m_VideoMaterial->StopVideo();
  270. m_VideoPlaying = false;
  271. return true;
  272. }
  273. bool VideoPlayerPanel::PauseVideo()
  274. {
  275. if ( !m_VideoLoaded || !m_VideoPlaying )
  276. return false;
  277. if ( !m_VideoPaused )
  278. {
  279. m_VideoMaterial->SetPaused( true );
  280. m_VideoPaused = true;
  281. }
  282. return true;
  283. }
  284. bool VideoPlayerPanel::UnpauseVideo()
  285. {
  286. if ( !m_VideoLoaded || !m_VideoPlaying )
  287. return false;
  288. if ( m_VideoPaused )
  289. {
  290. m_VideoMaterial->SetPaused( false );
  291. m_VideoPaused = false;
  292. }
  293. return true;
  294. }
  295. float VideoPlayerPanel::GetCurrentPlaybackTime()
  296. {
  297. if ( !m_VideoLoaded )
  298. {
  299. return 0.0f;
  300. }
  301. return m_VideoMaterial->GetCurrentVideoTime();
  302. }
  303. bool VideoPlayerPanel::SetCurrentPlaybackTime( float newTime )
  304. {
  305. if ( !m_VideoLoaded )
  306. return false;
  307. if ( newTime < 0.0f || newTime > m_VideoDuration )
  308. return false;
  309. return m_VideoMaterial->SetTime( newTime );
  310. }
  311. bool VideoPlayerPanel::HasAudio()
  312. {
  313. if ( !m_VideoLoaded )
  314. return false;
  315. return m_VideoMaterial->HasAudio();
  316. }
  317. bool VideoPlayerPanel::IsMuted()
  318. {
  319. if ( !m_VideoLoaded )
  320. return false;
  321. return m_VideoMaterial->IsMuted();
  322. }
  323. bool VideoPlayerPanel::SetMute( bool muted )
  324. {
  325. if ( !m_VideoLoaded )
  326. return false;
  327. m_VideoMaterial->SetMuted( muted );
  328. return true;
  329. }
  330. float VideoPlayerPanel::GetVolume()
  331. {
  332. if ( !m_VideoLoaded )
  333. return 0.0f;
  334. return m_VideoMaterial->GetVolume();
  335. }
  336. bool VideoPlayerPanel::SetVolume( float newVolume )
  337. {
  338. if ( !m_VideoLoaded )
  339. return false;
  340. return m_VideoMaterial->SetVolume( newVolume );
  341. }