Exemple #1
0
        internal void AddAsset(AssetObjectInfo assetInfo)
        {
            if (AssetList == null)
            {
                AssetList = new List <AssetObjectInfo>();
            }

            assetInfo.SetParent(this);
            AssetList.Add(assetInfo);
        }
        private static void traverseDirectory(int parentIndex, string path, List <BuildReportAsset> usedAssets, int heirarchyDepth, ref int directoriesTraversed, SortedDictionary <AssetHunterSerializableSystemType, bool> validTypeList)
        {
            directoriesTraversed++;

            EditorUtility.DisplayProgressBar(
                "Traversing Directories",
                "(" + directoriesTraversed + " of " + m_NumberOfDirectories + ") Analyzing " + path.Substring(path.IndexOf("/Assets") + 1),
                (float)directoriesTraversed / (float)m_NumberOfDirectories);

            //Get the settings to exclude certain folders or suffixes
            foreach (UnityEngine.Object dir in AssetHunterMainWindow.Instance.settings.m_DirectoryExcludes)
            {
                //TODO Can this be done more elegantly
                int                startingIndex = Application.dataPath.Length - 6;
                string             relativePath  = path.Substring(startingIndex, path.Length - startingIndex);
                UnityEngine.Object obj           = AssetDatabase.LoadAssetAtPath(relativePath, typeof(UnityEngine.Object));

                if (dir == obj)
                {
                    //This folder was exluded
                    return;
                }
            }

            //Exclude types and folders that should not be reviewed
            //TODO perhaps improve performance of this step (Also use String.Contains(excluder, StringComparison.OrdinalIgnoreCase)) might be better not to use LINQ
            string[] assetsInDirectory = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly)
                                         .Where(name => !name.EndsWith(".meta", StringComparison.OrdinalIgnoreCase) &&
                                                (!name.EndsWith(".unity", StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.EndsWith("thumbs.db", StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.EndsWith(".orig", StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.EndsWith(".mdb", StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.Contains(Path.DirectorySeparatorChar + "heureka" + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.Contains(Path.DirectorySeparatorChar + "plugins" + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.Contains(Path.DirectorySeparatorChar + "streamingassets" + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.Contains(Path.DirectorySeparatorChar + "resources" + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.Contains(Path.DirectorySeparatorChar + "editor default resources" + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.Contains(Path.DirectorySeparatorChar + "editor" + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.EndsWith(@".ds_store", StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.EndsWith(@".workspace.mel", StringComparison.OrdinalIgnoreCase)) &&
                                                (!name.EndsWith(@".mayaswatches", StringComparison.OrdinalIgnoreCase)))
                                         .ToArray();

            //TODO this could also be improved for performance
            for (int i = 0; i < assetsInDirectory.Length; i++)
            {
                assetsInDirectory[i] = assetsInDirectory[i].Substring(assetsInDirectory[i].IndexOf("/Assets") + 1);
                assetsInDirectory[i] = assetsInDirectory[i].Replace(@"\", "/");
            }

            //Remove the assets we ignore through settings && Find any assets that does not live in UsedAssets List
            //TODO for performance reasons, perhaps dont to this for each folder, but just once, when finished?
            //That would mean to do folder creation and populating unused assets lists after all folders are traversed
            var result = assetsInDirectory.Where(p => (!AssetHunterMainWindow.Instance.settings.m_AssetGUIDExcludes.Any(p2 => UnityEditor.AssetDatabase.GUIDToAssetPath(p2) == p)) &&
                                                 !usedAssets.Any(p2 => UnityEditor.AssetDatabase.GUIDToAssetPath(p2.GUID) == p));

            //Create new folder object
            AssetHunterProjectFolderInfo afInfo = new AssetHunterProjectFolderInfo();

            //TODO this could also be improved for performance
            afInfo.DirectoryName = path.Substring(path.IndexOf("/Assets") + 1).Replace(@"\", "/");
            afInfo.ParentIndex   = parentIndex;

            if (heirarchyDepth == 0)
            {
                afInfo.FoldOut = true;
            }

            //Add to static list
            AssetHunterMainWindow.Instance.AddProjectFolderInfo(afInfo);

            if (parentIndex != -1)
            {
                AssetHunterMainWindow.Instance.GetFolderList()[parentIndex].AddChildFolder(afInfo);
            }

            UnityEngine.Object objToFind;
            foreach (string assetName in result)
            {
                bool bExclude = false;

                foreach (string excluder in AssetHunterMainWindow.Instance.settings.m_AssetSubstringExcludes)
                {
                    //Exlude Asset Exclude substrings from settings
                    //If we find an excluded asset just continue to next iteration in loop
                    if (assetName.Contains(excluder, StringComparison.OrdinalIgnoreCase))
                    {
                        bExclude = true;
                    }
                }
                if (bExclude)
                {
                    continue;
                }

                objToFind = AssetDatabase.LoadAssetAtPath(assetName, typeof(UnityEngine.Object));

                if (objToFind == null)
                {
                    Debug.LogWarning("Couldnt find " + assetName);
                    continue;
                }

                AssetHunterSerializableSystemType assetType = new AssetHunterSerializableSystemType(objToFind.GetType());

                if (assetType.SystemType != typeof(MonoScript) && (!AssetHunterMainWindow.Instance.settings.m_AssetTypeExcludes.Contains(assetType)))
                {
                    AssetObjectInfo newAssetInfo = new AssetObjectInfo(assetName, assetType);
                    afInfo.AddAsset(newAssetInfo);
                }

                objToFind = null;

                //Memory leak safeguard
                //This have heavy performance implications
                if (AssetHunterMainWindow.Instance.settings.m_MemoryCleanupActive)
                {
                    UnloadUnused();
                }
            }

            string[] nextLevelDirectories = System.IO.Directory.GetDirectories(path, "*.*", System.IO.SearchOption.TopDirectoryOnly);

            //Memory leak safeguard per folder
            if (!AssetHunterMainWindow.Instance.settings.m_MemoryCleanupActive)
            {
                UnloadUnused();
            }

            foreach (string nld in nextLevelDirectories)
            {
                traverseDirectory(AssetHunterMainWindow.Instance.GetFolderList().IndexOf(afInfo), nld, usedAssets, (heirarchyDepth + 1), ref directoriesTraversed, validTypeList);
            }
        }
        private void drawAssetFolderInfoRecursively(AssetHunterProjectFolderInfo assetFolder, int indentLevel)
        {
            EditorGUI.indentLevel = indentLevel;

            if (!assetFolder.ShouldBeListed(m_unusedTypeDict))
            {
                return;
            }
            else
            {
                int assetCount = assetFolder.GetAssetCountInChildren();
                EditorGUILayout.BeginHorizontal();

                Color initialColor = GUI.color;
                GUI.color = AssetHunterHelper.AH_RED;
                float buttonSizeSelect = 60;
                float buttonSizeDelete = 100;

                if (GUILayout.Button("Delete all " + assetCount, GUILayout.Width(buttonSizeDelete)))
                {
                    m_folderMarkedForDeletion = assetFolder;
                }

                //Add space to align UI elements
                GUILayout.Space(buttonSizeSelect);

                //Create new style to have a bold foldout
                GUIStyle  style         = EditorStyles.foldout;
                FontStyle previousStyle = style.fontStyle;
                style.fontStyle = FontStyle.Bold;

                //Show foldout
                assetFolder.FoldOut = EditorGUILayout.Foldout(assetFolder.FoldOut, assetFolder.DirectoryName + " (" /* + assetFolder.FileSizeString + "/"*/ + assetFolder.FileSizeAccumulatedString + ")", style);

                //Reset style
                style.fontStyle = previousStyle;

                //Reset color
                GUI.color = initialColor;

                EditorGUILayout.EndHorizontal();
                if (assetFolder.FoldOut)
                {
                    foreach (AssetObjectInfo aInfo in assetFolder.AssetList)
                    {
                        if ((m_unusedTypeDict.ContainsKey(aInfo.m_Type) && m_unusedTypeDict[aInfo.m_Type] == false))
                        {
                            continue;
                        }

                        EditorGUI.indentLevel = (indentLevel + 1);
                        EditorGUILayout.BeginHorizontal();
                        GUI.color = Color.grey;
                        if (GUILayout.Button("Delete", GUILayout.Width(buttonSizeDelete)))
                        {
                            m_assetMarkedForDeletion = aInfo;
                        }
                        GUI.color = initialColor;
                        if (GUILayout.Button("Select", GUILayout.Width(buttonSizeSelect)))
                        {
                            Selection.activeObject = AssetDatabase.LoadAssetAtPath(aInfo.m_Path, aInfo.m_Type.SystemType);
                        }

                        EditorGUILayout.LabelField(aInfo.m_Name + " (" + aInfo.m_FileSizeString + ")", GUILayout.MaxWidth(600));
                        EditorGUILayout.EndHorizontal();
                    }

                    foreach (int childFolder in assetFolder.ChildFolderIndexers)
                    {
                        drawAssetFolderInfoRecursively(m_ProjectFolderList[childFolder], (indentLevel + 1));
                    }
                }
            }
        }
        /*private void OnUnusedScriptsUIUpdate()
         * {
         *  if (m_UsedScriptList == null || m_UsedScriptList.Count <= 0)
         *      return;
         *
         *  scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
         *  EditorGUILayout.BeginVertical();
         *
         *  EditorGUILayout.LabelField("List of unused scripts", EditorStyles.boldLabel);
         *  showUnusedScriptsUI();
         *
         *  EditorGUILayout.EndVertical();
         *  EditorGUILayout.EndScrollView();
         * }*/

        /*private void showUnusedScriptsUI()
         * {
         *
         *  //TODO
         *  //HERE IS A WAY TO FIND ALL CLASSES, Used, and Unused
         *  //http://answers.unity3d.com/questions/30382/editor-assembly.html
         *
         *  foreach (Type t in m_UnusedScriptList)
         *  {
         *      GUILayout.BeginHorizontal();
         *      MonoScript script = null;
         *
         *      if (GUILayout.Button(t.ToString(), GUILayout.Width(btnMinWidth * 2 + 14)))
         *      {
         *          MonoScript[] scripts = (MonoScript[])Resources.FindObjectsOfTypeAll(typeof(MonoScript));
         *          foreach (MonoScript m in scripts)
         *          {
         *              if (m.GetClass() == t)
         *                  script = m;
         *          }
         *          Selection.activeObject = script;
         *      }
         *      GUILayout.EndHorizontal();
         *  }
         * }*/

        #endregion

        private void showUnusedAssets()
        {
            EditorGUILayout.Separator();
            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("Collapse All", GUILayout.Width(btnMinWidth)))
            {
                foreach (AssetHunterProjectFolderInfo folder in m_ProjectFolderList)
                {
                    folder.FoldOut = false;
                }
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("Expand All", GUILayout.Width(btnMinWidth)))
            {
                foreach (AssetHunterProjectFolderInfo folder in m_ProjectFolderList)
                {
                    folder.FoldOut = true;
                }
            }
            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Separator();
            EditorGUILayout.Separator();
            int indentLevel = 0;

            drawAssetFolderInfoRecursively(m_ProjectFolderList[0], indentLevel);

            if (m_assetMarkedForDeletion != null)
            {
                if (EditorUtility.DisplayDialog("Delete asset", "Are you sure you want to delete " + m_assetMarkedForDeletion.m_Name, "Yes", "No"))
                {
                    m_assetMarkedForDeletion.Delete(m_unusedTypeDict);
                    //Delete potential empty folders
                    int deleteCount = 0;
                    deleteEmptyDirectories(getSystemFolderPath(m_assetMarkedForDeletion.m_ParentPath), ref deleteCount);
                    m_assetMarkedForDeletion = null;
                }
                else
                {
                    m_assetMarkedForDeletion = null;
                }
            }
            else if (m_folderMarkedForDeletion != null)
            {
                int dialogChoice = EditorUtility.DisplayDialogComplex(
                    "Delete all unused assets in folder",
                    "You can delete all assets below this folder, or you can choose to create a backup Unitypackage with all your deleted assets (which will be slow).\n\nRegardless you should always keep backups or preferably have your project under version control so actions such as mass-delete can be reverted",
                    "Delete All",
                    "Backup Unitypackage (Slow!)",
                    "Cancel");

                switch (dialogChoice)
                {
                //Normal delete
                case 0:
                    deleteAllInFolder(m_folderMarkedForDeletion, false);
                    break;

                //Delete with backup
                case 1:
                    deleteAllInFolder(m_folderMarkedForDeletion, true);
                    break;

                //Cancel
                case 2:
                    m_folderMarkedForDeletion = null;
                    break;

                default:
                    Debug.LogError("Unrecognized option.");
                    break;
                }
            }
        }
Exemple #5
0
 internal void RemoveAsset(AssetObjectInfo assetObjectInfo)
 {
     m_assetList.Remove(assetObjectInfo);
 }