DebugLogPopup.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using UnityEngine.EventSystems;
  4. using System.Collections;
  5. // Manager class for the debug popup
  6. namespace IngameDebugConsole
  7. {
  8. public class DebugLogPopup : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler
  9. {
  10. private RectTransform popupTransform;
  11. // Dimensions of the popup divided by 2
  12. private Vector2 halfSize;
  13. // Background image that will change color to indicate an alert
  14. private Image backgroundImage;
  15. // Canvas group to modify visibility of the popup
  16. private CanvasGroup canvasGroup;
  17. #pragma warning disable 0649
  18. [SerializeField]
  19. private DebugLogManager debugManager;
  20. [SerializeField]
  21. private Text newInfoCountText;
  22. [SerializeField]
  23. private Text newWarningCountText;
  24. [SerializeField]
  25. private Text newErrorCountText;
  26. [SerializeField]
  27. private Color alertColorInfo;
  28. [SerializeField]
  29. private Color alertColorWarning;
  30. [SerializeField]
  31. private Color alertColorError;
  32. #pragma warning restore 0649
  33. // Number of new debug entries since the log window has been closed
  34. private int newInfoCount = 0, newWarningCount = 0, newErrorCount = 0;
  35. private Color normalColor;
  36. private bool isPopupBeingDragged = false;
  37. private Vector2 normalizedPosition;
  38. // Coroutines for simple code-based animations
  39. private IEnumerator moveToPosCoroutine = null;
  40. private void Awake()
  41. {
  42. popupTransform = (RectTransform) transform;
  43. backgroundImage = GetComponent<Image>();
  44. canvasGroup = GetComponent<CanvasGroup>();
  45. normalColor = backgroundImage.color;
  46. halfSize = popupTransform.sizeDelta * 0.5f;
  47. Vector2 pos = popupTransform.anchoredPosition;
  48. if( pos.x != 0f || pos.y != 0f )
  49. normalizedPosition = pos.normalized; // Respect the initial popup position set in the prefab
  50. else
  51. normalizedPosition = new Vector2( 0.5f, 0f ); // Right edge by default
  52. }
  53. public void NewLogsArrived( int newInfo, int newWarning, int newError )
  54. {
  55. if( newInfo > 0 )
  56. {
  57. newInfoCount += newInfo;
  58. newInfoCountText.text = newInfoCount.ToString();
  59. }
  60. if( newWarning > 0 )
  61. {
  62. newWarningCount += newWarning;
  63. newWarningCountText.text = newWarningCount.ToString();
  64. }
  65. if( newError > 0 )
  66. {
  67. newErrorCount += newError;
  68. newErrorCountText.text = newErrorCount.ToString();
  69. }
  70. if( newErrorCount > 0 )
  71. backgroundImage.color = alertColorError;
  72. else if( newWarningCount > 0 )
  73. backgroundImage.color = alertColorWarning;
  74. else
  75. backgroundImage.color = alertColorInfo;
  76. }
  77. private void Reset()
  78. {
  79. newInfoCount = 0;
  80. newWarningCount = 0;
  81. newErrorCount = 0;
  82. newInfoCountText.text = "0";
  83. newWarningCountText.text = "0";
  84. newErrorCountText.text = "0";
  85. backgroundImage.color = normalColor;
  86. }
  87. // A simple smooth movement animation
  88. private IEnumerator MoveToPosAnimation( Vector2 targetPos )
  89. {
  90. float modifier = 0f;
  91. Vector2 initialPos = popupTransform.anchoredPosition;
  92. while( modifier < 1f )
  93. {
  94. modifier += 4f * Time.unscaledDeltaTime;
  95. popupTransform.anchoredPosition = Vector2.Lerp( initialPos, targetPos, modifier );
  96. yield return null;
  97. }
  98. }
  99. // Popup is clicked
  100. public void OnPointerClick( PointerEventData data )
  101. {
  102. // Hide the popup and show the log window
  103. if( !isPopupBeingDragged )
  104. debugManager.ShowLogWindow();
  105. }
  106. // Hides the log window and shows the popup
  107. public void Show()
  108. {
  109. canvasGroup.blocksRaycasts = true;
  110. canvasGroup.alpha = 1f;
  111. // Reset the counters
  112. Reset();
  113. // Update position in case resolution was changed while the popup was hidden
  114. UpdatePosition( true );
  115. }
  116. // Hide the popup
  117. public void Hide()
  118. {
  119. canvasGroup.blocksRaycasts = false;
  120. canvasGroup.alpha = 0f;
  121. isPopupBeingDragged = false;
  122. }
  123. public void OnBeginDrag( PointerEventData data )
  124. {
  125. isPopupBeingDragged = true;
  126. // If a smooth movement animation is in progress, cancel it
  127. if( moveToPosCoroutine != null )
  128. {
  129. StopCoroutine( moveToPosCoroutine );
  130. moveToPosCoroutine = null;
  131. }
  132. }
  133. // Reposition the popup
  134. public void OnDrag( PointerEventData data )
  135. {
  136. Vector2 localPoint;
  137. if( RectTransformUtility.ScreenPointToLocalPointInRectangle( debugManager.canvasTR, data.position, data.pressEventCamera, out localPoint ) )
  138. popupTransform.anchoredPosition = localPoint;
  139. }
  140. // Smoothly translate the popup to the nearest edge
  141. public void OnEndDrag( PointerEventData data )
  142. {
  143. isPopupBeingDragged = false;
  144. UpdatePosition( false );
  145. }
  146. public void UpdatePosition( bool immediately )
  147. {
  148. Vector2 canvasSize = debugManager.canvasTR.rect.size;
  149. float canvasWidth = canvasSize.x;
  150. float canvasHeight = canvasSize.y;
  151. // normalizedPosition allows us to glue the popup to a specific edge of the screen. It becomes useful when
  152. // the popup is at the right edge and we switch from portrait screen orientation to landscape screen orientation.
  153. // Without normalizedPosition, popup could jump to bottom or top edges instead of staying at the right edge
  154. Vector2 pos = immediately ? new Vector2( normalizedPosition.x * canvasWidth, normalizedPosition.y * canvasHeight ) : popupTransform.anchoredPosition;
  155. // Find distances to all four edges
  156. float distToLeft = canvasWidth * 0.5f + pos.x;
  157. float distToRight = canvasWidth - distToLeft;
  158. float distToBottom = canvasHeight * 0.5f + pos.y;
  159. float distToTop = canvasHeight - distToBottom;
  160. float horDistance = Mathf.Min( distToLeft, distToRight );
  161. float vertDistance = Mathf.Min( distToBottom, distToTop );
  162. // Find the nearest edge's coordinates
  163. if( horDistance < vertDistance )
  164. {
  165. if( distToLeft < distToRight )
  166. pos = new Vector2( canvasWidth * -0.5f + halfSize.x, pos.y );
  167. else
  168. pos = new Vector2( canvasWidth * 0.5f - halfSize.x, pos.y );
  169. pos.y = Mathf.Clamp( pos.y, canvasHeight * -0.5f + halfSize.y, canvasHeight * 0.5f - halfSize.y );
  170. }
  171. else
  172. {
  173. if( distToBottom < distToTop )
  174. pos = new Vector2( pos.x, canvasHeight * -0.5f + halfSize.y );
  175. else
  176. pos = new Vector2( pos.x, canvasHeight * 0.5f - halfSize.y );
  177. pos.x = Mathf.Clamp( pos.x, canvasWidth * -0.5f + halfSize.x, canvasWidth * 0.5f - halfSize.x );
  178. }
  179. normalizedPosition.Set( pos.x / canvasWidth, pos.y / canvasHeight );
  180. // If another smooth movement animation is in progress, cancel it
  181. if( moveToPosCoroutine != null )
  182. {
  183. StopCoroutine( moveToPosCoroutine );
  184. moveToPosCoroutine = null;
  185. }
  186. if( immediately )
  187. popupTransform.anchoredPosition = pos;
  188. else
  189. {
  190. // Smoothly translate the popup to the specified position
  191. moveToPosCoroutine = MoveToPosAnimation( pos );
  192. StartCoroutine( moveToPosCoroutine );
  193. }
  194. }
  195. }
  196. }