MergeManagerScene.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. 
  2. namespace GitMerge
  3. {
  4. using UnityEngine;
  5. using UnityEditor;
  6. using UnityEngine.SceneManagement;
  7. using UnityEditor.SceneManagement;
  8. using System.Collections.Generic;
  9. using Object = UnityEngine.Object;
  10. public class MergeManagerScene : MergeManagerBase
  11. {
  12. private const int NUMBER_OF_INITIALIZATION_STEPS = 3;
  13. private Scene theirScene;
  14. public MergeManagerScene(GitMergeWindow window, VCS vcs)
  15. : base(window, vcs)
  16. {
  17. }
  18. public bool TryInitializeMerge(string path = null)
  19. {
  20. var activeScene = EditorSceneManager.GetActiveScene();
  21. if (activeScene.isDirty)
  22. {
  23. window.ShowNotification(new GUIContent("Please make sure there are no unsaved changes before attempting to merge."));
  24. return false;
  25. }
  26. DisplayProgressBar(0, "Checking out scene...");
  27. isMergingScene = true;
  28. var scenePath = path ?? activeScene.path;
  29. // Overwrite the current scene to prevent the reload/ignore dialog that pops up after the upcoming changes to the file.
  30. // Pressing "reload" on it would invalidate the GameObject references we're about to collect.
  31. EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
  32. Lightmapping.ForceStop();
  33. vcs.CheckoutOurs(scenePath);
  34. CheckoutTheirVersionOf(scenePath);
  35. AssetDatabase.Refresh();
  36. DisplayProgressBar(1, "Opening scene...");
  37. activeScene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single);
  38. MergeAction.inMergePhase = false;
  39. ObjectDictionaries.Clear();
  40. List<GameObject> ourObjects;
  41. try
  42. {
  43. DisplayProgressBar(2, "Collecting differences...");
  44. // Find all of "our" objects
  45. ourObjects = GetAllSceneObjects();
  46. ObjectDictionaries.AddToOurObjects(ourObjects);
  47. // Add "their" objects
  48. theirScene = EditorSceneManager.OpenScene(theirFilename, OpenSceneMode.Additive);
  49. var addedObjects = GetAllNewSceneObjects(ourObjects);
  50. BuildAllMergeActions(ourObjects, addedObjects);
  51. ObjectDictionaries.AddToTheirObjects(addedObjects);
  52. MoveGameObjectsToScene(theirScene.GetRootGameObjects(), activeScene);
  53. }
  54. finally
  55. {
  56. EditorSceneManager.UnloadSceneAsync(theirScene);
  57. AssetDatabase.DeleteAsset(theirFilename);
  58. EditorUtility.ClearProgressBar();
  59. }
  60. if (allMergeActions.Count == 0)
  61. {
  62. window.ShowNotification(new GUIContent("No conflict found for this scene."));
  63. return false;
  64. }
  65. MergeAction.inMergePhase = true;
  66. return true;
  67. }
  68. private static void DisplayProgressBar(int step, string text)
  69. {
  70. var progress = step / (float)NUMBER_OF_INITIALIZATION_STEPS;
  71. EditorUtility.DisplayProgressBar("GitMerge for Unity", text, progress);
  72. }
  73. private static void MoveGameObjectsToScene(IEnumerable<GameObject> addedObjects, Scene scene)
  74. {
  75. foreach (var obj in addedObjects)
  76. {
  77. EditorSceneManager.MoveGameObjectToScene(obj, scene);
  78. }
  79. }
  80. private static List<GameObject> GetAllSceneObjects()
  81. {
  82. var objects = (GameObject[])Object.FindObjectsOfType(typeof(GameObject));
  83. return new List<GameObject>(objects);
  84. }
  85. /// <summary>
  86. /// Finds all GameObjects in the scene, minus the ones passed.
  87. /// </summary>
  88. private static List<GameObject> GetAllNewSceneObjects(List<GameObject> oldObjects)
  89. {
  90. var all = GetAllSceneObjects();
  91. foreach (var obj in oldObjects)
  92. {
  93. all.Remove(obj);
  94. }
  95. return all;
  96. }
  97. /// <summary>
  98. /// Completes the merge process after solving all conflicts.
  99. /// Cleans up the scene by deleting "their" GameObjects, clears merge related data structures,
  100. /// executes git add scene_name.
  101. /// </summary>
  102. public override void CompleteMerge()
  103. {
  104. MergeAction.inMergePhase = false;
  105. ObjectDictionaries.DestroyTheirObjects();
  106. ObjectDictionaries.Clear();
  107. EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
  108. allMergeActions = null;
  109. vcs.MarkAsMerged(fileName);
  110. // Directly committing here might not be that smart, since there might be more conflicts
  111. window.ShowNotification(new GUIContent("Scene successfully merged."));
  112. }
  113. /// <summary>
  114. /// Aborts merge by using "our" version in all conflicts.
  115. /// Cleans up merge related data.
  116. /// </summary>
  117. public override void AbortMerge(bool showNotification = true)
  118. {
  119. base.AbortMerge(showNotification);
  120. EditorSceneManager.CloseScene(theirScene, true);
  121. EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
  122. }
  123. }
  124. }