private IEnumerator ScanProjectFiles()
        {
            m_IsAlreadyScanningProject = true;
            string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;

            // List containing assets that have been modified.
            m_ProjectScanResults = k_ProjectScanReportDefaultText;
            m_ModifiedAssetList.Clear();
            m_ProgressPercentage = 0;

            // Read Conversion Data from Json file.
            if (m_ConversionData == null)
            {
                m_ConversionData = JsonUtility.FromJson <AssetConversionData>(File.ReadAllText(packageFullPath + "/PackageConversionData.json"));
            }

            // Get list of GUIDs for assets that might contain references to previous GUIDs that require updating.
            string searchFolder = string.IsNullOrEmpty(m_ProjectFolderToScan) ? "Assets" : ("Assets/" + m_ProjectFolderToScan);

            string[] guids = AssetDatabase.FindAssets("t:Object", new string[] { searchFolder }).Distinct().ToArray();

            k_ProjectScanLabelPrefix   = "<b>Phase 1 - Filtering:</b> ";
            m_ScanningTotalFiles       = guids.Length;
            m_ScanningCurrentFileIndex = 0;

            List <AssetFileRecord> projectFilesToScan = new List <AssetFileRecord>();

            foreach (var guid in guids)
            {
                if (m_CancelScanProcess)
                {
                    break;
                }

                string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);

                m_ScanningCurrentFileIndex += 1;
                m_ScanningCurrentFileName   = assetFilePath;
                m_ProgressPercentage        = (float)m_ScanningCurrentFileIndex / m_ScanningTotalFiles;

                // Filter out file types we have no interest in searching
                if (ShouldIgnoreFile(assetFilePath))
                {
                    continue;
                }

                string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);

                projectFilesToScan.Add(new AssetFileRecord(assetFilePath, assetMetaFilePath));

                yield return(null);
            }

            m_RemainingFilesToScan = m_ScanningTotalFiles = projectFilesToScan.Count;

            k_ProjectScanLabelPrefix = "<b>Phase 2 - Scanning:</b> ";

            for (int i = 0; i < m_ScanningTotalFiles; i++)
            {
                if (m_CancelScanProcess)
                {
                    break;
                }

                AssetFileRecord fileRecord = projectFilesToScan[i];

                ThreadPool.QueueUserWorkItem(Task =>
                {
                    ScanProjectFileAsync(fileRecord);

                    m_ScanningCurrentFileName = fileRecord.assetFilePath;

                    int completedScans = m_ScanningTotalFiles - Interlocked.Decrement(ref m_RemainingFilesToScan);

                    m_ScanningCurrentFileIndex = completedScans;
                    m_ProgressPercentage       = (float)completedScans / m_ScanningTotalFiles;
                });

                if (i % 64 == 0)
                {
                    yield return(new WaitForSeconds(2.0f));
                }
            }

            while (m_RemainingFilesToScan > 0 && !m_CancelScanProcess)
            {
                yield return(null);
            }

            m_IsAlreadyScanningProject = false;
            m_ScanningCurrentFileName  = string.Empty;
        }
        private static void ExtractPackageGUIDs()
        {
            // Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
            SetProjectSerializationAndSourceControlModes();

            string projectPath = Path.GetFullPath("Assets/..");

            // Create new instance of AssetConversionData file
            AssetConversionData data = new AssetConversionData();

            data.assetRecords = new List <AssetConversionRecord>();

            // Get full list of GUIDs used in the package which including folders.
            string[] packageGUIDs = AssetDatabase.FindAssets("t:Object", new string[] { "Assets/Packages/com.unity.TextMeshPro" });

            for (int i = 0; i < packageGUIDs.Length; i++)
            {
                // Could add a progress bar for this process (if needed)

                string guid          = packageGUIDs[i];
                string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
                //string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);

                //ObjectIdentifier[] localIdentifider = BundleBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(guid), BuildTarget.NoTarget);
                //System.Type[] types = BundleBuildInterface.GetTypeForObjects(localIdentifider);

                System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);

                // Filter out file types we are not interested in
                if (assetType == typeof(DefaultAsset))
                {
                    continue;
                }

                string newGuid = GenerateUniqueGUID();

                AssetConversionRecord record;
                record.referencedResource = Path.GetFileName(assetFilePath);
                record.target             = "fileID: 2108210716, guid: " + newGuid;

                record.replacement = "fileID: 11500000, guid: " + guid;

                //if (m_AssetRecords.FindIndex(item => item.oldGuid == guid) != -1)
                //    continue;

                data.assetRecords.Add(record);

                // Read the meta file for the given asset.
                //string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);

                //assetMetaFile = assetMetaFile.Replace("guid: " + guid, "guid: " + newGUID);

                //File.WriteAllText(projectPath + "/" + assetMetaFilePath, assetMetaFile);

                Debug.Log("Asset: [" + Path.GetFileName(assetFilePath) + "]   Type: " + assetType + "   Current GUID: [" + guid + "]   New GUID: [" + newGuid + "]");
            }

            // Write new information into JSON file
            string dataFile = JsonUtility.ToJson(data, true);

            File.WriteAllText(projectPath + "/Assets/Packages/com.unity.TextMeshPro/PackageConversionData.json", dataFile);

            // Restore project Asset Serialization and Source Control modes.
            RestoreProjectSerializationAndSourceControlModes();
        }
        /// <summary>
        ///
        /// </summary>
        private static void ConvertProjectGUIDsToUPM()
        {
            // Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
            SetProjectSerializationAndSourceControlModes();

            string projectPath     = Path.GetFullPath("Assets/..");
            string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;

            // List containing assets that have been modified.
            List <AssetModificationRecord> modifiedAssetList = new List <AssetModificationRecord>();

            // Read Conversion Data from Json file.
            AssetConversionData conversionData = JsonUtility.FromJson <AssetConversionData>(File.ReadAllText(packageFullPath + "/PackageConversionData.json"));

            // Get list of GUIDs for assets that might contain references to previous GUIDs that require updating.
            string[] projectGUIDs = AssetDatabase.FindAssets("t:Object");

            for (int i = 0; i < projectGUIDs.Length; i++)
            {
                // Could add a progress bar for this process

                string      guid          = projectGUIDs[i];
                string      assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
                System.Type assetType     = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);

                // Filter out file types we are not interested in
                if (assetType == typeof(DefaultAsset) || assetType == typeof(MonoScript) || assetType == typeof(Texture2D) || assetType == typeof(TextAsset) || assetType == typeof(Shader))
                {
                    continue;
                }

                // Read the asset data file
                string assetDataFile = File.ReadAllText(projectPath + "/" + assetFilePath);

                //Debug.Log("Searching Asset: [" + assetFilePath + "] of type: " + assetType);

                bool hasFileChanged = false;

                foreach (AssetConversionRecord record in conversionData.assetRecords)
                {
                    if (assetDataFile.Contains(record.target))
                    {
                        hasFileChanged = true;

                        assetDataFile = assetDataFile.Replace(record.target, record.replacement);

                        Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetFilePath + "].");
                    }
                }

                if (hasFileChanged)
                {
                    Debug.Log("Adding [" + assetFilePath + "] to list of assets to be modified.");

                    AssetModificationRecord modifiedAsset;
                    modifiedAsset.assetFilePath = assetFilePath;
                    modifiedAsset.assetDataFile = assetDataFile;

                    modifiedAssetList.Add(modifiedAsset);
                }
            }

            // Scan project meta files to update GUIDs of assets whose GUID has changed.
            projectGUIDs = AssetDatabase.FindAssets("t:Object");

            for (int i = 0; i < projectGUIDs.Length; i++)
            {
                string guid              = projectGUIDs[i];
                string assetFilePath     = AssetDatabase.GUIDToAssetPath(guid);
                string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);

                // Read the asset meta data file
                string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);

                bool hasFileChanged = false;

                foreach (AssetConversionRecord record in conversionData.assetRecords)
                {
                    if (assetMetaFile.Contains(record.target))
                    {
                        hasFileChanged = true;

                        assetMetaFile = assetMetaFile.Replace(record.target, record.replacement);

                        Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetMetaFilePath + "].");
                    }
                }

                if (hasFileChanged)
                {
                    Debug.Log("Adding [" + assetMetaFilePath + "] to list of meta files to be modified.");

                    AssetModificationRecord modifiedAsset;
                    modifiedAsset.assetFilePath = assetMetaFilePath;
                    modifiedAsset.assetDataFile = assetMetaFile;

                    modifiedAssetList.Add(modifiedAsset);
                }
            }

            // Display dialogue to show user a list of project files that will be modified upon their consent.
            if (EditorUtility.DisplayDialog("Save Modified Asset(s)?", "Are you sure you want to save all modified assets?", "YES", "NO"))
            {
                for (int i = 0; i < modifiedAssetList.Count; i++)
                {
                    // Make sure all file streams that might have been opened by Unity are closed.
                    //AssetDatabase.ReleaseCachedFileHandles();

                    Debug.Log("Writing asset file [" + modifiedAssetList[i].assetFilePath + "].");

                    //File.WriteAllText(projectPath + "/" + modifiedAssetList[i].assetFilePath, modifiedAssetList[i].assetDataFile);
                }
            }

            AssetDatabase.Refresh();

            // Restore project Asset Serialization and Source Control modes.
            RestoreProjectSerializationAndSourceControlModes();
        }
        private IEnumerator ScanProjectFiles()
        {
            m_IsAlreadyScanningProject = true;
            string projectPath     = Path.GetFullPath("Assets/..");
            string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;

            // List containing assets that have been modified.
            string scanResults = k_ProjectScanReportDefaultText;

            m_ModifiedAssetList.Clear();
            m_ProgressPercentage = 0;

            // Read Conversion Data from Json file.
            AssetConversionData conversionData        = JsonUtility.FromJson <AssetConversionData>(File.ReadAllText(packageFullPath + "/PackageConversionData.json"));
            AssetConversionData conversionData_Assets = JsonUtility.FromJson <AssetConversionData>(File.ReadAllText(packageFullPath + "/PackageConversionData_Assets.json"));

            // Get list of GUIDs for assets that might contain references to previous GUIDs that require updating.
            string[] projectGUIDs = AssetDatabase.FindAssets("t:Object");
            m_ScanningTotalFiles = projectGUIDs.Length;

            // Iterate through projectGUIDs to search project assets of the types likely to reference GUIDs and FileIDs used by previous versions of TextMesh Pro.
            for (int i = 0; i < projectGUIDs.Length; i++)
            {
                m_ScanningCurrentFileIndex = i + 1;

                string      guid          = projectGUIDs[i];
                string      assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
                System.Type assetType     = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);

                // Filter out asset types that we can't read or have not interest in searching.
                if (assetType == typeof(DefaultAsset) || assetType == typeof(MonoScript) || assetType == typeof(Texture2D) ||
                    assetType == typeof(TextAsset) || assetType == typeof(Shader) || assetType == typeof(Font) || assetType == typeof(UnityEditorInternal.AssemblyDefinitionAsset) ||
                    assetType == typeof(GUISkin) || assetType == typeof(PhysicsMaterial2D) || assetType == typeof(UnityEngine.U2D.SpriteAtlas) || assetType == typeof(UnityEngine.Tilemaps.Tile) ||
                    assetType == typeof(AudioClip) || assetType == typeof(ComputeShader) || assetType == typeof(UnityEditor.Animations.AnimatorController))
                {
                    continue;
                }

                // Read the asset data file
                string assetDataFile = string.Empty;
                try
                {
                    assetDataFile = File.ReadAllText(projectPath + "/" + assetFilePath);
                }
                catch
                {
                    // Continue to the next asset if we can't read the current one.
                    continue;
                }

                //Debug.Log("Searching Asset: [" + assetFilePath + "] of type: " + assetType);

                bool hasFileChanged = false;

                // Special handling / optimization if assetType is null
                if (assetType == null)
                {
                    foreach (AssetConversionRecord record in conversionData_Assets.assetRecords)
                    {
                        if (assetDataFile.Contains(record.target))
                        {
                            hasFileChanged = true;

                            assetDataFile = assetDataFile.Replace(record.target, record.replacement);

                            //Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetFilePath + "].");
                        }
                    }
                }
                else
                {
                    foreach (AssetConversionRecord record in conversionData.assetRecords)
                    {
                        if (assetDataFile.Contains(record.target))
                        {
                            hasFileChanged = true;

                            assetDataFile = assetDataFile.Replace(record.target, record.replacement);

                            //Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetFilePath + "].");
                        }
                    }
                }

                if (hasFileChanged)
                {
                    //Debug.Log("Adding [" + assetFilePath + "] to list of assets to be modified.");

                    AssetModificationRecord modifiedAsset;
                    modifiedAsset.assetFilePath = assetFilePath;
                    modifiedAsset.assetDataFile = assetDataFile;

                    m_ModifiedAssetList.Add(modifiedAsset);

                    scanResults += assetFilePath + "\n";
                }

                m_ProjectScanResults = scanResults;
                m_ProgressPercentage = (float)i / (projectGUIDs.Length * 2);

                yield return(null);
            }

            // Iterate through projectGUIDs (again) to search project meta files which reference GUIDs used by previous versions of TextMesh Pro.
            for (int i = 0; i < projectGUIDs.Length; i++)
            {
                string guid              = projectGUIDs[i];
                string assetFilePath     = AssetDatabase.GUIDToAssetPath(guid);
                string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);

                // Read the asset meta data file
                string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);

                bool hasFileChanged = false;

                foreach (AssetConversionRecord record in conversionData.assetRecords)
                {
                    if (assetMetaFile.Contains(record.target))
                    {
                        hasFileChanged = true;

                        assetMetaFile = assetMetaFile.Replace(record.target, record.replacement);

                        //Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetMetaFilePath + "].");
                    }
                }

                if (hasFileChanged)
                {
                    //Debug.Log("Adding [" + assetMetaFilePath + "] to list of meta files to be modified.");

                    AssetModificationRecord modifiedAsset;
                    modifiedAsset.assetFilePath = assetMetaFilePath;
                    modifiedAsset.assetDataFile = assetMetaFile;

                    m_ModifiedAssetList.Add(modifiedAsset);

                    scanResults += assetMetaFilePath + "\n";
                }

                m_ProjectScanResults = scanResults;
                m_ProgressPercentage = 0.5f + ((float)i / (projectGUIDs.Length * 2));

                yield return(null);
            }

            m_IsAlreadyScanningProject = false;
        }