DebugLogItem.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using UnityEngine.EventSystems;
  4. #if UNITY_EDITOR
  5. using UnityEditor;
  6. using System.Text.RegularExpressions;
  7. #endif
  8. // A UI element to show information about a debug entry
  9. namespace IngameDebugConsole
  10. {
  11. public class DebugLogItem : MonoBehaviour, IPointerClickHandler
  12. {
  13. #region Platform Specific Elements
  14. #if !UNITY_2018_1_OR_NEWER
  15. #if !UNITY_EDITOR && UNITY_ANDROID
  16. private static AndroidJavaClass m_ajc = null;
  17. private static AndroidJavaClass AJC
  18. {
  19. get
  20. {
  21. if( m_ajc == null )
  22. m_ajc = new AndroidJavaClass( "com.yasirkula.unity.DebugConsole" );
  23. return m_ajc;
  24. }
  25. }
  26. private static AndroidJavaObject m_context = null;
  27. private static AndroidJavaObject Context
  28. {
  29. get
  30. {
  31. if( m_context == null )
  32. {
  33. using( AndroidJavaObject unityClass = new AndroidJavaClass( "com.unity3d.player.UnityPlayer" ) )
  34. {
  35. m_context = unityClass.GetStatic<AndroidJavaObject>( "currentActivity" );
  36. }
  37. }
  38. return m_context;
  39. }
  40. }
  41. #elif !UNITY_EDITOR && UNITY_IOS
  42. [System.Runtime.InteropServices.DllImport( "__Internal" )]
  43. private static extern void _DebugConsole_CopyText( string text );
  44. #endif
  45. #endif
  46. #endregion
  47. #pragma warning disable 0649
  48. // Cached components
  49. [SerializeField]
  50. private RectTransform transformComponent;
  51. public RectTransform Transform { get { return transformComponent; } }
  52. [SerializeField]
  53. private Image imageComponent;
  54. public Image Image { get { return imageComponent; } }
  55. [SerializeField]
  56. private Text logText;
  57. [SerializeField]
  58. private Image logTypeImage;
  59. // Objects related to the collapsed count of the debug entry
  60. [SerializeField]
  61. private GameObject logCountParent;
  62. [SerializeField]
  63. private Text logCountText;
  64. [SerializeField]
  65. private RectTransform copyLogButton;
  66. #pragma warning restore 0649
  67. // Debug entry to show with this log item
  68. private DebugLogEntry logEntry;
  69. // Index of the entry in the list of entries
  70. private int entryIndex;
  71. public int Index { get { return entryIndex; } }
  72. private Vector2 logTextOriginalPosition;
  73. private Vector2 logTextOriginalSize;
  74. private float copyLogButtonHeight;
  75. private DebugLogRecycledListView manager;
  76. public void Initialize( DebugLogRecycledListView manager )
  77. {
  78. this.manager = manager;
  79. logTextOriginalPosition = logText.rectTransform.anchoredPosition;
  80. logTextOriginalSize = logText.rectTransform.sizeDelta;
  81. copyLogButtonHeight = copyLogButton.anchoredPosition.y + copyLogButton.sizeDelta.y + 2f; // 2f: space between text and button
  82. }
  83. public void SetContent( DebugLogEntry logEntry, int entryIndex, bool isExpanded )
  84. {
  85. this.logEntry = logEntry;
  86. this.entryIndex = entryIndex;
  87. Vector2 size = transformComponent.sizeDelta;
  88. if( isExpanded )
  89. {
  90. logText.horizontalOverflow = HorizontalWrapMode.Wrap;
  91. size.y = manager.SelectedItemHeight;
  92. if( !copyLogButton.gameObject.activeSelf )
  93. {
  94. copyLogButton.gameObject.SetActive( true );
  95. logText.rectTransform.anchoredPosition = new Vector2( logTextOriginalPosition.x, logTextOriginalPosition.y + copyLogButtonHeight * 0.5f );
  96. logText.rectTransform.sizeDelta = logTextOriginalSize - new Vector2( 0f, copyLogButtonHeight );
  97. }
  98. }
  99. else
  100. {
  101. logText.horizontalOverflow = HorizontalWrapMode.Overflow;
  102. size.y = manager.ItemHeight;
  103. if( copyLogButton.gameObject.activeSelf )
  104. {
  105. copyLogButton.gameObject.SetActive( false );
  106. logText.rectTransform.anchoredPosition = logTextOriginalPosition;
  107. logText.rectTransform.sizeDelta = logTextOriginalSize;
  108. }
  109. }
  110. transformComponent.sizeDelta = size;
  111. logText.text = isExpanded ? logEntry.ToString() : logEntry.logString;
  112. logTypeImage.sprite = logEntry.logTypeSpriteRepresentation;
  113. }
  114. // Show the collapsed count of the debug entry
  115. public void ShowCount()
  116. {
  117. logCountText.text = logEntry.count.ToString();
  118. if( !logCountParent.activeSelf )
  119. logCountParent.SetActive( true );
  120. }
  121. // Hide the collapsed count of the debug entry
  122. public void HideCount()
  123. {
  124. if( logCountParent.activeSelf )
  125. logCountParent.SetActive( false );
  126. }
  127. // This log item is clicked, show the debug entry's stack trace
  128. public void OnPointerClick( PointerEventData eventData )
  129. {
  130. #if UNITY_EDITOR
  131. if( eventData.button == PointerEventData.InputButton.Right )
  132. {
  133. Match regex = Regex.Match( logEntry.stackTrace, @"\(at .*\.cs:[0-9]+\)$", RegexOptions.Multiline );
  134. if( regex.Success )
  135. {
  136. string line = logEntry.stackTrace.Substring( regex.Index + 4, regex.Length - 5 );
  137. int lineSeparator = line.IndexOf( ':' );
  138. MonoScript script = AssetDatabase.LoadAssetAtPath<MonoScript>( line.Substring( 0, lineSeparator ) );
  139. if( script != null )
  140. AssetDatabase.OpenAsset( script, int.Parse( line.Substring( lineSeparator + 1 ) ) );
  141. }
  142. }
  143. else
  144. manager.OnLogItemClicked( this );
  145. #else
  146. manager.OnLogItemClicked( this );
  147. #endif
  148. }
  149. public void CopyLog()
  150. {
  151. string log = logEntry.ToString();
  152. if( string.IsNullOrEmpty( log ) )
  153. return;
  154. #if UNITY_EDITOR || UNITY_2018_1_OR_NEWER || ( !UNITY_ANDROID && !UNITY_IOS )
  155. GUIUtility.systemCopyBuffer = log;
  156. #elif UNITY_ANDROID
  157. AJC.CallStatic( "CopyText", Context, log );
  158. #elif UNITY_IOS
  159. _DebugConsole_CopyText( log );
  160. #endif
  161. }
  162. public float CalculateExpandedHeight( string content )
  163. {
  164. string text = logText.text;
  165. HorizontalWrapMode wrapMode = logText.horizontalOverflow;
  166. logText.text = content;
  167. logText.horizontalOverflow = HorizontalWrapMode.Wrap;
  168. float result = logText.preferredHeight + copyLogButtonHeight;
  169. logText.text = text;
  170. logText.horizontalOverflow = wrapMode;
  171. return Mathf.Max( manager.ItemHeight, result );
  172. }
  173. // Return a string containing complete information about the debug entry
  174. public override string ToString()
  175. {
  176. return logEntry.ToString();
  177. }
  178. }
  179. }