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
{
///
/// Static system to manage Analyze functionality.
///
[Serializable]
public static class AnalyzeSystem
{
///
/// 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:
///
/// class MyRule : AnalyzeRule {}
/// [InitializeOnLoad]
/// class RegisterMyRule
/// {
/// static RegisterMyRule()
/// {
/// AnalyzeSystem.RegisterNewRule<MyRule>();
/// }
/// }
///
///
/// The rule type.
public static void RegisterNewRule() 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 Rules { get; } = new List();
[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);
}
///
/// Serialize the analysis data to json and save to disk
///
/// File path to save to
public static void SerializeData(string path)
{
File.WriteAllText(path, JsonUtility.ToJson(m_AnalyzeData));
}
///
/// Load and deserialize analysis data from json file and reload
///
/// File path to load from
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(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>();
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());
}
}
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(AnalyzeRule rule)
{
string path = $"{AnalyzeRuleDataFolder}/{rule.ruleName}Data.json";
if (!File.Exists(path))
return default;
string fileRead = File.ReadAllText(path);
return JsonUtility.FromJson(fileRead);
}
internal static void ReplaceAnalyzeData(AnalyzeRule rule, List results)
{
m_AnalyzeData.Data[rule.ruleName] = results;
}
internal static List RefreshAnalysis() where TRule : AnalyzeRule
{
return RefreshAnalysis(FindRule());
}
internal static List RefreshAnalysis(AnalyzeRule rule)
{
if (rule == null)
return null;
if (!AnalyzeData.Data.ContainsKey(rule.ruleName))
AnalyzeData.Data.Add(rule.ruleName, new List());
AnalyzeData.Data[rule.ruleName] = rule.RefreshAnalysis(Settings);
return AnalyzeData.Data[rule.ruleName];
}
internal static void ClearAnalysis() where TRule : AnalyzeRule
{
ClearAnalysis(FindRule());
}
internal static void ClearAnalysis(AnalyzeRule rule)
{
if (rule == null)
return;
if (!AnalyzeData.Data.ContainsKey(rule.ruleName))
AnalyzeData.Data.Add(rule.ruleName, new List());
rule.ClearAnalysis();
;
AnalyzeData.Data[rule.ruleName].Clear();
}
internal static void FixIssues() where TRule : AnalyzeRule
{
FixIssues(FindRule());
}
internal static void FixIssues(AnalyzeRule rule)
{
rule?.FixIssues(Settings);
}
private static AnalyzeRule FindRule() 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;
}
}
}