MergeActionChangeValues.cs 8.7 KB

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