You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CrowdControl/Assets/Plugins/AssetUsageDetector/Editor/AssetUsageDetectorCache.cs

207 lines
5.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace AssetUsageDetectorNamespace
{
public partial class AssetUsageDetector
{
#region Helper Classes
private class CacheEntry
{
public enum Result { Unknown = 0, No = 1, Yes = 2 };
public string hash;
public string[] dependencies;
public long[] fileSizes;
public bool verified;
public Result searchResult;
public CacheEntry( string path )
{
Verify( path );
}
public CacheEntry( string hash, string[] dependencies, long[] fileSizes )
{
this.hash = hash;
this.dependencies = dependencies;
this.fileSizes = fileSizes;
}
public void Verify( string path )
{
string hash = AssetDatabase.GetAssetDependencyHash( path ).ToString();
if( this.hash != hash )
{
this.hash = hash;
Refresh( path );
}
verified = true;
}
public void Refresh( string path )
{
dependencies = AssetDatabase.GetDependencies( path, false );
if( fileSizes == null || fileSizes.Length != dependencies.Length )
fileSizes = new long[dependencies.Length];
int length = dependencies.Length;
for( int i = 0; i < length; i++ )
{
if( !string.IsNullOrEmpty( dependencies[i] ) )
{
FileInfo assetFile = new FileInfo( dependencies[i] );
fileSizes[i] = assetFile.Exists ? assetFile.Length : 0L;
}
else
{
// This dependency is empty which causes issues when passed to FileInfo constructor
// Find a non-empty dependency and move it to this index
for( int j = length - 1; j > i; j--, length-- )
{
if( !string.IsNullOrEmpty( dependencies[j] ) )
{
dependencies[i--] = dependencies[j];
break;
}
}
length--;
}
}
if( length != fileSizes.Length )
{
Array.Resize( ref dependencies, length );
Array.Resize( ref fileSizes, length );
}
}
}
#endregion
// An optimization to fetch the dependencies of an asset only once (key is the path of the asset)
private Dictionary<string, CacheEntry> assetDependencyCache;
private CacheEntry lastRefreshedCacheEntry;
private string CachePath { get { return Application.dataPath + "/../Library/AssetUsageDetector.cache"; } } // Path of the cache file
public void SaveCache()
{
if( assetDependencyCache == null )
return;
try
{
using( FileStream stream = new FileStream( CachePath, FileMode.Create ) )
using( BinaryWriter writer = new BinaryWriter( stream ) )
{
writer.Write( assetDependencyCache.Count );
foreach( var keyValuePair in assetDependencyCache )
{
CacheEntry cacheEntry = keyValuePair.Value;
string[] dependencies = cacheEntry.dependencies;
long[] fileSizes = cacheEntry.fileSizes;
writer.Write( keyValuePair.Key );
writer.Write( cacheEntry.hash );
writer.Write( dependencies.Length );
for( int i = 0; i < dependencies.Length; i++ )
{
writer.Write( dependencies[i] );
writer.Write( fileSizes[i] );
}
}
}
}
catch( Exception e )
{
Debug.LogException( e );
}
}
private void LoadCache()
{
if( File.Exists( CachePath ) )
{
using( FileStream stream = new FileStream( CachePath, FileMode.Open, FileAccess.Read ) )
using( BinaryReader reader = new BinaryReader( stream ) )
{
try
{
int cacheSize = reader.ReadInt32();
assetDependencyCache = new Dictionary<string, CacheEntry>( cacheSize );
for( int i = 0; i < cacheSize; i++ )
{
string assetPath = reader.ReadString();
string hash = reader.ReadString();
int dependenciesLength = reader.ReadInt32();
string[] dependencies = new string[dependenciesLength];
long[] fileSizes = new long[dependenciesLength];
for( int j = 0; j < dependenciesLength; j++ )
{
dependencies[j] = reader.ReadString();
fileSizes[j] = reader.ReadInt64();
}
assetDependencyCache[assetPath] = new CacheEntry( hash, dependencies, fileSizes );
}
}
catch( Exception e )
{
assetDependencyCache = null;
Debug.LogWarning( "Couldn't load cache (probably cache format has changed in an update), will regenerate cache.\n" + e.ToString() );
}
}
}
// Generate cache for all assets for the first time
if( assetDependencyCache == null )
{
assetDependencyCache = new Dictionary<string, CacheEntry>( 1024 * 8 );
string[] allAssets = AssetDatabase.GetAllAssetPaths();
if( allAssets.Length > 0 )
{
double startTime = EditorApplication.timeSinceStartup;
try
{
for( int i = 0; i < allAssets.Length; i++ )
{
if( i % 30 == 0 && EditorUtility.DisplayCancelableProgressBar( "Please wait...", "Generating cache for the first time (optional)", (float) i / allAssets.Length ) )
{
EditorUtility.ClearProgressBar();
Debug.LogWarning( "Initial cache generation cancelled, cache will be generated on the fly as more and more assets are searched." );
break;
}
assetDependencyCache[allAssets[i]] = new CacheEntry( allAssets[i] );
}
EditorUtility.ClearProgressBar();
Debug.Log( "Cache generated in " + ( EditorApplication.timeSinceStartup - startTime ).ToString( "F2" ) + " seconds" );
Debug.Log( "You can always reset the cache by deleting " + Path.GetFullPath( CachePath ) );
SaveCache();
}
catch( Exception e )
{
EditorUtility.ClearProgressBar();
Debug.LogException( e );
}
}
}
}
}
}