1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2024-12-23 01:59:43 +08:00
hl2sdk/game/client/c_slideshow_display.cpp
Nicholas Hastings 3957adff10 Sync with upstream (Issue #30).
Recompiled tier1 and mathlib  for all platforms will come in next commit.
2016-11-30 10:01:15 -05:00

377 lines
10 KiB
C++

//========= Copyright 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 ( IsX360() )
{
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 ] = {0};
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;
}
}
// 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 ( IsX360() )
{
// 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 ( !IsX360() )
{
g_pFullFileSystem->FindClose( matHandle );
}
}