UnityGame/Library/PackageCache/com.unity.render-pipelines.core/Runtime/Debugging/DebugUpdater.cs
2024-10-27 10:53:47 +03:00

215 lines
7.6 KiB
C#

#if ENABLE_INPUT_SYSTEM && ENABLE_INPUT_SYSTEM_PACKAGE
#define USE_INPUT_SYSTEM
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.UI;
using UnityEngine.InputSystem.EnhancedTouch;
#endif
using System;
using System.Collections;
using System.Diagnostics;
using UnityEngine.EventSystems;
namespace UnityEngine.Rendering
{
[CoreRPHelpURL("Rendering-Debugger")]
class DebugUpdater : MonoBehaviour
{
static DebugUpdater s_Instance = null;
ScreenOrientation m_Orientation;
bool m_RuntimeUiWasVisibleLastFrame = false;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
static void RuntimeInit()
{
#if DEVELOPMENT_BUILD || UNITY_EDITOR
if (DebugManager.instance.enableRuntimeUI)
EnableRuntime();
#endif
}
internal static void SetEnabled(bool enabled)
{
if (enabled)
EnableRuntime();
else
DisableRuntime();
}
static void EnableRuntime()
{
if (s_Instance != null)
return;
var go = new GameObject { name = "[Debug Updater]" };
s_Instance = go.AddComponent<DebugUpdater>();
s_Instance.m_Orientation = Screen.orientation;
DontDestroyOnLoad(go);
DebugManager.instance.EnableInputActions();
#if USE_INPUT_SYSTEM
EnhancedTouchSupport.Enable();
#endif
}
static void DisableRuntime()
{
DebugManager debugManager = DebugManager.instance;
debugManager.displayRuntimeUI = false;
debugManager.displayPersistentRuntimeUI = false;
if (s_Instance != null)
{
CoreUtils.Destroy(s_Instance.gameObject);
s_Instance = null;
}
}
internal static void HandleInternalEventSystemComponents(bool uiEnabled)
{
if (s_Instance == null)
return;
if (uiEnabled)
s_Instance.EnsureExactlyOneEventSystem();
else
s_Instance.DestroyDebugEventSystem();
}
void EnsureExactlyOneEventSystem()
{
var eventSystems = FindObjectsByType<EventSystem>(FindObjectsSortMode.None);
var debugEventSystem = GetComponent<EventSystem>();
if (eventSystems.Length > 1 && debugEventSystem != null)
{
Debug.Log($"More than one EventSystem detected in scene. Destroying EventSystem owned by DebugUpdater.");
DestroyDebugEventSystem();
}
else if (eventSystems.Length == 0)
{
Debug.Log($"No EventSystem available. Creating a new EventSystem to enable Rendering Debugger runtime UI.");
CreateDebugEventSystem();
}
else
{
StartCoroutine(DoAfterInputModuleUpdated(CheckInputModuleExists));
}
}
IEnumerator DoAfterInputModuleUpdated(Action action)
{
// EventSystem.current.currentInputModule is not updated immediately when EventSystem.current changes. It happens
// with a delay in EventSystem.Update(), so wait a couple of frames to ensure that has happened.
yield return new WaitForEndOfFrame();
yield return new WaitForEndOfFrame();
action.Invoke();
}
void CheckInputModuleExists()
{
if (EventSystem.current != null && EventSystem.current.currentInputModule == null)
{
Debug.LogWarning("Found a game object with EventSystem component but no corresponding BaseInputModule component - Debug UI input might not work correctly.");
}
}
#if USE_INPUT_SYSTEM
void AssignDefaultActions()
{
if (EventSystem.current != null && EventSystem.current.currentInputModule is InputSystemUIInputModule inputSystemModule)
{
// FIXME: In order to activate default input actions in player builds (required for touch input to work),
// we need to call InputSystemUIInputModule.AssignDefaultActions() which was added in com.unity.inputsystem@1.1.0-pre.5.
// However, there is a problem in InputSystem package version ordering, where it sorts this version as an
// older version than it should be. Hence we cannot write a version define to conditionally compile this function call.
// Instead, we use reflection to see if the function is there and can be invoked.
//
// Once com.unity.inputsystem@1.1.0 is available, create an INPUTSYSTEM_1_1_0_OR_GREATER version define and use it
// to conditionally call AssignDefaultActions().
System.Reflection.MethodInfo assignDefaultActionsMethod = inputSystemModule.GetType().GetMethod("AssignDefaultActions");
if (assignDefaultActionsMethod != null)
{
assignDefaultActionsMethod.Invoke(inputSystemModule, null);
}
}
CheckInputModuleExists();
}
#endif
void CreateDebugEventSystem()
{
gameObject.AddComponent<EventSystem>();
#if USE_INPUT_SYSTEM
gameObject.AddComponent<InputSystemUIInputModule>();
StartCoroutine(DoAfterInputModuleUpdated(AssignDefaultActions));
#else
gameObject.AddComponent<StandaloneInputModule>();
#endif
}
void DestroyDebugEventSystem()
{
var eventSystem = GetComponent<EventSystem>();
#if USE_INPUT_SYSTEM
var inputModule = GetComponent<InputSystemUIInputModule>();
if (inputModule)
{
CoreUtils.Destroy(inputModule);
StartCoroutine(DoAfterInputModuleUpdated(AssignDefaultActions));
}
#else
CoreUtils.Destroy(GetComponent<StandaloneInputModule>());
CoreUtils.Destroy(GetComponent<BaseInput>());
#endif
CoreUtils.Destroy(eventSystem);
}
void Update()
{
DebugManager debugManager = DebugManager.instance;
// Runtime UI visibility can change i.e. due to scene unload - allow component cleanup in this case.
if (m_RuntimeUiWasVisibleLastFrame != debugManager.displayRuntimeUI)
{
HandleInternalEventSystemComponents(debugManager.displayRuntimeUI);
}
debugManager.UpdateActions();
if (debugManager.GetAction(DebugAction.EnableDebugMenu) != 0.0f ||
debugManager.GetActionToggleDebugMenuWithTouch())
{
debugManager.displayRuntimeUI = !debugManager.displayRuntimeUI;
}
if (debugManager.displayRuntimeUI)
{
if (debugManager.GetAction(DebugAction.ResetAll) != 0.0f)
debugManager.Reset();
if (debugManager.GetActionReleaseScrollTarget())
debugManager.SetScrollTarget(null); // Allow mouse wheel scroll without causing auto-scroll
}
if (m_Orientation != Screen.orientation)
{
StartCoroutine(RefreshRuntimeUINextFrame());
m_Orientation = Screen.orientation;
}
m_RuntimeUiWasVisibleLastFrame = debugManager.displayRuntimeUI;
}
static IEnumerator RefreshRuntimeUINextFrame()
{
yield return null; // Defer runtime UI refresh to next frame to allow canvas to update first.
DebugManager.instance.ReDrawOnScreenDebug();
}
}
}