No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DebugUpdater.cs 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #if ENABLE_INPUT_SYSTEM && ENABLE_INPUT_SYSTEM_PACKAGE
  2. #define USE_INPUT_SYSTEM
  3. using UnityEngine.InputSystem;
  4. using UnityEngine.InputSystem.UI;
  5. using UnityEngine.InputSystem.EnhancedTouch;
  6. #endif
  7. using System;
  8. using System.Collections;
  9. using System.Diagnostics;
  10. using UnityEngine.EventSystems;
  11. namespace UnityEngine.Rendering
  12. {
  13. [CoreRPHelpURL("Rendering-Debugger")]
  14. class DebugUpdater : MonoBehaviour
  15. {
  16. static DebugUpdater s_Instance = null;
  17. ScreenOrientation m_Orientation;
  18. bool m_RuntimeUiWasVisibleLastFrame = false;
  19. [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
  20. static void RuntimeInit()
  21. {
  22. #if DEVELOPMENT_BUILD || UNITY_EDITOR
  23. if (DebugManager.instance.enableRuntimeUI)
  24. EnableRuntime();
  25. #endif
  26. }
  27. internal static void SetEnabled(bool enabled)
  28. {
  29. if (enabled)
  30. EnableRuntime();
  31. else
  32. DisableRuntime();
  33. }
  34. static void EnableRuntime()
  35. {
  36. if (s_Instance != null)
  37. return;
  38. var go = new GameObject { name = "[Debug Updater]" };
  39. s_Instance = go.AddComponent<DebugUpdater>();
  40. s_Instance.m_Orientation = Screen.orientation;
  41. DontDestroyOnLoad(go);
  42. DebugManager.instance.EnableInputActions();
  43. #if USE_INPUT_SYSTEM
  44. EnhancedTouchSupport.Enable();
  45. #endif
  46. }
  47. static void DisableRuntime()
  48. {
  49. DebugManager debugManager = DebugManager.instance;
  50. debugManager.displayRuntimeUI = false;
  51. debugManager.displayPersistentRuntimeUI = false;
  52. if (s_Instance != null)
  53. {
  54. CoreUtils.Destroy(s_Instance.gameObject);
  55. s_Instance = null;
  56. }
  57. }
  58. internal static void HandleInternalEventSystemComponents(bool uiEnabled)
  59. {
  60. if (s_Instance == null)
  61. return;
  62. if (uiEnabled)
  63. s_Instance.EnsureExactlyOneEventSystem();
  64. else
  65. s_Instance.DestroyDebugEventSystem();
  66. }
  67. void EnsureExactlyOneEventSystem()
  68. {
  69. var eventSystems = FindObjectsByType<EventSystem>(FindObjectsSortMode.None);
  70. var debugEventSystem = GetComponent<EventSystem>();
  71. if (eventSystems.Length > 1 && debugEventSystem != null)
  72. {
  73. Debug.Log($"More than one EventSystem detected in scene. Destroying EventSystem owned by DebugUpdater.");
  74. DestroyDebugEventSystem();
  75. }
  76. else if (eventSystems.Length == 0)
  77. {
  78. Debug.Log($"No EventSystem available. Creating a new EventSystem to enable Rendering Debugger runtime UI.");
  79. CreateDebugEventSystem();
  80. }
  81. else
  82. {
  83. StartCoroutine(DoAfterInputModuleUpdated(CheckInputModuleExists));
  84. }
  85. }
  86. IEnumerator DoAfterInputModuleUpdated(Action action)
  87. {
  88. // EventSystem.current.currentInputModule is not updated immediately when EventSystem.current changes. It happens
  89. // with a delay in EventSystem.Update(), so wait a couple of frames to ensure that has happened.
  90. yield return new WaitForEndOfFrame();
  91. yield return new WaitForEndOfFrame();
  92. action.Invoke();
  93. }
  94. void CheckInputModuleExists()
  95. {
  96. if (EventSystem.current != null && EventSystem.current.currentInputModule == null)
  97. {
  98. Debug.LogWarning("Found a game object with EventSystem component but no corresponding BaseInputModule component - Debug UI input might not work correctly.");
  99. }
  100. }
  101. #if USE_INPUT_SYSTEM
  102. void AssignDefaultActions()
  103. {
  104. if (EventSystem.current != null && EventSystem.current.currentInputModule is InputSystemUIInputModule inputSystemModule)
  105. {
  106. // FIXME: In order to activate default input actions in player builds (required for touch input to work),
  107. // we need to call InputSystemUIInputModule.AssignDefaultActions() which was added in com.unity.inputsystem@1.1.0-pre.5.
  108. // However, there is a problem in InputSystem package version ordering, where it sorts this version as an
  109. // older version than it should be. Hence we cannot write a version define to conditionally compile this function call.
  110. // Instead, we use reflection to see if the function is there and can be invoked.
  111. //
  112. // Once com.unity.inputsystem@1.1.0 is available, create an INPUTSYSTEM_1_1_0_OR_GREATER version define and use it
  113. // to conditionally call AssignDefaultActions().
  114. System.Reflection.MethodInfo assignDefaultActionsMethod = inputSystemModule.GetType().GetMethod("AssignDefaultActions");
  115. if (assignDefaultActionsMethod != null)
  116. {
  117. assignDefaultActionsMethod.Invoke(inputSystemModule, null);
  118. }
  119. }
  120. CheckInputModuleExists();
  121. }
  122. #endif
  123. void CreateDebugEventSystem()
  124. {
  125. gameObject.AddComponent<EventSystem>();
  126. #if USE_INPUT_SYSTEM
  127. gameObject.AddComponent<InputSystemUIInputModule>();
  128. StartCoroutine(DoAfterInputModuleUpdated(AssignDefaultActions));
  129. #else
  130. gameObject.AddComponent<StandaloneInputModule>();
  131. #endif
  132. }
  133. void DestroyDebugEventSystem()
  134. {
  135. var eventSystem = GetComponent<EventSystem>();
  136. #if USE_INPUT_SYSTEM
  137. var inputModule = GetComponent<InputSystemUIInputModule>();
  138. if (inputModule)
  139. {
  140. CoreUtils.Destroy(inputModule);
  141. StartCoroutine(DoAfterInputModuleUpdated(AssignDefaultActions));
  142. }
  143. #else
  144. CoreUtils.Destroy(GetComponent<StandaloneInputModule>());
  145. CoreUtils.Destroy(GetComponent<BaseInput>());
  146. #endif
  147. CoreUtils.Destroy(eventSystem);
  148. }
  149. void Update()
  150. {
  151. DebugManager debugManager = DebugManager.instance;
  152. // Runtime UI visibility can change i.e. due to scene unload - allow component cleanup in this case.
  153. if (m_RuntimeUiWasVisibleLastFrame != debugManager.displayRuntimeUI)
  154. {
  155. HandleInternalEventSystemComponents(debugManager.displayRuntimeUI);
  156. }
  157. debugManager.UpdateActions();
  158. if (debugManager.GetAction(DebugAction.EnableDebugMenu) != 0.0f ||
  159. debugManager.GetActionToggleDebugMenuWithTouch())
  160. {
  161. debugManager.displayRuntimeUI = !debugManager.displayRuntimeUI;
  162. }
  163. if (debugManager.displayRuntimeUI)
  164. {
  165. if (debugManager.GetAction(DebugAction.ResetAll) != 0.0f)
  166. debugManager.Reset();
  167. if (debugManager.GetActionReleaseScrollTarget())
  168. debugManager.SetScrollTarget(null); // Allow mouse wheel scroll without causing auto-scroll
  169. }
  170. if (m_Orientation != Screen.orientation)
  171. {
  172. StartCoroutine(RefreshRuntimeUINextFrame());
  173. m_Orientation = Screen.orientation;
  174. }
  175. m_RuntimeUiWasVisibleLastFrame = debugManager.displayRuntimeUI;
  176. }
  177. static IEnumerator RefreshRuntimeUINextFrame()
  178. {
  179. yield return null; // Defer runtime UI refresh to next frame to allow canvas to update first.
  180. DebugManager.instance.ReDrawOnScreenDebug();
  181. }
  182. }
  183. }