MergeManagerPrefab.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. 
  2. namespace GitMerge
  3. {
  4. using UnityEngine;
  5. using UnityEditor;
  6. using System.Collections.Generic;
  7. using UnityEditor.SceneManagement;
  8. public class MergeManagerPrefab : MergeManagerBase
  9. {
  10. public static GameObject ourPrefab { private set; get; }
  11. private static GameObject theirPrefab;
  12. public static GameObject ourPrefabInstance { private set; get; }
  13. private static string previouslyOpenedScenePath;
  14. public MergeManagerPrefab(GitMergeWindow window, VCS vcs)
  15. : base(window, vcs)
  16. {
  17. }
  18. public bool TryInitializeMerge(string prefabPath)
  19. {
  20. if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
  21. {
  22. return false;
  23. }
  24. isMergingScene = false;
  25. MergeAction.inMergePhase = false;
  26. ObjectDictionaries.Clear();
  27. vcs.CheckoutOurs(prefabPath);
  28. CheckoutTheirVersionOf(prefabPath);
  29. AssetDatabase.Refresh();
  30. ourPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
  31. if (ourPrefab == null)
  32. {
  33. DeleteTheirPrefabAndLoadPreviousScene();
  34. return false;
  35. }
  36. // Open a new Scene that will only display the prefab.
  37. previouslyOpenedScenePath = EditorSceneManager.GetActiveScene().path;
  38. EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
  39. Lightmapping.ForceStop();
  40. // Instantiate our object in order to view it while merging.
  41. ourPrefabInstance = PrefabUtility.InstantiatePrefab(ourPrefab) as GameObject;
  42. // UI Elements need a Canvas to be displayed correctly:
  43. if (ourPrefabInstance.GetComponentInChildren<RectTransform>() != null) {
  44. GameObject defaultCanvas = new GameObject("Canvas");
  45. defaultCanvas.AddComponent<Canvas>().renderMode = RenderMode.ScreenSpaceOverlay;
  46. ourPrefabInstance.transform.SetParent(defaultCanvas.transform, false);
  47. }
  48. var ourObjects = GetAllObjects(ourPrefab);
  49. theirPrefab = AssetDatabase.LoadAssetAtPath(theirFilename, typeof(GameObject)) as GameObject;
  50. var theirObjects = GetAllObjects(theirPrefab);
  51. BuildAllMergeActions(ourObjects, theirObjects);
  52. AssetDatabase.DeleteAsset(theirFilename);
  53. if (allMergeActions.Count == 0)
  54. {
  55. DeleteTheirPrefabAndLoadPreviousScene();
  56. window.ShowNotification(new GUIContent("No conflict found for this prefab."));
  57. return false;
  58. }
  59. MergeAction.inMergePhase = true;
  60. ourPrefabInstance.Highlight();
  61. return true;
  62. }
  63. private static void DeleteTheirPrefabAndLoadPreviousScene()
  64. {
  65. AssetDatabase.DeleteAsset(theirFilename);
  66. OpenPreviousScene();
  67. }
  68. /// <summary>
  69. /// Recursively find all GameObjects that are part of the prefab
  70. /// </summary>
  71. /// <param name="prefab">The prefab to analyze</param>
  72. /// <param name="list">The list with all the objects already found. Pass null in the beginning.</param>
  73. /// <returns>The list with all the objects</returns>
  74. private static List<GameObject> GetAllObjects(GameObject prefab, List<GameObject> list = null)
  75. {
  76. if (list == null)
  77. {
  78. list = new List<GameObject>();
  79. }
  80. list.Add(prefab);
  81. foreach (Transform t in prefab.transform)
  82. {
  83. GetAllObjects(t.gameObject, list);
  84. }
  85. return list;
  86. }
  87. /// <summary>
  88. /// Completes the merge process after solving all conflicts.
  89. /// Cleans up the scene by deleting "their" GameObjects, clears merge related data structures,
  90. /// executes git add scene_name.
  91. /// </summary>
  92. public override void CompleteMerge()
  93. {
  94. MergeAction.inMergePhase = false;
  95. // ObjectDictionaries.Clear();
  96. allMergeActions = null;
  97. // TODO: Could we explicitly just save the prefab?
  98. AssetDatabase.SaveAssets();
  99. vcs.MarkAsMerged(fileName);
  100. // Directly committing here might not be that smart, since there might be more conflicts.
  101. ourPrefab = null;
  102. DeleteTheirPrefabAndLoadPreviousScene();
  103. window.ShowNotification(new GUIContent("Prefab successfully merged."));
  104. }
  105. /// <summary>
  106. /// Aborts merge by using "our" version in all conflicts.
  107. /// Cleans up merge related data.
  108. /// </summary>
  109. public override void AbortMerge(bool showNotification = true)
  110. {
  111. base.AbortMerge(showNotification);
  112. DeleteTheirPrefabAndLoadPreviousScene();
  113. ourPrefab = null;
  114. }
  115. /// <summary>
  116. /// Opens the previously opened scene, if there was any.
  117. /// </summary>
  118. private static void OpenPreviousScene()
  119. {
  120. if (!string.IsNullOrEmpty(previouslyOpenedScenePath))
  121. {
  122. EditorSceneManager.OpenScene(previouslyOpenedScenePath);
  123. previouslyOpenedScenePath = null;
  124. }
  125. }
  126. }
  127. }