//-----------------------------------------------------------------------------
// Finds and/or creates a symbol based on the string
//-----------------------------------------------------------------------------
void CLocalizedStringTable::AddString(char const *pString, wchar_t *pValue, const char *fileName)
{
	if (!pString) 
		return;

	wchar_t *str = Find(pString);
	
	// it's already in the table
	if (str)
		return;

	// didn't find, insert the string into the vector.
	int len = strlen(pString) + 1;
	int stridx = m_Names.AddMultipleToTail( len );
	memcpy( &m_Names[stridx], pString, len * sizeof(char) );

	len = wcslen(pValue) + 1;
	int valueidx = m_Values.AddMultipleToTail( len );
	memcpy( &m_Values[valueidx], pValue, len * sizeof(wchar_t) );

	localizedstring_t stringMapItem;
	stringMapItem.nameIndex = stridx;
	stringMapItem.valueIndex = valueidx;
	if (fileName)
	{
		stringMapItem.filename = fileName;
	}
	else
	{
		stringMapItem.filename = m_CurrentFile;
	}
	m_Lookup.Insert( stringMapItem );
}
void CAI_GoalEntity::InputUpdateActors( inputdata_t &inputdata )
{
	int i;
	CUtlRBTree<CAI_BaseNPC *> prevActors;
	CUtlRBTree<CAI_BaseNPC *>::IndexType_t index;

	SetDefLessFunc( prevActors );
	
	PruneActors();
	
	for ( i = 0; i < m_actors.Count(); i++ )
	{
		prevActors.Insert( m_actors[i] );
	}
	
	ResolveNames();
	
	for ( i = 0; i < m_actors.Count(); i++ )
	{
		index = prevActors.Find( m_actors[i] );
		if ( index == prevActors.InvalidIndex() )
		{
			if ( m_flags & ACTIVE )
				EnableGoal( m_actors[i] );
		}
		else
			prevActors.Remove( m_actors[i] );
	}
	
	for ( index = prevActors.FirstInorder(); index != prevActors.InvalidIndex(); index = prevActors.NextInorder( index ) )
	{
		if ( m_flags & ACTIVE )
			DisableGoal( prevActors[ index ] );
	}
}
Пример #3
0
//-----------------------------------------------------------------------------
// Fixes up all elements
//-----------------------------------------------------------------------------
void CImportSFMV6::BuildList( CDmElement *pElement, CUtlRBTree< CDmElement *, int >& list )
{
	if ( !pElement )
		return;

	if ( list.Find( pElement ) != list.InvalidIndex() )
		return;

	list.Insert( pElement );

	// Descend to bottom of tree, then do fixup coming back up the tree
	for ( CDmAttribute *pAttribute = pElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() )
	{
		if ( pAttribute->GetType() == AT_ELEMENT )
		{
			CDmElement *pElement = pAttribute->GetValueElement<CDmElement>( );
			BuildList( pElement, list );
			continue;
		}

		if ( pAttribute->GetType() == AT_ELEMENT_ARRAY )
		{
			CDmrElementArray<> array( pAttribute );
			int nCount = array.Count();
			for ( int i = 0; i < nCount; ++i )
			{
				CDmElement *pChild = array[ i ];
				BuildList( pChild, list );
			}
			continue;
		}
	}
}
void CPhysicsListenerCollision::event_friction_pair_created( IVP_Friction_Core_Pair *pair )
{
	corepair_t test(pair);
	unsigned short index = m_pairList.Find( test );
	if ( m_pairList.IsValidIndex( index ) )
	{
		corepair_t &save = m_pairList.Element(index);
		// found this one already, update the time
		if ( save.lastImpactTime.get_seconds() > pair->last_impact_time_pair.get_seconds() )
		{
			pair->last_impact_time_pair = save.lastImpactTime;
		}
		else
		{
			save.lastImpactTime = pair->last_impact_time_pair;
		}
	}
	else
	{
		if ( m_pairList.Count() < 16 )
		{
			m_pairList.Insert( test );
		}
	}
}
Пример #5
0
bool CChoreoChannel::GetSortedCombinedEventList( char const *cctoken, CUtlRBTree< CChoreoEvent * >& events )
{
	events.RemoveAll();

	int i;
	// Sort items
	int c = GetNumEvents();
	for ( i = 0; i < c; i++ )
	{
		CChoreoEvent *e = GetEvent( i );
		Assert( e );
		if ( e->GetType() != CChoreoEvent::SPEAK )
			continue;

		if ( e->GetCloseCaptionType() == CChoreoEvent::CC_DISABLED )
			continue;

		// A master with no slaves is not a combined event
		if ( e->GetCloseCaptionType() == CChoreoEvent::CC_MASTER &&
			 e->GetNumSlaves() == 0 )
			 continue;

		char const *token = e->GetCloseCaptionToken();
		if ( Q_stricmp( token, cctoken ) )
			continue;

		events.Insert( e );
	}

	return ( events.Count() > 0 ) ? true : false;
}
int CCombatCharVisCache::LookupVisibility( const CBaseCombatCharacter *pChar1, CBaseCombatCharacter *pChar2 )
{
	VisCacheEntry_t cacheEntry;
	if ( pChar1 < pChar2 )
	{
		cacheEntry.m_hEntity1 = pChar1;
		cacheEntry.m_hEntity2 = pChar2;
	}
	else
	{
		cacheEntry.m_hEntity1 = pChar2;
		cacheEntry.m_hEntity2 = pChar1;
	}

	int iCache = m_VisCache.Find( cacheEntry );
	if ( iCache == m_VisCache.InvalidIndex() )
	{
		if ( m_VisCache.Count() == m_VisCache.InvalidIndex() )
			return VIS_CACHE_INVALID;

		iCache = m_VisCache.Insert( cacheEntry );
		m_VisCache[iCache].m_flTime = gpGlobals->curtime - 2.0f * VIS_CACHE_ENTRY_LIFE;
	}

	return ( pChar1 < pChar2 ) ? iCache : - iCache - 1;
}
void AddNewTranslation( const char *pOriginalMaterialName, const char *pNewMaterialName )
{
	NameTranslationLookup_t newEntry;
	
	newEntry.m_OriginalFileName = s_SymbolTable.AddString( pOriginalMaterialName );
	newEntry.m_PatchFileName = s_SymbolTable.AddString( pNewMaterialName );

	s_MapPatchedMatToOriginalMat.Insert( newEntry );
}
Пример #8
0
AISquadEnemyInfo_t *CAI_Squad::FindEnemyInfo( CBaseEntity *pEnemy )
{
	int i;
	if ( gpGlobals->curtime > m_flEnemyInfoCleanupTime )
	{
		if ( m_EnemyInfos.Count() )
		{
			m_pLastFoundEnemyInfo = NULL;
			CUtlRBTree<CBaseEntity *> activeEnemies;
			SetDefLessFunc( activeEnemies );

			// Gather up the set of active enemies
			for ( i = 0; i < m_SquadMembers.Count(); i++ )
			{
				CBaseEntity *pMemberEnemy = m_SquadMembers[i]->GetEnemy();
				if ( pMemberEnemy && activeEnemies.Find( pMemberEnemy ) == activeEnemies.InvalidIndex() )
				{
					activeEnemies.Insert( pMemberEnemy );
				}
			}
			
			// Remove the records for deleted or unused enemies
			for ( i = m_EnemyInfos.Count() - 1; i >= 0; --i )
			{
				if ( m_EnemyInfos[i].hEnemy == NULL || activeEnemies.Find( m_EnemyInfos[i].hEnemy ) == activeEnemies.InvalidIndex() )
				{
					m_EnemyInfos.FastRemove( i );
				}
			}
		}
		
		m_flEnemyInfoCleanupTime = gpGlobals->curtime + 30;
	}

	if ( m_pLastFoundEnemyInfo && m_pLastFoundEnemyInfo->hEnemy == pEnemy )
		return m_pLastFoundEnemyInfo;

	for ( i = 0; i < m_EnemyInfos.Count(); i++ )
	{
		if ( m_EnemyInfos[i].hEnemy == pEnemy )
		{
			m_pLastFoundEnemyInfo = &m_EnemyInfos[i];
			return &m_EnemyInfos[i];
		}
	}

	m_pLastFoundEnemyInfo = NULL;
	i = m_EnemyInfos.AddToTail();
	m_EnemyInfos[i].hEnemy = pEnemy;

	m_pLastFoundEnemyInfo = &m_EnemyInfos[i];
	return &m_EnemyInfos[i];
}
Пример #9
0
//-----------------------------------------------------------------------------
// Purpose: Takes the texinfo_t referenced by the .vmt and the computed depth for the
//  surface and looks up or creates a texdata/texinfo for the mangled one-off water .vmt file
// Input  : *pBaseInfo - 
//			depth - 
// Output : int
//-----------------------------------------------------------------------------
int FindOrCreateWaterTexInfo( texinfo_t *pBaseInfo, float depth )
{
	char fullname[ 512 ];
	char materialname[ 512 ];

	// Get the base texture/material name
	char const *name = TexDataStringTable_GetString( GetTexData( pBaseInfo->texdata )->nameStringTableID );

	GetWaterTextureName( mapbase, name, (int)depth, fullname );

	// See if we already have an entry for this depth
	WaterTexInfo lookup;
	lookup.m_FullName = fullname;
	int idx = g_WaterTexInfos.Find( lookup );

	// If so, return the existing entry texinfo index
	if ( idx != g_WaterTexInfos.InvalidIndex() )
	{
		return g_WaterTexInfos[ idx ].m_nTexInfo;
	}

	// Otherwise, fill in the rest of the data
	lookup.m_nWaterDepth = (int)depth;
	// Remember the current material name
	sprintf( materialname, "%s", name );
	strlwr( materialname );
	lookup.m_MaterialName = materialname;

	texinfo_t ti;
	// Make a copy
	ti = *pBaseInfo;
	// Create a texdata that is based on the underlying existing entry
	ti.texdata = FindAliasedTexData( fullname, GetTexData( pBaseInfo->texdata ) );

	// Find or create a new index
	lookup.m_nTexInfo = FindOrCreateTexInfo( ti );

	// Add the new texinfo to the RB tree
	idx = g_WaterTexInfos.Insert( lookup );

	// Msg( "created texinfo for %s\n", lookup.m_FullName.String() );

	// Go ahead and create the new vmt file.
	EmitWaterMaterialFile( &g_WaterTexInfos[idx] );

	// Return the new texinfo
	return g_WaterTexInfos[ idx ].m_nTexInfo;
}
void IFaceposerModels::CFacePoserModel::BuildValidChecksums( CUtlRBTree< CRC32_t > &tree )
{
	StudioModel *model = m_pModel;
	if ( !model )
		return;

	CStudioHdr *hdr = model->GetStudioHdr();
	if ( !hdr )
		return;	

	for ( int i = 0; i < hdr->GetNumSeq(); i++ )
	{
		CRC32_t crc = GetBitmapCRC( i );
		tree.Insert( crc );
	}
}
Пример #11
0
HTOOLHANDLE CClientTools::AttachToEntity( EntitySearchResult entityToAttach )
{
	C_BaseEntity *ent = reinterpret_cast< C_BaseEntity * >( entityToAttach );
	if ( !ent )
		return (HTOOLHANDLE)0;

	HTOOLHANDLE curHandle = ent->GetToolHandle();
	if ( curHandle != 0 )
		return curHandle; // Already attaached

	HToolEntry_t newHandle( s_nNextHandle++, ent );

	m_Handles.Insert( newHandle );
	m_ActiveHandles.AddToTail( newHandle.m_Handle );

	return (HTOOLHANDLE)newHandle.m_Handle;
}
//-----------------------------------------------------------------------------
// Purpose: Recursively determine directory tree
//-----------------------------------------------------------------------------
static void RecurseFileTree_r( const char *pBasePath, const char *pDirPath, int depth, CUtlVector< CUtlString > &dirList, bool bIsModPath )
{
	if ( depth >= 2 )
	{
		// too much unecessary detail
		return;
	}

	// ignore path roots, only interested in subdirs
	const char *pSubName = pDirPath + strlen( pBasePath );
	if ( pSubName[0] )
	{
		GamePath_t gamePath;
		gamePath.pathName = pSubName;
		gamePath.bIsModPath = bIsModPath;
		
		int iIndex = g_PathTable.Find( gamePath );
		if ( iIndex == g_PathTable.InvalidIndex() )
		{
			g_PathTable.Insert( gamePath );
		}
	}

	// recurse from source directory, get directories only
	CUtlVector< CUtlString > fileList;
	int dirCount = GetFileList( pDirPath, "\\", fileList );
	if ( !dirCount )
	{
		// add directory name to search tree
		int j = dirList.AddToTail();
		dirList[j].Set( pDirPath );
		return;
	}

	for ( int i=0; i<dirCount; i++ )
	{
		// form new path name, recurse into
		RecurseFileTree_r( pBasePath, fileList[i].String(), depth+1, dirList, bIsModPath );
	}

	int j = dirList.AddToTail();
	dirList[j].Set( pDirPath );
}
Пример #13
0
//-----------------------------------------------------------------------------
// Make sure the details are compiled with static prop
//-----------------------------------------------------------------------------
static bool IsModelValid( const char* pModelName )
{
	StaticPropLookup_t lookup;
	lookup.m_ModelName = pModelName;

	int i = s_StaticPropLookup.Find( lookup );
	if (i != s_StaticPropLookup.InvalidIndex() )
		return s_StaticPropLookup[i].m_IsValid;

	CUtlBuffer buf;
	lookup.m_IsValid = LoadStudioModel( pModelName, "detail_prop", buf );
	if (!lookup.m_IsValid)
	{
		Warning("Error loading studio model \"%s\"!\n", pModelName );
	}

	s_StaticPropLookup.Insert( lookup );
	return lookup.m_IsValid;
}
CUtlSymbol CUtlSymbolTable::AddString( char const* pString )
{
	if (!pString) 
		return CUtlSymbol( UTL_INVAL_SYMBOL );

	CUtlSymbol id = Find( pString );
	
	if (id.IsValid())
		return id;

	int len = strlen(pString) + 1;

	// Find a pool with space for this string, or allocate a new one.
	int iPool = FindPoolWithSpace( len );
	if ( iPool == -1 )
	{
		// Add a new pool.
		int newPoolSize = max( len, MIN_STRING_POOL_SIZE );
		StringPool_t *pPool = (StringPool_t*)malloc( sizeof( StringPool_t ) + newPoolSize - 1 );
		pPool->m_TotalLen = newPoolSize;
		pPool->m_SpaceUsed = 0;
		iPool = m_StringPools.AddToTail( pPool );
	}

	// Copy the string in.
	StringPool_t *pPool = m_StringPools[iPool];
	Assert( pPool->m_SpaceUsed < 0xFFFF );	// This should never happen, because if we had a string > 64k, it
											// would have been given its entire own pool.
	
	unsigned int iStringOffset = pPool->m_SpaceUsed;

	memcpy( &pPool->m_Data[pPool->m_SpaceUsed], pString, len );
	pPool->m_SpaceUsed += len;

	// didn't find, insert the string into the vector.
	CStringPoolIndex index;
	index.m_iPool = iPool;
	index.m_iOffset = iStringOffset;

	UtlSymId_t idx = m_Lookup.Insert( index );
	return CUtlSymbol( idx );
}
Пример #15
0
//-----------------------------------------------------------------------------
// Purpose: returns a pointer to an image
//-----------------------------------------------------------------------------
IImage *CSchemeManager::GetImage(const char *imageName, bool hardwareFiltered)
{
	if ( !imageName || strlen(imageName) <= 0 ) // frame icons and the like are in the scheme file and may not be defined, so if this is null then fail silently
	{
		return NULL; 
	}

	// set up to search for the bitmap
	CachedBitmapHandle_t searchBitmap;
	searchBitmap.bitmap = NULL;

	// Prepend 'vgui/'. Resource files try to load images assuming they live in the vgui directory.
	// Used to do this in Bitmap::Bitmap, moved so that the s_pszSearchString is searching for the
	// filename with 'vgui/' already added.
	char szFileName[256];

	if ( Q_stristr( imageName, ".pic" ) )
	{
		Q_snprintf( szFileName, sizeof(szFileName), "%s", imageName );
	}
	else
	{
		Q_snprintf( szFileName, sizeof(szFileName), "vgui/%s", imageName );
	}

	s_pszSearchString = szFileName;

	int i = m_Bitmaps.Find(searchBitmap);
	if (m_Bitmaps.IsValidIndex(i))
	{
		return m_Bitmaps[i].bitmap;
	}

	// couldn't find the image, try and load it
	CachedBitmapHandle_t bitmap = { new Bitmap(szFileName, hardwareFiltered) };
	m_Bitmaps.Insert(bitmap);
	return bitmap.bitmap;
}
Пример #16
0
void CHL2GameMovement::GetSortedDismountNodeList( const Vector &org, float radius, CFuncLadder *ladder, CUtlRBTree< NearbyDismount_t, int >& list )
{
	float radiusSqr = radius * radius;

	int i;
	int c = ladder->GetDismountCount();
	for ( i = 0; i < c; i++ )
	{
		CInfoLadderDismount *spot = ladder->GetDismount( i );
		if ( !spot )
			continue;

		float distSqr = ( spot->GetAbsOrigin() - org ).LengthSqr();
		if ( distSqr > radiusSqr )
			continue;

		NearbyDismount_t nd;
		nd.dismount = spot;
		nd.distSqr = distSqr;

		list.Insert( nd );
	}
}
void logprint( char const *logfile, const char *fmt, ... )
{
	char string[ 8192 ];
	va_list va;
	va_start( va, fmt );
	vsprintf( string, fmt, va );
	va_end( va );

	FILE *fp = NULL;

	UnusedContent::CUtlSymbol sym = g_Analysis.symbols.Find( logfile );
	static CUtlRBTree< UnusedContent::CUtlSymbol, int >	previousfiles( 0, 0, DefLessFunc( UnusedContent::CUtlSymbol ) );
	if ( previousfiles.Find( sym ) == previousfiles.InvalidIndex() )
	{
		previousfiles.Insert( sym );
		fp = fopen( logfile, "wb" );
	}
	else
	{
		fp = fopen( logfile, "ab" );
	}

	if ( fp )
	{
		char *p = string;
		while ( *p )
		{
			if ( *p == '\n' )
			{
				fputc( '\r', fp );
			}
			fputc( *p, fp );
			p++;
		}
		fclose( fp );
	}
}
void AddToWhiteList( char const *path )
{
	vprint( 2, "+\t'%s'\n", path );

	char dir[ 512 ];
	Q_strncpy( dir, path, sizeof( dir ) );

	// Get the base filename from the path
	_strlwr( dir );
	Q_FixSlashes( dir );

	CUtlVector< FileEntry > files;

	char *lastslash = strrchr( dir, '\\' );
	if ( lastslash == 0 )
	{
		BuildFileListWildcard( 1, files, "", dir, 0 );
	}
	else
	{
		char *wild = lastslash + 1;
		*lastslash = 0;

		BuildFileListWildcard( 1, files, dir, wild, 0 );
	}

	int c = files.Count();
	for ( int i = 0; i < c; ++i )
	{
		UnusedContent::CUtlSymbol sym = files[ i ].sym;
		if ( g_WhiteList.Find( sym ) == g_WhiteList.InvalidIndex() )
		{
			g_WhiteList.Insert( sym );
			++wl_added;
		}
	}
}
Пример #19
0
//-----------------------------------------------------------------------------
// Add, find collision model in cache
//-----------------------------------------------------------------------------
static CPhysCollide* GetCollisionModel( char const* pModelName )
{
	// Convert to a common string
	char* pTemp = (char*)_alloca(strlen(pModelName) + 1);
	strcpy( pTemp, pModelName );
	_strlwr( pTemp );

	char* pSlash = strchr( pTemp, '\\' );
	while( pSlash )
	{
		*pSlash = '/';
		pSlash = strchr( pTemp, '\\' );
	}

	// Find it in the cache
	ModelCollisionLookup_t lookup;
	lookup.m_Name = pTemp;
	int i = s_ModelCollisionCache.Find( lookup );
	if (i != s_ModelCollisionCache.InvalidIndex())
		return s_ModelCollisionCache[i].m_pCollide;

	// Load the studio model file
	CUtlBuffer buf;
	if (!LoadStudioModel(pModelName, "prop_static", buf))
	{
		Warning("Error loading studio model \"%s\"!\n", pModelName );

		// This way we don't try to load it multiple times
		lookup.m_pCollide = 0;
		s_ModelCollisionCache.Insert( lookup );

		return 0;
	}

	// Compute the convex hull of the model...
	studiohdr_t* pStudioHdr = (studiohdr_t*)buf.PeekGet();

	// necessary for vertex access
	SetCurrentModel( pStudioHdr );

	lookup.m_pCollide = ComputeConvexHull( pStudioHdr );
	s_ModelCollisionCache.Insert( lookup );

	if ( !lookup.m_pCollide )
	{
		Warning("Bad geometry on \"%s\"!\n", pModelName );
	}

	// Debugging
	if (g_DumpStaticProps)
	{
		static int propNum = 0;
		char tmp[128];
		sprintf( tmp, "staticprop%03d.txt", propNum );
		DumpCollideToGlView( lookup.m_pCollide, tmp );
		++propNum;
	}

	FreeCurrentModelVertexes();

	// Insert into cache...
	return lookup.m_pCollide;
}
Пример #20
0
//-----------------------------------------------------------------------------
// Purpose: Creates a target address, for sending messages to reliably
//-----------------------------------------------------------------------------
int CTrackerNET::FindTarget(CNetAddress &address, int targetID, int sequenceNumber)
{
	bool createNew = true;
	NetworkTarget_t *target = NULL;
	int listIndex = 0;

	// find the address in the map
	int targetIndex = FindTargetIndexByAddress(address);
	if (m_TargetMap.IsValidIndex(targetIndex))
	{
		listIndex = m_TargetMap[targetIndex].targetIndex;
		target = &(m_TargetList[listIndex]);

		// make sure the targetID's match, otherwise the connection has been invalidated
		if (targetID == -1 || target->targetID == targetID)
		{
			return listIndex;
		}
		else
		{
			if (sequenceNumber == 1)
			{
				//!! reset the connection
				WriteToLog("-> Connection Reset (%d) (%d, %d)\n", sequenceNumber, targetID, target->targetID);
			}
			else
			{
				WriteToLog("-> Connection Restart (%d) (%d, %d)\n", sequenceNumber, targetID, target->targetID);
			}
			createNew = false;
		}
	}

	if (createNew)
	{
		// add a new connection to the end of the list
		listIndex = m_TargetList.AddToTail();
		target = &(m_TargetList[listIndex]);
		target->needAck = false;

		// add the target to the map
		TargetMapItem_t newItem;
		newItem.targetIndex = listIndex;
		newItem.netAddress = address;
		m_TargetMap.Insert(newItem);

		// ensure that it's the first one in the sequence
		if (sequenceNumber > 1)
		{
			WriteToLog("-> Contacted by unknown old connection (targetID:%d)\n", targetID);
		}
	}

	// append to the end of the list
	target->netAddress = address;

	// initialize sequence numbers
	target->outgoingSequence = 1;
	target->outgoingAcknowledged = 0;
	target->incomingSequence = 0;
	target->incomingAcknowledged = 0;

	if (sequenceNumber != -1)
	{
		// this is the first packet we've received, but from and old connection; so jump the correct sequence number
		target->incomingSequence = sequenceNumber - 1;
	}

//	target->createTime = m_pThreads->GetTime();
	if (targetID >= 0)
	{
		target->targetID = targetID;
	}
	else
	{
		target->targetID = RandomLong(1, MAX_RANDOM_RANGE);
	}

	if (createNew && targetID >= 0)
	{
		WriteToLog("Creating new target ID (%d)\n", target->targetID);
	}
	else
	{
		WriteToLog("Establishing connection to target ID (%d)\n", target->targetID);
	}

	return listIndex;
}
void ParseFilesFromResList( UnusedContent::CUtlSymbol & resfilesymbol, CUtlRBTree< ReferencedFile, int >& files, char const *resfile )
{
	int addedStrings = 0;
	int resourcesConsidered = 0;

	int offset = Q_strlen( gamedir );

	char basedir[MAX_PATH];
	Q_strncpy( basedir, gamedir, sizeof( basedir ) );
	if ( !Q_StripLastDir( basedir, sizeof( basedir ) ) )
		Error( "Can't get basedir from %s.", gamedir );

	FileHandle_t resfilehandle;
	resfilehandle = g_pFileSystem->Open( resfile, "rb" );
	if ( FILESYSTEM_INVALID_HANDLE != resfilehandle )
	{
		// Read in the entire file
		int length = g_pFileSystem->Size(resfilehandle);
		if ( length > 0 )
		{
			char *pStart = (char *)new char[ length + 1 ];
			if ( pStart && ( length == g_pFileSystem->Read(pStart, length, resfilehandle) ) )
			{
				pStart[ length ] = 0;

				char *pFileList = pStart;

				char token[512];

				while ( 1 )
				{
					pFileList = ParseFile( pFileList, token, NULL );
					if ( !pFileList )
						break;

					if ( strlen( token ) > 0 )
					{
						char szFileName[ 256 ];
						Q_snprintf( szFileName, sizeof( szFileName ), "%s%s", basedir, token );
						_strlwr( szFileName );
						Q_FixSlashes( szFileName );
						while ( szFileName[ strlen( szFileName ) - 1 ] == '\n' ||
							szFileName[ strlen( szFileName ) - 1 ] == '\r' )
						{
							szFileName[ strlen( szFileName ) - 1 ] = 0;
						}

						if ( Q_strnicmp( szFileName, gamedir, offset ) )
							continue;

						char *pFile = szFileName + offset;
						++resourcesConsidered;

						ReferencedFile rf;
						rf.sym = g_Analysis.symbols.AddString( pFile );

						int idx = files.Find( rf );
						if ( idx == files.InvalidIndex() )
						{
							++addedStrings;
							rf.maplist.AddToTail( resfilesymbol );
							files.Insert( rf );
						}
						else
						{
							// 
							ReferencedFile & slot = files[ idx ];
							if ( slot.maplist.Find( resfilesymbol ) == slot.maplist.InvalidIndex() )
							{
								slot.maplist.AddToTail( resfilesymbol );
							}

						}
					}
				}

			}
			delete[] pStart;
		}

		g_pFileSystem->Close(resfilehandle);
	}

	int filesFound = addedStrings;

	vprint( 1, "Found %i new resources (%i total) in %s\n", filesFound, resourcesConsidered, resfile );
}
void CPlayerLogoProxy::OnBind( void *pC_BaseEntity )
{
	// Decal's are bound with the player index as the passed in paramter
	int playerindex = (int)pC_BaseEntity;

	if ( playerindex <= 0 )
		return;

	if ( playerindex > gpGlobals->maxClients )
		return;

	if ( !m_pBaseTextureVar )
		return;

	// Find player
	player_info_t info;
	engine->GetPlayerInfo( playerindex, &info );

	if ( !info.customFiles[0] ) 
		return;

	// So we don't trash this too hard

	ITexture *texture = NULL;

	PlayerLogo logo;
	logo.crc = (unsigned int)info.customFiles[0];
	logo.texture = NULL;

	int lookup = m_Logos.Find( logo );
	if ( lookup == m_Logos.InvalidIndex() )
	{
		char crcfilename[ 512 ];
		char logohex[ 16 ];
		Q_binarytohex( (byte *)&info.customFiles[0], sizeof( info.customFiles[0] ), logohex, sizeof( logohex ) );

		Q_snprintf( crcfilename, sizeof( crcfilename ), "temp/%s", logohex );

		texture = materials->FindTexture( crcfilename, TEXTURE_GROUP_DECAL, false );
		if ( texture )
		{
			// Make sure it doesn't get flushed
			texture->IncrementReferenceCount();
			logo.texture = texture;
		}

		m_Logos.Insert( logo );
	}
	else
	{
		texture = m_Logos[ lookup ].texture;
	}

	if ( texture )
	{
		m_pBaseTextureVar->SetTextureValue( texture );
	}
	else if ( m_pDefaultTexture )
	{
		m_pBaseTextureVar->SetTextureValue( m_pDefaultTexture );
	}

	if ( ToolsEnabled() )
	{
		ToolFramework_RecordMaterialParams( GetMaterial() );
	}
}