source-engine/game/client/game_controls/slideshowpanel.cpp

319 lines
7.5 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "cbase.h"
#include "game_controls/slideshowpanel.h"
#include "vgui/IVGui.h"
#include "filesystem.h"
2022-03-01 20:00:42 +00:00
#include "fmtstr.h"
2020-04-22 16:56:21 +00:00
//-----------------------------------------------------------------------------
using namespace vgui;
//-----------------------------------------------------------------------------
DECLARE_BUILD_FACTORY( CCrossfadableImagePanel );
DECLARE_BUILD_FACTORY( CSlideshowPanel );
//-----------------------------------------------------------------------------
CCrossfadableImagePanel::CCrossfadableImagePanel( Panel* pParent, const char *pName )
: EditablePanel( pParent, pName ),
m_iSrcImg( 0 ),
m_flBlend( 0.0f ),
m_flBlendTime( 0.0f ),
m_flStartBlendTime( 0.0f ),
m_bBlending( false )
{
m_pImages[ 0 ] = new ImagePanel( this, "Image0" );
m_pImages[ 1 ] = new ImagePanel( this, "Image1" );
ivgui()->AddTickSignal( GetVPanel(), 10 );
}
CCrossfadableImagePanel::~CCrossfadableImagePanel()
{
ivgui()->RemoveTickSignal( GetVPanel() );
}
void CCrossfadableImagePanel::ApplySettings( KeyValues *pInResourceData )
{
BaseClass::ApplySettings( pInResourceData );
}
void CCrossfadableImagePanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
SrcImg()->SetTileImage( false );
DstImg()->SetTileImage( false );
}
void CCrossfadableImagePanel::PerformLayout()
{
BaseClass::PerformLayout();
for ( int i = 0; i < 2; ++i )
{
m_pImages[ i ]->SetBounds( 0, 0, GetWide(), GetTall() );
m_pImages[ i ]->SetVisible( true );
}
}
// Helper macro to perform a call on both images
#define CALL_FUNC_ON_BOTH_IMAGES( _call ) \
AssertMsg( m_pImages[ 0 ], "m_pImages[ 0 ] is NULL!" ); \
AssertMsg( m_pImages[ 1 ], "m_pImages[ 1 ] is NULL!" ); \
m_pImages[0]->_call; \
m_pImages[1]->_call;
void CCrossfadableImagePanel::SetShouldScaleImage( bool bState )
{
CALL_FUNC_ON_BOTH_IMAGES( SetShouldScaleImage( bState ) );
}
void CCrossfadableImagePanel::SetScaleAmount( float flScale )
{
CALL_FUNC_ON_BOTH_IMAGES( SetScaleAmount( flScale ) );
}
void CCrossfadableImagePanel::SetFillColor( Color c )
{
CALL_FUNC_ON_BOTH_IMAGES( SetFillColor( c ) );
}
void CCrossfadableImagePanel::SetDrawColor( Color clrDrawColor )
{
CALL_FUNC_ON_BOTH_IMAGES( SetDrawColor( clrDrawColor ) );
}
void CCrossfadableImagePanel::InstallMouseHandler( Panel *pHandler )
{
CALL_FUNC_ON_BOTH_IMAGES( InstallMouseHandler( pHandler ) );
}
IImage *CCrossfadableImagePanel::GetImage()
{
return SrcImg()->GetImage();
}
const char *CCrossfadableImagePanel::GetImageName()
{
return SrcImg()->GetImageName();
}
float CCrossfadableImagePanel::GetScaleAmount()
{
return SrcImg()->GetScaleAmount();
}
bool CCrossfadableImagePanel::GetShouldScaleImage()
{
return SrcImg()->GetShouldScaleImage();
}
Color CCrossfadableImagePanel::GetFillColor()
{
return SrcImg()->GetFillColor();
}
Color CCrossfadableImagePanel::GetDrawColor()
{
return SrcImg()->GetDrawColor();
}
void CCrossfadableImagePanel::SetImage( IImage *pImage, float flBlendTime/*=0.0f*/ )
{
DstImg()->SetImage( pImage );
SetupImageBlend( flBlendTime );
}
void CCrossfadableImagePanel::SetImage( const char *pImageName, float flBlendTime/*=0.0f*/ )
{
DstImg()->SetImage( pImageName );
SetupImageBlend( flBlendTime );
}
void CCrossfadableImagePanel::SetupImageBlend( float flBlendTime )
{
m_bBlending = true;
m_flBlendTime = flBlendTime;
m_flStartBlendTime = gpGlobals->realtime;
m_flBlend = 0.0f;
}
void CCrossfadableImagePanel::OnSizeChanged( int nWide, int nTall )
{
m_pImages[ 0 ]->SetSize( nWide, nTall );
m_pImages[ 1 ]->SetSize( nWide, nTall );
}
void CCrossfadableImagePanel::OnTick()
{
if ( m_bBlending )
{
// Compute current blend value
if ( m_flBlendTime == 0.0f )
{
m_flBlend = 1.0f;
}
else
{
float t = clamp( ( gpGlobals->realtime - m_flStartBlendTime ) / m_flBlendTime, 0.0f, 1.0f );
m_flBlend = clamp( t * t * (3 - 2*t), 0.0f, 1.0f ); // S-curve
}
// Set alpha channel on source image
Color clrDraw;
clrDraw = SrcImg()->GetDrawColor();
clrDraw[ 3 ] = ( int )( 255 * ( 1 - m_flBlend ) );
SrcImg()->SetDrawColor( clrDraw );
// Set alpha channel on destination image
clrDraw = DstImg()->GetDrawColor();
clrDraw[ 3 ] = ( int )( 255 * m_flBlend );
DstImg()->SetDrawColor( clrDraw );
// If we're done, don't blend next think
if ( m_flBlend >= 1.0f )
{
m_bBlending = false;
m_iSrcImg = !m_iSrcImg;
m_flBlend = 0.0f;
}
}
}
//-----------------------------------------------------------------------------
CSlideshowPanel::CSlideshowPanel( Panel *pParent, const char *pName )
: EditablePanel( pParent, pName ),
m_iCurImg( 0 ),
m_flInterval( 3.0f ),
m_flTransitionLength( 0.5f )
{
m_pImagePanel = new CCrossfadableImagePanel( this, "CrossfadableImage" );
// Setup the first transition time
UpdateNextTransitionTime();
// Add tick signal
ivgui()->AddTickSignal( GetVPanel(), 10 );
}
CSlideshowPanel::~CSlideshowPanel()
{
// Remove tick signal
ivgui()->RemoveTickSignal( GetVPanel() );
}
void CSlideshowPanel::SetInterval( float flInterval )
{
m_flInterval = flInterval;
UpdateNextTransitionTime();
}
void CSlideshowPanel::SetTransitionTime( float flTransitionLength )
{
m_flTransitionLength = flTransitionLength;
UpdateNextTransitionTime();
}
void CSlideshowPanel::UpdateNextTransitionTime()
{
m_flNextTransitionTime = gpGlobals->realtime + m_flInterval;
}
void CSlideshowPanel::AddImage( const char *pImageName )
{
if ( pImageName && strlen( pImageName ) > 0 )
{
AddImage( scheme()->GetImage( pImageName, m_pImagePanel->GetShouldScaleImage() ) );
}
}
void CSlideshowPanel::AddImage( IImage *pImage )
{
// Cache a pointer to the image
m_vecImages.AddToTail( pImage );
if ( m_vecImages.Count() == 1 )
{
GetImagePanel()->SetImage( pImage );
}
}
void CSlideshowPanel::FillWithImages( const char *pBasePath )
{
int i = 0;
while ( 1 )
{
CFmtStr fmtImagePath( "materials/vgui/%s%i.vmt", pBasePath, i );
V_FixDoubleSlashes( fmtImagePath.Access() );
if ( !g_pFullFileSystem->FileExists( fmtImagePath.Access() ) )
break;
fmtImagePath.sprintf( "%s%i.vmt", pBasePath, i );
AddImage( fmtImagePath.Access() );
++i;
}
}
void CSlideshowPanel::ApplySettings( KeyValues *pInResourceData )
{
BaseClass::ApplySettings( pInResourceData );
int iDefaultImage = pInResourceData->GetInt( "default_index", 0 );
int i = 0;
while ( 1 )
{
CFmtStr fmtImageKeyName( "image_%i", i );
const char *pImagePath = pInResourceData->GetString( fmtImageKeyName.Access(), NULL );
if ( !pImagePath )
break;
AddImage( pImagePath );
if ( iDefaultImage == i )
{
GetImagePanel()->SetImage( pImagePath );
}
++i;
}
GetImagePanel()->SetSize(
XRES( pInResourceData->GetInt( "wide" ) ),
YRES( pInResourceData->GetInt( "tall" ) )
);
GetImagePanel()->SetShouldScaleImage( pInResourceData->GetBool( "scaleImage" ) );
GetImagePanel()->SetScaleAmount( pInResourceData->GetFloat( "scaleAmount" ) );
}
void CSlideshowPanel::OnSizeChanged( int nWide, int nTall )
{
GetImagePanel()->SetSize( nWide, nTall );
}
void CSlideshowPanel::OnTick()
{
if ( GetImageCount() > 1 && gpGlobals->realtime >= m_flNextTransitionTime )
{
// Iterate to next image
m_iCurImg = ( m_iCurImg + 1 ) % GetImageCount();
// Setup new image
GetImagePanel()->SetImage( m_vecImages[ m_iCurImg ], m_flTransitionLength );
// Set transition time to be the end of the blend
m_flNextTransitionTime = gpGlobals->realtime + m_flInterval;
}
}