230 lines
7.6 KiB
C#
230 lines
7.6 KiB
C#
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.IO;
|
||
|
using System.Linq;
|
||
|
using UnityEditor.AddressableAssets.Build.AnalyzeRules;
|
||
|
using UnityEditor.AddressableAssets.GUI;
|
||
|
using UnityEditor.AddressableAssets.Settings;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.AddressableAssets;
|
||
|
|
||
|
namespace UnityEditor.AddressableAssets.Build
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Static system to manage Analyze functionality.
|
||
|
/// </summary>
|
||
|
[Serializable]
|
||
|
public static class AnalyzeSystem
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Method used to register any custom AnalyzeRules with the AnalyzeSystem. This replaces calling into the AnalyzeWindow
|
||
|
/// directly to remove logic from the GUI. The recommended pattern is to create
|
||
|
/// your rules like so:
|
||
|
/// <code>
|
||
|
/// class MyRule : AnalyzeRule {}
|
||
|
/// [InitializeOnLoad]
|
||
|
/// class RegisterMyRule
|
||
|
/// {
|
||
|
/// static RegisterMyRule()
|
||
|
/// {
|
||
|
/// AnalyzeSystem.RegisterNewRule<MyRule>();
|
||
|
/// }
|
||
|
/// }
|
||
|
/// </code>
|
||
|
/// </summary>
|
||
|
/// <typeparam name="TRule">The rule type.</typeparam>
|
||
|
public static void RegisterNewRule<TRule>() where TRule : AnalyzeRule, new()
|
||
|
{
|
||
|
foreach (var rule in Rules)
|
||
|
{
|
||
|
if (rule.GetType().Equals(typeof(TRule)))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Rules.Add(new TRule());
|
||
|
}
|
||
|
|
||
|
internal static string AnalyzeRuleDataFolder
|
||
|
{
|
||
|
get { return $"{Addressables.LibraryPath}/AnalyzeData"; }
|
||
|
}
|
||
|
|
||
|
internal static string AnalyzeRuleDataName => "AnalyzeRuleData.json";
|
||
|
internal static string AnalyzeRuleDataPath => AnalyzeRuleDataFolder + "/" + AnalyzeRuleDataName;
|
||
|
|
||
|
internal static string AnalyzeRuleDataAssetsFolderPath
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
var settings = AddressableAssetSettingsDefaultObject.Settings;
|
||
|
var path = AddressableAssetSettingsDefaultObject.kDefaultConfigFolder;
|
||
|
if (settings != null && settings.IsPersisted)
|
||
|
path = settings.ConfigFolder;
|
||
|
|
||
|
return path + "/AnalyzeData/";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal static AddressableAssetSettings Settings => AddressableAssetSettingsDefaultObject.Settings;
|
||
|
|
||
|
internal static List<AnalyzeRule> Rules { get; } = new List<AnalyzeRule>();
|
||
|
|
||
|
[SerializeField]
|
||
|
private static AddressablesAnalyzeResultData m_AnalyzeData;
|
||
|
|
||
|
internal static AssetSettingsAnalyzeTreeView TreeView { get; set; }
|
||
|
|
||
|
internal static AddressablesAnalyzeResultData AnalyzeData
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (m_AnalyzeData == null)
|
||
|
{
|
||
|
if (!Directory.Exists(AnalyzeRuleDataFolder))
|
||
|
Directory.CreateDirectory(AnalyzeRuleDataFolder);
|
||
|
DeserializeData();
|
||
|
}
|
||
|
|
||
|
return m_AnalyzeData;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal static void ReloadUI()
|
||
|
{
|
||
|
TreeView?.Reload();
|
||
|
}
|
||
|
|
||
|
internal static void SerializeData()
|
||
|
{
|
||
|
SerializeData(AnalyzeRuleDataPath);
|
||
|
}
|
||
|
|
||
|
internal static void DeserializeData()
|
||
|
{
|
||
|
DeserializeData(AnalyzeRuleDataPath);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Serialize the analysis data to json and save to disk
|
||
|
/// </summary>
|
||
|
/// <param name="path">File path to save to</param>
|
||
|
public static void SerializeData(string path)
|
||
|
{
|
||
|
File.WriteAllText(path, JsonUtility.ToJson(m_AnalyzeData));
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Load and deserialize analysis data from json file and reload
|
||
|
/// </summary>
|
||
|
/// <param name="path">File path to load from</param>
|
||
|
public static void DeserializeData(string path)
|
||
|
{
|
||
|
if (!File.Exists(path))
|
||
|
File.WriteAllText(path, JsonUtility.ToJson(new AddressablesAnalyzeResultData()));
|
||
|
|
||
|
//Cleans up the previous result data
|
||
|
if (Directory.Exists(AnalyzeRuleDataAssetsFolderPath))
|
||
|
Directory.Delete(AnalyzeRuleDataAssetsFolderPath, true);
|
||
|
|
||
|
m_AnalyzeData = JsonUtility.FromJson<AddressablesAnalyzeResultData>(File.ReadAllText(path));
|
||
|
if (m_AnalyzeData == null)
|
||
|
Addressables.LogWarning($"Unable to load Analyze Result Data at {path}.");
|
||
|
else
|
||
|
{
|
||
|
if (m_AnalyzeData.Data == null)
|
||
|
m_AnalyzeData.Data = new Dictionary<string, List<AnalyzeRule.AnalyzeResult>>();
|
||
|
|
||
|
foreach (var rule in Rules)
|
||
|
{
|
||
|
if (rule == null)
|
||
|
{
|
||
|
Addressables.LogWarning("An unknown Analyze rule is being skipped because it is null.");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!m_AnalyzeData.Data.ContainsKey(rule.ruleName))
|
||
|
m_AnalyzeData.Data.Add(rule.ruleName, new List<AnalyzeRule.AnalyzeResult>());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ReloadUI();
|
||
|
}
|
||
|
|
||
|
internal static void SaveDataForRule(AnalyzeRule rule, object data)
|
||
|
{
|
||
|
string jsonData = JsonUtility.ToJson(data);
|
||
|
string path = $"{AnalyzeRuleDataFolder}/{rule.ruleName}Data.json";
|
||
|
File.WriteAllText(path, jsonData);
|
||
|
}
|
||
|
|
||
|
internal static T GetDataForRule<T>(AnalyzeRule rule)
|
||
|
{
|
||
|
string path = $"{AnalyzeRuleDataFolder}/{rule.ruleName}Data.json";
|
||
|
if (!File.Exists(path))
|
||
|
return default;
|
||
|
string fileRead = File.ReadAllText(path);
|
||
|
return JsonUtility.FromJson<T>(fileRead);
|
||
|
}
|
||
|
|
||
|
internal static void ReplaceAnalyzeData(AnalyzeRule rule, List<AnalyzeRule.AnalyzeResult> results)
|
||
|
{
|
||
|
m_AnalyzeData.Data[rule.ruleName] = results;
|
||
|
}
|
||
|
|
||
|
internal static List<AnalyzeRule.AnalyzeResult> RefreshAnalysis<TRule>() where TRule : AnalyzeRule
|
||
|
{
|
||
|
return RefreshAnalysis(FindRule<TRule>());
|
||
|
}
|
||
|
|
||
|
internal static List<AnalyzeRule.AnalyzeResult> RefreshAnalysis(AnalyzeRule rule)
|
||
|
{
|
||
|
if (rule == null)
|
||
|
return null;
|
||
|
|
||
|
if (!AnalyzeData.Data.ContainsKey(rule.ruleName))
|
||
|
AnalyzeData.Data.Add(rule.ruleName, new List<AnalyzeRule.AnalyzeResult>());
|
||
|
|
||
|
AnalyzeData.Data[rule.ruleName] = rule.RefreshAnalysis(Settings);
|
||
|
|
||
|
return AnalyzeData.Data[rule.ruleName];
|
||
|
}
|
||
|
|
||
|
internal static void ClearAnalysis<TRule>() where TRule : AnalyzeRule
|
||
|
{
|
||
|
ClearAnalysis(FindRule<TRule>());
|
||
|
}
|
||
|
|
||
|
internal static void ClearAnalysis(AnalyzeRule rule)
|
||
|
{
|
||
|
if (rule == null)
|
||
|
return;
|
||
|
|
||
|
if (!AnalyzeData.Data.ContainsKey(rule.ruleName))
|
||
|
AnalyzeData.Data.Add(rule.ruleName, new List<AnalyzeRule.AnalyzeResult>());
|
||
|
|
||
|
rule.ClearAnalysis();
|
||
|
;
|
||
|
AnalyzeData.Data[rule.ruleName].Clear();
|
||
|
}
|
||
|
|
||
|
internal static void FixIssues<TRule>() where TRule : AnalyzeRule
|
||
|
{
|
||
|
FixIssues(FindRule<TRule>());
|
||
|
}
|
||
|
|
||
|
internal static void FixIssues(AnalyzeRule rule)
|
||
|
{
|
||
|
rule?.FixIssues(Settings);
|
||
|
}
|
||
|
|
||
|
private static AnalyzeRule FindRule<TRule>() where TRule : AnalyzeRule
|
||
|
{
|
||
|
var rule = Rules.FirstOrDefault(r => r.GetType().IsAssignableFrom(typeof(TRule)));
|
||
|
if (rule == null)
|
||
|
throw new ArgumentException($"No rule found corresponding to type {typeof(TRule)}");
|
||
|
|
||
|
return rule;
|
||
|
}
|
||
|
}
|
||
|
}
|