309 lines
10 KiB
C#
309 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Profiling;
|
|
|
|
namespace HeurekaGames.AssetHunterPRO.BaseTreeviewImpl.AssetTreeView
|
|
{
|
|
[System.Serializable]
|
|
public class AH_TreeviewElement : TreeElement, ISerializationCallbackReceiver
|
|
{
|
|
#region Fields
|
|
[SerializeField]
|
|
private string absPath;
|
|
//[SerializeField]
|
|
private string relativePath;
|
|
[SerializeField]
|
|
private string guid;
|
|
//[SerializeField]
|
|
private Type assetType;
|
|
[SerializeField]
|
|
private string assetTypeSerialized;
|
|
private long assetSize;
|
|
//private string assestSizeStringRepresentation;
|
|
//[SerializeField]
|
|
private long fileSize;
|
|
//[SerializeField]
|
|
//private string fileSizeStringRepresentation;
|
|
[SerializeField]
|
|
private List<string> scenesReferencingAsset;
|
|
[SerializeField]
|
|
private bool usedInBuild;
|
|
[SerializeField]
|
|
private bool isFolder;
|
|
[SerializeField]
|
|
private Dictionary<AH_MultiColumnHeader.AssetShowMode, long> combinedAssetSizeInFolder = new Dictionary<AH_MultiColumnHeader.AssetShowMode, long>();
|
|
|
|
//Dictionary of asset types and their icons (Cant be serialized)
|
|
private static Dictionary<Type, Texture> iconDictionary = new Dictionary<Type, Texture>();
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public string RelativePath
|
|
{
|
|
get
|
|
{
|
|
if(!string.IsNullOrEmpty(relativePath))
|
|
return relativePath;
|
|
else
|
|
return relativePath = UnityEditor.AssetDatabase.GUIDToAssetPath(GUID);
|
|
}
|
|
}
|
|
|
|
public string GUID
|
|
{
|
|
get
|
|
{
|
|
return guid;
|
|
}
|
|
}
|
|
|
|
public Type AssetType
|
|
{
|
|
get
|
|
{
|
|
return assetType;
|
|
}
|
|
}
|
|
|
|
public string AssetTypeSerialized
|
|
{
|
|
get
|
|
{
|
|
if(String.IsNullOrEmpty(assetTypeSerialized) && assetType!=null)
|
|
assetTypeSerialized = Heureka_Serializer.SerializeType(assetType);
|
|
return assetTypeSerialized;
|
|
}
|
|
}
|
|
|
|
public long AssetSize
|
|
{
|
|
get
|
|
{
|
|
if(UsedInBuild && assetSize == 0)
|
|
{
|
|
UnityEngine.Object asset = UnityEditor.AssetDatabase.LoadMainAssetAtPath(RelativePath);
|
|
//#if UNITY_2017_1_OR_NEWER
|
|
if (asset != null)
|
|
return this.assetSize = Profiler.GetRuntimeMemorySizeLong(asset) / 2;
|
|
else
|
|
return -1;
|
|
}
|
|
else
|
|
return assetSize;
|
|
}
|
|
}
|
|
|
|
public string AssetSizeStringRepresentation
|
|
{
|
|
get
|
|
{
|
|
return AH_Utils.GetSizeAsString(AssetSize);
|
|
}
|
|
}
|
|
|
|
public long FileSize
|
|
{
|
|
get
|
|
{
|
|
if (fileSize != 0)
|
|
return fileSize;
|
|
else
|
|
{
|
|
var fileInfo = new System.IO.FileInfo(absPath);
|
|
if (fileInfo.Exists)
|
|
return fileSize = fileInfo != null ? fileInfo.Length : 0;
|
|
else
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
public string FileSizeStringRepresentation
|
|
{
|
|
get
|
|
{
|
|
return AH_Utils.GetSizeAsString(fileSize);
|
|
}
|
|
}
|
|
|
|
public List<string> ScenesReferencingAsset
|
|
{
|
|
get { return scenesReferencingAsset; }
|
|
}
|
|
|
|
public int SceneRefCount
|
|
{
|
|
get { return (scenesReferencingAsset != null) ? scenesReferencingAsset.Count : 0; }
|
|
}
|
|
|
|
public bool UsedInBuild
|
|
{
|
|
get { return usedInBuild; }
|
|
}
|
|
|
|
public bool IsFolder
|
|
{
|
|
get { return isFolder; }
|
|
}
|
|
#endregion
|
|
|
|
public AH_TreeviewElement(string absPath, int depth, int id, string relativepath, string assetID, List<string> scenesReferencing, bool isUsedInBuild) : base(System.IO.Path.GetFileName(absPath), depth, id)
|
|
{
|
|
this.absPath = absPath;
|
|
var assetPath = relativepath;
|
|
this.guid = UnityEditor.AssetDatabase.AssetPathToGUID(assetPath);
|
|
this.scenesReferencingAsset = scenesReferencing;
|
|
this.usedInBuild = isUsedInBuild;
|
|
|
|
//Return if its a folder
|
|
if (isFolder = UnityEditor.AssetDatabase.IsValidFolder(assetPath))
|
|
return;
|
|
|
|
//Return if its not an asset
|
|
if (!string.IsNullOrEmpty(this.guid))
|
|
{
|
|
this.assetType = UnityEditor.AssetDatabase.GetMainAssetTypeAtPath(assetPath);
|
|
updateIconDictEntry();
|
|
}
|
|
}
|
|
|
|
internal long GetFileSizeRecursively(AH_MultiColumnHeader.AssetShowMode showMode)
|
|
{
|
|
if (combinedAssetSizeInFolder == null)
|
|
combinedAssetSizeInFolder = new Dictionary<AH_MultiColumnHeader.AssetShowMode, long>();
|
|
|
|
if (combinedAssetSizeInFolder.ContainsKey(showMode))
|
|
return combinedAssetSizeInFolder[showMode];
|
|
|
|
//TODO store these values instead of calculating each and every time?
|
|
long combinedChildrenSize = 0;
|
|
//Combine the size of all the children
|
|
if (hasChildren)
|
|
foreach (AH_TreeviewElement item in children)
|
|
{
|
|
bool validAsset = (showMode == AH_MultiColumnHeader.AssetShowMode.All) ||
|
|
((showMode == AH_MultiColumnHeader.AssetShowMode.Unused && !item.usedInBuild) ||
|
|
(showMode == AH_MultiColumnHeader.AssetShowMode.Used && item.usedInBuild));
|
|
|
|
//Loop thropugh folders and assets thats used not in build
|
|
if (validAsset || item.isFolder)
|
|
combinedChildrenSize += item.GetFileSizeRecursively(showMode);
|
|
}
|
|
|
|
combinedChildrenSize += this.FileSize;
|
|
|
|
//Cache the value
|
|
combinedAssetSizeInFolder.Add(showMode, combinedChildrenSize);
|
|
|
|
return combinedChildrenSize;
|
|
}
|
|
|
|
#region Serialization callbacks
|
|
//TODO Maybe we can store type infos in BuildInfoTreeView instead of on each individual element, might be performance heavy
|
|
|
|
//Store serializable string so we can retrieve type after serialization
|
|
public void OnBeforeSerialize()
|
|
{
|
|
if (assetType != null)
|
|
assetTypeSerialized = Heureka_Serializer.SerializeType(assetType);
|
|
}
|
|
|
|
//Set type from serialized property
|
|
public void OnAfterDeserialize()
|
|
{
|
|
if (!string.IsNullOrEmpty(AssetTypeSerialized))
|
|
{
|
|
this.assetType = Heureka_Serializer.DeSerializeType(AssetTypeSerialized);
|
|
//assetTypeSerialized = "";
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
internal bool AssetMatchesState(AH_MultiColumnHeader.AssetShowMode showMode)
|
|
{
|
|
//Test if we want to add this element (We dont want to show "used" when window searches for "unused"
|
|
return (AssetType != null && ((showMode == AH_MultiColumnHeader.AssetShowMode.All) || ((showMode == AH_MultiColumnHeader.AssetShowMode.Used && usedInBuild) || (showMode == AH_MultiColumnHeader.AssetShowMode.Unused && !usedInBuild))));
|
|
}
|
|
|
|
internal bool HasChildrenThatMatchesState(AH_MultiColumnHeader.AssetShowMode showMode)
|
|
{
|
|
if (!hasChildren)
|
|
return false;
|
|
|
|
//Check if a valid child exit somewhere in this branch
|
|
foreach (AH_TreeviewElement child in children)
|
|
{
|
|
if (child.AssetMatchesState(showMode))
|
|
return true;
|
|
else if (child.HasChildrenThatMatchesState(showMode))
|
|
return true;
|
|
else
|
|
continue;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal List<string> GetUnusedPathsRecursively()
|
|
{
|
|
List<string> unusedAssetsInFolder = new List<string>();
|
|
|
|
//Combine the size of all the children
|
|
if (hasChildren)
|
|
foreach (AH_TreeviewElement item in children)
|
|
{
|
|
if (item.isFolder)
|
|
unusedAssetsInFolder.AddRange(item.GetUnusedPathsRecursively());
|
|
//Loop thropugh folders and assets thats used not in build
|
|
else if (!item.usedInBuild)
|
|
unusedAssetsInFolder.Add(item.RelativePath);
|
|
}
|
|
return unusedAssetsInFolder;
|
|
}
|
|
|
|
internal static List<string> GetStoredIconTypes()
|
|
{
|
|
List<string> iconTypesSerialized = new List<string>();
|
|
foreach (var item in iconDictionary)
|
|
{
|
|
iconTypesSerialized.Add(Heureka_Serializer.SerializeType(item.Key));
|
|
}
|
|
return iconTypesSerialized;
|
|
}
|
|
|
|
internal static List<Texture> GetStoredIconTextures()
|
|
{
|
|
List<Texture> iconTexturesSerialized = new List<Texture>();
|
|
foreach (var item in iconDictionary)
|
|
{
|
|
iconTexturesSerialized.Add(item.Value);
|
|
}
|
|
return iconTexturesSerialized;
|
|
}
|
|
|
|
private void updateIconDictEntry()
|
|
{
|
|
if (assetType != null && !iconDictionary.ContainsKey(assetType))
|
|
iconDictionary.Add(assetType, UnityEditor.EditorGUIUtility.ObjectContent(null, assetType).image);
|
|
}
|
|
|
|
internal static void UpdateIconDictAfterSerialization(List<string> serializationHelperListIconTypes, List<Texture> serializationHelperListIconTextures)
|
|
{
|
|
iconDictionary = new Dictionary<Type, Texture>();
|
|
for (int i = 0; i < serializationHelperListIconTypes.Count; i++)
|
|
{
|
|
Type deserializedType = Heureka_Serializer.DeSerializeType(serializationHelperListIconTypes[i]);
|
|
if (deserializedType != null)
|
|
iconDictionary.Add(Heureka_Serializer.DeSerializeType(serializationHelperListIconTypes[i]), serializationHelperListIconTextures[i]);
|
|
}
|
|
}
|
|
|
|
internal static Texture GetIcon(Type assetType)
|
|
{
|
|
return iconDictionary[assetType];
|
|
}
|
|
}
|
|
} |