//------------------------------------------------------------ // Game Framework // Copyright © 2013-2021 loyalsoft. All rights reserved. // Homepage: http://www.game7000.com/ // Feedback: http://www.game7000.com/ //------------------------------------------------------------ using GameFramework; using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace UnityGameFramework.Editor.ResourceTools { /// /// 资源分析器。 /// internal sealed class ResourceAnalyzer : EditorWindow { private ResourceAnalyzerController m_Controller = null; private bool m_Analyzed = false; private int m_ToolbarIndex = 0; private int m_AssetCount = 0; private string[] m_CachedAssetNames = null; private int m_SelectedAssetIndex = -1; private string m_SelectedAssetName = null; private DependencyData m_SelectedDependencyData = null; private AssetsOrder m_AssetsOrder = AssetsOrder.AssetNameAsc; private string m_AssetsFilter = null; private Vector2 m_AssetsScroll = Vector2.zero; private Vector2 m_DependencyResourcesScroll = Vector2.zero; private Vector2 m_DependencyAssetsScroll = Vector2.zero; private Vector2 m_ScatteredDependencyAssetsScroll = Vector2.zero; private int m_ScatteredAssetCount = 0; private string[] m_CachedScatteredAssetNames = null; private int m_SelectedScatteredAssetIndex = -1; private string m_SelectedScatteredAssetName = null; private Asset[] m_SelectedHostAssets = null; private ScatteredAssetsOrder m_ScatteredAssetsOrder = ScatteredAssetsOrder.AssetNameAsc; private string m_ScatteredAssetsFilter = null; private Vector2 m_ScatteredAssetsScroll = Vector2.zero; private Vector2 m_HostAssetsScroll = Vector2.zero; private int m_CircularDependencyCount = 0; private string[][] m_CachedCircularDependencyDatas = null; private Vector2 m_CircularDependencyScroll = Vector2.zero; [MenuItem("Game Framework/Resource Tools/Resource Analyzer", false, 42)] private static void Open() { ResourceAnalyzer window = GetWindow("Resource Analyzer", true); window.minSize = new Vector2(800f, 600f); } private void OnEnable() { m_Controller = new ResourceAnalyzerController(); m_Controller.OnLoadingResource += OnLoadingResource; m_Controller.OnLoadingAsset += OnLoadingAsset; m_Controller.OnLoadCompleted += OnLoadCompleted; m_Controller.OnAnalyzingAsset += OnAnalyzingAsset; m_Controller.OnAnalyzeCompleted += OnAnalyzeCompleted; m_Analyzed = false; m_ToolbarIndex = 0; m_AssetCount = 0; m_CachedAssetNames = null; m_SelectedAssetIndex = -1; m_SelectedAssetName = null; m_SelectedDependencyData = new DependencyData(); m_AssetsOrder = AssetsOrder.ScatteredDependencyAssetCountDesc; m_AssetsFilter = null; m_AssetsScroll = Vector2.zero; m_DependencyResourcesScroll = Vector2.zero; m_DependencyAssetsScroll = Vector2.zero; m_ScatteredDependencyAssetsScroll = Vector2.zero; m_ScatteredAssetCount = 0; m_CachedScatteredAssetNames = null; m_SelectedScatteredAssetIndex = -1; m_SelectedScatteredAssetName = null; m_SelectedHostAssets = new Asset[] { }; m_ScatteredAssetsOrder = ScatteredAssetsOrder.HostAssetCountDesc; m_ScatteredAssetsFilter = null; m_ScatteredAssetsScroll = Vector2.zero; m_HostAssetsScroll = Vector2.zero; m_CircularDependencyCount = 0; m_CachedCircularDependencyDatas = null; m_CircularDependencyScroll = Vector2.zero; } private void OnGUI() { EditorGUILayout.BeginVertical(GUILayout.Width(position.width), GUILayout.Height(position.height)); { GUILayout.Space(5f); int toolbarIndex = GUILayout.Toolbar(m_ToolbarIndex, new string[] { "Summary", "Asset Dependency Viewer", "Scattered Asset Viewer", "Circular Dependency Viewer" }, GUILayout.Height(30f)); if (toolbarIndex != m_ToolbarIndex) { m_ToolbarIndex = toolbarIndex; GUI.FocusControl(null); } switch (m_ToolbarIndex) { case 0: DrawSummary(); break; case 1: DrawAssetDependencyViewer(); break; case 2: DrawScatteredAssetViewer(); break; case 3: DrawCircularDependencyViewer(); break; } } EditorGUILayout.EndVertical(); } private void DrawAnalyzeButton() { if (!m_Analyzed) { EditorGUILayout.HelpBox("Please analyze first.", MessageType.Info); } if (GUILayout.Button("Analyze", GUILayout.Height(30f))) { m_Controller.Clear(); m_SelectedAssetIndex = -1; m_SelectedAssetName = null; m_SelectedDependencyData = new DependencyData(); m_SelectedScatteredAssetIndex = -1; m_SelectedScatteredAssetName = null; m_SelectedHostAssets = new Asset[] { }; if (m_Controller.Prepare()) { m_Controller.Analyze(); m_Analyzed = true; m_AssetCount = m_Controller.GetAssetNames().Length; m_ScatteredAssetCount = m_Controller.GetScatteredAssetNames().Length; m_CachedCircularDependencyDatas = m_Controller.GetCircularDependencyDatas(); m_CircularDependencyCount = m_CachedCircularDependencyDatas.Length; OnAssetsOrderOrFilterChanged(); OnScatteredAssetsOrderOrFilterChanged(); } else { EditorUtility.DisplayDialog("Resource Analyze", "Can not parse 'ResourceCollection.xml', please use 'Resource Editor' tool first.", "OK"); } } } private void DrawSummary() { DrawAnalyzeButton(); } private void DrawAssetDependencyViewer() { if (!m_Analyzed) { DrawAnalyzeButton(); return; } EditorGUILayout.BeginHorizontal(); { GUILayout.Space(5f); EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.4f)); { GUILayout.Space(5f); string title = null; if (string.IsNullOrEmpty(m_AssetsFilter)) { title = Utility.Text.Format("Assets In Resources ({0})", m_AssetCount.ToString()); } else { title = Utility.Text.Format("Assets In Resources ({0}/{1})", m_CachedAssetNames.Length.ToString(), m_AssetCount.ToString()); } EditorGUILayout.LabelField(title, EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height - 150f)); { m_AssetsScroll = EditorGUILayout.BeginScrollView(m_AssetsScroll); { int selectedIndex = GUILayout.SelectionGrid(m_SelectedAssetIndex, m_CachedAssetNames, 1, "toggle"); if (selectedIndex != m_SelectedAssetIndex) { m_SelectedAssetIndex = selectedIndex; m_SelectedAssetName = m_CachedAssetNames[selectedIndex]; m_SelectedDependencyData = m_Controller.GetDependencyData(m_SelectedAssetName); } } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical("box"); { EditorGUILayout.LabelField("Asset Name", m_SelectedAssetName ?? ""); EditorGUILayout.LabelField("Resource Name", m_SelectedAssetName == null ? "" : m_Controller.GetAsset(m_SelectedAssetName).Resource.FullName); EditorGUILayout.BeginHorizontal(); { AssetsOrder assetsOrder = (AssetsOrder)EditorGUILayout.EnumPopup("Order by", m_AssetsOrder); if (assetsOrder != m_AssetsOrder) { m_AssetsOrder = assetsOrder; OnAssetsOrderOrFilterChanged(); } } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { string assetsFilter = EditorGUILayout.TextField("Assets Filter", m_AssetsFilter); if (assetsFilter != m_AssetsFilter) { m_AssetsFilter = assetsFilter; OnAssetsOrderOrFilterChanged(); } EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(m_AssetsFilter)); { if (GUILayout.Button("x", GUILayout.Width(20f))) { m_AssetsFilter = null; GUI.FocusControl(null); OnAssetsOrderOrFilterChanged(); } } EditorGUI.EndDisabledGroup(); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.6f - 14f)); { GUILayout.Space(5f); EditorGUILayout.LabelField(Utility.Text.Format("Dependency Resources ({0})", m_SelectedDependencyData.DependencyResourceCount.ToString()), EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height * 0.2f)); { m_DependencyResourcesScroll = EditorGUILayout.BeginScrollView(m_DependencyResourcesScroll); { Resource[] dependencyResources = m_SelectedDependencyData.GetDependencyResources(); foreach (Resource dependencyResource in dependencyResources) { GUILayout.Label(dependencyResource.FullName); } } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); EditorGUILayout.LabelField(Utility.Text.Format("Dependency Assets ({0})", m_SelectedDependencyData.DependencyAssetCount.ToString()), EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height * 0.3f)); { m_DependencyAssetsScroll = EditorGUILayout.BeginScrollView(m_DependencyAssetsScroll); { Asset[] dependencyAssets = m_SelectedDependencyData.GetDependencyAssets(); foreach (Asset dependencyAsset in dependencyAssets) { EditorGUILayout.BeginHorizontal(); { if (GUILayout.Button("GO", GUILayout.Width(30f))) { m_SelectedAssetName = dependencyAsset.Name; m_SelectedAssetIndex = new List(m_CachedAssetNames).IndexOf(m_SelectedAssetName); m_SelectedDependencyData = m_Controller.GetDependencyData(m_SelectedAssetName); } GUILayout.Label(dependencyAsset.Name); } EditorGUILayout.EndHorizontal(); } } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); EditorGUILayout.LabelField(Utility.Text.Format("Scattered Dependency Assets ({0})", m_SelectedDependencyData.ScatteredDependencyAssetCount.ToString()), EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height * 0.5f - 116f)); { m_ScatteredDependencyAssetsScroll = EditorGUILayout.BeginScrollView(m_ScatteredDependencyAssetsScroll); { string[] scatteredDependencyAssetNames = m_SelectedDependencyData.GetScatteredDependencyAssetNames(); foreach (string scatteredDependencyAssetName in scatteredDependencyAssetNames) { EditorGUILayout.BeginHorizontal(); { int count = m_Controller.GetHostAssets(scatteredDependencyAssetName).Length; EditorGUI.BeginDisabledGroup(count < 2); { if (GUILayout.Button("GO", GUILayout.Width(30f))) { m_SelectedScatteredAssetName = scatteredDependencyAssetName; m_SelectedScatteredAssetIndex = new List(m_CachedScatteredAssetNames).IndexOf(m_SelectedScatteredAssetName); m_SelectedHostAssets = m_Controller.GetHostAssets(m_SelectedScatteredAssetName); m_ToolbarIndex = 2; GUI.FocusControl(null); } } EditorGUI.EndDisabledGroup(); GUILayout.Label(count > 1 ? Utility.Text.Format("{0} ({1})", scatteredDependencyAssetName, count.ToString()) : scatteredDependencyAssetName); } EditorGUILayout.EndHorizontal(); } } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndHorizontal(); } private void DrawScatteredAssetViewer() { if (!m_Analyzed) { DrawAnalyzeButton(); return; } EditorGUILayout.BeginHorizontal(); { GUILayout.Space(5f); EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.4f)); { GUILayout.Space(5f); string title = null; if (string.IsNullOrEmpty(m_ScatteredAssetsFilter)) { title = Utility.Text.Format("Scattered Assets ({0})", m_ScatteredAssetCount.ToString()); } else { title = Utility.Text.Format("Scattered Assets ({0}/{1})", m_CachedScatteredAssetNames.Length.ToString(), m_ScatteredAssetCount.ToString()); } EditorGUILayout.LabelField(title, EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height - 132f)); { m_ScatteredAssetsScroll = EditorGUILayout.BeginScrollView(m_ScatteredAssetsScroll); { int selectedIndex = GUILayout.SelectionGrid(m_SelectedScatteredAssetIndex, m_CachedScatteredAssetNames, 1, "toggle"); if (selectedIndex != m_SelectedScatteredAssetIndex) { m_SelectedScatteredAssetIndex = selectedIndex; m_SelectedScatteredAssetName = m_CachedScatteredAssetNames[selectedIndex]; m_SelectedHostAssets = m_Controller.GetHostAssets(m_SelectedScatteredAssetName); } } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical("box"); { EditorGUILayout.LabelField("Scattered Asset Name", m_SelectedScatteredAssetName ?? ""); EditorGUILayout.BeginHorizontal(); { ScatteredAssetsOrder scatteredAssetsOrder = (ScatteredAssetsOrder)EditorGUILayout.EnumPopup("Order by", m_ScatteredAssetsOrder); if (scatteredAssetsOrder != m_ScatteredAssetsOrder) { m_ScatteredAssetsOrder = scatteredAssetsOrder; OnScatteredAssetsOrderOrFilterChanged(); } } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { string scatteredAssetsFilter = EditorGUILayout.TextField("Assets Filter", m_ScatteredAssetsFilter); if (scatteredAssetsFilter != m_ScatteredAssetsFilter) { m_ScatteredAssetsFilter = scatteredAssetsFilter; OnScatteredAssetsOrderOrFilterChanged(); } EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(m_ScatteredAssetsFilter)); { if (GUILayout.Button("x", GUILayout.Width(20f))) { m_ScatteredAssetsFilter = null; GUI.FocusControl(null); OnScatteredAssetsOrderOrFilterChanged(); } } EditorGUI.EndDisabledGroup(); } EditorGUILayout.EndHorizontal(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndVertical(); EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.6f - 14f)); { GUILayout.Space(5f); EditorGUILayout.LabelField(Utility.Text.Format("Host Assets ({0})", m_SelectedHostAssets.Length.ToString()), EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height - 68f)); { m_HostAssetsScroll = EditorGUILayout.BeginScrollView(m_HostAssetsScroll); { foreach (Asset hostAsset in m_SelectedHostAssets) { EditorGUILayout.BeginHorizontal(); { if (GUILayout.Button("GO", GUILayout.Width(30f))) { m_SelectedAssetName = hostAsset.Name; m_SelectedAssetIndex = new List(m_CachedAssetNames).IndexOf(m_SelectedAssetName); m_SelectedDependencyData = m_Controller.GetDependencyData(m_SelectedAssetName); m_ToolbarIndex = 1; GUI.FocusControl(null); } GUILayout.Label(Utility.Text.Format("{0} [{1}]", hostAsset.Name, hostAsset.Resource.FullName)); } EditorGUILayout.EndHorizontal(); } } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndHorizontal(); } private void DrawCircularDependencyViewer() { if (!m_Analyzed) { DrawAnalyzeButton(); return; } EditorGUILayout.BeginHorizontal(); { GUILayout.Space(5f); EditorGUILayout.BeginVertical(); { GUILayout.Space(5f); EditorGUILayout.LabelField(Utility.Text.Format("Circular Dependency ({0})", m_CircularDependencyCount.ToString()), EditorStyles.boldLabel); m_CircularDependencyScroll = EditorGUILayout.BeginScrollView(m_CircularDependencyScroll); { int count = 0; foreach (string[] circularDependencyData in m_CachedCircularDependencyDatas) { GUILayout.Label(Utility.Text.Format("{0}) {1}", (++count).ToString(), circularDependencyData[circularDependencyData.Length - 1]), EditorStyles.boldLabel); EditorGUILayout.BeginVertical("box"); { foreach (string circularDependency in circularDependencyData) { EditorGUILayout.BeginHorizontal(); { GUILayout.Label(circularDependency); if (GUILayout.Button("GO", GUILayout.Width(30f))) { m_SelectedAssetName = circularDependency; m_SelectedAssetIndex = new List(m_CachedAssetNames).IndexOf(m_SelectedAssetName); m_SelectedDependencyData = m_Controller.GetDependencyData(m_SelectedAssetName); m_ToolbarIndex = 1; GUI.FocusControl(null); } } EditorGUILayout.EndHorizontal(); } } EditorGUILayout.EndVertical(); GUILayout.Space(5f); } } EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndHorizontal(); } private void OnAssetsOrderOrFilterChanged() { m_CachedAssetNames = m_Controller.GetAssetNames(m_AssetsOrder, m_AssetsFilter); if (!string.IsNullOrEmpty(m_SelectedAssetName)) { m_SelectedAssetIndex = new List(m_CachedAssetNames).IndexOf(m_SelectedAssetName); } } private void OnScatteredAssetsOrderOrFilterChanged() { m_CachedScatteredAssetNames = m_Controller.GetScatteredAssetNames(m_ScatteredAssetsOrder, m_ScatteredAssetsFilter); if (!string.IsNullOrEmpty(m_SelectedScatteredAssetName)) { m_SelectedScatteredAssetIndex = new List(m_CachedScatteredAssetNames).IndexOf(m_SelectedScatteredAssetName); } } private void OnLoadingResource(int index, int count) { EditorUtility.DisplayProgressBar("Loading Resources", Utility.Text.Format("Loading resources, {0}/{1} loaded.", index.ToString(), count.ToString()), (float)index / count); } private void OnLoadingAsset(int index, int count) { EditorUtility.DisplayProgressBar("Loading Assets", Utility.Text.Format("Loading assets, {0}/{1} loaded.", index.ToString(), count.ToString()), (float)index / count); } private void OnLoadCompleted() { EditorUtility.ClearProgressBar(); } private void OnAnalyzingAsset(int index, int count) { EditorUtility.DisplayProgressBar("Analyzing Assets", Utility.Text.Format("Analyzing assets, {0}/{1} analyzed.", index.ToString(), count.ToString()), (float)index / count); } private void OnAnalyzeCompleted() { EditorUtility.ClearProgressBar(); } } }