private static void CollectNode(GameObjectTreeNode node, ICollection <GameObject> gameObjects)
 {
     gameObjects.Add(node.gameObject);
     foreach (var i in node.Nodes.Cast <GameObjectTreeNode>())
     {
         CollectNode(i, gameObjects);
     }
 }
        public static (string, List <TreeNode>) BuildAssetData()
        {
            StatusStripUpdate("Building asset list...");

            string productName        = null;
            var    objectCount        = assetsManager.assetsFileList.Sum(x => x.objects.Count);
            var    objectAssetItemDic = new Dictionary <Object, AssetItem>(objectCount);
            var    containers         = new List <(PPtr <Object>, string)>();
            var    i = 0;

            Progress.Reset();
            foreach (var assetsFile in assetsManager.assetsFileList)
            {
                foreach (var asset in assetsFile.objects)
                {
                    var assetItem = new AssetItem(asset);
                    objectAssetItemDic.Add(asset, assetItem);
                    assetItem.UniqueID = " #" + i;
                    var exportable = false;
                    switch (asset)
                    {
                    case GameObject m_GameObject:
                        assetItem.Text = m_GameObject.m_Name;
                        break;

                    case Texture2D m_Texture2D:
                        if (!string.IsNullOrEmpty(m_Texture2D.m_StreamData?.path))
                        {
                            assetItem.FullSize = asset.byteSize + m_Texture2D.m_StreamData.size;
                        }
                        assetItem.Text = m_Texture2D.m_Name;
                        exportable     = true;
                        break;

                    case AudioClip m_AudioClip:
                        if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
                        {
                            assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size;
                        }
                        assetItem.Text = m_AudioClip.m_Name;
                        exportable     = true;
                        break;

                    case VideoClip m_VideoClip:
                        if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath))
                        {
                            assetItem.FullSize = asset.byteSize + (long)m_VideoClip.m_ExternalResources.m_Size;
                        }
                        assetItem.Text = m_VideoClip.m_Name;
                        exportable     = true;
                        break;

                    case Shader m_Shader:
                        assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
                        exportable     = true;
                        break;

                    case Mesh _:
                    case TextAsset _:
                    case AnimationClip _:
                    case Font _:
                    case MovieTexture _:
                    case Sprite _:
                        assetItem.Text = ((NamedObject)asset).m_Name;
                        exportable     = true;
                        break;

                    case Animator m_Animator:
                        if (m_Animator.m_GameObject.TryGet(out var gameObject))
                        {
                            assetItem.Text = gameObject.m_Name;
                        }

                        exportable = true;
                        break;

                    case MonoBehaviour m_MonoBehaviour:
                        if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var m_Script))
                        {
                            assetItem.Text = m_Script.m_ClassName;
                        }
                        else
                        {
                            assetItem.Text = m_MonoBehaviour.m_Name;
                        }

                        exportable = true;
                        break;

                    case PlayerSettings m_PlayerSettings:
                        productName = m_PlayerSettings.productName;
                        break;

                    case AssetBundle m_AssetBundle:
                        foreach (var m_Container in m_AssetBundle.m_Container)
                        {
                            var preloadIndex = m_Container.Value.preloadIndex;
                            var preloadSize  = m_Container.Value.preloadSize;
                            var preloadEnd   = preloadIndex + preloadSize;
                            for (var k = preloadIndex; k < preloadEnd; k++)
                            {
                                containers.Add((m_AssetBundle.m_PreloadTable[k], m_Container.Key));
                            }
                        }

                        assetItem.Text = m_AssetBundle.m_Name;
                        break;

                    case ResourceManager m_ResourceManager:
                        foreach (var m_Container in m_ResourceManager.m_Container)
                        {
                            containers.Add((m_Container.Value, m_Container.Key));
                        }

                        break;

                    case NamedObject m_NamedObject:
                        assetItem.Text = m_NamedObject.m_Name;
                        break;
                    }

                    if (assetItem.Text == "")
                    {
                        assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
                    }

                    if (Properties.Settings.Default.displayAll || exportable)
                    {
                        exportableAssets.Add(assetItem);
                    }

                    Progress.Report(++i, objectCount);
                }
            }

            foreach (var(pptr, container) in containers)
            {
                if (!pptr.TryGet(out var obj))
                {
                    continue;
                }
                if (objectAssetItemDic[obj].Container != string.Empty)
                {
                    continue;
                }
                objectAssetItemDic[obj].Container = container;
            }

            containers.Clear();

            visibleAssets = exportableAssets;

            StatusStripUpdate("Building tree structure...");

            var treeNodeCollection = new List <TreeNode>();
            var treeNodeDictionary = new Dictionary <GameObject, GameObjectTreeNode>();
            var assetsFileCount    = assetsManager.assetsFileList.Count;
            var j = 0;

            Progress.Reset();
            foreach (var assetsFile in assetsManager.assetsFileList)
            {
                var fileNode = new GameObjectTreeNode(assetsFile.fileName); //RootNode

                foreach (var obj in assetsFile.objects)
                {
                    if (!(obj is GameObject m_GameObject))
                    {
                        continue;
                    }

                    if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode))
                    {
                        currentNode = new GameObjectTreeNode(m_GameObject);
                        treeNodeDictionary.Add(m_GameObject, currentNode);
                    }

                    foreach (var pptr in m_GameObject.m_Components)
                    {
                        if (!pptr.TryGet(out var m_Component))
                        {
                            continue;
                        }
                        objectAssetItemDic[m_Component].TreeNode = currentNode;

                        switch (m_Component)
                        {
                        case MeshFilter m_MeshFilter:
                        {
                            if (m_MeshFilter.m_Mesh.TryGet(out var m_Mesh))
                            {
                                objectAssetItemDic[m_Mesh].TreeNode = currentNode;
                            }

                            break;
                        }

                        case SkinnedMeshRenderer m_SkinnedMeshRenderer:
                        {
                            if (m_SkinnedMeshRenderer.m_Mesh.TryGet(out var m_Mesh))
                            {
                                objectAssetItemDic[m_Mesh].TreeNode = currentNode;
                            }

                            break;
                        }
                        }
                    }

                    var parentNode = fileNode;

                    if (m_GameObject.m_Transform != null)
                    {
                        if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father))
                        {
                            if (m_Father.m_GameObject.TryGet(out var parentGameObject))
                            {
                                if (!treeNodeDictionary.TryGetValue(parentGameObject, out parentNode))
                                {
                                    parentNode = new GameObjectTreeNode(parentGameObject);
                                    treeNodeDictionary.Add(parentGameObject, parentNode);
                                }
                            }
                        }
                    }

                    parentNode.Nodes.Add(currentNode);
                }

                if (fileNode.Nodes.Count > 0)
                {
                    treeNodeCollection.Add(fileNode);
                }

                Progress.Report(++j, assetsFileCount);
            }

            treeNodeDictionary.Clear();

            objectAssetItemDic.Clear();

            return(productName, treeNodeCollection);
        }