ObjectDictionaries.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. 
  2. namespace GitMerge
  3. {
  4. using UnityEngine;
  5. using System.Collections.Generic;
  6. /// <summary>
  7. /// Dictionaries that categorize the scene's objects into our objects, their objects, and temporary
  8. /// copies of their objects that have been instantiated while merging.
  9. /// </summary>
  10. public static class ObjectDictionaries
  11. {
  12. // This dict holds all of "our" objects.
  13. // Needed for Reference handling.
  14. private static Dictionary<ObjectID, Object> ourObjects = new Dictionary<ObjectID, Object>();
  15. // This dict maps our instances of their objects.
  16. // Whenever we instantiate a copy of "their" new object, they're both added here.
  17. private static Dictionary<Object, Object> ourInstances = new Dictionary<Object, Object>();
  18. // This dict holds all of "their" GameObjects.
  19. // Needed for scene cleaning after merge.
  20. // <GameObject, originallyActive>
  21. private static Dictionary<GameObject, bool> theirObjects = new Dictionary<GameObject, bool>();
  22. // This dict holds all GameObjects that might or might not exist,
  23. // depending on the current merge state. The referenced objects are the versions that will definitely exist throughout the merge.
  24. // Also maps the MergeActions responsible for their existence to them.
  25. private static Dictionary<GameObject, MergeActionExistence> schroedingersObjects = new Dictionary<GameObject, MergeActionExistence>();
  26. public static void AddToOurObjects(List<GameObject> objects)
  27. {
  28. foreach (var obj in objects)
  29. {
  30. SetAsOurObject(obj);
  31. }
  32. }
  33. public static void AddToTheirObjects(List<GameObject> objects)
  34. {
  35. foreach (var obj in objects)
  36. {
  37. SetAsTheirs(obj, false);
  38. }
  39. }
  40. public static void SetAsOurObject(GameObject go)
  41. {
  42. AddOurObject(go);
  43. foreach (var c in go.GetComponents<Component>())
  44. {
  45. AddOurObject(c);
  46. }
  47. }
  48. public static void SetAsOurObject(Component c)
  49. {
  50. AddOurObject(c);
  51. }
  52. private static void AddOurObject(Object o)
  53. {
  54. if (o == null)
  55. return;
  56. ourObjects.Add(ObjectID.GetFor(o), o);
  57. }
  58. public static void RemoveOurObject(GameObject go)
  59. {
  60. foreach (var c in go.GetComponents<Component>())
  61. {
  62. RemoveOurSingleObject(c);
  63. }
  64. RemoveOurSingleObject(go);
  65. }
  66. public static void RemoveOurObject(Component c)
  67. {
  68. RemoveOurSingleObject(c);
  69. }
  70. private static void RemoveOurSingleObject(Object o)
  71. {
  72. if (o == null)
  73. return;
  74. ourObjects.Remove(ObjectID.GetFor(o));
  75. }
  76. public static Object GetOurObject(ObjectID id)
  77. {
  78. Object result = null;
  79. ourObjects.TryGetValue(id, out result);
  80. return result;
  81. }
  82. /// <summary>
  83. /// Returns:
  84. /// * the given object if it is "ours"
  85. /// * "our" counterpart of obj if it is "theirs"
  86. /// * null if the object is deleted for some reason
  87. /// The returned object can be an instance of "their" object temporarily added for the merge
  88. /// </summary>
  89. /// <param name="obj">the original object</param>
  90. /// <returns>the counterpart of the object in "our" version</returns>
  91. public static Object GetOurCounterpartFor(Object obj)
  92. {
  93. var result = obj;
  94. if (IsTheirs(obj))
  95. {
  96. result = GetOurObject(ObjectID.GetFor(obj));
  97. if (!result)
  98. {
  99. result = GetOurInstanceOfCopy(obj);
  100. }
  101. }
  102. return result;
  103. }
  104. public static void Clear()
  105. {
  106. ourObjects.Clear();
  107. theirObjects.Clear();
  108. ourInstances.Clear();
  109. schroedingersObjects.Clear();
  110. }
  111. /// <summary>
  112. /// Mark o as an instance of theirs
  113. /// </summary>
  114. public static void SetAsCopy(GameObject o, GameObject theirs)
  115. {
  116. ourInstances.Add(theirs, o);
  117. var instanceComponents = o.GetComponents<Component>();
  118. var theirComponents = theirs.GetComponents<Component>();
  119. for (int i = 0; i < instanceComponents.Length; ++i)
  120. {
  121. SetAsCopy(instanceComponents[i], theirComponents[i]);
  122. }
  123. }
  124. public static void SetAsCopy(Component c, Component theirs)
  125. {
  126. if (c == null)
  127. return;
  128. ourInstances.Add(theirs, c);
  129. }
  130. public static void RemoveCopyOf(GameObject theirs)
  131. {
  132. ourInstances.Remove(theirs);
  133. foreach (var c in theirs.GetComponents<Component>())
  134. {
  135. if (c != null)
  136. {
  137. ourInstances.Remove(c);
  138. }
  139. }
  140. }
  141. public static void RemoveCopyOf(Component theirs)
  142. {
  143. ourInstances.Remove(theirs);
  144. }
  145. /// <summary>
  146. /// Returns:
  147. /// * the given object if it is "ours"
  148. /// * "our" instance of obj if it is "theirs"
  149. /// * null if there is no such instance
  150. /// </summary>
  151. /// <param name="obj">the original object</param>
  152. /// <returns>the instance of the original object</returns>
  153. public static Object GetOurInstanceOfCopy(Object obj)
  154. {
  155. var result = obj;
  156. if (IsTheirs(obj))
  157. {
  158. ourInstances.TryGetValue(obj, out result);
  159. }
  160. return result;
  161. }
  162. private static bool IsTheirs(Object obj)
  163. {
  164. var go = obj as GameObject;
  165. if (go)
  166. {
  167. return theirObjects.ContainsKey(go);
  168. }
  169. var c = obj as Component;
  170. if (c)
  171. {
  172. return theirObjects.ContainsKey(c.gameObject);
  173. }
  174. return false;
  175. }
  176. public static void SetAsTheirs(GameObject go, bool active)
  177. {
  178. if (!theirObjects.ContainsKey(go))
  179. {
  180. theirObjects.Add(go, go.activeSelf);
  181. }
  182. go.SetActiveForMerging(false);
  183. }
  184. /// <summary>
  185. /// Copy an object that has been disabled and hidden for merging into the scene,
  186. /// enable and unhide the copy.
  187. /// </summary>
  188. /// <param name="go">The original GameObject.</param>
  189. /// <returns>The copy GameObject.</returns>
  190. public static GameObject InstantiateFromMerging(GameObject go)
  191. {
  192. var copy = GameObject.Instantiate(go) as GameObject;
  193. // Destroy children.
  194. foreach (Transform t in copy.GetComponent<Transform>())
  195. {
  196. Object.DestroyImmediate(t.gameObject);
  197. }
  198. bool wasActive;
  199. if (!theirObjects.TryGetValue(go, out wasActive))
  200. {
  201. wasActive = go.activeSelf;
  202. }
  203. // Apply some special properties of the GameObject.
  204. copy.SetActive(wasActive);
  205. copy.hideFlags = HideFlags.None;
  206. copy.name = go.name;
  207. copy.GetComponent<Transform>().parent = GetOurCounterpartFor(go.GetComponent<Transform>().parent) as Transform;
  208. return copy;
  209. }
  210. public static void DestroyTheirObjects()
  211. {
  212. foreach (var obj in theirObjects.Keys)
  213. {
  214. if (obj != null && obj.transform.parent == null)
  215. {
  216. Object.DestroyImmediate(obj);
  217. }
  218. }
  219. theirObjects.Clear();
  220. }
  221. public static void AddToSchroedingersObjects(GameObject go, MergeActionExistence mergeAction)
  222. {
  223. schroedingersObjects.Add(go, mergeAction);
  224. }
  225. public static void EnsureExistence(GameObject go)
  226. {
  227. schroedingersObjects[go].EnsureExistence();
  228. }
  229. }
  230. }