TMP_PackageUtilities.cs 35 KB

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