MergeActionChangeValues.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. 
  2. namespace GitMerge
  3. {
  4. using UnityEngine;
  5. using UnityEditor;
  6. using System.Linq;
  7. /// <summary>
  8. /// The MergeAction allowing to merge the value of a single property of a Component.
  9. /// </summary>
  10. public class MergeActionChangeValues : MergeAction
  11. {
  12. protected SerializedProperty ourProperty;
  13. protected SerializedProperty theirProperty;
  14. protected object ourInitialValue;
  15. protected object theirInitialValue;
  16. protected readonly string ourString;
  17. protected readonly string theirString;
  18. protected readonly string fieldname;
  19. public MergeActionChangeValues(GameObject ours, SerializedProperty ourProperty, SerializedProperty theirProperty)
  20. : base(ours, null)
  21. {
  22. this.ourProperty = ourProperty;
  23. this.theirProperty = theirProperty;
  24. fieldname = ourProperty.serializedObject.targetObject.GetPlainType() + "." + ourProperty.GetPlainName();
  25. ourInitialValue = ourProperty.GetValue();
  26. theirInitialValue = theirProperty.GetValue();
  27. ourString = SerializedValueString(ourProperty);
  28. theirString = SerializedValueString(theirProperty);
  29. }
  30. protected override void ApplyOurs()
  31. {
  32. ourProperty.SetValue(ourInitialValue);
  33. ourProperty.serializedObject.ApplyModifiedProperties();
  34. }
  35. protected override void ApplyTheirs()
  36. {
  37. var value = theirInitialValue;
  38. //If we're about references here, get "our" version of the object.
  39. if (ourProperty.propertyType == SerializedPropertyType.ObjectReference)
  40. {
  41. var id = ObjectID.GetFor(theirInitialValue as Object);
  42. var obj = ObjectDictionaries.GetOurObject(id);
  43. //If we didn't have our own version of the object before, it must be new
  44. if (!obj)
  45. {
  46. //Get our copy of the new object if it exists
  47. obj = ObjectDictionaries.GetOurInstanceOfCopy(value as Object);
  48. }
  49. value = obj;
  50. }
  51. ourProperty.SetValue(value);
  52. ourProperty.serializedObject.ApplyModifiedProperties();
  53. }
  54. public override void OnGUI()
  55. {
  56. GUILayout.BeginVertical();
  57. GUILayout.Label(fieldname + ": " + ourProperty.propertyType);
  58. GUILayout.BeginHorizontal();
  59. GUILayout.BeginVertical();
  60. GUILayout.Label(ourString, GUILayout.Width(100));
  61. DisplayArray(ourInitialValue);
  62. GUILayout.EndVertical();
  63. if (MergeButton(">>>", usingOurs))
  64. {
  65. UseOurs();
  66. }
  67. var c = GUI.backgroundColor;
  68. GUI.backgroundColor = Color.white;
  69. //GUILayout.Label(ourProperty.propertyType + "/" + ourProperty.type + ": " + ourProperty.GetValue());
  70. PropertyField(ourProperty);
  71. GUI.backgroundColor = c;
  72. if (MergeButton("<<<", usingTheirs))
  73. {
  74. UseTheirs();
  75. }
  76. GUILayout.BeginVertical();
  77. GUILayout.Label(theirString, GUILayout.Width(100));
  78. DisplayArray(theirInitialValue);
  79. GUILayout.EndVertical();
  80. GUILayout.EndHorizontal();
  81. GUILayout.EndVertical();
  82. }
  83. private void DisplayArray(object value)
  84. {
  85. if (ourProperty.IsRealArray() && ourProperty.isExpanded)
  86. {
  87. var values = (object[])value;
  88. for (int i = 0; i < values.Length; ++i)
  89. {
  90. GUILayout.Label(ValueString(values[i]), GUILayout.Width(100));
  91. }
  92. }
  93. }
  94. /// <summary>
  95. /// Displays the property field in the center of the window.
  96. /// This method distinguishes between certain properties.
  97. /// The GameObject tag, for example, shouldn't be displayed with a regular string field.
  98. /// </summary>
  99. /// <param name="p">The SerializedProerty to display</param>
  100. /// <param name="width">The width of the whole thing in the ui</param>
  101. private void PropertyField(SerializedProperty p, float width = 170)
  102. {
  103. if (p.IsRealArray())
  104. {
  105. DisplayArrayProperty(p, width);
  106. }
  107. else
  108. {
  109. var oldValue = p.GetValue();
  110. if (fieldname == "GameObject.TagString")
  111. {
  112. var oldTag = oldValue as string;
  113. var newTag = EditorGUILayout.TagField("", oldTag, GUILayout.Width(width));
  114. if (newTag != oldTag)
  115. {
  116. p.SetValue(newTag);
  117. }
  118. }
  119. else if (fieldname == "GameObject.StaticEditorFlags")
  120. {
  121. DisplayStaticFlagChooser(p, width);
  122. }
  123. else
  124. {
  125. EditorGUILayout.PropertyField(p, new GUIContent(""), GUILayout.Width(width));
  126. }
  127. if (!object.Equals(p.GetValue(), oldValue))
  128. {
  129. p.serializedObject.ApplyModifiedProperties();
  130. UsedNew();
  131. }
  132. }
  133. }
  134. private void DisplayArrayProperty(SerializedProperty p, float width)
  135. {
  136. GUILayout.BeginVertical();
  137. GUILayout.BeginHorizontal(GUILayout.Width(170));
  138. EditorGUILayout.PropertyField(p, new GUIContent("Array"), GUILayout.Width(80));
  139. if (p.isExpanded)
  140. {
  141. var copy = p.Copy();
  142. var size = copy.arraySize;
  143. copy.Next(true);
  144. copy.Next(true);
  145. PropertyField(copy, 70);
  146. GUILayout.EndHorizontal();
  147. for (int i = 0; i < size; ++i)
  148. {
  149. copy.Next(false);
  150. PropertyField(copy);
  151. }
  152. }
  153. else
  154. {
  155. GUILayout.EndHorizontal();
  156. }
  157. GUILayout.EndVertical();
  158. }
  159. /// <summary>
  160. /// Displays Toggles that let the user set the static flags of the object.
  161. /// </summary>
  162. /// <param name="p">The StaticEditorFlags SerializedProperty to display</param>
  163. /// <param name="width">The width of the whole thing in the ui</param>
  164. private void DisplayStaticFlagChooser(SerializedProperty p, float width)
  165. {
  166. var flags = (StaticEditorFlags)p.intValue;
  167. GUILayout.BeginVertical(GUILayout.Width(width));
  168. p.isExpanded = EditorGUILayout.Foldout(p.isExpanded, SerializedValueString(p));
  169. var allOn = true;
  170. if (p.isExpanded)
  171. {
  172. foreach (var flag in System.Enum.GetValues(typeof(StaticEditorFlags)).Cast<StaticEditorFlags>())
  173. {
  174. var wasOn = (flags & flag) != 0;
  175. var on = EditorGUILayout.Toggle(flag + "", wasOn);
  176. if (wasOn != on)
  177. {
  178. flags = flags ^ flag;
  179. }
  180. if (!on)
  181. {
  182. allOn = false;
  183. }
  184. }
  185. }
  186. if (allOn)
  187. {
  188. flags = (StaticEditorFlags)(-1);
  189. }
  190. p.intValue = (int)flags;
  191. GUILayout.EndVertical();
  192. }
  193. private string SerializedValueString(SerializedProperty p)
  194. {
  195. if (fieldname == "GameObject.StaticEditorFlags")
  196. {
  197. switch (p.intValue)
  198. {
  199. case 0:
  200. return "Not static";
  201. case -1:
  202. return "Static";
  203. default:
  204. return "Mixed static";
  205. }
  206. }
  207. else if (p.IsRealArray())
  208. {
  209. return "Array[" + p.arraySize + "]";
  210. }
  211. return ValueString(p.GetValue());
  212. }
  213. private static string ValueString(object o)
  214. {
  215. if (o == null)
  216. {
  217. return "[none]";
  218. }
  219. return o.ToString();
  220. }
  221. private static bool MergeButton(string text, bool green)
  222. {
  223. if (green)
  224. {
  225. GUI.color = Color.green;
  226. }
  227. bool result = GUILayout.Button(text, GUILayout.ExpandWidth(false));
  228. GUI.color = Color.white;
  229. return result;
  230. }
  231. }
  232. }