Files
Hasebe/Library/PackageCache/com.unity.addressables@42676f2a154e/Editor/AutoGroupGenerator/DependencyGraphCommandQueue.cs
T
2026-09-21 12:15:57 +03:00

277 lines
7.8 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
namespace AutoGroupGenerator
{
/// <summary>
/// Command queue that generates the dependency graph of project assets.
/// </summary>
internal class DependencyGraphCommandQueue : CommandQueue
{
#region Constants
private static readonly HashSet<string> k_IgnoredExtensions = new(StringComparer.OrdinalIgnoreCase)
{
".cs", ".hlsl", ".asmdef", ".asmref", ".dll", ".unitypackage", ".txt"
};
private static readonly string[] k_IgnoredPaths = new[]
{
"Assets/AddressableAssetsData",
"Assets/StreamingAssets",
"/Editor/",
"/Resources/"
};
private const string k_AssetsFolder = "Assets/";
private const string k_PackagesFolder = "Packages/";
private const int k_MemReliefStride = 1000;
#endregion
#region Fields
private readonly DataContainer m_DataContainer;
private int m_TotalAssetCount = 0;
private HashSet<string> m_AutoGroupGeneratorSettingsFiles;
private Dictionary<string, bool> m_AssetIgnoreCache;
int m_LoadedAssetCount;
#endregion
#region Methods
public DependencyGraphCommandQueue(DataContainer dataContainer)
{
m_DataContainer = dataContainer;
Title = nameof(DependencyGraphCommandQueue);
}
public override void PreExecute()
{
ClearQueue();
m_DataContainer.DependencyGraph = new DependencyGraph();
m_AutoGroupGeneratorSettingsFiles = FindAutoGroupGeneratorDependencies();
m_AssetIgnoreCache = new Dictionary<string, bool>();
var assetPaths = AssetDatabase.GetAllAssetPaths();
m_TotalAssetCount = assetPaths.Length;
foreach (var assetPath in assetPaths)
{
var path = assetPath;
AddCommand(() => AddAssetToDependencyGraph(path), path);
}
if (m_DataContainer.Settings.SaveGraphOnDisk)
{
AddCommand(SaveGraphOnDisk, "Saving DependencyGraph");
}
}
public override void PostExecute()
{
SaveOutputReportToFile();
m_AutoGroupGeneratorSettingsFiles = null;
m_AssetIgnoreCache = null;
}
private void AddAssetToDependencyGraph(string assetPath)
{
var dependencyGraph = m_DataContainer.DependencyGraph;
if (SkipAsset(assetPath))
{
return;
}
string[] dependencies = null;
try
{
dependencies = AssetDatabase.GetDependencies(assetPath, false);
}
catch
{
}
if (dependencies == null || dependencies.Length == 0)
{
dependencyGraph.AddNode(assetPath);
return;
}
foreach (var dependency in dependencies)
{
if (SkipAsset(dependency))
{
continue;
}
dependencyGraph.AddEdge(assetPath, dependency);
}
}
private bool SkipAsset(string assetPath)
{
if (m_AssetIgnoreCache.TryGetValue(assetPath, out var cachedValue))
{
return cachedValue;
}
bool shouldIgnoreAsset = ShouldIgnoreAsset(assetPath);
m_AssetIgnoreCache.Add(assetPath, shouldIgnoreAsset);
return shouldIgnoreAsset;
}
private bool ShouldIgnoreAsset(string assetPath)
{
if (string.IsNullOrWhiteSpace(assetPath) ||
AssetDatabase.IsValidFolder(assetPath))
{
return true;
}
if (!assetPath.StartsWith(k_AssetsFolder, StringComparison.OrdinalIgnoreCase) &&
!assetPath.StartsWith(k_PackagesFolder, StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (assetPath.Contains('[') && assetPath.Contains(']')) // Addressable entries cannot contain brackets
return true;
var extension = Path.GetExtension(assetPath);
if (k_IgnoredExtensions.Contains(extension))
{
return true;
}
foreach (var ignoredPath in k_IgnoredPaths)
{
if (assetPath.Contains(ignoredPath, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
if (m_AutoGroupGeneratorSettingsFiles.Contains(assetPath))
{
return true;
}
if (m_DataContainer.Settings.ScanForUnsupportedFiles)
{
var assetSupported = LoadAssetAndCheckSupported(assetPath);
m_LoadedAssetCount++;
if (m_LoadedAssetCount % k_MemReliefStride == 0)
EditorUtil.UnloadUnusedEditorMemory();
if (!assetSupported)
return true;
}
if (m_DataContainer.Settings.ScanForUnsupportedFiles && !LoadAssetAndCheckSupported(assetPath))
{
return true;
}
return false;
}
private HashSet<string> FindAutoGroupGeneratorDependencies()
{
var AutoGroupGeneratorSettingsFiles = new HashSet<string>();
AutoGroupGeneratorSettingsFiles.UnionWith(AssetDatabaseUtil.FindAssetPathsForType<AutoGroupGeneratorSettings>());
AutoGroupGeneratorSettingsFiles.UnionWith(AssetDatabaseUtil.FindAssetPathsForType<InputRule>());
AutoGroupGeneratorSettingsFiles.UnionWith(AssetDatabaseUtil.FindAssetPathsForType<OutputRule>());
return AutoGroupGeneratorSettingsFiles;
}
private bool LoadAssetAndCheckSupported(string assetPath)
{
try
{
Type mainAssetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (mainAssetType == null || mainAssetType == typeof(DefaultAsset))
{
return false;
}
if (!AreAssetFlagsEligibleForBuild(assetPath))
{
return false;
}
}
catch
{
return false;
}
return true;
}
private bool AreAssetFlagsEligibleForBuild(string path)
{
UnityEngine.Object asset = AssetDatabase.LoadMainAssetAtPath(path);
if (asset == null)
{
return false;
}
HideFlags flags = asset.hideFlags;
return (flags & HideFlags.DontSave) == 0 &&
(flags & HideFlags.DontSaveInBuild) == 0 &&
(flags & HideFlags.DontSaveInEditor) == 0;
}
private void SaveGraphOnDisk()
{
var data = JsonUtility.ToJson(m_DataContainer.DependencyGraph.Serialize());
FileUtils.SaveToFile(Constants.FilePaths.DependencyGraphFilePath, data);
}
void SaveOutputReportToFile()
{
if (!m_DataContainer.Settings.ProcessReport.HasFlag(ProcessStepReport.DependencyGraph))
return;
Graph<string> graph = m_DataContainer.DependencyGraph.ConvertNodeType(n => n.AssetPath);
var summary = $"AssetDatabase.GetAllAssetPaths().Count = {m_TotalAssetCount}, " +
$" DependencyGraph.NodeCount = {graph.NodeCount})";
var data = graph.ToSerializableData();
JsonReport.SaveJsonReport(GetType(), summary, data);
}
#endregion
}
}