TMP_PackageUtilities.cs 35 KB

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