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.

317 lines
7.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //=======================================================================================//
  4. #include "cbase.h"
  5. #include "game_controls/slideshowpanel.h"
  6. #include "vgui/IVGui.h"
  7. #include "filesystem.h"
  8. //-----------------------------------------------------------------------------
  9. using namespace vgui;
  10. //-----------------------------------------------------------------------------
  11. DECLARE_BUILD_FACTORY( CCrossfadableImagePanel );
  12. DECLARE_BUILD_FACTORY( CSlideshowPanel );
  13. //-----------------------------------------------------------------------------
  14. CCrossfadableImagePanel::CCrossfadableImagePanel( Panel* pParent, const char *pName )
  15. : EditablePanel( pParent, pName ),
  16. m_iSrcImg( 0 ),
  17. m_flBlend( 0.0f ),
  18. m_flBlendTime( 0.0f ),
  19. m_flStartBlendTime( 0.0f ),
  20. m_bBlending( false )
  21. {
  22. m_pImages[ 0 ] = new ImagePanel( this, "Image0" );
  23. m_pImages[ 1 ] = new ImagePanel( this, "Image1" );
  24. ivgui()->AddTickSignal( GetVPanel(), 10 );
  25. }
  26. CCrossfadableImagePanel::~CCrossfadableImagePanel()
  27. {
  28. ivgui()->RemoveTickSignal( GetVPanel() );
  29. }
  30. void CCrossfadableImagePanel::ApplySettings( KeyValues *pInResourceData )
  31. {
  32. BaseClass::ApplySettings( pInResourceData );
  33. }
  34. void CCrossfadableImagePanel::ApplySchemeSettings( IScheme *pScheme )
  35. {
  36. BaseClass::ApplySchemeSettings( pScheme );
  37. SrcImg()->SetTileImage( false );
  38. DstImg()->SetTileImage( false );
  39. }
  40. void CCrossfadableImagePanel::PerformLayout()
  41. {
  42. BaseClass::PerformLayout();
  43. for ( int i = 0; i < 2; ++i )
  44. {
  45. m_pImages[ i ]->SetBounds( 0, 0, GetWide(), GetTall() );
  46. m_pImages[ i ]->SetVisible( true );
  47. }
  48. }
  49. // Helper macro to perform a call on both images
  50. #define CALL_FUNC_ON_BOTH_IMAGES( _call ) \
  51. AssertMsg( m_pImages[ 0 ], "m_pImages[ 0 ] is NULL!" ); \
  52. AssertMsg( m_pImages[ 1 ], "m_pImages[ 1 ] is NULL!" ); \
  53. m_pImages[0]->_call; \
  54. m_pImages[1]->_call;
  55. void CCrossfadableImagePanel::SetShouldScaleImage( bool bState )
  56. {
  57. CALL_FUNC_ON_BOTH_IMAGES( SetShouldScaleImage( bState ) );
  58. }
  59. void CCrossfadableImagePanel::SetScaleAmount( float flScale )
  60. {
  61. CALL_FUNC_ON_BOTH_IMAGES( SetScaleAmount( flScale ) );
  62. }
  63. void CCrossfadableImagePanel::SetFillColor( Color c )
  64. {
  65. CALL_FUNC_ON_BOTH_IMAGES( SetFillColor( c ) );
  66. }
  67. void CCrossfadableImagePanel::SetDrawColor( Color clrDrawColor )
  68. {
  69. CALL_FUNC_ON_BOTH_IMAGES( SetDrawColor( clrDrawColor ) );
  70. }
  71. void CCrossfadableImagePanel::InstallMouseHandler( Panel *pHandler )
  72. {
  73. CALL_FUNC_ON_BOTH_IMAGES( InstallMouseHandler( pHandler ) );
  74. }
  75. IImage *CCrossfadableImagePanel::GetImage()
  76. {
  77. return SrcImg()->GetImage();
  78. }
  79. const char *CCrossfadableImagePanel::GetImageName()
  80. {
  81. return SrcImg()->GetImageName();
  82. }
  83. float CCrossfadableImagePanel::GetScaleAmount()
  84. {
  85. return SrcImg()->GetScaleAmount();
  86. }
  87. bool CCrossfadableImagePanel::GetShouldScaleImage()
  88. {
  89. return SrcImg()->GetShouldScaleImage();
  90. }
  91. Color CCrossfadableImagePanel::GetFillColor()
  92. {
  93. return SrcImg()->GetFillColor();
  94. }
  95. Color CCrossfadableImagePanel::GetDrawColor()
  96. {
  97. return SrcImg()->GetDrawColor();
  98. }
  99. void CCrossfadableImagePanel::SetImage( IImage *pImage, float flBlendTime/*=0.0f*/ )
  100. {
  101. DstImg()->SetImage( pImage );
  102. SetupImageBlend( flBlendTime );
  103. }
  104. void CCrossfadableImagePanel::SetImage( const char *pImageName, float flBlendTime/*=0.0f*/ )
  105. {
  106. DstImg()->SetImage( pImageName );
  107. SetupImageBlend( flBlendTime );
  108. }
  109. void CCrossfadableImagePanel::SetupImageBlend( float flBlendTime )
  110. {
  111. m_bBlending = true;
  112. m_flBlendTime = flBlendTime;
  113. m_flStartBlendTime = gpGlobals->realtime;
  114. m_flBlend = 0.0f;
  115. }
  116. void CCrossfadableImagePanel::OnSizeChanged( int nWide, int nTall )
  117. {
  118. m_pImages[ 0 ]->SetSize( nWide, nTall );
  119. m_pImages[ 1 ]->SetSize( nWide, nTall );
  120. }
  121. void CCrossfadableImagePanel::OnTick()
  122. {
  123. if ( m_bBlending )
  124. {
  125. // Compute current blend value
  126. if ( m_flBlendTime == 0.0f )
  127. {
  128. m_flBlend = 1.0f;
  129. }
  130. else
  131. {
  132. float t = clamp( ( gpGlobals->realtime - m_flStartBlendTime ) / m_flBlendTime, 0.0f, 1.0f );
  133. m_flBlend = clamp( t * t * (3 - 2*t), 0.0f, 1.0f ); // S-curve
  134. }
  135. // Set alpha channel on source image
  136. Color clrDraw;
  137. clrDraw = SrcImg()->GetDrawColor();
  138. clrDraw[ 3 ] = ( int )( 255 * ( 1 - m_flBlend ) );
  139. SrcImg()->SetDrawColor( clrDraw );
  140. // Set alpha channel on destination image
  141. clrDraw = DstImg()->GetDrawColor();
  142. clrDraw[ 3 ] = ( int )( 255 * m_flBlend );
  143. DstImg()->SetDrawColor( clrDraw );
  144. // If we're done, don't blend next think
  145. if ( m_flBlend >= 1.0f )
  146. {
  147. m_bBlending = false;
  148. m_iSrcImg = !m_iSrcImg;
  149. m_flBlend = 0.0f;
  150. }
  151. }
  152. }
  153. //-----------------------------------------------------------------------------
  154. CSlideshowPanel::CSlideshowPanel( Panel *pParent, const char *pName )
  155. : EditablePanel( pParent, pName ),
  156. m_iCurImg( 0 ),
  157. m_flInterval( 3.0f ),
  158. m_flTransitionLength( 0.5f )
  159. {
  160. m_pImagePanel = new CCrossfadableImagePanel( this, "CrossfadableImage" );
  161. // Setup the first transition time
  162. UpdateNextTransitionTime();
  163. // Add tick signal
  164. ivgui()->AddTickSignal( GetVPanel(), 10 );
  165. }
  166. CSlideshowPanel::~CSlideshowPanel()
  167. {
  168. // Remove tick signal
  169. ivgui()->RemoveTickSignal( GetVPanel() );
  170. }
  171. void CSlideshowPanel::SetInterval( float flInterval )
  172. {
  173. m_flInterval = flInterval;
  174. UpdateNextTransitionTime();
  175. }
  176. void CSlideshowPanel::SetTransitionTime( float flTransitionLength )
  177. {
  178. m_flTransitionLength = flTransitionLength;
  179. UpdateNextTransitionTime();
  180. }
  181. void CSlideshowPanel::UpdateNextTransitionTime()
  182. {
  183. m_flNextTransitionTime = gpGlobals->realtime + m_flInterval;
  184. }
  185. void CSlideshowPanel::AddImage( const char *pImageName )
  186. {
  187. if ( pImageName && strlen( pImageName ) > 0 )
  188. {
  189. AddImage( scheme()->GetImage( pImageName, m_pImagePanel->GetShouldScaleImage() ) );
  190. }
  191. }
  192. void CSlideshowPanel::AddImage( IImage *pImage )
  193. {
  194. // Cache a pointer to the image
  195. m_vecImages.AddToTail( pImage );
  196. if ( m_vecImages.Count() == 1 )
  197. {
  198. GetImagePanel()->SetImage( pImage );
  199. }
  200. }
  201. void CSlideshowPanel::FillWithImages( const char *pBasePath )
  202. {
  203. int i = 0;
  204. while ( 1 )
  205. {
  206. CFmtStr fmtImagePath( "materials/vgui/%s%i.vmt", pBasePath, i );
  207. V_FixDoubleSlashes( fmtImagePath.Access() );
  208. if ( !g_pFullFileSystem->FileExists( fmtImagePath.Access() ) )
  209. break;
  210. fmtImagePath.sprintf( "%s%i.vmt", pBasePath, i );
  211. AddImage( fmtImagePath.Access() );
  212. ++i;
  213. }
  214. }
  215. void CSlideshowPanel::ApplySettings( KeyValues *pInResourceData )
  216. {
  217. BaseClass::ApplySettings( pInResourceData );
  218. int iDefaultImage = pInResourceData->GetInt( "default_index", 0 );
  219. int i = 0;
  220. while ( 1 )
  221. {
  222. CFmtStr fmtImageKeyName( "image_%i", i );
  223. const char *pImagePath = pInResourceData->GetString( fmtImageKeyName.Access(), NULL );
  224. if ( !pImagePath )
  225. break;
  226. AddImage( pImagePath );
  227. if ( iDefaultImage == i )
  228. {
  229. GetImagePanel()->SetImage( pImagePath );
  230. }
  231. ++i;
  232. }
  233. GetImagePanel()->SetSize(
  234. XRES( pInResourceData->GetInt( "wide" ) ),
  235. YRES( pInResourceData->GetInt( "tall" ) )
  236. );
  237. GetImagePanel()->SetShouldScaleImage( pInResourceData->GetBool( "scaleImage" ) );
  238. GetImagePanel()->SetScaleAmount( pInResourceData->GetFloat( "scaleAmount" ) );
  239. }
  240. void CSlideshowPanel::OnSizeChanged( int nWide, int nTall )
  241. {
  242. GetImagePanel()->SetSize( nWide, nTall );
  243. }
  244. void CSlideshowPanel::OnTick()
  245. {
  246. if ( GetImageCount() > 1 && gpGlobals->realtime >= m_flNextTransitionTime )
  247. {
  248. // Iterate to next image
  249. m_iCurImg = ( m_iCurImg + 1 ) % GetImageCount();
  250. // Setup new image
  251. GetImagePanel()->SetImage( m_vecImages[ m_iCurImg ], m_flTransitionLength );
  252. // Set transition time to be the end of the blend
  253. m_flNextTransitionTime = gpGlobals->realtime + m_flInterval;
  254. }
  255. }