Counter Strike : Global Offensive Source Code
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.
|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "decals.h"
#include "igamesystem.h"
#include "utlsymbol.h"
#include "utldict.h"
#include "keyvalues.h"
#include "filesystem.h"
#include <ctype.h>
#ifdef CLIENT_DLL
#include "iefx.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define DECAL_LIST_FILE "scripts/decals_subrect.txt"
//#define DECAL_LIST_FILE "scripts/decals.txt"
#define TRANSLATION_DATA_SECTION "TranslationData"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CDecalEmitterSystem : public IDecalEmitterSystem, public CAutoGameSystem { public: CDecalEmitterSystem( char const *name ) : CAutoGameSystem( name ) { }
virtual bool Init(); virtual void Shutdown(); virtual void LevelInitPreEntity();
// Public interface
virtual int GetDecalIndexForName( char const *decalname ); virtual char const *TranslateDecalForGameMaterial( char const *decalName, unsigned char gamematerial );
private: char const *ImpactDecalForGameMaterial( int gamematerial ); void LoadDecalsFromScript( char const *filename ); void Clear();
struct DecalListEntry { DecalListEntry() { name = UTL_INVAL_SYMBOL; precache_index = -1; weight = 1.0f; }
CUtlSymbol name; int precache_index; float weight; };
struct DecalEntry { DecalEntry() { }
DecalEntry( const DecalEntry& src ) { int c = src.indices.Count(); for ( int i = 0; i < c; i++ ) { indices.AddToTail( src.indices[ i ] ); } }
DecalEntry& operator = ( const DecalEntry& src ) { if ( this == &src ) return *this;
int c = src.indices.Count(); for ( int i = 0; i < c; i++ ) { indices.AddToTail( src.indices[ i ] ); }
return *this; }
CUtlVector< int > indices; };
CUtlVector< DecalListEntry > m_AllDecals; CUtlDict< DecalEntry, int > m_Decals; CUtlSymbolTable m_DecalFileNames; CUtlDict< int, int > m_GameMaterialTranslation; };
static CDecalEmitterSystem g_DecalSystem( "CDecalEmitterSystem" ); IDecalEmitterSystem *decalsystem = &g_DecalSystem;
//-----------------------------------------------------------------------------
// Purpose:
// Input : *decalname -
// Output : int
//-----------------------------------------------------------------------------
int CDecalEmitterSystem::GetDecalIndexForName( char const *decalname ) { if ( !decalname || !decalname[ 0 ] ) return -1;
int idx = m_Decals.Find( decalname ); if ( idx == m_Decals.InvalidIndex() ) return -1;
DecalEntry *e = &m_Decals[ idx ]; Assert( e ); int count = e->indices.Count(); if ( count <= 0 ) return -1;
float totalweight = 0.0f; int slot = 0;
for ( int i = 0; i < count; i++ ) { int idx = e->indices[ i ]; DecalListEntry *item = &m_AllDecals[ idx ]; Assert( item ); if ( !totalweight ) { slot = idx; }
// Always assume very first slot will match
totalweight += item->weight; if ( !totalweight || random->RandomFloat(0,totalweight) < item->weight ) { slot = idx; } }
return m_AllDecals[ slot ].precache_index; }
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CDecalEmitterSystem::Init() { LoadDecalsFromScript( DECAL_LIST_FILE ); return true; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CDecalEmitterSystem::LevelInitPreEntity() { // Precache all entries
int c = m_AllDecals.Count(); for ( int i = 0 ; i < c; i++ ) { DecalListEntry& e = m_AllDecals[ i ]; #if defined( CLIENT_DLL )
e.precache_index = effects->Draw_DecalIndexFromName( (char *)m_DecalFileNames.String( e.name ) ); #else
e.precache_index = engine->PrecacheDecal( m_DecalFileNames.String( e.name ) ); #endif
} }
//-----------------------------------------------------------------------------
// Purpose:
// Input : *filename -
//-----------------------------------------------------------------------------
void CDecalEmitterSystem::LoadDecalsFromScript( char const *filename ) { KeyValues *kv = new KeyValues( filename ); Assert( kv ); if ( kv ) { KeyValues *translation = NULL; if ( kv->LoadFromFile( filesystem, filename ) ) { KeyValues *p = kv; while ( p ) { if ( p->GetFirstSubKey() ) { char const *keyname = p->GetName();
if ( !Q_stricmp( keyname, TRANSLATION_DATA_SECTION ) ) { translation = p; } else { DecalEntry entry;
for ( KeyValues *sub = p->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) { MEM_ALLOC_CREDIT();
DecalListEntry decal; decal.precache_index = -1; decal.name = m_DecalFileNames.AddString( sub->GetName() ); decal.weight = sub->GetFloat();
// Add to global list
int idx = m_AllDecals.AddToTail( decal );
// Add index only to local list
entry.indices.AddToTail( idx ); }
// Add entry to main dictionary
m_Decals.Insert( keyname, entry ); } } p = p->GetNextKey(); } } else { Msg( "CDecalEmitterSystem::LoadDecalsFromScript: Unable to load '%s'\n", filename ); }
if ( !translation ) { Msg( "CDecalEmitterSystem::LoadDecalsFromScript: Script '%s' missing section '%s'\n", filename, TRANSLATION_DATA_SECTION ); } else { // Now parse game material to entry translation table
for ( KeyValues *sub = translation->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) { // Don't add NULL string to list
if ( !Q_stricmp( sub->GetString(), "" ) ) continue;
int idx = m_Decals.Find( sub->GetString() ); if ( idx != m_Decals.InvalidIndex() ) { const char *value = sub->GetName(); int gameMaterial; if ( !V_isdigit( value[0]) ) { gameMaterial = toupper( value[0] ); } else { gameMaterial = atoi( value ); }
char gm[ 2 ]; gm[0] = gameMaterial; gm[1] = 0; m_GameMaterialTranslation.Insert( gm, idx ); } else { Msg( "CDecalEmitterSystem::LoadDecalsFromScript: Translation for game material type '%s' references unknown decal '%s'\n", sub->GetName(), sub->GetString() ); } } }
kv->deleteThis(); } }
//-----------------------------------------------------------------------------
// Purpose:
// Input : gamematerial -
// Output : char const
//-----------------------------------------------------------------------------
char const *CDecalEmitterSystem::ImpactDecalForGameMaterial( int gamematerial ) { char gm[ 2 ]; gm[0] = (char)gamematerial; gm[1] = 0;
int idx = m_GameMaterialTranslation.Find( gm ); if ( idx == m_GameMaterialTranslation.InvalidIndex() ) return NULL;
return m_Decals.GetElementName( m_GameMaterialTranslation.Element(idx) ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CDecalEmitterSystem::Shutdown() { Clear(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CDecalEmitterSystem::Clear() { m_DecalFileNames.RemoveAll(); m_Decals.Purge(); m_AllDecals.Purge(); m_GameMaterialTranslation.Purge(); }
//-----------------------------------------------------------------------------
// Purpose:
// Input : *decalName -
// gamematerial -
// Output : char const
//-----------------------------------------------------------------------------
char const *CDecalEmitterSystem::TranslateDecalForGameMaterial( char const *decalName, unsigned char gamematerial ) { if ( gamematerial == CHAR_TEX_CONCRETE ) return decalName;
if ( !Q_stricmp( decalName, "Impact.Concrete" ) ) { if ( gamematerial == '-' ) return "";
char const *d = ImpactDecalForGameMaterial( gamematerial ); if ( d ) { return d; } }
return decalName; }
|