You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

876 lines
36 KiB

  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.IO;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using TMPro.EditorUtilities;
  7. namespace TMPro
  8. {
  9. /// <summary>
  10. /// Data structure containing the target and replacement fileIDs and GUIDs which will require remapping from previous version of TextMesh Pro to the new TextMesh Pro UPM package.
  11. /// </summary>
  12. [System.Serializable]
  13. struct AssetConversionRecord
  14. {
  15. public string referencedResource;
  16. public string target;
  17. public string replacement;
  18. }
  19. /// <summary>
  20. /// Data structure containing a list of target and replacement fileID and GUID requiring remapping from previous versions of TextMesh Pro to the new TextMesh Pro UPM package.
  21. /// This data structure is populated with the data contained in the PackageConversionData.json file included in the package.
  22. /// </summary>
  23. [System.Serializable]
  24. class AssetConversionData
  25. {
  26. public List<AssetConversionRecord> assetRecords;
  27. }
  28. public class TMP_ProjectConversionUtility : EditorWindow
  29. {
  30. // Create Sprite Asset Editor Window
  31. [MenuItem("Window/TextMeshPro/Project Files GUID Remapping Tool", false, 2100)]
  32. static void ShowConverterWindow()
  33. {
  34. var window = GetWindow<TMP_ProjectConversionUtility>();
  35. window.titleContent = new GUIContent("Conversion Tool");
  36. window.Focus();
  37. }
  38. /// <summary>
  39. ///
  40. /// </summary>
  41. struct AssetModificationRecord
  42. {
  43. public string assetFilePath;
  44. public string assetDataFile;
  45. }
  46. private static string m_ProjectFolderToScan;
  47. private static bool m_IsAlreadyScanningProject;
  48. private static bool m_CancelScanProcess;
  49. private static string k_ProjectScanReportDefaultText = "<color=#FFFF80><b>Project Scan Results</b></color>\n";
  50. private static string m_ProjectScanResults = string.Empty;
  51. private static Vector2 m_ProjectScanResultScrollPosition;
  52. private static float m_ProgressPercentage = 0;
  53. private static int m_ScanningTotalFiles;
  54. private static int m_ScanningCurrentFileIndex;
  55. private static string m_ScanningCurrentFileName;
  56. private static List<AssetModificationRecord> m_ModifiedAssetList = new List<AssetModificationRecord>();
  57. void OnEnable()
  58. {
  59. // Set Editor Window Size
  60. SetEditorWindowSize();
  61. m_ProjectScanResults = k_ProjectScanReportDefaultText;
  62. }
  63. void OnGUI()
  64. {
  65. GUILayout.BeginVertical();
  66. {
  67. // Scan project files and resources
  68. GUILayout.BeginVertical(EditorStyles.helpBox);
  69. {
  70. GUILayout.Label("Scan Project Files", EditorStyles.boldLabel);
  71. GUILayout.Label("Press the <i>Scan Project Files</i> button to begin scanning your project for files & resources that were created with a previous version of TextMesh Pro.", TMP_UIStyleManager.label);
  72. GUILayout.Space(10f);
  73. GUILayout.Label("Project folder to be scanned. Example \"Assets/TextMesh Pro\"");
  74. m_ProjectFolderToScan = EditorGUILayout.TextField("Folder Path: Assets/", m_ProjectFolderToScan);
  75. GUILayout.Space(5f);
  76. GUI.enabled = m_IsAlreadyScanningProject == false ? true : false;
  77. if (GUILayout.Button("Scan Project Files"))
  78. {
  79. m_CancelScanProcess = false;
  80. // Make sure Asset Serialization mode is set to ForceText and Version Control mode to Visible Meta Files.
  81. if (CheckProjectSerializationAndSourceControlModes() == true)
  82. {
  83. EditorCoroutine.StartCoroutine(ScanProjectFiles());
  84. }
  85. else
  86. {
  87. EditorUtility.DisplayDialog("Project Settings Change Required", "In menu options \"Edit - Project Settings - Editor\", please change Asset Serialization Mode to ForceText and Source Control Mode to Visible Meta Files.", "OK", string.Empty);
  88. }
  89. }
  90. GUI.enabled = true;
  91. // Display progress bar
  92. Rect rect = GUILayoutUtility.GetRect(0f, 20f, GUILayout.ExpandWidth(true));
  93. EditorGUI.ProgressBar(rect, m_ProgressPercentage, "Scan Progress (" + m_ScanningCurrentFileIndex + "/" + m_ScanningTotalFiles + ")");
  94. // Display cancel button and name of file currently being scanned.
  95. if (m_IsAlreadyScanningProject)
  96. {
  97. Rect cancelRect = new Rect(rect.width - 20, rect.y + 2, 20, 16);
  98. if (GUI.Button(cancelRect, "X"))
  99. {
  100. m_CancelScanProcess = true;
  101. }
  102. GUILayout.Label("Scanning: " + m_ScanningCurrentFileName);
  103. }
  104. else
  105. GUILayout.Label(string.Empty);
  106. GUILayout.Space(5);
  107. // Creation Feedback
  108. GUILayout.BeginVertical(TMP_UIStyleManager.textAreaBoxWindow, GUILayout.ExpandHeight(true));
  109. {
  110. m_ProjectScanResultScrollPosition = EditorGUILayout.BeginScrollView(m_ProjectScanResultScrollPosition, GUILayout.ExpandHeight(true));
  111. EditorGUILayout.LabelField(m_ProjectScanResults, TMP_UIStyleManager.label);
  112. EditorGUILayout.EndScrollView();
  113. }
  114. GUILayout.EndVertical();
  115. GUILayout.Space(5f);
  116. }
  117. GUILayout.EndVertical();
  118. // Scan project files and resources
  119. GUILayout.BeginVertical(EditorStyles.helpBox);
  120. {
  121. GUILayout.Label("Save Modified Project Files", EditorStyles.boldLabel);
  122. GUILayout.Label("Pressing the <i>Save Modified Project Files</i> button will update the files in the <i>Project Scan Results</i> listed above. <color=#FFFF80>Please make sure that you have created a backup of your project first</color> as these file modifications are permanent and cannot be undone.", TMP_UIStyleManager.label);
  123. GUILayout.Space(5f);
  124. GUI.enabled = m_IsAlreadyScanningProject == false && m_ModifiedAssetList.Count > 0 ? true : false;
  125. if (GUILayout.Button("Save Modified Project Files"))
  126. {
  127. UpdateProjectFiles();
  128. }
  129. GUILayout.Space(10f);
  130. }
  131. GUILayout.EndVertical();
  132. }
  133. GUILayout.EndVertical();
  134. GUILayout.Space(5f);
  135. }
  136. void OnInspectorUpdate()
  137. {
  138. Repaint();
  139. }
  140. /// <summary>
  141. /// Limits the minimum size of the editor window.
  142. /// </summary>
  143. void SetEditorWindowSize()
  144. {
  145. EditorWindow editorWindow = this;
  146. Vector2 currentWindowSize = editorWindow.minSize;
  147. editorWindow.minSize = new Vector2(Mathf.Max(640, currentWindowSize.x), Mathf.Max(420, currentWindowSize.y));
  148. }
  149. private IEnumerator ScanProjectFiles()
  150. {
  151. m_IsAlreadyScanningProject = true;
  152. string projectPath = Path.GetFullPath("Assets/..");
  153. string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;
  154. // List containing assets that have been modified.
  155. string scanResults = k_ProjectScanReportDefaultText;
  156. m_ModifiedAssetList.Clear();
  157. m_ProgressPercentage = 0;
  158. // Read Conversion Data from Json file.
  159. AssetConversionData conversionData = JsonUtility.FromJson<AssetConversionData>(File.ReadAllText(packageFullPath + "/PackageConversionData.json"));
  160. AssetConversionData conversionData_Assets = JsonUtility.FromJson<AssetConversionData>(File.ReadAllText(packageFullPath + "/PackageConversionData_Assets.json"));
  161. // Get list of GUIDs for assets that might contain references to previous GUIDs that require updating.
  162. string searchFolder = string.IsNullOrEmpty(m_ProjectFolderToScan) ? "Assets" : ("Assets/" + m_ProjectFolderToScan);
  163. string[] projectGUIDs = AssetDatabase.FindAssets("t:Object", new string[] { searchFolder });
  164. m_ScanningTotalFiles = projectGUIDs.Length;
  165. bool cancelScanning = false;
  166. // Iterate through projectGUIDs to search project assets of the types likely to reference GUIDs and FileIDs used by previous versions of TextMesh Pro.
  167. for (int i = 0; i < projectGUIDs.Length && cancelScanning == false; i++)
  168. {
  169. if (m_CancelScanProcess)
  170. {
  171. cancelScanning = true;
  172. ResetScanProcess();
  173. continue;
  174. }
  175. m_ScanningCurrentFileIndex = i + 1;
  176. string guid = projectGUIDs[i];
  177. string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
  178. string assetFileExtension = Path.GetExtension(assetFilePath);
  179. System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);
  180. // Filter out asset types that we can't read or have not interest in searching.
  181. if (assetType == typeof(DefaultAsset) || assetType == typeof(MonoScript) || assetType == typeof(Texture2D) || assetType == typeof(Texture3D) || assetType == typeof(Cubemap) ||
  182. assetType == typeof(TextAsset) || assetType == typeof(Shader) || assetType == typeof(Font) || assetType == typeof(UnityEditorInternal.AssemblyDefinitionAsset) ||
  183. assetType == typeof(GUISkin) || assetType == typeof(PhysicsMaterial2D) || assetType == typeof(PhysicMaterial) || assetType == typeof(UnityEngine.U2D.SpriteAtlas) || assetType == typeof(UnityEngine.Tilemaps.Tile) ||
  184. assetType == typeof(AudioClip) || assetType == typeof(ComputeShader) || assetType == typeof(UnityEditor.Animations.AnimatorController) || assetType == typeof(UnityEngine.AI.NavMeshData) ||
  185. assetType == typeof(Mesh) || assetType == typeof(RenderTexture) || assetType == typeof(Texture2DArray) || assetType == typeof(LightingDataAsset) || assetType == typeof(AvatarMask) ||
  186. assetType == typeof(AnimatorOverrideController) || assetType == typeof(TerrainData) || assetType == typeof(HumanTemplate) || assetType == typeof(Flare) || assetType == typeof(UnityEngine.Video.VideoClip))
  187. continue;
  188. // Exclude FBX
  189. if (assetType == typeof(GameObject) && (assetFileExtension == ".FBX" || assetFileExtension == ".fbx"))
  190. continue;
  191. m_ScanningCurrentFileName = assetFilePath;
  192. //Debug.Log("Searching Asset: [" + assetFilePath + "] with file extension [" + assetFileExtension + "] of type [" + assetType + "]");
  193. // Read the asset data file
  194. string assetDataFile = string.Empty;
  195. try
  196. {
  197. assetDataFile = File.ReadAllText(projectPath + "/" + assetFilePath);
  198. }
  199. catch
  200. {
  201. // Continue to the next asset if we can't read the current one.
  202. continue;
  203. }
  204. bool hasFileChanged = false;
  205. // Special handling / optimization if assetType is null
  206. if (assetType == null)
  207. {
  208. foreach (AssetConversionRecord record in conversionData_Assets.assetRecords)
  209. {
  210. if (assetDataFile.Contains(record.target))
  211. {
  212. hasFileChanged = true;
  213. assetDataFile = assetDataFile.Replace(record.target, record.replacement);
  214. //Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetFilePath + "].");
  215. }
  216. }
  217. }
  218. else
  219. {
  220. foreach (AssetConversionRecord record in conversionData.assetRecords)
  221. {
  222. if (assetDataFile.Contains(record.target))
  223. {
  224. hasFileChanged = true;
  225. assetDataFile = assetDataFile.Replace(record.target, record.replacement);
  226. //Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetFilePath + "].");
  227. }
  228. }
  229. }
  230. if (hasFileChanged)
  231. {
  232. //Debug.Log("Adding [" + assetFilePath + "] to list of assets to be modified.");
  233. AssetModificationRecord modifiedAsset;
  234. modifiedAsset.assetFilePath = assetFilePath;
  235. modifiedAsset.assetDataFile = assetDataFile;
  236. m_ModifiedAssetList.Add(modifiedAsset);
  237. scanResults += assetFilePath + "\n";
  238. }
  239. m_ProjectScanResults = scanResults;
  240. m_ProgressPercentage = (float)i / (projectGUIDs.Length * 2);
  241. yield return null;
  242. }
  243. // Iterate through projectGUIDs (again) to search project meta files which reference GUIDs used by previous versions of TextMesh Pro.
  244. for (int i = 0; i < projectGUIDs.Length && cancelScanning == false; i++)
  245. {
  246. if (m_CancelScanProcess)
  247. {
  248. cancelScanning = true;
  249. ResetScanProcess();
  250. continue;
  251. }
  252. string guid = projectGUIDs[i];
  253. string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
  254. string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);
  255. // Read the asset meta data file
  256. string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);
  257. bool hasFileChanged = false;
  258. m_ScanningCurrentFileName = assetMetaFilePath;
  259. foreach (AssetConversionRecord record in conversionData.assetRecords)
  260. {
  261. if (assetMetaFile.Contains(record.target))
  262. {
  263. hasFileChanged = true;
  264. assetMetaFile = assetMetaFile.Replace(record.target, record.replacement);
  265. //Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetMetaFilePath + "].");
  266. }
  267. }
  268. if (hasFileChanged)
  269. {
  270. //Debug.Log("Adding [" + assetMetaFilePath + "] to list of meta files to be modified.");
  271. AssetModificationRecord modifiedAsset;
  272. modifiedAsset.assetFilePath = assetMetaFilePath;
  273. modifiedAsset.assetDataFile = assetMetaFile;
  274. m_ModifiedAssetList.Add(modifiedAsset);
  275. scanResults += assetMetaFilePath + "\n";
  276. }
  277. m_ProjectScanResults = scanResults;
  278. m_ProgressPercentage = 0.5f + ((float)i / (projectGUIDs.Length * 2));
  279. yield return null;
  280. }
  281. m_IsAlreadyScanningProject = false;
  282. m_ScanningCurrentFileName = string.Empty;
  283. }
  284. /// <summary>
  285. ///
  286. /// </summary>
  287. private static void ResetScanProcess()
  288. {
  289. m_IsAlreadyScanningProject = false;
  290. m_ScanningCurrentFileName = string.Empty;
  291. m_ProgressPercentage = 0;
  292. m_ScanningCurrentFileIndex = 0;
  293. m_ScanningTotalFiles = 0;
  294. }
  295. /// <summary>
  296. ///
  297. /// </summary>
  298. private static void UpdateProjectFiles()
  299. {
  300. // Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
  301. CheckProjectSerializationAndSourceControlModes();
  302. string projectPath = Path.GetFullPath("Assets/..");
  303. // Display dialogue to show user a list of project files that will be modified upon their consent.
  304. if (EditorUtility.DisplayDialog("Save Modified Asset(s)?", "Are you sure you want to save all modified assets?", "YES", "NO"))
  305. {
  306. for (int i = 0; i < m_ModifiedAssetList.Count; i++)
  307. {
  308. // Make sure all file streams that might have been opened by Unity are closed.
  309. //AssetDatabase.ReleaseCachedFileHandles();
  310. //Debug.Log("Writing asset file [" + m_ModifiedAssetList[i].assetFilePath + "].");
  311. File.WriteAllText(projectPath + "/" + m_ModifiedAssetList[i].assetFilePath, m_ModifiedAssetList[i].assetDataFile);
  312. }
  313. }
  314. AssetDatabase.Refresh();
  315. m_ProgressPercentage = 0;
  316. m_ProjectScanResults = k_ProjectScanReportDefaultText;
  317. }
  318. /// <summary>
  319. /// Check project Asset Serialization and Source Control modes
  320. /// </summary>
  321. private static bool CheckProjectSerializationAndSourceControlModes()
  322. {
  323. // Check Project Asset Serialization and Visible Meta Files mode.
  324. if (EditorSettings.serializationMode != SerializationMode.ForceText || EditorSettings.externalVersionControl != "Visible Meta Files")
  325. {
  326. return false;
  327. }
  328. return true;
  329. }
  330. }
  331. public class TMP_PackageUtilities : Editor
  332. {
  333. enum SaveAssetDialogueOptions { Unset = 0, Save = 1, SaveAll = 2, DoNotSave = 3 };
  334. private static SerializationMode m_ProjectAssetSerializationMode;
  335. private static string m_ProjectExternalVersionControl;
  336. struct AssetRemappingRecord
  337. {
  338. public string oldGuid;
  339. public string newGuid;
  340. public string assetPath;
  341. }
  342. struct AssetModificationRecord
  343. {
  344. public string assetFilePath;
  345. public string assetDataFile;
  346. }
  347. // Create Sprite Asset Editor Window
  348. //[MenuItem("Window/TextMeshPro/Generate New Package GUIDs", false, 1500)]
  349. public static void GenerateNewPackageGUIDs_Menu()
  350. {
  351. GenerateNewPackageGUIDs();
  352. }
  353. /// <summary>
  354. ///
  355. /// </summary>
  356. [MenuItem("Window/TextMeshPro/Import TMP Essential Resources", false, 2050)]
  357. public static void ImportProjectResourcesMenu()
  358. {
  359. ImportProjectResources();
  360. }
  361. /// <summary>
  362. ///
  363. /// </summary>
  364. [MenuItem("Window/TextMeshPro/Import TMP Examples and Extras", false, 2051)]
  365. public static void ImportExamplesContentMenu()
  366. {
  367. ImportExtraContent();
  368. }
  369. // Create Sprite Asset Editor Window
  370. //[MenuItem("Window/TextMeshPro/Convert TMP Project Files to UPM", false, 1510)]
  371. public static void ConvertProjectGUIDsMenu()
  372. {
  373. ConvertProjectGUIDsToUPM();
  374. //GetVersionInfo();
  375. }
  376. // Create Sprite Asset Editor Window
  377. //[MenuItem("Window/TextMeshPro/Convert GUID (Source to DLL)", false, 2010)]
  378. public static void ConvertGUIDFromSourceToDLLMenu()
  379. {
  380. //ConvertGUIDFromSourceToDLL();
  381. //GetVersionInfo();
  382. }
  383. // Create Sprite Asset Editor Window
  384. //[MenuItem("Window/TextMeshPro/Convert GUID (DLL to Source)", false, 2020)]
  385. public static void ConvertGUIDFromDllToSourceMenu()
  386. {
  387. //ConvertGUIDFromDLLToSource();
  388. //GetVersionInfo();
  389. }
  390. // Create Sprite Asset Editor Window
  391. //[MenuItem("Window/TextMeshPro/Extract Package GUIDs", false, 1530)]
  392. public static void ExtractPackageGUIDMenu()
  393. {
  394. ExtractPackageGUIDs();
  395. }
  396. private static void GetVersionInfo()
  397. {
  398. string version = TMP_Settings.version;
  399. Debug.Log("The version of this TextMesh Pro UPM package is (" + version + ").");
  400. }
  401. /// <summary>
  402. ///
  403. /// </summary>
  404. private static void ImportExtraContent()
  405. {
  406. string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;
  407. AssetDatabase.ImportPackage(packageFullPath + "/Package Resources/TMP Examples & Extras.unitypackage", true);
  408. }
  409. /// <summary>
  410. ///
  411. /// </summary>
  412. private static void ImportProjectResources()
  413. {
  414. string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;
  415. AssetDatabase.ImportPackage(packageFullPath + "/Package Resources/TMP Essential Resources.unitypackage", true);
  416. }
  417. /// <summary>
  418. ///
  419. /// </summary>
  420. private static void GenerateNewPackageGUIDs()
  421. {
  422. // Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
  423. SetProjectSerializationAndSourceControlModes();
  424. string projectPath = Path.GetFullPath("Assets/..");
  425. // Clear existing dictionary of AssetRecords
  426. List<AssetRemappingRecord> assetRecords = new List<AssetRemappingRecord>();
  427. // Get full list of GUIDs used in the package which including folders.
  428. string[] packageGUIDs = AssetDatabase.FindAssets("t:Object", new string[] { "Assets/Packages/com.unity.TextMeshPro" });
  429. for (int i = 0; i < packageGUIDs.Length; i++)
  430. {
  431. // Could add a progress bar for this process (if needed)
  432. string guid = packageGUIDs[i];
  433. string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
  434. string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);
  435. //System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);
  436. AssetRemappingRecord assetRecord;
  437. assetRecord.oldGuid = guid;
  438. assetRecord.assetPath = assetFilePath;
  439. string newGUID = GenerateUniqueGUID();
  440. assetRecord.newGuid = newGUID;
  441. if (assetRecords.FindIndex(item => item.oldGuid == guid) != -1)
  442. continue;
  443. assetRecords.Add(assetRecord);
  444. // Read the meta file for the given asset.
  445. string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);
  446. assetMetaFile = assetMetaFile.Replace("guid: " + guid, "guid: " + newGUID);
  447. File.WriteAllText(projectPath + "/" + assetMetaFilePath, assetMetaFile);
  448. //Debug.Log("Asset: [" + assetFilePath + "] Type: " + assetType + " Current GUID: [" + guid + "] New GUID: [" + newGUID + "]");
  449. }
  450. AssetDatabase.Refresh();
  451. // Get list of GUIDs for assets that might need references to previous GUIDs which need to be updated.
  452. packageGUIDs = AssetDatabase.FindAssets("t:Object"); // ("t:Object", new string[] { "Assets/Asset Importer" });
  453. for (int i = 0; i < packageGUIDs.Length; i++)
  454. {
  455. // Could add a progress bar for this process
  456. string guid = packageGUIDs[i];
  457. string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
  458. System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);
  459. // Filter out file types we are not interested in
  460. if (assetType == typeof(DefaultAsset) || assetType == typeof(MonoScript) || assetType == typeof(Texture2D) || assetType == typeof(TextAsset) || assetType == typeof(Shader))
  461. continue;
  462. // Read the asset data file
  463. string assetDataFile = File.ReadAllText(projectPath + "/" + assetFilePath);
  464. //Debug.Log("Searching Asset: [" + assetFilePath + "] of type: " + assetType);
  465. bool hasFileChanged = false;
  466. foreach (AssetRemappingRecord record in assetRecords)
  467. {
  468. if (assetDataFile.Contains(record.oldGuid))
  469. {
  470. hasFileChanged = true;
  471. assetDataFile = assetDataFile.Replace(record.oldGuid, record.newGuid);
  472. Debug.Log("Replacing old GUID: [" + record.oldGuid + "] by new GUID: [" + record.newGuid + "] in asset file: [" + assetFilePath + "].");
  473. }
  474. }
  475. if (hasFileChanged)
  476. {
  477. // Add file to list of changed files
  478. File.WriteAllText(projectPath + "/" + assetFilePath, assetDataFile);
  479. }
  480. }
  481. AssetDatabase.Refresh();
  482. // Restore project Asset Serialization and Source Control modes.
  483. RestoreProjectSerializationAndSourceControlModes();
  484. }
  485. private static void ExtractPackageGUIDs()
  486. {
  487. // Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
  488. SetProjectSerializationAndSourceControlModes();
  489. string projectPath = Path.GetFullPath("Assets/..");
  490. // Create new instance of AssetConversionData file
  491. AssetConversionData data = new AssetConversionData();
  492. data.assetRecords = new List<AssetConversionRecord>();
  493. // Get full list of GUIDs used in the package which including folders.
  494. string[] packageGUIDs = AssetDatabase.FindAssets("t:Object", new string[] { "Assets/Packages/com.unity.TextMeshPro" });
  495. for (int i = 0; i < packageGUIDs.Length; i++)
  496. {
  497. // Could add a progress bar for this process (if needed)
  498. string guid = packageGUIDs[i];
  499. string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
  500. //string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);
  501. //ObjectIdentifier[] localIdentifider = BundleBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(guid), BuildTarget.NoTarget);
  502. //System.Type[] types = BundleBuildInterface.GetTypeForObjects(localIdentifider);
  503. System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);
  504. // Filter out file types we are not interested in
  505. if (assetType == typeof(DefaultAsset))
  506. continue;
  507. string newGuid = GenerateUniqueGUID();
  508. AssetConversionRecord record;
  509. record.referencedResource = Path.GetFileName(assetFilePath);
  510. record.target = "fileID: 2108210716, guid: " + newGuid;
  511. record.replacement = "fileID: 11500000, guid: " + guid;
  512. //if (m_AssetRecords.FindIndex(item => item.oldGuid == guid) != -1)
  513. // continue;
  514. data.assetRecords.Add(record);
  515. // Read the meta file for the given asset.
  516. //string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);
  517. //assetMetaFile = assetMetaFile.Replace("guid: " + guid, "guid: " + newGUID);
  518. //File.WriteAllText(projectPath + "/" + assetMetaFilePath, assetMetaFile);
  519. Debug.Log("Asset: [" + Path.GetFileName(assetFilePath) + "] Type: " + assetType + " Current GUID: [" + guid + "] New GUID: [" + newGuid + "]");
  520. }
  521. // Write new information into JSON file
  522. string dataFile = JsonUtility.ToJson(data, true);
  523. File.WriteAllText(projectPath + "/Assets/Packages/com.unity.TextMeshPro/PackageConversionData.json", dataFile);
  524. // Restore project Asset Serialization and Source Control modes.
  525. RestoreProjectSerializationAndSourceControlModes();
  526. }
  527. /// <summary>
  528. ///
  529. /// </summary>
  530. private static void ConvertProjectGUIDsToUPM()
  531. {
  532. // Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
  533. SetProjectSerializationAndSourceControlModes();
  534. string projectPath = Path.GetFullPath("Assets/..");
  535. string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;
  536. // List containing assets that have been modified.
  537. List<AssetModificationRecord> modifiedAssetList = new List<AssetModificationRecord>();
  538. // Read Conversion Data from Json file.
  539. AssetConversionData conversionData = JsonUtility.FromJson<AssetConversionData>(File.ReadAllText(packageFullPath + "/PackageConversionData.json"));
  540. // Get list of GUIDs for assets that might contain references to previous GUIDs that require updating.
  541. string[] projectGUIDs = AssetDatabase.FindAssets("t:Object");
  542. for (int i = 0; i < projectGUIDs.Length; i++)
  543. {
  544. // Could add a progress bar for this process
  545. string guid = projectGUIDs[i];
  546. string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
  547. System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);
  548. // Filter out file types we are not interested in
  549. if (assetType == typeof(DefaultAsset) || assetType == typeof(MonoScript) || assetType == typeof(Texture2D) || assetType == typeof(TextAsset) || assetType == typeof(Shader))
  550. continue;
  551. // Read the asset data file
  552. string assetDataFile = File.ReadAllText(projectPath + "/" + assetFilePath);
  553. //Debug.Log("Searching Asset: [" + assetFilePath + "] of type: " + assetType);
  554. bool hasFileChanged = false;
  555. foreach (AssetConversionRecord record in conversionData.assetRecords)
  556. {
  557. if (assetDataFile.Contains(record.target))
  558. {
  559. hasFileChanged = true;
  560. assetDataFile = assetDataFile.Replace(record.target, record.replacement);
  561. Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetFilePath + "].");
  562. }
  563. }
  564. if (hasFileChanged)
  565. {
  566. Debug.Log("Adding [" + assetFilePath + "] to list of assets to be modified.");
  567. AssetModificationRecord modifiedAsset;
  568. modifiedAsset.assetFilePath = assetFilePath;
  569. modifiedAsset.assetDataFile = assetDataFile;
  570. modifiedAssetList.Add(modifiedAsset);
  571. }
  572. }
  573. // Scan project meta files to update GUIDs of assets whose GUID has changed.
  574. projectGUIDs = AssetDatabase.FindAssets("t:Object");
  575. for (int i = 0; i < projectGUIDs.Length; i++)
  576. {
  577. string guid = projectGUIDs[i];
  578. string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
  579. string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);
  580. // Read the asset meta data file
  581. string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);
  582. bool hasFileChanged = false;
  583. foreach (AssetConversionRecord record in conversionData.assetRecords)
  584. {
  585. if (assetMetaFile.Contains(record.target))
  586. {
  587. hasFileChanged = true;
  588. assetMetaFile = assetMetaFile.Replace(record.target, record.replacement);
  589. Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetMetaFilePath + "].");
  590. }
  591. }
  592. if (hasFileChanged)
  593. {
  594. Debug.Log("Adding [" + assetMetaFilePath + "] to list of meta files to be modified.");
  595. AssetModificationRecord modifiedAsset;
  596. modifiedAsset.assetFilePath = assetMetaFilePath;
  597. modifiedAsset.assetDataFile = assetMetaFile;
  598. modifiedAssetList.Add(modifiedAsset);
  599. }
  600. }
  601. // Display dialogue to show user a list of project files that will be modified upon their consent.
  602. if (EditorUtility.DisplayDialog("Save Modified Asset(s)?", "Are you sure you want to save all modified assets?", "YES", "NO"))
  603. {
  604. for (int i = 0; i < modifiedAssetList.Count; i++)
  605. {
  606. // Make sure all file streams that might have been opened by Unity are closed.
  607. //AssetDatabase.ReleaseCachedFileHandles();
  608. Debug.Log("Writing asset file [" + modifiedAssetList[i].assetFilePath + "].");
  609. //File.WriteAllText(projectPath + "/" + modifiedAssetList[i].assetFilePath, modifiedAssetList[i].assetDataFile);
  610. }
  611. }
  612. AssetDatabase.Refresh();
  613. // Restore project Asset Serialization and Source Control modes.
  614. RestoreProjectSerializationAndSourceControlModes();
  615. }
  616. /// <summary>
  617. ///
  618. /// </summary>
  619. /// <returns></returns>
  620. private static string GenerateUniqueGUID()
  621. {
  622. string monoGuid = System.Guid.NewGuid().ToString();
  623. char[] charGuid = new char[32];
  624. int index = 0;
  625. for (int i = 0; i < monoGuid.Length; i++)
  626. {
  627. if (monoGuid[i] != '-')
  628. charGuid[index++] = monoGuid[i];
  629. }
  630. string guid = new string(charGuid);
  631. // Make sure new GUID is not already used by some other asset.
  632. if (AssetDatabase.GUIDToAssetPath(guid) != string.Empty)
  633. guid = GenerateUniqueGUID();
  634. return guid;
  635. }
  636. /// <summary>
  637. /// Change project asset serialization mode to ForceText (if necessary)
  638. /// </summary>
  639. private static void SetProjectSerializationAndSourceControlModes()
  640. {
  641. // Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
  642. m_ProjectAssetSerializationMode = EditorSettings.serializationMode;
  643. if (m_ProjectAssetSerializationMode != SerializationMode.ForceText)
  644. UnityEditor.EditorSettings.serializationMode = SerializationMode.ForceText;
  645. m_ProjectExternalVersionControl = EditorSettings.externalVersionControl;
  646. if (m_ProjectExternalVersionControl != "Visible Meta Files")
  647. UnityEditor.EditorSettings.externalVersionControl = "Visible Meta Files";
  648. }
  649. /// <summary>
  650. /// Revert potential change to asset serialization mode (if necessary)
  651. /// </summary>
  652. private static void RestoreProjectSerializationAndSourceControlModes()
  653. {
  654. // Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
  655. if (m_ProjectAssetSerializationMode != EditorSettings.serializationMode)
  656. EditorSettings.serializationMode = m_ProjectAssetSerializationMode;
  657. if (m_ProjectExternalVersionControl != EditorSettings.externalVersionControl)
  658. EditorSettings.externalVersionControl = m_ProjectExternalVersionControl;
  659. }
  660. }
  661. }