290 lines
11 KiB
C#
290 lines
11 KiB
C#
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using System.Linq;
|
|
|
|
//Only avaliable in 2018
|
|
#if UNITY_2018_1_OR_NEWER
|
|
using UnityEditor.Build.Reporting;
|
|
#endif
|
|
#if ADRESSABLES_1_2_0_OR_NEWER
|
|
using UnityEditor.AddressableAssets;
|
|
#endif
|
|
|
|
namespace HeurekaGames.AssetHunterPRO
|
|
{
|
|
[System.Serializable]
|
|
public class AH_SerializedBuildInfo
|
|
{
|
|
private const string mergeIdentifier = "MergedBuildInfo";
|
|
|
|
public string versionNumber;
|
|
public string buildTargetInfo;
|
|
public string dateTime;
|
|
public ulong TotalSize;
|
|
|
|
//Temporary dict for populating the asset usage data
|
|
Dictionary<string, List<string>> assetDict = new Dictionary<string, List<string>>();
|
|
//The serialized information stored in the JSON
|
|
public List<AH_SerializableAssetInfo> AssetListUnSorted = new List<AH_SerializableAssetInfo>();
|
|
|
|
//Only avaliable in 2018
|
|
#if UNITY_2018_1_OR_NEWER
|
|
public List<AH_BuildReportFileInfo> BuildReportInfoList = new List<AH_BuildReportFileInfo>();
|
|
#endif
|
|
|
|
//A sorted version of the assetList
|
|
SortedList<string, AH_SerializableAssetInfo> assetListSorted = new SortedList<string, AH_SerializableAssetInfo>();
|
|
|
|
|
|
public SortedList<string, AH_SerializableAssetInfo> AssetListSorted
|
|
{
|
|
get
|
|
{
|
|
return assetListSorted;
|
|
}
|
|
}
|
|
|
|
void setMetaData()
|
|
{
|
|
setMetaData(EditorUserBuildSettings.activeBuildTarget.ToString());
|
|
}
|
|
|
|
void setMetaData(string buildTargetInfoString)
|
|
{
|
|
dateTime = AH_SerializationHelper.GetDateString();
|
|
buildTargetInfo = buildTargetInfoString;
|
|
versionNumber = AH_Window.VERSION;
|
|
}
|
|
|
|
private void addFolderToReport(string foldername)
|
|
{
|
|
var foo = System.IO.Directory.GetDirectories(Application.dataPath, foldername, System.IO.SearchOption.AllDirectories);
|
|
//Add resources to build report
|
|
var folders = (from subdirectory in System.IO.Directory.GetDirectories(Application.dataPath, foldername, System.IO.SearchOption.AllDirectories)
|
|
where subdirectory.EndsWith(System.IO.Path.DirectorySeparatorChar + foldername)
|
|
select subdirectory).ToArray<string>();
|
|
|
|
//Change pats to project relative
|
|
for (int i = 0; i < folders.Count(); i++)
|
|
{
|
|
var relativePath =
|
|
folders[i] = FileUtil.GetProjectRelativePath(folders[i]);
|
|
}
|
|
|
|
//For some reason streamingassets folders are generated by unity when building, only to be deleted immediately after. Need to take that under consideration here.
|
|
folders = folders.Where(x => AssetDatabase.IsValidFolder(x)).ToArray();
|
|
|
|
//Make sure folder result is valid
|
|
if (folders != null && folders.Count() >= 1 && !string.IsNullOrEmpty(folders[0]))
|
|
foreach (string assetguid in AssetDatabase.FindAssets("*", folders))
|
|
{
|
|
AddBuildDependency(null, AssetDatabase.GUIDToAssetPath(assetguid));
|
|
}
|
|
}
|
|
|
|
private void SerializeAndSave()
|
|
{
|
|
setMetaData();
|
|
AH_SerializationHelper.SerializeAndSave(this);
|
|
}
|
|
|
|
internal void MergeWith(string fullName)
|
|
{
|
|
AH_SerializedBuildInfo newBuildInfo = AH_SerializationHelper.LoadBuildReport(fullName);
|
|
if (newBuildInfo != null)
|
|
{
|
|
Debug.Log("AH: Merging with " + fullName);
|
|
foreach (var newItem in newBuildInfo.AssetListUnSorted)
|
|
{
|
|
//If asset ID already exists
|
|
if (AssetListUnSorted.Any(val => val.ID == newItem.ID))
|
|
{
|
|
AH_SerializableAssetInfo OrigItem = AssetListUnSorted.Find(val => val.ID == newItem.ID);
|
|
//Check if new scene ref list have entries that doesn't exist in orig
|
|
bool newSceneRefsExist = newItem.Refs.Any(val => !OrigItem.Refs.Contains(val));
|
|
//Get the new refs
|
|
if (newSceneRefsExist)
|
|
{
|
|
List<string> newSceneRefs = newItem.Refs.FindAll(val => !OrigItem.Refs.Contains(val));
|
|
//Add them to list
|
|
OrigItem.Refs.AddRange(newSceneRefs); //Does this serialize as expected? Since we are adding through a setter?
|
|
}
|
|
}
|
|
else
|
|
AssetListUnSorted.Add(newItem);
|
|
}
|
|
|
|
}
|
|
else
|
|
Debug.Log("AH: Merging failed: " + fullName);
|
|
}
|
|
|
|
internal bool IsMergedReport()
|
|
{
|
|
return buildTargetInfo.Equals(mergeIdentifier);
|
|
}
|
|
|
|
internal void SaveAfterMerge()
|
|
{
|
|
setMetaData(mergeIdentifier);
|
|
AH_SerializationHelper.SerializeAndSave(this);
|
|
}
|
|
|
|
//Add the assets specific to buildtarget
|
|
private void addBuildtargetAssets(BuildTarget buildTarget)
|
|
{
|
|
BuildTargetGroup targetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget);
|
|
|
|
List<Texture> buildTargetAssetDependencies = AH_Utils.GetTargetGroupAssetDependencies(targetGroup);
|
|
|
|
//Add all the textures to unsorted
|
|
foreach (var item in buildTargetAssetDependencies)
|
|
{
|
|
AddBuildDependency(null, AssetDatabase.GetAssetPath(item));
|
|
}
|
|
}
|
|
|
|
//Only avaliable in 2018
|
|
#if UNITY_2018_1_OR_NEWER
|
|
internal void ProcessBuildReport(BuildReport report)
|
|
{
|
|
TotalSize = report.summary.totalSize;
|
|
foreach (var file in report.GetFiles())
|
|
{
|
|
BuildReportInfoList.Add(new AH_BuildReportFileInfo(file));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//Stores in XML friendly format and saves
|
|
internal void FinalizeReport(BuildTarget target)
|
|
{
|
|
addBuildtargetAssets(target);
|
|
FinalizeReport();
|
|
}
|
|
|
|
internal void FinalizeReport()
|
|
{
|
|
//TODO: "Note that if the Resources folder is an Editor subfolder, the Assets in it are loadable from Editor scripts but are stripped from builds."
|
|
//https://docs.unity3d.com/Manual/SpecialFolders.html
|
|
addFolderToReport("Resources");
|
|
addFolderToReport("StreamingAssets");
|
|
addAssetBundlesToReport();
|
|
addAdressablesToReport();
|
|
addRenderPipelinesToReport();
|
|
|
|
//Add all the used assets to list
|
|
foreach (var item in assetDict)
|
|
{
|
|
var sceneIDs = item.Value.Select(x => AssetDatabase.AssetPathToGUID(x)).ToList(); //Id scene IDs from paths
|
|
AH_SerializableAssetInfo newAssetInfo = new AH_SerializableAssetInfo(item.Key, sceneIDs);
|
|
AssetListUnSorted.Add(newAssetInfo);
|
|
}
|
|
|
|
//TODO Clean AssetListUnsorted to make sure we dont have duplicates? How does this work with the scene refs
|
|
SerializeAndSave();
|
|
}
|
|
|
|
private void addRenderPipelinesToReport()
|
|
{
|
|
#if UNITY_2019_3_OR_NEWER
|
|
var pipelines = UnityEngine.Rendering.GraphicsSettings.allConfiguredRenderPipelines;
|
|
|
|
foreach (var pipeline in pipelines)
|
|
{
|
|
var path = AssetDatabase.GetAssetPath(pipeline);
|
|
AddBuildDependency("", path);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
private void addAdressablesToReport()
|
|
{
|
|
#if ADRESSABLES_1_2_0_OR_NEWER
|
|
if (AddressableAssetSettingsDefaultObject.SettingsExists)
|
|
{
|
|
var fooSettings = AddressableAssetSettingsDefaultObject.Settings;
|
|
|
|
//Get all the build relevant files for addressables
|
|
string[] guids = AssetDatabase.FindAssets(string.Format("t:{0}", typeof(AddressableAssetSettingsDefaultObject)));
|
|
foreach (var guid in guids)
|
|
AddBuildDependency("", AssetDatabase.GUIDToAssetPath(guid));
|
|
|
|
guids = AssetDatabase.FindAssets(string.Format("addressables_content_state"));
|
|
foreach (var guid in guids)
|
|
AddBuildDependency("", AssetDatabase.GUIDToAssetPath(guid));
|
|
|
|
//TODO add addressable as path? (But that requires some refactor since we assume that to be a scene rather than an addressable NB: IF we do that we need to make sure dependencies are still being added in AddBuildDependency method
|
|
AddBuildDependency("", AssetDatabase.GetAssetPath(AddressableAssetSettingsDefaultObject.Settings));
|
|
|
|
foreach (var item in AddressableAssetSettingsDefaultObject.Settings.groups)
|
|
{
|
|
foreach (var entry in item.entries)
|
|
{
|
|
AddBuildDependency("", entry.AssetPath);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
private void addAssetBundlesToReport()
|
|
{
|
|
string[] assetBundleNames = AssetDatabase.GetAllAssetBundleNames();
|
|
|
|
foreach (var bundleName in assetBundleNames)
|
|
{
|
|
foreach (var bundledAssetPath in AssetDatabase.GetAssetPathsFromAssetBundle(bundleName))
|
|
{
|
|
//TODO add assetbundle as path? (But that requires some refactor since we assume that to be a scene rather than a bundle NB: IF we do that we need to make sure dependencies are still being added in AddBuildDependency method
|
|
AddBuildDependency("", bundledAssetPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void AddBuildDependency(string scenePath, string assetPath)
|
|
{
|
|
if (!assetDict.ContainsKey(assetPath))
|
|
assetDict.Add(assetPath, new List<string>());
|
|
|
|
if (!string.IsNullOrEmpty(scenePath))
|
|
assetDict[assetPath].Add(scenePath);
|
|
//This is not a scene asset so it must be in resources/streaming ressources so we need to manage dependencies manually
|
|
else
|
|
{
|
|
string[] dependencies = AssetDatabase.GetDependencies(assetPath, false);
|
|
dependencies.ToList().AddRange(AssetDatabase.GetDependencies(assetPath, true).ToList());
|
|
//Loop assets
|
|
foreach (var aPath in dependencies)
|
|
{
|
|
//This asset is already referenced, so return
|
|
if (assetDict.ContainsKey(aPath))
|
|
continue;
|
|
|
|
//Dependencies also return the asset itself, and we dont want to keep looking at the same asset
|
|
if (!assetPath.Equals(aPath))
|
|
AddBuildDependency(scenePath, aPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal AH_SerializableAssetInfo GetItemInfo(string assetID)
|
|
{
|
|
AH_SerializableAssetInfo assetInfo;
|
|
if (assetListSorted.TryGetValue(assetID, out assetInfo))
|
|
return assetInfo;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
internal void Sort()
|
|
{
|
|
foreach (var item in AssetListUnSorted)
|
|
{
|
|
if (!assetListSorted.ContainsKey(item.ID))
|
|
assetListSorted.Add(item.ID, item);
|
|
}
|
|
}
|
|
}
|
|
} |