CollabToolbarButton.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor.Collaboration;
  5. using UnityEditor.Connect;
  6. using UnityEditor.Web;
  7. using UnityEngine;
  8. namespace UnityEditor
  9. {
  10. internal class CollabToolbarButton : SubToolbar, IDisposable
  11. {
  12. // Must match s_CollabIcon array
  13. enum CollabToolbarState
  14. {
  15. NeedToEnableCollab,
  16. UpToDate,
  17. Conflict,
  18. OperationError,
  19. ServerHasChanges,
  20. FilesToPush,
  21. InProgress,
  22. Disabled,
  23. Offline
  24. }
  25. private class CollabToolbarContent
  26. {
  27. readonly string m_iconName;
  28. readonly string m_toolTip;
  29. readonly CollabToolbarState m_state;
  30. static Dictionary<CollabToolbarContent, GUIContent> m_CollabIcons;
  31. public CollabToolbarState RegisteredForState
  32. {
  33. get { return m_state; }
  34. }
  35. public GUIContent GuiContent
  36. {
  37. get
  38. {
  39. if (m_CollabIcons == null)
  40. {
  41. m_CollabIcons = new Dictionary<CollabToolbarContent, GUIContent>();
  42. }
  43. if (!m_CollabIcons.ContainsKey(this))
  44. {
  45. m_CollabIcons.Add(this, EditorGUIUtility.TrTextContentWithIcon("Collab", m_toolTip, m_iconName));
  46. }
  47. return m_CollabIcons[this];
  48. }
  49. }
  50. public CollabToolbarContent(CollabToolbarState state, string iconName, string toolTip)
  51. {
  52. m_state = state;
  53. m_iconName = iconName;
  54. m_toolTip = toolTip;
  55. }
  56. }
  57. CollabToolbarContent[] m_toolbarContents;
  58. CollabToolbarState m_CollabToolbarState = CollabToolbarState.UpToDate;
  59. const float kCollabButtonWidth = 78.0f;
  60. ButtonWithAnimatedIconRotation m_CollabButton;
  61. string m_DynamicTooltip;
  62. static bool m_ShowCollabTooltip = false;
  63. private GUIContent currentCollabContent
  64. {
  65. get
  66. {
  67. CollabToolbarContent toolbarContent =
  68. m_toolbarContents.FirstOrDefault(c => c.RegisteredForState.Equals(m_CollabToolbarState));
  69. GUIContent content = new GUIContent(toolbarContent == null? m_toolbarContents.First().GuiContent : toolbarContent.GuiContent);
  70. if (!m_ShowCollabTooltip)
  71. {
  72. content.tooltip = null;
  73. }
  74. else if (m_DynamicTooltip != "")
  75. {
  76. content.tooltip = m_DynamicTooltip;
  77. }
  78. if (Collab.instance.AreTestsRunning())
  79. {
  80. content.text = "CTF";
  81. }
  82. return content;
  83. }
  84. }
  85. public CollabToolbarButton()
  86. {
  87. m_toolbarContents = new[]
  88. {
  89. new CollabToolbarContent(CollabToolbarState.NeedToEnableCollab, "CollabNew", " You need to enable collab."),
  90. new CollabToolbarContent(CollabToolbarState.UpToDate, "Collab", " You are up to date."),
  91. new CollabToolbarContent(CollabToolbarState.Conflict, "CollabConflict", " Please fix your conflicts prior to publishing."),
  92. new CollabToolbarContent(CollabToolbarState.OperationError, "CollabError", " Last operation failed. Please retry later."),
  93. new CollabToolbarContent(CollabToolbarState.ServerHasChanges, "CollabPull", " Please update, there are server changes."),
  94. new CollabToolbarContent(CollabToolbarState.FilesToPush, "CollabPush", " You have files to publish."),
  95. new CollabToolbarContent(CollabToolbarState.InProgress, "CollabProgress", " Operation in progress."),
  96. new CollabToolbarContent(CollabToolbarState.Disabled, "CollabNew", " Collab is disabled."),
  97. new CollabToolbarContent(CollabToolbarState.Offline, "CollabNew", " Please check your network connection.")
  98. };
  99. Collab.instance.StateChanged += OnCollabStateChanged;
  100. UnityConnect.instance.StateChanged += OnUnityConnectStateChanged;
  101. UnityConnect.instance.UserStateChanged += OnUnityConnectUserStateChanged;
  102. }
  103. void OnUnityConnectUserStateChanged(UserInfo state)
  104. {
  105. UpdateCollabToolbarState();
  106. }
  107. void OnUnityConnectStateChanged(ConnectInfo state)
  108. {
  109. UpdateCollabToolbarState();
  110. }
  111. public override void OnGUI(Rect rect)
  112. {
  113. DoCollabDropDown(rect);
  114. }
  115. Rect GUIToScreenRect(Rect guiRect)
  116. {
  117. Vector2 screenPoint = GUIUtility.GUIToScreenPoint(new Vector2(guiRect.x, guiRect.y));
  118. guiRect.x = screenPoint.x;
  119. guiRect.y = screenPoint.y;
  120. return guiRect;
  121. }
  122. void ShowPopup(Rect rect)
  123. {
  124. // window should be centered on the button
  125. ReserveRight(kCollabButtonWidth / 2, ref rect);
  126. ReserveBottom(5, ref rect);
  127. // calculate screen rect before saving assets since it might open the AssetSaveDialog window
  128. var screenRect = GUIToScreenRect(rect);
  129. // save all the assets
  130. AssetDatabase.SaveAssets();
  131. if (Collab.ShowToolbarAtPosition != null && Collab.ShowToolbarAtPosition(screenRect))
  132. {
  133. GUIUtility.ExitGUI();
  134. }
  135. }
  136. void DoCollabDropDown(Rect rect)
  137. {
  138. UpdateCollabToolbarState();
  139. GUIStyle collabButtonStyle = "OffsetDropDown";
  140. bool showPopup = Toolbar.requestShowCollabToolbar;
  141. Toolbar.requestShowCollabToolbar = false;
  142. bool enable = !EditorApplication.isPlaying;
  143. using (new EditorGUI.DisabledScope(!enable))
  144. {
  145. bool animate = m_CollabToolbarState == CollabToolbarState.InProgress;
  146. EditorGUIUtility.SetIconSize(new Vector2(12, 12));
  147. if (GetCollabButton().OnGUI(rect, currentCollabContent, animate, collabButtonStyle))
  148. {
  149. showPopup = true;
  150. }
  151. EditorGUIUtility.SetIconSize(Vector2.zero);
  152. }
  153. if (m_CollabToolbarState == CollabToolbarState.Disabled)
  154. return;
  155. if (showPopup)
  156. {
  157. ShowPopup(rect);
  158. }
  159. }
  160. public void OnCollabStateChanged(CollabInfo info)
  161. {
  162. UpdateCollabToolbarState();
  163. }
  164. public void UpdateCollabToolbarState()
  165. {
  166. var currentCollabState = CollabToolbarState.UpToDate;
  167. bool networkAvailable = UnityConnect.instance.connectInfo.online && UnityConnect.instance.connectInfo.loggedIn;
  168. m_DynamicTooltip = "";
  169. if (UnityConnect.instance.isDisableCollabWindow)
  170. {
  171. currentCollabState = CollabToolbarState.Disabled;
  172. }
  173. else if (networkAvailable)
  174. {
  175. Collab collab = Collab.instance;
  176. CollabInfo currentInfo = collab.collabInfo;
  177. UnityErrorInfo errInfo;
  178. bool error = false;
  179. if (collab.GetError((UnityConnect.UnityErrorFilter.ByContext | UnityConnect.UnityErrorFilter.ByChild), out errInfo))
  180. {
  181. error = (errInfo.priority <= (int)UnityConnect.UnityErrorPriority.Error);
  182. m_DynamicTooltip = errInfo.shortMsg;
  183. }
  184. if (!currentInfo.ready)
  185. {
  186. currentCollabState = CollabToolbarState.InProgress;
  187. }
  188. else if (error)
  189. {
  190. currentCollabState = CollabToolbarState.OperationError;
  191. }
  192. else if (currentInfo.inProgress)
  193. {
  194. currentCollabState = CollabToolbarState.InProgress;
  195. }
  196. else
  197. {
  198. bool collabEnable = Collab.instance.IsCollabEnabledForCurrentProject();
  199. if (UnityConnect.instance.projectInfo.projectBound == false || !collabEnable)
  200. {
  201. currentCollabState = CollabToolbarState.NeedToEnableCollab;
  202. }
  203. else if (currentInfo.update)
  204. {
  205. currentCollabState = CollabToolbarState.ServerHasChanges;
  206. }
  207. else if (currentInfo.conflict)
  208. {
  209. currentCollabState = CollabToolbarState.Conflict;
  210. }
  211. else if (currentInfo.publish)
  212. {
  213. currentCollabState = CollabToolbarState.FilesToPush;
  214. }
  215. }
  216. }
  217. else
  218. {
  219. currentCollabState = CollabToolbarState.Offline;
  220. }
  221. if (Collab.IsToolbarVisible != null)
  222. {
  223. if (currentCollabState != m_CollabToolbarState ||
  224. Collab.IsToolbarVisible() == m_ShowCollabTooltip)
  225. {
  226. m_CollabToolbarState = currentCollabState;
  227. m_ShowCollabTooltip = !Collab.IsToolbarVisible();
  228. Toolbar.RepaintToolbar();
  229. }
  230. }
  231. }
  232. void ReserveRight(float width, ref Rect pos)
  233. {
  234. pos.x += width;
  235. }
  236. void ReserveBottom(float height, ref Rect pos)
  237. {
  238. pos.y += height;
  239. }
  240. ButtonWithAnimatedIconRotation GetCollabButton()
  241. {
  242. if (m_CollabButton == null)
  243. {
  244. const int repaintsPerSecond = 20;
  245. const float animSpeed = 500f;
  246. const bool mouseDownButton = true;
  247. m_CollabButton = new ButtonWithAnimatedIconRotation(() => (float)EditorApplication.timeSinceStartup * animSpeed, Toolbar.RepaintToolbar, repaintsPerSecond, mouseDownButton);
  248. }
  249. return m_CollabButton;
  250. }
  251. public void Dispose()
  252. {
  253. Collab.instance.StateChanged -= OnCollabStateChanged;
  254. UnityConnect.instance.StateChanged -= OnUnityConnectStateChanged;
  255. UnityConnect.instance.UserStateChanged -= OnUnityConnectUserStateChanged;
  256. if (m_CollabButton != null)
  257. m_CollabButton.Clear();
  258. }
  259. }
  260. } // namespace