Firstborn/Library/PackageCache/com.unity.addressables@1.19.19/Editor/Diagnostics/GUI/EventViewerWindow.cs

529 lines
21 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using UnityEditor.AddressableAssets.Diagnostics.Data;
using UnityEditor.AddressableAssets.Diagnostics.GUI.Graph;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using UnityEngine.ResourceManagement.Diagnostics;
using UnityEngine.Serialization;
using UnityEditor.Networking.PlayerConnection;
using UnityEngine.Networking.PlayerConnection;
namespace UnityEditor.AddressableAssets.Diagnostics.GUI
{
class EventViewerWindow : EditorWindow, IComparer<EventDataSet>
{
EventDataPlayerSessionCollection m_EventData;
GUIContent m_PrevFrameIcon;
GUIContent m_NextFrameIcon;
int m_PlayerSessionIndex;
int m_InspectFrame;
int m_EventListFrame = -1;
VerticalSplitter m_VerticalSplitter = new VerticalSplitter();
HorizontalSplitter m_HorizontalSplitter = new HorizontalSplitter();
float m_LastEventListUpdate;
bool m_DraggingInspectLine;
int m_LatestFrame;
TreeViewState m_EventListTreeViewState;
MultiColumnHeaderState m_EventListMchs;
EventListView m_EventList;
TreeViewState m_GraphListTreeViewState;
MultiColumnHeaderState m_GraphListMchs;
EventGraphListView m_GraphList;
EventDataPlayerSession activeSession
{
get { return m_EventData == null ? null : m_EventData.GetSessionByIndex(m_PlayerSessionIndex); }
}
protected virtual bool ShowEventDetailPanel { get { return false; } }
protected virtual bool ShowEventPanel { get { return false; } }
void OnEnable()
{
EditorConnection.instance.Initialize();
EditorConnection.instance.Register(DiagnosticEventCollectorSingleton.PlayerConnectionGuid, OnPlayerConnectionMessage);
EditorConnection.instance.RegisterConnection(OnPlayerConnection);
EditorConnection.instance.RegisterDisconnection(OnPlayerDisconnection);
m_LastEventListUpdate = 0;
m_PrevFrameIcon = EditorGUIUtility.IconContent("Profiler.PrevFrame", "|Go one frame backwards");
m_NextFrameIcon = EditorGUIUtility.IconContent("Profiler.NextFrame", "|Go one frame forwards");
EditorApplication.playModeStateChanged += OnEditorPlayModeChanged;
if (m_EventData == null)
{
RegisterEventHandler(true);
m_EventData = new EventDataPlayerSessionCollection(OnRecordEvent);
m_EventData.GetPlayerSession(0, true).IsActive = true;
}
}
void OnDisable()
{
EditorConnection.instance.Unregister(DiagnosticEventCollectorSingleton.PlayerConnectionGuid, OnPlayerConnectionMessage);
RegisterEventHandler(false);
EditorApplication.playModeStateChanged -= OnEditorPlayModeChanged;
}
void OnPlayerConnection(int id)
{
if (m_EventData == null)
m_EventData = new EventDataPlayerSessionCollection(OnRecordEvent);
m_EventData.GetPlayerSession(id, true).IsActive = true;
int connectedSessionIndex = m_EventData.GetSessionIndexById(id);
m_PlayerSessionIndex = connectedSessionIndex != -1 ? connectedSessionIndex : 0;
}
void OnPlayerDisconnection(int id)
{
if (m_EventData == null)
return;
m_EventData.RemoveSession(id);
m_PlayerSessionIndex = 0;
}
void OnPlayerConnectionMessage(MessageEventArgs args)
{
var evt = DiagnosticEvent.Deserialize(args.data);
OnEvent(evt, args.playerId);
}
void RegisterEventHandler(bool reg)
{
if (ProjectConfigData.PostProfilerEvents)
DiagnosticEventCollectorSingleton.RegisterEventHandler(OnEditorPlayModeEvent, reg, true);
}
void OnEditorPlayModeEvent(DiagnosticEvent evt)
{
if (m_EventData == null)
m_EventData = new EventDataPlayerSessionCollection(OnRecordEvent);
if (m_EventData.GetPlayerSession(0, false) == null)
m_EventData.AddSession("Editor", m_PlayerSessionIndex = 0);
OnEvent(evt, 0);
}
public void OnEvent(DiagnosticEvent diagnosticEvent, int session)
{
if (m_EventData == null)
m_EventData = new EventDataPlayerSessionCollection(OnRecordEvent);
var entryCreated = m_EventData.ProcessEvent(diagnosticEvent, session);
OnEventProcessed(diagnosticEvent, entryCreated);
}
public int Compare(EventDataSet x, EventDataSet y)
{
return x.CompareTo(y);
}
protected virtual bool CanHandleEvent(string graph)
{
if (graph.Contains("Count"))
return true;
return OnCanHandleEvent(graph);
}
protected virtual bool OnCanHandleEvent(string graph) { return true; }
void OnEditorPlayModeChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.EnteredPlayMode)
{
m_EventData = new EventDataPlayerSessionCollection(OnRecordEvent);
m_EventData.GetPlayerSession(0, true).IsActive = true;
m_LastEventListUpdate = 0;
m_InspectFrame = -1;
m_LatestFrame = -1;
m_PlayerSessionIndex = 0;
RegisterEventHandler(true);
}
if (state == PlayModeStateChange.EnteredEditMode)
{
RegisterEventHandler(false);
}
}
protected virtual bool OnDisplayEvent(DiagnosticEvent diagnosticEvent)
{
var sel = m_GraphList.GetSelection();
if (sel == null || sel.Count == 0)
return true;
foreach (var s in sel)
{
// m_GraphList.Fi
}
return true;
}
protected virtual bool OnRecordEvent(DiagnosticEvent diagnosticEvent)
{
return false;
}
int m_LastRepaintedFrame = -1;
void OnEventProcessed(DiagnosticEvent diagnosticEvent, bool entryCreated)
{
if (!CanHandleEvent(diagnosticEvent.Graph))
return;
bool moveInspectFrame = m_LatestFrame < 0 || m_InspectFrame == m_LatestFrame;
m_LatestFrame = diagnosticEvent.Frame;
if (entryCreated)
{
if (m_GraphList != null)
m_GraphList.Reload();
}
if (moveInspectFrame)
SetInspectFrame(m_LatestFrame);
if (diagnosticEvent.Frame != m_LastRepaintedFrame)
{
Repaint();
m_LastRepaintedFrame = diagnosticEvent.Frame;
}
}
void SetInspectFrame(int frame)
{
m_InspectFrame = frame;
if (m_InspectFrame > m_LatestFrame)
m_InspectFrame = m_LatestFrame;
if (m_InspectFrame < 0)
m_InspectFrame = 0;
if (m_EventList != null)
m_EventList.SetEvents(activeSession == null ? null : activeSession.GetFrameEvents(m_InspectFrame));
m_LastEventListUpdate = Time.unscaledTime;
m_EventListFrame = m_InspectFrame;
}
void OnGUI()
{
if (activeSession == null)
return;
InitializeGui();
//this prevent arrow key events from reaching the treeview, so navigation via keys is disabled
if (Event.current.type == EventType.KeyDown)
{
if (Event.current.keyCode == KeyCode.RightArrow)
{
SetInspectFrame(m_InspectFrame + 1);
return;
}
if (Event.current.keyCode == KeyCode.LeftArrow)
{
SetInspectFrame(m_InspectFrame - 1);
return;
}
}
DrawToolBar(activeSession);
var r = EditorGUILayout.GetControlRect();
Rect contentRect = new Rect(r.x, r.y, r.width, position.height - r.y);
var graphRect = m_GraphList.GraphRect;
if (ShowEventPanel)
{
Rect top, bot;
bool resizingVer = m_VerticalSplitter.OnGUI(contentRect, out top, out bot);
ProcessInspectFrame(graphRect);
m_GraphList.DrawGraphs(top, activeSession, m_InspectFrame);
DrawInspectFrame(graphRect);
bool resizingHor = false;
if (ShowEventDetailPanel)
{
Rect left, right;
resizingHor = m_HorizontalSplitter.OnGUI(bot, out left, out right);
m_EventList.OnGUI(left);
OnDrawEventDetail(right, m_EventList.selectedEvent);
}
else
{
m_EventList.OnGUI(bot);
}
if (resizingVer || resizingHor)
Repaint();
}
else
{
ProcessInspectFrame(graphRect);
m_GraphList.DrawGraphs(contentRect, activeSession, m_InspectFrame);
DrawInspectFrame(graphRect);
}
}
protected virtual void OnDrawEventDetail(Rect right, DiagnosticEvent selectedEvent)
{
}
void OnInspectorUpdate()
{
if (m_EventData == null) return;
m_EventData.Update();
if (activeSession != null && activeSession.NeedsReload)
{
activeSession.NeedsReload = false;
m_EventList?.Reload();
}
Repaint();
}
void ProcessInspectFrame(Rect graphRect)
{
if (Event.current.type == EventType.MouseDown && graphRect.Contains(Event.current.mousePosition))
{
if (EditorApplication.isPlaying)
EditorApplication.isPaused = true;
m_DraggingInspectLine = true;
SetInspectFrame(m_InspectFrame);
}
if (m_DraggingInspectLine && (Event.current.type == EventType.MouseDrag || Event.current.type == EventType.Repaint))
SetInspectFrame(m_GraphList.visibleStartTime + (int)GraphUtility.PixelToValue(Event.current.mousePosition.x, graphRect.xMin, graphRect.xMax, m_GraphList.visibleDuration));
if (Event.current.type == EventType.MouseUp)
{
m_DraggingInspectLine = false;
SetInspectFrame(m_InspectFrame);
}
}
void DrawInspectFrame(Rect graphPanelRect)
{
if (m_InspectFrame != m_LatestFrame)
{
var ix = graphPanelRect.xMin + GraphUtility.ValueToPixel(m_InspectFrame, m_GraphList.visibleStartTime, m_GraphList.visibleStartTime + m_GraphList.visibleDuration, graphPanelRect.width);
EditorGUI.DrawRect(new Rect(ix - 1, graphPanelRect.yMin, 3, graphPanelRect.height), Color.white * .8f);
}
}
void DrawToolBar(EventDataPlayerSession session)
{
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
if (GUILayout.Button("Clear Events", EditorStyles.toolbarButton))
{
RegisterEventHandler(false);
session.Clear();
m_GraphList?.Reload();
RegisterEventHandler(true);
}
if (m_GraphList != null && m_GraphList.HasHiddenEvents && GUILayout.Button("Unhide All Hidden Events", EditorStyles.toolbarButton))
m_GraphList.UnhideAllHiddenEvents();
GUILayout.FlexibleSpace();
GUILayout.Label(m_InspectFrame == m_LatestFrame ? "Frame: " : "Frame: " + m_InspectFrame + "/" + m_LatestFrame, EditorStyles.miniLabel);
using (new EditorGUI.DisabledScope(m_InspectFrame <= 0))
if (GUILayout.Button(m_PrevFrameIcon, EditorStyles.toolbarButton))
SetInspectFrame(m_InspectFrame - 1);
using (new EditorGUI.DisabledScope(m_InspectFrame >= m_LatestFrame))
if (GUILayout.Button(m_NextFrameIcon, EditorStyles.toolbarButton))
SetInspectFrame(m_InspectFrame + 1);
if (GUILayout.Button("Current", EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
SetInspectFrame(m_LatestFrame);
GUILayout.EndHorizontal();
}
protected virtual void OnGetColumns(List<string> columnNames, List<float> columnSizes)
{
if (columnNames == null || columnSizes == null)
return;
columnNames.Add("Event"); columnSizes.Add(50);
columnNames.Add("Id"); columnSizes.Add(200);
// columnNames.Add("Data"); columnSizes.Add(400);
}
protected virtual bool OnDrawColumnCell(Rect cellRect, DiagnosticEvent diagnosticEvent, int column)
{
return false;
}
protected virtual void DrawColumnCell(Rect cellRect, DiagnosticEvent diagnosticEvent, int column)
{
if (!OnDrawColumnCell(cellRect, diagnosticEvent, column))
{
switch (column)
{
case 0: EditorGUI.LabelField(cellRect, diagnosticEvent.Stream.ToString()); break;
case 1: EditorGUI.LabelField(cellRect, diagnosticEvent.DisplayName); break;
// case 2: EditorGUI.LabelField(cellRect, diagnosticEvent. == null ? "null" : diagnosticEvent.Data.ToString()); break;
}
}
}
void InitializeGui()
{
if (m_GraphList == null)
{
if (m_GraphListTreeViewState == null)
m_GraphListTreeViewState = new TreeViewState();
var headerState = EventGraphListView.CreateDefaultHeaderState();
if (MultiColumnHeaderState.CanOverwriteSerializedFields(m_GraphListMchs, headerState))
MultiColumnHeaderState.OverwriteSerializedFields(m_GraphListMchs, headerState);
m_GraphListMchs = headerState;
m_GraphList = new EventGraphListView(() => { return activeSession == null ? null : activeSession.RootStreamEntry; }, m_GraphListTreeViewState, m_GraphListMchs, CanHandleEvent, this);
InitializeGraphView(m_GraphList);
m_GraphList.Reload();
}
if (m_EventList == null)
{
if (m_EventListTreeViewState == null)
m_EventListTreeViewState = new TreeViewState();
var columns = new List<string>();
var sizes = new List<float>();
OnGetColumns(columns, sizes);
var headerState = EventListView.CreateDefaultMultiColumnHeaderState(columns, sizes);
if (MultiColumnHeaderState.CanOverwriteSerializedFields(m_EventListMchs, headerState))
MultiColumnHeaderState.OverwriteSerializedFields(m_EventListMchs, headerState);
m_EventListMchs = headerState;
m_EventList = new EventListView(m_EventListTreeViewState, m_EventListMchs, DrawColumnCell, OnDisplayEvent);
m_EventList.Reload();
}
if (m_EventListFrame != m_InspectFrame && m_InspectFrame != m_LatestFrame && !m_DraggingInspectLine && Time.unscaledTime - m_LastEventListUpdate > .25f)
{
if (activeSession != null)
m_EventList.SetEvents(activeSession.GetFrameEvents(m_InspectFrame));
m_LastEventListUpdate = Time.unscaledTime;
m_EventListFrame = m_InspectFrame;
}
if (m_GraphListMchs != null && m_GraphListMchs.columns.Length > 2)
{
string warningText = string.Empty;
if (!ProjectConfigData.PostProfilerEvents)
warningText = "Warning: 'Send Profiler events' must be enabled in your Addressable Asset settings to view profile data. Changes to 'Send Profiler Events' will be applied on the following build.";
m_GraphListMchs.columns[2].headerContent.text = warningText;
}
}
void InitializeGraphView(EventGraphListView graphView)
{
graphView.DefineGraph("FrameCount", 1, new GraphLayerBarChartMesh(1, "FPS", "Current Frame Rate", Color.blue),
new GraphLayerLabel(1, "FPS", "Current Frame Rate", Color.white, GraphColors.LabelGraphLabelBackground, v => string.Format("{0} FPS", v)));
graphView.DefineGraph("MemoryCount", 2, new GraphLayerBarChartMesh(2, "MonoHeap", "Current Mono Heap Size", Color.green * .75f),
new GraphLayerLabel(2, "MonoHeap", "Current Mono Heap Size", Color.white, GraphColors.LabelGraphLabelBackground, v => string.Format("{0:0.0}MB", (v / 1024f))));
OnInitializeGraphView(graphView);
}
protected virtual void OnInitializeGraphView(EventGraphListView graphView) {}
}
[Serializable]
class VerticalSplitter
{
[NonSerialized]
Rect m_Rect = new Rect(0, 0, 0, 3);
public Rect SplitterRect { get { return m_Rect; } }
[FormerlySerializedAs("m_currentPercent")]
[SerializeField]
float m_CurrentPercent;
bool m_Resizing;
float m_MinPercent;
float m_MaxPercent;
public VerticalSplitter(float percent = .8f, float minPer = .2f, float maxPer = .9f)
{
m_CurrentPercent = percent;
m_MinPercent = minPer;
m_MaxPercent = maxPer;
}
public bool OnGUI(Rect content, out Rect top, out Rect bot)
{
m_Rect.x = content.x;
m_Rect.y = (int)(content.y + content.height * m_CurrentPercent);
m_Rect.width = content.width;
EditorGUIUtility.AddCursorRect(m_Rect, MouseCursor.ResizeVertical);
if (Event.current.type == EventType.MouseDown && m_Rect.Contains(Event.current.mousePosition))
m_Resizing = true;
if (m_Resizing)
{
EditorGUIUtility.AddCursorRect(content, MouseCursor.ResizeVertical);
var mousePosInRect = Event.current.mousePosition.y - content.y;
m_CurrentPercent = Mathf.Clamp(mousePosInRect / content.height, m_MinPercent, m_MaxPercent);
m_Rect.y = Mathf.Min((int)(content.y + content.height * m_CurrentPercent), content.yMax - m_Rect.height);
if (Event.current.type == EventType.MouseUp)
m_Resizing = false;
}
top = new Rect(content.x, content.y, content.width, m_Rect.yMin - content.yMin);
bot = new Rect(content.x, m_Rect.yMax, content.width, content.yMax - m_Rect.yMax);
return m_Resizing;
}
}
[Serializable]
class HorizontalSplitter
{
[NonSerialized]
Rect m_Rect = new Rect(0, 0, 3, 0);
public Rect SplitterRect { get { return m_Rect; } }
[FormerlySerializedAs("m_currentPercent")]
[SerializeField]
float m_CurrentPercent;
bool m_Resizing;
float m_MinPercent;
float m_MaxPercent;
public HorizontalSplitter(float percent = .8f, float minPer = .2f, float maxPer = .9f)
{
m_CurrentPercent = percent;
m_MinPercent = minPer;
m_MaxPercent = maxPer;
}
public bool OnGUI(Rect content, out Rect left, out Rect right)
{
m_Rect.y = content.y;
m_Rect.x = (int)(content.x + content.width * m_CurrentPercent);
m_Rect.height = content.height;
EditorGUIUtility.AddCursorRect(m_Rect, MouseCursor.ResizeHorizontal);
if (Event.current.type == EventType.MouseDown && m_Rect.Contains(Event.current.mousePosition))
m_Resizing = true;
if (m_Resizing)
{
EditorGUIUtility.AddCursorRect(content, MouseCursor.ResizeHorizontal);
var mousePosInRect = Event.current.mousePosition.x - content.x;
m_CurrentPercent = Mathf.Clamp(mousePosInRect / content.width, m_MinPercent, m_MaxPercent);
m_Rect.x = Mathf.Min((int)(content.x + content.width * m_CurrentPercent), content.xMax - m_Rect.width);
if (Event.current.type == EventType.MouseUp)
m_Resizing = false;
}
left = new Rect(content.x, content.y, m_Rect.xMin, content.height);
right = new Rect(m_Rect.xMax, content.y, content.width - m_Rect.xMax, content.height);
return m_Resizing;
}
}
}