private void AnalyzeAsset(string assetName, Asset hostAsset, DependencyData dependencyData, HashSet <string> scriptAssetNames)
        {
            string[] dependencyAssetNames = AssetDatabase.GetDependencies(assetName, false);
            foreach (string dependencyAssetName in dependencyAssetNames)
            {
                if (scriptAssetNames.Contains(dependencyAssetName))
                {
                    continue;
                }

                if (dependencyAssetName == assetName)
                {
                    continue;
                }

                if (dependencyAssetName.EndsWith(".unity", StringComparison.Ordinal))
                {
                    // 忽略对场景的依赖
                    continue;
                }

                Stamp stamp = new Stamp(hostAsset.Name, dependencyAssetName);
                if (m_AnalyzedStamps.Contains(stamp))
                {
                    continue;
                }

                m_AnalyzedStamps.Add(stamp);

                string guid = AssetDatabase.AssetPathToGUID(dependencyAssetName);
                if (string.IsNullOrEmpty(guid))
                {
                    Debug.LogWarning(Utility.Text.Format("Can not find guid by asset '{0}'.", dependencyAssetName));
                    continue;
                }

                Asset asset = m_ResourceCollection.GetAsset(guid);
                if (asset != null)
                {
                    dependencyData.AddDependencyAsset(asset);
                }
                else
                {
                    dependencyData.AddScatteredDependencyAsset(dependencyAssetName);

                    List <Asset> scatteredAssets = null;
                    if (!m_ScatteredAssets.TryGetValue(dependencyAssetName, out scatteredAssets))
                    {
                        scatteredAssets = new List <Asset>();
                        m_ScatteredAssets.Add(dependencyAssetName, scatteredAssets);
                    }

                    scatteredAssets.Add(hostAsset);

                    AnalyzeAsset(dependencyAssetName, hostAsset, dependencyData, scriptAssetNames);
                }
            }
        }
        public DependencyData GetDependencyData(string assetName)
        {
            DependencyData dependencyData = null;

            if (m_DependencyDatas.TryGetValue(assetName, out dependencyData))
            {
                return(dependencyData);
            }

            return(dependencyData);
        }
        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), 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, 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 <string>(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();
        }
        public void Analyze()
        {
            m_DependencyDatas.Clear();
            m_ScatteredAssets.Clear();
            m_CircularDependencyDatas.Clear();
            m_AnalyzedStamps.Clear();

            HashSet <string> scriptAssetNames = GetFilteredAssetNames("t:Script");

            Asset[] assets = m_ResourceCollection.GetAssets();
            int     count  = assets.Length;

            for (int i = 0; i < count; i++)
            {
                if (OnAnalyzingAsset != null)
                {
                    OnAnalyzingAsset(i, count);
                }

                string assetName = assets[i].Name;
                if (string.IsNullOrEmpty(assetName))
                {
                    Debug.LogWarning(Utility.Text.Format("Can not find asset by guid '{0}'.", assets[i].Guid));
                    continue;
                }

                DependencyData dependencyData = new DependencyData();
                AnalyzeAsset(assetName, assets[i], dependencyData, scriptAssetNames);
                dependencyData.RefreshData();
                m_DependencyDatas.Add(assetName, dependencyData);
            }

            foreach (List <Asset> scatteredAsset in m_ScatteredAssets.Values)
            {
                scatteredAsset.Sort((a, b) => a.Name.CompareTo(b.Name));
            }

            m_CircularDependencyDatas.AddRange(new CircularDependencyChecker(m_AnalyzedStamps.ToArray()).Check());

            if (OnAnalyzeCompleted != null)
            {
                OnAnalyzeCompleted();
            }
        }
        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 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 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);
                    }
                    else
                    {
                        title = Utility.Text.Format("Scattered Assets ({0}/{1})", m_CachedScatteredAssetNames.Length, m_ScatteredAssetCount);
                    }
                    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 ?? "<None>");
                        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), 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 <string>(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 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);
                    }
                    else
                    {
                        title = Utility.Text.Format("Assets In Resources ({0}/{1})", m_CachedAssetNames.Length, m_AssetCount);
                    }
                    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 ?? "<None>");
                        EditorGUILayout.LabelField("Resource Name", m_SelectedAssetName == null ? "<None>" : 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), 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), 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 <string>(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), 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 <string>(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) : scatteredDependencyAssetName);
                                }
                                EditorGUILayout.EndHorizontal();
                            }
                        }
                        EditorGUILayout.EndScrollView();
                    }
                    EditorGUILayout.EndVertical();
                }
                EditorGUILayout.EndVertical();
            }
            EditorGUILayout.EndHorizontal();
        }