//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
const char* CClientTools::GetModelName( HTOOLHANDLE handle )
{
	int idx = m_Handles.Find( HToolEntry_t( handle ) );
	if ( idx == m_Handles.InvalidIndex() )
		return NULL;

	HToolEntry_t &entry = m_Handles[ idx ];
	if ( entry.m_hEntity )
	{
		return STRING( entry.m_hEntity->GetModelName() );
	}
	Assert( 0 );
	return NULL;
}
示例#2
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;
}
//-----------------------------------------------------------------------------
// Use this to turn on/off the presence of an underlying game entity
//-----------------------------------------------------------------------------
void CClientTools::SetEnabled( HTOOLHANDLE handle, bool enabled )
{
	int idx = m_Handles.Find( HToolEntry_t( handle ) );
	if ( idx == m_Handles.InvalidIndex() )
		return;

	HToolEntry_t *slot = &m_Handles[ idx ];
	Assert( slot );
	if ( slot == NULL )
		return;

	C_BaseEntity *ent = slot->m_hEntity.Get();
	if ( ent == NULL ||	ent->entindex() == 0 )
		return; // Don't disable/enable the "world"

	ent->EnableInToolView( enabled );
}
//-----------------------------------------------------------------------------
// 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;
}
//-----------------------------------------------------------------------------
// 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 );
}
void RemoveFromWhiteList( 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;
		int idx = g_WhiteList.Find( sym );
		if ( idx != g_WhiteList.InvalidIndex() )
		{
			g_WhiteList.RemoveAt( idx );
			++wl_removed;
		}
	}
}
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 );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : handle - 
//-----------------------------------------------------------------------------
bool CClientTools::IsValidHandle( HTOOLHANDLE handle )
{
	return m_Handles.Find( HToolEntry_t( handle ) ) != m_Handles.InvalidIndex();
}
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() );
	}
}
void BuildWhiteList()
{
	// Search for unusedcontent.cfg file
	if ( !g_pFileSystem->FileExists( WHITELIST_FILE ) )
	{
		vprint( 1, "Running with no whitelist.cfg file!!!\n" );
		return;
	}

	vprint( 1, "\nBuilding whitelist\n" );

	KeyValues *kv = new KeyValues( WHITELIST_FILE );
	if ( kv )
	{
		if ( kv->LoadFromFile( g_pFileSystem, WHITELIST_FILE, NULL ) )
		{
			for ( KeyValues *sub = kv->GetFirstSubKey(); sub; sub = sub->GetNextKey() )
			{
				if ( !Q_stricmp( sub->GetName(), "add" ) )
				{
					AddToWhiteList( sub->GetString() );
				}
				else if ( !Q_stricmp( sub->GetName(), "remove" ) )
				{
					RemoveFromWhiteList( sub->GetString() );
				}
				else
				{
					vprint( 1, "Unknown subkey '%s' in %s\n", sub->GetName(), WHITELIST_FILE );
				}
			}
		}

		kv->deleteThis();
	}

	if ( verbose || printwhitelist )
	{
		vprint( 1, "Whitelist:\n\n" );


		for ( int i = g_WhiteList.FirstInorder(); 
			i != g_WhiteList.InvalidIndex(); 
			i = g_WhiteList.NextInorder( i ) )
		{
			UnusedContent::CUtlSymbol& sym = g_WhiteList[ i ];

			char const *resolved = g_Analysis.symbols.String( sym );
			vprint( 2, "  %s\n", resolved );
		}
	}

	// dump the whitelist file list anyway
	{
		filesystem->RemoveFile( "whitelist_files.txt", "GAME" );
		for ( int i = g_WhiteList.FirstInorder(); 
			i != g_WhiteList.InvalidIndex(); 
			i = g_WhiteList.NextInorder( i ) )
		{
			UnusedContent::CUtlSymbol& sym = g_WhiteList[ i ];
			char const *resolved = g_Analysis.symbols.String( sym );
			logprint( "whitelist_files.txt", "\"%s\"\n", resolved );
		}
	}


	vprint( 1, "Whitelist resolves to %d files (added %i/removed %i)\n\n", g_WhiteList.Count(), wl_added, wl_removed );
}
void Correlate( CUtlRBTree< ReferencedFile, int >& referencedfiles, CUtlVector< FileEntry >& contentfiles, const char *modname )
{
	int i;
	int c = contentfiles.Count();
	
	double totalDiskSize = 0;
	double totalReferencedDiskSize = 0;
	double totalWhiteListDiskSize = 0;

	for ( i = 0; i < c; ++i )
	{
		totalDiskSize += contentfiles [ i ].size;
	}

	vprint( 0, "Content tree size on disk %s\n", Q_pretifymem( totalDiskSize, 3 ) );
	
	// Analysis is to walk tree and see which files on disk are referenced in the .lst files
	// Need a fast lookup from file symbol to referenced list
	CUtlRBTree< ReferencedFile, int >	tree( 0, 0, ReferencedFileLessFunc );
	c = referencedfiles.Count();
	for ( i = 0 ; i < c; ++i )
	{
		tree.Insert( referencedfiles[ i ] );
	}

	// Now walk the on disk file and see check off resources which are in referenced
	c = contentfiles.Count();
	int invalidindex = tree.InvalidIndex();
	unsigned int refcounted = 0;
	unsigned int whitelisted = 0;

	filesystem->RemoveFile( CFmtStr( "%swhitelist.lst", g_szReslistDir ), "GAME" );

	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];

		ReferencedFile foo;
		foo.sym = entry.sym;

		bool gameref = tree.Find( foo ) != invalidindex;
		char const *fn = g_Analysis.symbols.String( entry.sym );

		bool whitelist = g_WhiteList.Find( entry.sym ) != g_WhiteList.InvalidIndex();

		if ( gameref || whitelist )
		{
			entry.referenced = gameref ? REFERENCED_GAME : REFERENCED_WHITELIST;
			totalReferencedDiskSize += entry.size;
			if ( entry.referenced == REFERENCED_WHITELIST )
			{
				logprint( CFmtStr( "%swhitelist.lst", g_szReslistDir ), "\"%s\\%s\"\n", modname, fn );

				totalWhiteListDiskSize += entry.size;
				++whitelisted;
			}
			++refcounted;
		}
	}

	vprint( 0, "Found %i referenced (%i whitelist) files in tree, %s\n", refcounted, whitelisted, Q_pretifymem( totalReferencedDiskSize, 2 ) );
	vprint( 0, "%s appear unused\n", Q_pretifymem( totalDiskSize - totalReferencedDiskSize, 2 ) );

	// Now sort and dump the unreferenced ones..
	vprint( 0, "Sorting unreferenced files list...\n" );

	CUtlRBTree< FileEntry, int >	unreftree( 0, 0, FileEntryLessFunc );
	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];
		if ( entry.referenced != REFERENCED_NO )
			continue;

		unreftree.Insert( entry );
	}

	// Now walk the unref tree in order
	i = unreftree.FirstInorder();
	invalidindex = unreftree.InvalidIndex();
	int index = 0;
	while ( i != invalidindex )
	{
		FileEntry & entry = unreftree[ i ];

		if ( showreferencedfiles )
		{
			vprint( 1, "%6i %12s: %s\n", ++index, Q_pretifymem( entry.size, 2 ), g_Analysis.symbols.String( entry.sym ) );
		}
		
		i = unreftree.NextInorder( i );
	}

	if ( showmapfileusage )
	{
		vprint( 0, "Writing referenced.csv...\n" );

		// Now walk the list of referenced files and print out how many and which maps reference them
		i = tree.FirstInorder();
		invalidindex = tree.InvalidIndex();
		index = 0;
		while ( i != invalidindex )
		{
			ReferencedFile & entry = tree[ i ];

			char ext[ 32 ];
			Q_ExtractFileExtension( g_Analysis.symbols.String( entry.sym ), ext, sizeof( ext ) );

			logprint( "referenced.csv", "\"%s\",\"%s\",%d", g_Analysis.symbols.String( entry.sym ), ext, entry.maplist.Count() );

			int mapcount = entry.maplist.Count();
			for ( int j = 0 ; j < mapcount; ++j )
			{
				char basemap[ 128 ];
				Q_FileBase( g_Analysis.symbols.String( entry.maplist[ j ] ), basemap, sizeof( basemap ) );
				logprint( "referenced.csv", ",\"%s\"", basemap );
			}

			logprint( "referenced.csv", "\n" );
			
			i = tree.NextInorder( i );
		}
	}


	vprint( 0, "\nBuilding directory summary list...\n" );

	// Now build summaries by root branch off of gamedir (e.g., for sound, materials, models, etc.)
	CUtlDict< DirEntry, int > directories;
	invalidindex = directories.InvalidIndex();
	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];

		// Get the dir name
		char const *dirname = g_Analysis.symbols.String( entry.sym );

		const char *backslash = strstr( dirname, "\\" );

		char dir[ 256 ];
		if ( !backslash )
		{
			dir[0] = 0;
		}
		else
		{
			Q_strncpy( dir, dirname, backslash - dirname + 1);
		}

		
		int idx = directories.Find( dir );
		if ( idx == invalidindex )
		{
			DirEntry foo;
			idx = directories.Insert( dir, foo );
		}

		DirEntry & de = directories[ idx ];
		de.total += entry.size;
		if ( entry.referenced == REFERENCED_NO )
		{
			de.unreferenced += entry.size;
		}
		if ( entry.referenced == REFERENCED_WHITELIST )
		{
			de.whitelist += entry.size;
		}
	}

	if ( spewdeletions )
	{
		// Spew deletion commands to console
		if ( immediatedelete )
		{
			vprint( 0, "\n\nDeleting files...\n" );
		}
		else
		{
			vprint( 0, "\n\nGenerating deletions.bat\n" );
		}

		i = unreftree.FirstInorder();
		invalidindex = unreftree.InvalidIndex();
		float deletionSize = 0.0f;
		int deletionCount = 0;

		while ( i != invalidindex )
		{
			FileEntry & entry = unreftree[ i ];
			i = unreftree.NextInorder( i );

			// Don't delete stuff that's in the white list
			if ( g_WhiteList.Find( entry.sym ) != g_WhiteList.InvalidIndex() )
			{
				if ( verbose )
				{
					vprint( 0, "whitelist blocked deletion of %s\n", g_Analysis.symbols.String( entry.sym ) );
				}
				continue;
			}

			++deletionCount;
			deletionSize += entry.size;

			if ( immediatedelete ) 
			{
				if ( _chmod( g_Analysis.symbols.String( entry.sym ), _S_IWRITE ) == -1 )
				{
					vprint( 0, "Could not find file %s\n", g_Analysis.symbols.String( entry.sym ) );
				}
				if ( _unlink( g_Analysis.symbols.String( entry.sym ) ) == -1 )
				{
					vprint( 0, "Could not delete file %s\n", g_Analysis.symbols.String( entry.sym ) );
				}

				if ( deletionCount % 1000 == 0 )
				{
					vprint( 0, "...deleted %i files\n", deletionCount );
				}
			}
			else
			{
				logprint( "deletions.bat", "del \"%s\" /f\n",  g_Analysis.symbols.String( entry.sym ) );
			}
		}

		vprint( 0, "\nFile deletion (%d files, %s)\n\n", deletionCount, Q_pretifymem(deletionSize, 2) );
	}

	double grand_total = 0;
	double grand_total_unref = 0;
	double grand_total_white = 0;

	char totalstring[ 20 ];
	char unrefstring[ 20 ];
	char refstring[ 20 ];
	char whiteliststring[ 20 ];

	vprint( 0, "---------------------------------------- Summary ----------------------------------------\n" );

	vprint( 0, "% 15s               % 15s               % 15s               % 15s %12s\n",
		"Referenced",
		"WhiteListed",
		"Unreferenced",
		"Total",
		"Directory" );

	// Now walk the dictionary in order
	i = directories.First();
	while ( i != invalidindex )
	{
		DirEntry & de = directories[ i ];

		double remainder = de.total - de.unreferenced;

		float percent_unref = 0.0f;
		float percent_white = 0.0f;
		if ( de.total > 0 )
		{
			percent_unref = 100.0f * (float)de.unreferenced / (float)de.total;
			percent_white = 100.0f * (float)de.whitelist / (float)de.total;
		}

		Q_strncpy( totalstring, Q_pretifymem( de.total, 2 ), sizeof( totalstring ) );
		Q_strncpy( unrefstring, Q_pretifymem( de.unreferenced, 2 ), sizeof( unrefstring ) );
		Q_strncpy( refstring, Q_pretifymem( remainder, 2 ), sizeof( refstring ) );
		Q_strncpy( whiteliststring, Q_pretifymem( de.whitelist, 2 ), sizeof( whiteliststring ) );

		vprint( 0, "%15s (%8.3f%%)   %15s (%8.3f%%)   %15s (%8.3f%%)   %15s => dir: %s\n",
			refstring, 100.0f - percent_unref, whiteliststring, percent_white, unrefstring, percent_unref, totalstring, directories.GetElementName( i ) );

		grand_total += de.total;
		grand_total_unref += de.unreferenced;
		grand_total_white += de.whitelist;

		i = directories.Next( i );
	}

	Q_strncpy( totalstring, Q_pretifymem( grand_total, 2 ), sizeof( totalstring ) );
	Q_strncpy( unrefstring, Q_pretifymem( grand_total_unref, 2 ), sizeof( unrefstring ) );
	Q_strncpy( refstring, Q_pretifymem( grand_total - grand_total_unref, 2 ), sizeof( refstring ) );
	Q_strncpy( whiteliststring, Q_pretifymem( grand_total_white, 2 ), sizeof( whiteliststring ) );

	double percent_unref = 100.0 * grand_total_unref / grand_total;
	double percent_white = 100.0 * grand_total_white / grand_total;

	vprint( 0, "-----------------------------------------------------------------------------------------\n" );
	vprint( 0, "%15s (%8.3f%%)   %15s (%8.3f%%)   %15s (%8.3f%%)   %15s\n",
		refstring, 100.0f - percent_unref, whiteliststring, percent_white, unrefstring, percent_unref, totalstring );
}
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 );
}
//-----------------------------------------------------------------------------
//	ExcludePathsDlg_Populate
//
//	Generate a path table.
//-----------------------------------------------------------------------------
void ExcludePathsDlg_Populate( HWND hWnd, bool bRefresh )
{
	struct GamePath_t 
	{
		CUtlString	pathName;
		bool		bIsModPath;
	};

	CUtlVector< GamePath_t > gamePaths;		

	// can skip the time consuming directory scan, unless forced
	if ( bRefresh || !g_PathTable.Count() )
	{
		g_PathTable.Purge();

		for ( int i = 0; i < ARRAYSIZE( g_GameNames ); i++ )
		{
			char szTargetPath[MAX_PATH];
			V_strncpy( szTargetPath, g_localPath, sizeof( szTargetPath ) );
			V_AppendSlash( szTargetPath, sizeof( szTargetPath ) );
			V_strncat( szTargetPath, g_GameNames[i].pName, sizeof( szTargetPath ) );

			GamePath_t gamePath;
			gamePath.pathName = szTargetPath;
			gamePath.bIsModPath = g_GameNames[i].bIsModPath;
			gamePaths.AddToTail( gamePath );
		}

		// iterate all game paths
		for ( int i = 0; i < gamePaths.Count(); i++ )
		{
			CUtlVector< CUtlString > dirList;
			RecurseFileTree_r( g_localPath, gamePaths[i].pathName.String(), 0, dirList, gamePaths[i].bIsModPath );
		}
	}

	// reset the tree
	HWND hWndTree = GetDlgItem( hWnd, IDC_PATHS_TREE );
	TreeView_DeleteAllItems( hWndTree );

	// reset and add root
	// only the root is at depth 0
	AddItemToTree( hWndTree, ROOT_NAME, 0, false );

	// build the tree view
	for ( int iIndex = g_PathTable.FirstInorder(); iIndex != g_PathTable.InvalidIndex(); iIndex = g_PathTable.NextInorder( iIndex ) )
	{
		// due to sorting, number of slashes is depth
		const char *pString = g_PathTable[iIndex].pathName.String();
		int depth = 0;
		for ( int j = 0; j < (int)strlen( pString ); j++ )
		{
			if ( pString[j] == '\\' )
			{
				depth++;
			}
		}
		if ( !depth )
		{
			depth = 1;
		}

		char szPath[MAX_PATH];
		V_FileBase( pString, szPath, sizeof( szPath ) );
		AddItemToTree( hWndTree, szPath, depth, g_PathTable[iIndex].bIsModPath );
	}

	HTREEITEM hTreeRoot = TreeView_GetRoot( hWndTree );
	for ( int i = 0; i < g_ExcludePaths.Count(); i++ )
	{
		HTREEITEM hTree = ExcludePathsDlg_Find_r( hWndTree, hTreeRoot, 0, "", g_ExcludePaths[i].String() );
		if ( hTree )
		{
			ExcludePathsDlg_SetCheckState_r( hWndTree, hTree, 0, true );
		}
	}

	// expand the root node to show state
	ExcludePathsDlg_ExpandToShowState_r( hWndTree, hTreeRoot, 0 );
}
示例#14
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;
}