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.
378 lines
10 KiB
378 lines
10 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//=============================================================================//
|
|
#include "cbase.h"
|
|
#include "c_slideshow_display.h"
|
|
#include "c_te_legacytempents.h"
|
|
#include "tempent.h"
|
|
#include "engine/IEngineSound.h"
|
|
#include "dlight.h"
|
|
#include "iefx.h"
|
|
#include "SoundEmitterSystem/isoundemittersystembase.h"
|
|
#include "filesystem.h"
|
|
#include "keyvalues.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
|
|
#define SLIDESHOW_LIST_BUFFER_MAX 8192
|
|
|
|
|
|
enum SlideshowCycleTypes
|
|
{
|
|
SLIDESHOW_CYCLE_RANDOM,
|
|
SLIDESHOW_CYCLE_FORWARD,
|
|
SLIDESHOW_CYCLE_BACKWARD,
|
|
|
|
SLIDESHOW_CYCLE_TOTAL
|
|
};
|
|
|
|
|
|
CUtlVector< C_SlideshowDisplay* > g_SlideshowDisplays;
|
|
|
|
|
|
IMPLEMENT_CLIENTCLASS_DT(C_SlideshowDisplay, DT_SlideshowDisplay, CSlideshowDisplay)
|
|
RecvPropBool( RECVINFO(m_bEnabled) ),
|
|
RecvPropString( RECVINFO( m_szDisplayText ) ),
|
|
RecvPropString( RECVINFO( m_szSlideshowDirectory ) ),
|
|
RecvPropArray3( RECVINFO_ARRAY(m_chCurrentSlideLists), RecvPropInt( RECVINFO(m_chCurrentSlideLists[0]) ) ),
|
|
RecvPropFloat( RECVINFO(m_fMinSlideTime) ),
|
|
RecvPropFloat( RECVINFO(m_fMaxSlideTime) ),
|
|
RecvPropInt( RECVINFO(m_iCycleType) ),
|
|
RecvPropBool( RECVINFO(m_bNoListRepeats) ),
|
|
END_RECV_TABLE()
|
|
|
|
|
|
C_SlideshowDisplay::C_SlideshowDisplay()
|
|
{
|
|
g_SlideshowDisplays.AddToTail( this );
|
|
}
|
|
|
|
C_SlideshowDisplay::~C_SlideshowDisplay()
|
|
{
|
|
g_SlideshowDisplays.FindAndRemove( this );
|
|
}
|
|
|
|
void C_SlideshowDisplay::Spawn( void )
|
|
{
|
|
BaseClass::Spawn();
|
|
|
|
m_NextSlideTime = 0;
|
|
|
|
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
|
}
|
|
|
|
void C_SlideshowDisplay::OnDataChanged( DataUpdateType_t updateType )
|
|
{
|
|
BaseClass::OnDataChanged( updateType );
|
|
|
|
if ( updateType == DATA_UPDATE_CREATED )
|
|
{
|
|
BuildSlideShowImagesList();
|
|
}
|
|
else if ( updateType == DATA_UPDATE_DATATABLE_CHANGED )
|
|
{
|
|
m_iCurrentSlideList = 0;
|
|
m_iCurrentSlide = 0;
|
|
}
|
|
}
|
|
|
|
int C_SlideshowDisplay::GetMaterialIndex( int iSlideIndex )
|
|
{
|
|
if ( !m_SlideMaterialLists[ 0 ] )
|
|
return 0;
|
|
|
|
return m_SlideMaterialLists[ 0 ]->iSlideMaterials[ iSlideIndex ];
|
|
}
|
|
|
|
int C_SlideshowDisplay::NumMaterials( void )
|
|
{
|
|
if ( !m_SlideMaterialLists[ 0 ] )
|
|
return 0;
|
|
|
|
return m_SlideMaterialLists[ 0 ]->iSlideMaterials.Count();
|
|
}
|
|
|
|
void C_SlideshowDisplay::ClientThink( void )
|
|
{
|
|
BaseClass::ClientThink();
|
|
|
|
if ( !m_bEnabled )
|
|
return;
|
|
|
|
// Check if it's time for the next slide
|
|
if ( m_NextSlideTime > gpGlobals->curtime )
|
|
return;
|
|
|
|
// Set the time to cycle to the next slide
|
|
m_NextSlideTime = gpGlobals->curtime + RandomFloat( m_fMinSlideTime, m_fMaxSlideTime );
|
|
|
|
// Get the amount of items to pick from
|
|
int iNumCurrentSlideLists;
|
|
for ( iNumCurrentSlideLists = 0; iNumCurrentSlideLists < 16; ++iNumCurrentSlideLists )
|
|
{
|
|
if ( m_chCurrentSlideLists[ iNumCurrentSlideLists ] == (unsigned char)-1 )
|
|
break;
|
|
}
|
|
|
|
// Bail if no slide lists are selected
|
|
if ( iNumCurrentSlideLists == 0 )
|
|
return;
|
|
|
|
// Cycle the list
|
|
switch ( m_iCycleType )
|
|
{
|
|
case SLIDESHOW_CYCLE_RANDOM:
|
|
{
|
|
int iOldSlideList = m_iCurrentSlideList;
|
|
m_iCurrentSlideList = RandomInt( 0, iNumCurrentSlideLists - 1 );
|
|
|
|
// Prevent repeats if we don't want them
|
|
if ( m_bNoListRepeats && iNumCurrentSlideLists > 1 && m_iCurrentSlideList == iOldSlideList )
|
|
{
|
|
++m_iCurrentSlideList;
|
|
|
|
if ( m_iCurrentSlideList >= iNumCurrentSlideLists )
|
|
m_iCurrentSlideList = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case SLIDESHOW_CYCLE_FORWARD:
|
|
if ( m_iCurrentSlideList >= iNumCurrentSlideLists )
|
|
m_iCurrentSlideList = 0;
|
|
break;
|
|
|
|
case SLIDESHOW_CYCLE_BACKWARD:
|
|
if ( m_iCurrentSlideList < 0 )
|
|
m_iCurrentSlideList = iNumCurrentSlideLists - 1;
|
|
break;
|
|
}
|
|
|
|
SlideMaterialList_t *pSlideMaterialList = m_SlideMaterialLists[ m_chCurrentSlideLists[ m_iCurrentSlideList ] ];
|
|
|
|
// Cycle in the list
|
|
switch ( m_iCycleType )
|
|
{
|
|
case SLIDESHOW_CYCLE_RANDOM:
|
|
m_iCurrentSlide = RandomInt( 0, pSlideMaterialList->iSlideMaterials.Count() - 1 );
|
|
break;
|
|
|
|
case SLIDESHOW_CYCLE_FORWARD:
|
|
++m_iCurrentSlide;
|
|
if ( m_iCurrentSlide >= pSlideMaterialList->iSlideMaterials.Count() )
|
|
{
|
|
++m_iCurrentSlideList;
|
|
if ( m_iCurrentSlideList >= iNumCurrentSlideLists )
|
|
m_iCurrentSlideList = 0;
|
|
pSlideMaterialList = m_SlideMaterialLists[ m_chCurrentSlideLists[ m_iCurrentSlideList ] ];
|
|
m_iCurrentSlide = 0;
|
|
}
|
|
break;
|
|
|
|
case SLIDESHOW_CYCLE_BACKWARD:
|
|
--m_iCurrentSlide;
|
|
if ( m_iCurrentSlide < 0 )
|
|
{
|
|
--m_iCurrentSlideList;
|
|
if ( m_iCurrentSlideList < 0 )
|
|
m_iCurrentSlideList = iNumCurrentSlideLists - 1;
|
|
pSlideMaterialList = m_SlideMaterialLists[ m_chCurrentSlideLists[ m_iCurrentSlideList ] ];
|
|
m_iCurrentSlide = pSlideMaterialList->iSlideMaterials.Count() - 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Set the current material to what we've cycled to
|
|
m_iCurrentMaterialIndex = pSlideMaterialList->iSlideMaterials[ m_iCurrentSlide ];
|
|
m_iCurrentSlideIndex = pSlideMaterialList->iSlideIndex[ m_iCurrentSlide ];
|
|
}
|
|
|
|
void C_SlideshowDisplay::BuildSlideShowImagesList( void )
|
|
{
|
|
FileFindHandle_t matHandle;
|
|
char szDirectory[_MAX_PATH];
|
|
char szMatFileName[_MAX_PATH] = {'\0'};
|
|
char szFileBuffer[ SLIDESHOW_LIST_BUFFER_MAX ];
|
|
char *pchCurrentLine = NULL;
|
|
|
|
if ( IsGameConsole() )
|
|
{
|
|
Q_snprintf( szDirectory, sizeof( szDirectory ), "materials/vgui/%s/slides.txt", m_szSlideshowDirectory );
|
|
|
|
FileHandle_t fh = g_pFullFileSystem->Open( szDirectory, "rt" );
|
|
if ( !fh )
|
|
{
|
|
DevWarning( "Couldn't read slideshow image file %s!", szDirectory );
|
|
return;
|
|
}
|
|
|
|
int iFileSize = MIN( g_pFullFileSystem->Size( fh ), SLIDESHOW_LIST_BUFFER_MAX );
|
|
|
|
int iBytesRead = g_pFullFileSystem->Read( szFileBuffer, iFileSize, fh );
|
|
g_pFullFileSystem->Close( fh );
|
|
|
|
// Ensure we don't write outside of our buffer
|
|
if ( iBytesRead > iFileSize )
|
|
iBytesRead = iFileSize;
|
|
szFileBuffer[ iBytesRead ] = '\0';
|
|
|
|
pchCurrentLine = szFileBuffer;
|
|
|
|
// Seek to end of first line
|
|
char *pchNextLine = pchCurrentLine;
|
|
while ( *pchNextLine != '\0' && *pchNextLine != '\n' && *pchNextLine != ' ' )
|
|
++pchNextLine;
|
|
|
|
if ( *pchNextLine != '\0' )
|
|
{
|
|
// Mark end of string
|
|
*pchNextLine = '\0';
|
|
|
|
// Seek to start of next string
|
|
++pchNextLine;
|
|
while ( *pchNextLine != '\0' && ( *pchNextLine == '\n' || *pchNextLine == ' ' ) )
|
|
++pchNextLine;
|
|
}
|
|
|
|
Q_strncpy( szMatFileName, pchCurrentLine, sizeof(szMatFileName) );
|
|
pchCurrentLine = pchNextLine;
|
|
}
|
|
else
|
|
{
|
|
Q_snprintf( szDirectory, sizeof( szDirectory ), "materials/vgui/%s/*.vmt", m_szSlideshowDirectory );
|
|
const char *pMatFileName = g_pFullFileSystem->FindFirst( szDirectory, &matHandle );
|
|
|
|
if ( pMatFileName )
|
|
Q_strncpy( szMatFileName, pMatFileName, sizeof(szMatFileName) );
|
|
}
|
|
|
|
int iSlideIndex = 0;
|
|
|
|
while ( szMatFileName[ 0 ] )
|
|
{
|
|
char szFileName[_MAX_PATH];
|
|
Q_snprintf( szFileName, sizeof( szFileName ), "vgui/%s/%s", m_szSlideshowDirectory, szMatFileName );
|
|
szFileName[ Q_strlen( szFileName ) - 4 ] = '\0';
|
|
|
|
int iMatIndex = ::GetMaterialIndex( szFileName );
|
|
|
|
// Get material keywords
|
|
char szFullFileName[_MAX_PATH];
|
|
Q_snprintf( szFullFileName, sizeof( szFullFileName ), "materials/vgui/%s/%s", m_szSlideshowDirectory, szMatFileName );
|
|
|
|
KeyValues *pMaterialKeys = new KeyValues( "material" );
|
|
bool bLoaded = pMaterialKeys->LoadFromFile( g_pFullFileSystem, szFullFileName, NULL );
|
|
if ( bLoaded )
|
|
{
|
|
char szKeywords[ 256 ];
|
|
V_strcpy_safe( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) );
|
|
|
|
char *pchKeyword = szKeywords;
|
|
|
|
while ( pchKeyword[ 0 ] != '\0' )
|
|
{
|
|
char *pNextKeyword = pchKeyword;
|
|
|
|
// Skip commas and spaces
|
|
while ( pNextKeyword[ 0 ] != '\0' && pNextKeyword[ 0 ] != ',' )
|
|
++pNextKeyword;
|
|
|
|
if ( pNextKeyword[ 0 ] != '\0' )
|
|
{
|
|
pNextKeyword[ 0 ] = '\0';
|
|
++pNextKeyword;
|
|
|
|
while ( pNextKeyword[ 0 ] != '\0' && ( pNextKeyword[ 0 ] == ',' || pNextKeyword[ 0 ] == ' ' ) )
|
|
++pNextKeyword;
|
|
}
|
|
|
|
// Find the list with the current keyword
|
|
int iList;
|
|
for ( iList = 0; iList < m_SlideMaterialLists.Count(); ++iList )
|
|
{
|
|
if ( Q_strcmp( m_SlideMaterialLists[ iList ]->szSlideKeyword, pchKeyword ) == 0 )
|
|
break;
|
|
}
|
|
|
|
if ( iList >= m_SlideMaterialLists.Count() )
|
|
{
|
|
// Couldn't find the list, so create it
|
|
iList = m_SlideMaterialLists.AddToTail( new SlideMaterialList_t );
|
|
V_strcpy_safe( m_SlideMaterialLists[ iList ]->szSlideKeyword, pchKeyword );
|
|
}
|
|
|
|
// Add material index to this list
|
|
m_SlideMaterialLists[ iList ]->iSlideMaterials.AddToTail( iMatIndex );
|
|
m_SlideMaterialLists[ iList ]->iSlideIndex.AddToTail( iSlideIndex );
|
|
|
|
pchKeyword = pNextKeyword;
|
|
}
|
|
}
|
|
pMaterialKeys->deleteThis();
|
|
pMaterialKeys = NULL;
|
|
|
|
// Find the generic list
|
|
int iList;
|
|
for ( iList = 0; iList < m_SlideMaterialLists.Count(); ++iList )
|
|
{
|
|
if ( Q_strcmp( m_SlideMaterialLists[ iList ]->szSlideKeyword, "" ) == 0 )
|
|
break;
|
|
}
|
|
|
|
if ( iList >= m_SlideMaterialLists.Count() )
|
|
{
|
|
// Couldn't find the generic list, so create it
|
|
iList = m_SlideMaterialLists.AddToHead( new SlideMaterialList_t );
|
|
V_strcpy_safe( m_SlideMaterialLists[ iList ]->szSlideKeyword, "" );
|
|
}
|
|
|
|
// Add material index to this list
|
|
m_SlideMaterialLists[ iList ]->iSlideMaterials.AddToTail( iMatIndex );
|
|
m_SlideMaterialLists[ iList ]->iSlideIndex.AddToTail( iSlideIndex );
|
|
|
|
if ( IsGameConsole() )
|
|
{
|
|
// Seek to end of first line
|
|
char *pchNextLine = pchCurrentLine;
|
|
while ( *pchNextLine != '\0' && *pchNextLine != '\n' && *pchNextLine != ' ' )
|
|
++pchNextLine;
|
|
|
|
if ( *pchNextLine != '\0' )
|
|
{
|
|
// Mark end of string
|
|
*pchNextLine = '\0';
|
|
|
|
// Seek to start of next string
|
|
++pchNextLine;
|
|
while ( *pchNextLine != '\0' && ( *pchNextLine == '\n' || *pchNextLine == ' ' ) )
|
|
++pchNextLine;
|
|
}
|
|
|
|
Q_strncpy( szMatFileName, pchCurrentLine, sizeof(szMatFileName) );
|
|
pchCurrentLine = pchNextLine;
|
|
}
|
|
else
|
|
{
|
|
const char *pMatFileName = g_pFullFileSystem->FindNext( matHandle );
|
|
|
|
if ( pMatFileName )
|
|
Q_strncpy( szMatFileName, pMatFileName, sizeof(szMatFileName) );
|
|
else
|
|
szMatFileName[ 0 ] = '\0';
|
|
}
|
|
|
|
++iSlideIndex;
|
|
}
|
|
|
|
if ( !IsGameConsole() )
|
|
{
|
|
g_pFullFileSystem->FindClose( matHandle );
|
|
}
|
|
}
|