|
|
//========= 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 ); } }
|