1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305 |
- using UnityEngine;
- using System;
- using System.Collections.Generic;
- using UnityEngine.Profiling;
- namespace UnityEditor.Performance.ProfileAnalyzer
- {
- [Serializable]
- internal class FrameTimeGraphGlobalSettings
- {
- public bool showThreads = false;
- public bool showSelectedMarker = true;
- public bool showFrameLines = true;
- public bool showFrameLineText = true;
- public bool showOrderedByFrameDuration = false;
- }
- internal class FrameTimeGraph
- {
- static FrameTimeGraphGlobalSettings m_GlobalSettings = new FrameTimeGraphGlobalSettings();
- static public void SetGlobalSettings(FrameTimeGraphGlobalSettings globalSettings)
- {
- m_GlobalSettings = globalSettings;
- }
- public struct Data
- {
- public readonly float ms;
- public readonly int frameOffset;
- public Data(float _ms, int _index)
- {
- ms = _ms;
- frameOffset = _index;
- }
- };
- public delegate void SetRange(List<int> selected, int clickCount, FrameTimeGraph.State inputStatus);
- public delegate void SetActive(bool active);
- public enum State
- {
- None,
- Dragging,
- DragComplete
- };
- enum DragDirection
- {
- Start,
- Forward,
- Backward,
- None
- };
- enum AxisMode
- {
- One60HzFrame,
- Two60HzFrames,
- Four60HzFrames,
- Max,
- Custom
- };
- Draw2D m_2D;
- int m_DragBeginFirstOffset;
- int m_DragBeginLastOffset;
- bool m_Dragging;
- int m_DragFirstOffset;
- int m_DragLastOffset;
- bool m_Moving;
- int m_MoveHandleOffset;
- bool m_SingleControlAction;
- int m_ClickCount;
- double m_LastClickTime;
- bool m_MouseReleased;
- bool m_Zoomed;
- int m_ZoomStartOffset;
- int m_ZoomEndOffset;
- Color m_ColorBarBackground;
- Color m_ColorBarBackgroundSelected;
- Color m_ColorBar;
- Color m_ColorBarOutOfRange;
- Color m_ColorBarSelected;
- Color m_ColorBarThreads;
- Color m_ColorBarThreadsOutOfRange;
- Color m_ColorBarThreadsSelected;
- Color m_ColorBarMarker;
- Color m_ColorBarMarkerOutOfRange;
- Color m_ColorBarMarkerSelected;
- Color m_ColorGridLine;
- FrameTimeGraph m_PairedWithFrameTimeGraph;
- internal static class Styles
- {
- public static readonly GUIContent menuItemClearSelection = new GUIContent("Clear Selection");
- public static readonly GUIContent menuItemSelectAll = new GUIContent("Select All");
- public static readonly GUIContent menuItemInvertSelection = new GUIContent("Invert Selection");
- public static readonly GUIContent menuItemZoomSelection = new GUIContent("Zoom Selection");
- public static readonly GUIContent menuItemZoomAll = new GUIContent("Zoom All");
- public static readonly GUIContent menuItemSelectMin = new GUIContent("Select Shortest Frame");
- public static readonly GUIContent menuItemSelectMax = new GUIContent("Select Longest Frame");
- public static readonly GUIContent menuItemSelectMedian = new GUIContent("Select Median Frame");
- public static readonly GUIContent menuItemSelectPrevious = new GUIContent("Move selection left _LEFT");
- public static readonly GUIContent menuItemSelectNext = new GUIContent("Move selection right _RIGHT");
- public static readonly GUIContent menuItemSelectGrow = new GUIContent("Grow selection _=");
- public static readonly GUIContent menuItemSelectShrink = new GUIContent("Shrink selection _-");
- public static readonly GUIContent menuItemSelectGrowLeft = new GUIContent("Grow selection left _<");
- public static readonly GUIContent menuItemSelectGrowRight = new GUIContent("Grow selection right _>");
- public static readonly GUIContent menuItemSelectShrinkLeft = new GUIContent("Shrink selection left _&<");
- public static readonly GUIContent menuItemSelectShrinkRight = new GUIContent("Shrink selection right _&>");
- public static readonly GUIContent menuItemSelectGrowFast = new GUIContent("Grow selection (fast) _#=");
- public static readonly GUIContent menuItemSelectShrinkFast = new GUIContent("Shrink selection (fast) _#-");
- public static readonly GUIContent menuItemSelectGrowLeftFast = new GUIContent("Grow selection left (fast) _#<");
- public static readonly GUIContent menuItemSelectGrowRightFast = new GUIContent("Grow selection right (fast) _#>");
- public static readonly GUIContent menuItemSelectShrinkLeftFast = new GUIContent("Shrink selection left (fast) _#&<");
- public static readonly GUIContent menuItemSelectShrinkRightFast = new GUIContent("Shrink selection right (fast) _#&>");
- public static readonly GUIContent menuItemShowSelectedMarker = new GUIContent("Show Selected Marker");
- public static readonly GUIContent menuItemShowThreads = new GUIContent("Show Filtered Threads");
- // public static readonly GUIContent menuItemDetailedMode = new GUIContent("Detailed mode");
- public static readonly GUIContent menuItemShowFrameLines = new GUIContent("Show Frame Lines");
- public static readonly GUIContent menuItemShowFrameLineText = new GUIContent("Show Frame Line Text");
- public static readonly GUIContent menuItemShowOrderedByFrameDuration = new GUIContent("Order by Frame Duration");
- }
- const int kXAxisWidth = 80;
- const int kYAxisDetailThreshold = 40;
- const int kOverrunHeight = 3;
- static AxisMode s_YAxisMode;
- static float m_YAxisMs;
- bool m_IsOrderedByFrameDuration;
- List<Data> m_Values = new List<Data> {};
- List<int> m_LastSelectedFrameOffsets = new List<int> {};
- int[] m_FrameOffsetToDataOffsetMapping = new int[] {};
- SetRange m_SetRange;
- SetActive m_SetActive;
- List<int> m_CurrentSelection = new List<int>();
- int m_CurrentSelectionFirstDataOffset;
- int m_CurrentSelectionLastDataOffset;
- int m_GraphId;
- int m_ControlID;
- static int s_LastSelectedGraphId = -1;
- static int s_CurrentSelectedGraphId = -1;
- bool m_Enabled;
- struct BarData
- {
- public float x;
- public float y;
- public float w;
- public float h;
- public int startDataOffset;
- public int endDataOffset;
- public float yMin;
- public float yMax;
- public BarData(float _x, float _y, float _w, float _h, int _startDataOffset, int _endDataOffset, float _yMin, float _yMax)
- {
- x = _x;
- y = _y;
- w = _w;
- h = _h;
- startDataOffset = _startDataOffset;
- endDataOffset = _endDataOffset;
- yMin = _yMin;
- yMax = _yMax;
- }
- }
- List<BarData> m_Bars = new List<BarData>();
- DisplayUnits m_Units;
- Rect m_LastRect;
- int m_MaxFrames;
- string DisplayUnits()
- {
- return m_Units.Postfix();
- }
- string ToDisplayUnits(float ms, bool showUnits = false, int limitToNDigits = 5)
- {
- return m_Units.ToString(ms, showUnits, limitToNDigits);
- }
- public void SetUnits(Units units)
- {
- m_Units = new DisplayUnits(units);
- }
- public void Reset()
- {
- m_Zoomed = false;
- m_Dragging = false;
- ClearDragSelection();
- m_Moving = false;
- m_ClickCount = 0;
- m_MouseReleased = false;
- }
- void Init()
- {
- Reset();
- m_PairedWithFrameTimeGraph = null;
- m_YAxisMs = 100f;
- s_YAxisMode = AxisMode.Max;
- m_IsOrderedByFrameDuration = false;
- m_Enabled = true;
- m_LastRect = new Rect(0, 0, 0, 0);
- m_MaxFrames = -1;
- }
- public void MakeGraphActive(bool activate)
- {
- if (activate)
- {
- if (s_CurrentSelectedGraphId != m_GraphId)
- {
- s_LastSelectedGraphId = m_GraphId;
- s_CurrentSelectedGraphId = m_GraphId;
- // Make sure we are not still selecting another graph
- GUIUtility.hotControl = 0;
- m_SetActive(true);
- }
- if (GUI.GetNameOfFocusedControl() != "FrameTimeGraph")
- {
- // Take focus away from any other control
- // Doesn't really matter what the name is here
- GUI.FocusControl("FrameTimeGraph");
- }
- }
- else
- {
- if (s_CurrentSelectedGraphId == m_GraphId)
- {
- s_CurrentSelectedGraphId = -1;
- // Remember this was the active control
- // Before this point one of the inner labels would have been active
- // GUIUtility.hotControl = m_ControlID;
- m_SetActive(false);
- }
- }
- }
- public bool IsGraphActive()
- {
- if (s_CurrentSelectedGraphId == m_GraphId)
- return true;
- if (s_LastSelectedGraphId == m_GraphId && GUIUtility.hotControl == m_ControlID)
- return true;
- return false;
- }
- public FrameTimeGraph(int graphID, Draw2D draw2D, Units units, Color background, Color backgroundSelected, Color barColor, Color barSelected, Color barMarker, Color barMarkerSelected, Color barThreads, Color barThreadsSelected, Color colorGridlines)
- {
- m_GraphId = graphID;
- m_ControlID = 0;
- m_2D = draw2D;
- SetUnits(units);
- Init();
- float ratio = 0.75f;
- m_ColorBarBackground = background;
- m_ColorBarBackgroundSelected = backgroundSelected;
- m_ColorBar = barColor;
- m_ColorBarOutOfRange = new Color(barColor.r * ratio, barColor.g * ratio, barColor.b * ratio);
- m_ColorBarSelected = barSelected;
- m_ColorBarMarker = barMarker;
- m_ColorBarMarkerOutOfRange = new Color(barMarker.r * ratio, barMarker.g * ratio, barMarker.b * ratio);
- m_ColorBarMarkerSelected = barMarkerSelected;
- m_ColorBarThreads = barThreads;
- m_ColorBarThreadsOutOfRange = new Color(barThreads.r * ratio, barThreads.g * ratio, barThreads.b * ratio);
- m_ColorBarThreadsSelected = barThreadsSelected;
- m_ColorGridLine = colorGridlines;
- }
- int ClampToRange(int value, int min, int max)
- {
- if (value < min)
- value = min;
- if (value > max)
- value = max;
- return value;
- }
- int GetDataOffsetForXUnclamped(int xPosition, int width, int totalDataSize)
- {
- int visibleDataSize;
- if (m_Zoomed)
- visibleDataSize = (m_ZoomEndOffset - m_ZoomStartOffset) + 1;
- else
- visibleDataSize = totalDataSize;
- int dataOffset = (int)(xPosition * visibleDataSize / width);
- if (m_Zoomed)
- dataOffset += m_ZoomStartOffset;
- return dataOffset;
- }
- int GetDataOffsetForX(int xPosition, int width, int totalDataSize)
- {
- //xPosition = ClampToRange(xPosition, 0, width-1);
- int dataOffset = GetDataOffsetForXUnclamped(xPosition, width, totalDataSize);
- return ClampToRange(dataOffset, 0, totalDataSize - 1);
- }
- int GetXForDataOffset(int dataOffset, int width, int totalDataSize)
- {
- //frameOffset = ClampToRange(frameOffset, 0, frames-1);
- int visibleDataSize;
- if (m_Zoomed)
- {
- dataOffset = ClampToRange(dataOffset, m_ZoomStartOffset, m_ZoomEndOffset + 1);
- dataOffset -= m_ZoomStartOffset;
- visibleDataSize = (m_ZoomEndOffset - m_ZoomStartOffset) + 1;
- }
- else
- visibleDataSize = totalDataSize;
- int x = (int)(dataOffset * width / visibleDataSize);
- x = ClampToRange(x, 0, width - 1);
- return x;
- }
- void SetDragMovement(int startOffset, int endOffset, int currentSelectionFirstDataOffset, int currentSelectionLastDataOffset)
- {
- // Maintain length but clamp to range
- int frames = m_Values.Count;
- int currentSelectionRange = currentSelectionLastDataOffset - currentSelectionFirstDataOffset;
- endOffset = startOffset + currentSelectionRange;
- startOffset = ClampToRange(startOffset, 0, frames - (currentSelectionRange + 1));
- endOffset = ClampToRange(endOffset, 0, frames - 1);
- SetDragSelection(startOffset, endOffset);
- if (m_PairedWithFrameTimeGraph != null && !m_SingleControlAction)
- {
- m_PairedWithFrameTimeGraph.SetDragSelection(m_DragFirstOffset, m_DragLastOffset);
- }
- }
- void SetDragSelection(int startOffset, int endOffset, DragDirection dragDirection)
- {
- // No need to clamp these as input is clamped.
- switch (dragDirection)
- {
- case DragDirection.Forward:
- SetDragSelection(m_DragBeginFirstOffset, endOffset);
- break;
- case DragDirection.Backward:
- SetDragSelection(startOffset, m_DragBeginLastOffset);
- break;
- case DragDirection.Start:
- SetDragSelection(startOffset, endOffset);
- // Record first selected bar range
- m_DragBeginFirstOffset = m_DragFirstOffset;
- m_DragBeginLastOffset = m_DragLastOffset;
- break;
- }
- if (m_PairedWithFrameTimeGraph != null && !m_SingleControlAction)
- {
- m_PairedWithFrameTimeGraph.SetDragSelection(m_DragFirstOffset, m_DragLastOffset);
- }
- }
- public void SetDragSelection(int startOffset, int endOffset)
- {
- m_DragFirstOffset = startOffset;
- m_DragLastOffset = endOffset;
- }
- public void ClearDragSelection()
- {
- m_DragFirstOffset = -1;
- m_DragLastOffset = -1;
- }
- public bool HasDragRegion()
- {
- return (m_DragFirstOffset != -1);
- }
- public void GetSelectedRange(List<int> frameOffsets, out int firstDataOffset, out int lastDataOffset, out int firstFrameOffset, out int lastFrameOffset)
- {
- int frames = m_Values != null ? m_Values.Count : 0;
- firstDataOffset = 0;
- lastDataOffset = frames - 1;
- firstFrameOffset = 0;
- lastFrameOffset = frames - 1;
- if (m_FrameOffsetToDataOffsetMapping.Length > 0)
- {
- // By default data is ordered by index so first/last will be the selected visible range
- if (frameOffsets.Count >= 1)
- {
- firstFrameOffset = frameOffsets[0];
- lastFrameOffset = firstFrameOffset;
- firstDataOffset = GetDataOffset(firstFrameOffset);
- lastDataOffset = firstDataOffset;
- }
- if (frameOffsets.Count >= 2)
- {
- lastFrameOffset = frameOffsets[frameOffsets.Count - 1];
- lastDataOffset = GetDataOffset(lastFrameOffset);
- }
- if (m_GlobalSettings.showOrderedByFrameDuration)
- {
- // Need to find the selected items with lowest and highest ms values
- if (frameOffsets.Count > 0)
- {
- int dataOffset = GetDataOffset(firstFrameOffset);
- firstDataOffset = dataOffset;
- lastDataOffset = dataOffset;
- float firstDataMS = m_Values[dataOffset].ms;
- float lastDataMS = m_Values[dataOffset].ms;
- foreach (int frameOffset in frameOffsets)
- {
- dataOffset = GetDataOffset(frameOffset);
- float ms = m_Values[dataOffset].ms;
- if (ms <= firstDataMS && dataOffset < firstDataOffset)
- {
- firstDataMS = ms;
- firstDataOffset = dataOffset;
- }
- if (ms >= lastDataMS && dataOffset > lastDataOffset)
- {
- lastDataMS = ms;
- lastDataOffset = dataOffset;
- }
- }
- }
- }
- }
- }
- public bool IsMultiSelectControlHeld()
- {
- #if UNITY_EDITOR_OSX
- return Event.current.command;
- #else
- return Event.current.control;
- #endif
- }
- public State ProcessInput()
- {
- if (!IsEnabled())
- return State.None;
- if (m_Values == null)
- return State.None;
- if (m_LastRect.width == 0 || m_MaxFrames < 0)
- return State.None;
- Rect rect = m_LastRect;
- int maxFrames = m_MaxFrames;
- int dataLength = m_Values.Count;
- if (dataLength <= 0)
- return State.None;
- if (m_IsOrderedByFrameDuration != m_GlobalSettings.showOrderedByFrameDuration)
- {
- // Reorder if necessary
- SetData(m_Values);
- }
- int currentSelectionFirstDataOffset;
- int currentSelectionLastDataOffset;
- int currentSelectionFirstFrameOffset;
- int currentSelectionLastFrameOffset;
- GetSelectedRange(m_LastSelectedFrameOffsets, out currentSelectionFirstDataOffset, out currentSelectionLastDataOffset, out currentSelectionFirstFrameOffset, out currentSelectionLastFrameOffset);
- m_CurrentSelection.Clear();
- m_CurrentSelection.AddRange(m_LastSelectedFrameOffsets);
- m_CurrentSelectionFirstDataOffset = currentSelectionFirstDataOffset;
- m_CurrentSelectionLastDataOffset = currentSelectionLastDataOffset;
- if (Event.current.isKey && Event.current.type == EventType.KeyDown && !m_Dragging && !m_MouseReleased)
- {
- if (IsGraphActive())
- {
- int step = Event.current.shift ? 10 : 1;
- var eventUsed = false;
- switch (Event.current.keyCode)
- {
- case KeyCode.LeftArrow:
- SelectPrevious(step);
- eventUsed = true;
- break;
- case KeyCode.RightArrow:
- SelectNext(step);
- eventUsed = true;
- break;
- case KeyCode.Less:
- case KeyCode.Comma:
- if (Event.current.alt)
- SelectShrinkLeft(step);
- else
- SelectGrowLeft(step);
- eventUsed = true;
- break;
- case KeyCode.Greater:
- case KeyCode.Period:
- if (Event.current.alt)
- SelectShrinkRight(step);
- else
- SelectGrowRight(step);
- eventUsed = true;
- break;
- case KeyCode.Plus:
- case KeyCode.Equals:
- case KeyCode.KeypadPlus:
- if (Event.current.alt)
- SelectShrink(step);
- else
- SelectGrow(step);
- eventUsed = true;
- break;
- case KeyCode.Underscore:
- case KeyCode.Minus:
- case KeyCode.KeypadMinus:
- if (Event.current.alt)
- SelectGrow(step);
- else
- SelectShrink(step);
- eventUsed = true;
- break;
- }
- if (eventUsed)
- Event.current.Use();
- }
- }
- float doubleClickTimeout = 0.25f;
- if (m_MouseReleased)
- {
- if ((EditorApplication.timeSinceStartup - m_LastClickTime) > doubleClickTimeout)
- {
- // By this point we will know if its a single or double click
- bool append = IsMultiSelectControlHeld();
- CallSetRange(m_DragFirstOffset, m_DragLastOffset, m_ClickCount, m_SingleControlAction, FrameTimeGraph.State.DragComplete, append);
- ClearDragSelection();
- if (m_PairedWithFrameTimeGraph != null && !m_SingleControlAction)
- m_PairedWithFrameTimeGraph.ClearDragSelection();
- m_MouseReleased = false;
- }
- }
- int width = (int)rect.width;
- int height = (int)rect.height;
- float xStart = rect.xMin;
- if (height > kYAxisDetailThreshold)
- {
- float h = GUI.skin.label.lineHeight;
- xStart += kXAxisWidth;
- width -= kXAxisWidth;
- }
- if (maxFrames > 0)
- {
- if (!m_Zoomed)
- width = width * dataLength / maxFrames;
- }
- // Process input
- Event e = Event.current;
- if (e.isMouse)
- {
- if (m_Dragging)
- {
- if (e.type == EventType.MouseUp)
- {
- m_Dragging = false;
- m_Moving = false;
- // Delay the action as we are checking for double click
- m_MouseReleased = true;
- return State.Dragging;
- }
- }
- int x = (int)(e.mousePosition.x - xStart);
- int dataOffset = GetDataOffsetForXUnclamped(x, width, dataLength);
- if (m_Moving)
- dataOffset -= m_MoveHandleOffset;
- dataOffset = ClampToRange(dataOffset, 0, dataLength - 1);
- int frameOffsetBeforeNext = Math.Max(dataOffset, GetDataOffsetForX(x + 1, width, dataLength) - 1);
- if (m_Dragging)
- {
- if (e.button == 0)
- {
- // Still dragging (doesn't have to be within the y bounds)
- if (m_Moving)
- {
- // Forward drag from start point
- SetDragMovement(dataOffset, frameOffsetBeforeNext, currentSelectionFirstDataOffset, currentSelectionLastDataOffset);
- }
- else
- {
- DragDirection dragDirection = (dataOffset < m_DragBeginFirstOffset) ? DragDirection.Backward : DragDirection.Forward;
- SetDragSelection(dataOffset, frameOffsetBeforeNext, dragDirection);
- }
- CallSetRange(m_DragFirstOffset, m_DragLastOffset, m_ClickCount, m_SingleControlAction, FrameTimeGraph.State.Dragging);
- return State.Dragging;
- }
- }
- else
- {
- if (e.mousePosition.x >= rect.x && e.mousePosition.x <= rect.xMax &&
- e.mousePosition.y >= rect.y && e.mousePosition.y <= rect.yMax)
- {
- if (e.mousePosition.x >= xStart && e.mousePosition.x <= (xStart + width) &&
- e.mousePosition.y >= rect.y && e.mousePosition.y < rect.yMax)
- {
- MakeGraphActive(true);
- if (e.type == EventType.MouseDown && e.button == 0)
- {
- // Drag start (must be within the bounds of the control)
- // Might be single or double click
- m_LastClickTime = EditorApplication.timeSinceStartup;
- m_ClickCount = e.clickCount;
- m_Dragging = true;
- m_Moving = false;
- if (currentSelectionFirstDataOffset != 0 || currentSelectionLastDataOffset != dataLength - 1)
- {
- // Selection is valid
- if (e.shift && dataOffset >= currentSelectionFirstDataOffset && frameOffsetBeforeNext <= currentSelectionLastDataOffset)
- {
- // Moving if shift held and we are inside the current selection range
- m_Moving = true;
- }
- }
- if (m_PairedWithFrameTimeGraph != null)
- m_SingleControlAction = e.alt; // Record if we are acting only on this control rather than the paired one too
- else
- m_SingleControlAction = true;
- if (m_Moving)
- {
- m_MoveHandleOffset = dataOffset - currentSelectionFirstDataOffset;
- SetDragMovement(currentSelectionFirstDataOffset, currentSelectionLastDataOffset, currentSelectionFirstDataOffset, currentSelectionLastDataOffset);
- }
- else
- {
- //SetDragSelection(dataOffset, frameOffsetBeforeNext, DragDirection.Start);
- // Select just 1 frame
- SetDragSelection(dataOffset, dataOffset, DragDirection.Start);
- }
- CallSetRange(m_DragFirstOffset, m_DragLastOffset, m_ClickCount, m_SingleControlAction, FrameTimeGraph.State.Dragging);
- return State.Dragging;
- }
- }
- }
- else
- {
- // Left this graph area
- MakeGraphActive(false);
- }
- }
- }
- if (m_MouseReleased)
- {
- // Not finished drag fully yet
- CallSetRange(m_DragFirstOffset, m_DragLastOffset, m_ClickCount, m_SingleControlAction, FrameTimeGraph.State.Dragging);
- return State.Dragging;
- }
- return State.None;
- }
- public float GetDataRange()
- {
- if (m_Values == null)
- return 0f;
- int frames = m_Values.Count;
- float min = 0f;
- float max = 0f;
- for (int frameOffset = 0; frameOffset < frames; frameOffset++)
- {
- float ms = m_Values[frameOffset].ms;
- if (ms > max)
- max = ms;
- }
- float hRange = max - min;
- return hRange;
- }
- public void PairWith(FrameTimeGraph otherFrameTimeGraph)
- {
- if (m_PairedWithFrameTimeGraph != null)
- {
- // Clear existing pairing
- m_PairedWithFrameTimeGraph.m_PairedWithFrameTimeGraph = null;
- }
- m_PairedWithFrameTimeGraph = otherFrameTimeGraph;
- if (otherFrameTimeGraph != null)
- otherFrameTimeGraph.m_PairedWithFrameTimeGraph = this;
- }
- public FrameTimeGraph GetPairedWith()
- {
- return m_PairedWithFrameTimeGraph;
- }
- public float GetYAxisRange(float yMax)
- {
- switch (s_YAxisMode)
- {
- case AxisMode.One60HzFrame:
- return 1000f / 60f;
- case AxisMode.Two60HzFrames:
- return 2000f / 60f;
- case AxisMode.Four60HzFrames:
- return 4000f / 60f;
- case AxisMode.Max:
- return yMax;
- case AxisMode.Custom:
- return m_YAxisMs;
- }
- return yMax;
- }
- public void SetData(List<Data> values)
- {
- if (values == null)
- return;
- m_Values = values;
- if (m_GlobalSettings.showOrderedByFrameDuration)
- m_Values.Sort((a, b) => { return a.ms.CompareTo(b.ms); });
- else
- m_Values.Sort((a, b) => { return a.frameOffset.CompareTo(b.frameOffset); });
- m_FrameOffsetToDataOffsetMapping = new int[m_Values.Count];
- for (int dataOffset = 0; dataOffset < m_Values.Count; dataOffset++)
- m_FrameOffsetToDataOffsetMapping[m_Values[dataOffset].frameOffset] = dataOffset;
- m_CurrentSelection.Clear();
- for (int frameIndex = 0; frameIndex < m_Values.Count; frameIndex++)
- {
- m_CurrentSelection.Add(frameIndex);
- }
- m_CurrentSelectionFirstDataOffset = 0;
- m_CurrentSelectionLastDataOffset = m_Values.Count - 1;
- m_IsOrderedByFrameDuration = m_GlobalSettings.showOrderedByFrameDuration;
- }
- int GetDataOffset(int frameOffset)
- {
- if (frameOffset < 0 || frameOffset >= m_FrameOffsetToDataOffsetMapping.Length)
- {
- Debug.Log(string.Format("{0} out of range of frame offset to data offset mapping {1}", frameOffset, m_FrameOffsetToDataOffsetMapping.Length));
- return 0;
- }
- return m_FrameOffsetToDataOffsetMapping[frameOffset];
- }
- public bool HasData()
- {
- if (m_Values == null)
- return false;
- if (m_Values.Count == 0)
- return false;
- return true;
- }
- public void SetActiveCallback(SetActive setActive)
- {
- m_SetActive = setActive;
- }
- public void SetRangeCallback(SetRange setRange)
- {
- m_SetRange = setRange;
- }
- void CallSetRange(int startDataOffset, int endDataOffset, int clickCount, bool singleControlAction, FrameTimeGraph.State inputStatus, bool append = false, bool effectPaired = true)
- {
- if (m_SetRange == null)
- return;
- if (startDataOffset < 0 && endDataOffset < 0)
- {
- // Clear
- m_SetRange(new List<int>(), clickCount, inputStatus);
- return;
- }
- startDataOffset = Math.Max(0, startDataOffset);
- endDataOffset = Math.Min(endDataOffset, m_Values.Count - 1);
- List<int> selected = new List<int>();
- if (append && m_LastSelectedFrameOffsets.Count != m_Values.Count)
- {
- foreach (int frameOffset in m_LastSelectedFrameOffsets)
- {
- int dataOffset = m_FrameOffsetToDataOffsetMapping[frameOffset];
- if (dataOffset >= 0 && dataOffset < m_Values.Count)
- {
- selected.Add(frameOffset);
- }
- }
- }
- for (int dataOffset = startDataOffset; dataOffset <= endDataOffset; dataOffset++)
- {
- if (dataOffset >= 0 && dataOffset < m_Values.Count)
- {
- int frameOffset = m_Values[dataOffset].frameOffset;
- if (append == false || !selected.Contains(frameOffset))
- {
- selected.Add(frameOffset);
- }
- }
- }
- // Sort selection in frame index order so start is lowest and end is highest
- selected.Sort();
- if (selected.Count == 0)
- return;
- m_SetRange(selected, clickCount, inputStatus);
- if (m_PairedWithFrameTimeGraph != null && m_PairedWithFrameTimeGraph.m_Values.Count > 1 && effectPaired && !singleControlAction)
- {
- // Update selection on the other frame time graph
- int mainMaxFrame = m_Values.Count - 1;
- int otherMaxFrame = m_PairedWithFrameTimeGraph.m_Values.Count - 1;
- int startOffset = startDataOffset;
- int endOffset = endDataOffset;
- if (startOffset > otherMaxFrame)
- {
- if (append)
- {
- // Nothing more to do
- return;
- }
- // Select all, if the main selection is outsize the range of the other
- startOffset = 0;
- endOffset = otherMaxFrame;
- }
- else
- {
- if (startOffset == 0 && endOffset == mainMaxFrame)
- {
- // If clearing main selection then clear the other section fully too
- endOffset = otherMaxFrame;
- }
- startOffset = ClampToRange(startOffset, 0, otherMaxFrame);
- endOffset = ClampToRange(endOffset, 0, otherMaxFrame);
- }
- m_PairedWithFrameTimeGraph.CallSetRange(startOffset, endOffset, clickCount, singleControlAction, inputStatus, append, false);
- }
- }
- bool HasNoSelection()
- {
- if (m_Values == null)
- return false;
- int frames = m_Values.Count;
- return ((m_CurrentSelectionFirstDataOffset < 0 || m_CurrentSelectionLastDataOffset >= frames) &&
- (m_CurrentSelectionLastDataOffset < 0 || m_CurrentSelectionLastDataOffset >= frames));
- }
- bool HasSelectedAll()
- {
- if (m_Values == null)
- return false;
- int frames = m_Values.Count;
- return (m_CurrentSelectionFirstDataOffset == 0 && m_CurrentSelectionLastDataOffset == (frames - 1));
- }
- bool HasSubsetSelected()
- {
- if (m_Values == null)
- return false;
- return !(HasSelectedAll() || HasNoSelection());
- }
- void RegenerateBars(float x, float y, float width, float height, float yRange)
- {
- int frames = m_Values.Count;
- if (frames <= 0)
- return;
- m_Bars.Clear();
- int nextDataOffset = GetDataOffsetForX(0, (int)width, frames);
- for (int barX = 0; barX < width; barX++)
- {
- int startDataOffset = nextDataOffset;
- nextDataOffset = GetDataOffsetForX(barX + 1, (int)width, frames);
- int endDataOffset = Math.Max(startDataOffset, nextDataOffset - 1);
- float min = m_Values[startDataOffset].ms;
- float max = min;
- for (int dataOffset = startDataOffset + 1; dataOffset <= endDataOffset; dataOffset++)
- {
- float ms = m_Values[dataOffset].ms;
- if (ms < min)
- min = ms;
- if (ms > max)
- max = ms;
- }
- float maxClamped = Math.Min(max, yRange);
- float h = height * maxClamped / yRange;
- m_Bars.Add(new BarData(x + barX, y, 1, h, startDataOffset, endDataOffset, min, max));
- }
- }
- public void SetEnabled(bool enabled)
- {
- m_Enabled = enabled;
- }
- public bool IsEnabled()
- {
- return m_Enabled;
- }
- float GetTotalSelectionTime(List<int> selectedFrameOffsets)
- {
- float totalMs = 0;
- for (int i = 0; i < selectedFrameOffsets.Count; i++)
- {
- int frameOffset = selectedFrameOffsets[i];
- int dataOffset = m_FrameOffsetToDataOffsetMapping[frameOffset];
- totalMs += m_Values[dataOffset].ms;
- }
- return totalMs;
- }
- float GetTotalSelectionTime(int firstOffset, int lastOffset)
- {
- float totalMs = 0;
- for (int frameOffset = firstOffset; frameOffset <= lastOffset; frameOffset++)
- {
- if (frameOffset < m_FrameOffsetToDataOffsetMapping.Length)
- {
- int dataOffset = m_FrameOffsetToDataOffsetMapping[frameOffset];
- totalMs += m_Values[dataOffset].ms;
- }
- }
- return totalMs;
- }
- void ShowFrameLines(float x, float y, float yRange, float width, float height)
- {
- float msSegment = 1000f / 60f;
- int lines = (int)(yRange / msSegment);
- int step = 1;
- for (int line = 1; line <= lines; line += step, step *= 2)
- {
- float ms = line * msSegment;
- float h = height * ms / yRange;
- m_2D.DrawLine(x, y + h, x + width - 1, y + h, m_ColorGridLine);
- }
- }
- bool InSelectedRegion(int startDataOffset, int endDataOffset, int selectedFirstOffset, int selectedLastOffset, Dictionary<int, int> frameOffsetToSelectionIndex, bool subsetSelected)
- {
- bool inSelectionRegion = false;
- bool showCurrentSelection = false;
- if (HasDragRegion())
- {
- if (endDataOffset >= selectedFirstOffset && startDataOffset <= selectedLastOffset)
- {
- inSelectionRegion = true;
- }
- if (IsMultiSelectControlHeld() && m_LastSelectedFrameOffsets.Count != m_Values.Count)
- {
- // Show current selection too
- showCurrentSelection = true;
- }
- }
- else
- {
- showCurrentSelection = true;
- }
- if (showCurrentSelection)
- {
- //if (subsetSelected)
- {
- for (int dataOffset = startDataOffset; dataOffset <= endDataOffset; dataOffset++)
- {
- int frameOffset = m_Values[dataOffset].frameOffset;
- if (frameOffsetToSelectionIndex.ContainsKey(frameOffset))
- {
- inSelectionRegion = true;
- break;
- }
- }
- }
- }
- return inSelectionRegion;
- }
- public void Draw(Rect rect, ProfileAnalysis analysis, List<int> selectedFrameOffsets, float yMax, int offsetToDisplayMapping, int offsetToIndexMapping, string selectedMarkerName, int maxFrames = 0, ProfileAnalysis fullAnalysis = null)
- {
- Profiler.BeginSample("FrameTimeGraph.Draw");
- // Must be outside repaint to make sure next controls work correctly (specifically marker name filter)
- int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
- if (Event.current.type == EventType.Repaint)
- {
- m_LastRect = rect;
- // Control id would change during non repaint phase if tooltips displayed if we update this outside the repaint
- m_ControlID = controlID;
- }
- m_MaxFrames = maxFrames;
- if (m_Values == null)
- return;
- m_LastSelectedFrameOffsets = selectedFrameOffsets;
- int totalDataSize = m_Values.Count;
- if (totalDataSize <= 0)
- return;
- if (m_IsOrderedByFrameDuration != m_GlobalSettings.showOrderedByFrameDuration)
- {
- // Reorder if necessary
- SetData(m_Values);
- }
- // Get start and end selection span
- int currentSelectionFirstDataOffset;
- int currentSelectionLastDataOffset;
- int currentSelectionFirstFrameOffset;
- int currentSelectionLastFrameOffset;
- GetSelectedRange(selectedFrameOffsets, out currentSelectionFirstDataOffset, out currentSelectionLastDataOffset, out currentSelectionFirstFrameOffset, out currentSelectionLastFrameOffset);
- // Create mapping from offset to selection for faster selection detection
- Dictionary<int, int> frameOffsetToSelectionIndex = new Dictionary<int, int>();
- for (int i = 0; i < selectedFrameOffsets.Count; i++)
- {
- int frameOffset = selectedFrameOffsets[i];
- frameOffsetToSelectionIndex[frameOffset] = i;
- }
- Event current = Event.current;
- int selectedFirstOffset;
- int selectedLastOffset;
- int selectedCount;
- bool subsetSelected = false;
- if (HasDragRegion())
- {
- selectedFirstOffset = m_DragFirstOffset;
- selectedLastOffset = m_DragLastOffset;
- if (selectedFirstOffset > m_Values.Count - 1)
- {
- // Selection off the end
- selectedFirstOffset = m_Values.Count;
- selectedLastOffset = m_Values.Count;
- selectedCount = 0;
- }
- else
- {
- selectedFirstOffset = ClampToRange(selectedFirstOffset, 0, m_Values.Count - 1);
- selectedLastOffset = ClampToRange(selectedLastOffset, 0, m_Values.Count - 1);
- selectedCount = 1 + (selectedLastOffset - selectedFirstOffset);
- subsetSelected = true;
- }
- }
- else
- {
- selectedFirstOffset = currentSelectionFirstDataOffset;
- selectedLastOffset = currentSelectionLastDataOffset;
- selectedCount = selectedFrameOffsets.Count;
- subsetSelected = (selectedCount > 0 && selectedCount != totalDataSize);
- }
- // Draw frames and selection
- float width = rect.width;
- float height = rect.height;
- bool showAxis = false;
- float xStart = 0f;
- float yStart = 0f;
- if (height > kYAxisDetailThreshold)
- {
- showAxis = true;
- float h = GUI.skin.label.lineHeight;
- xStart += kXAxisWidth;
- width -= kXAxisWidth;
- yStart += h;
- height -= h;
- }
- if (maxFrames > 0)
- {
- if (!m_Zoomed)
- width = width * totalDataSize / maxFrames;
- }
- // Start / End
- int startOffset = m_Zoomed ? m_ZoomStartOffset : 0;
- int endOffset = m_Zoomed ? m_ZoomEndOffset : totalDataSize - 1;
- // Get try index values
- int startIndex = offsetToDisplayMapping + startOffset;
- int endIndex = offsetToDisplayMapping + endOffset;
- int selectedFirstIndex = offsetToDisplayMapping + selectedFirstOffset;
- int selectedLastIndex = offsetToDisplayMapping + selectedLastOffset;
- string detailsString = "";
- if (!showAxis)
- {
- string frameRangeString;
- if (startIndex == endIndex)
- frameRangeString = string.Format("Total Range {0}", startIndex);
- else
- frameRangeString = string.Format("Total Range {0} - {1} [{2}]", startIndex, endIndex, 1 + (endIndex - startIndex));
- // Selection range
- string selectedTooltip = "";
- if (subsetSelected)
- {
- if (selectedFirstIndex == selectedLastIndex)
- selectedTooltip = string.Format("\nSelected {0}\n", selectedFirstIndex);
- else
- selectedTooltip = string.Format("\nSelected {0} - {1} [{2}]", selectedFirstIndex, selectedLastIndex, selectedCount);
- }
- detailsString = string.Format("\n\n{0}{1}", frameRangeString, selectedTooltip);
- }
- float yRange = GetYAxisRange(yMax);
- bool lastEnabled = GUI.enabled;
- bool enabled = IsEnabled();
- GUI.enabled = enabled;
- if (m_2D.DrawStart(rect, Draw2D.Origin.BottomLeft))
- {
- float totalMs;
- if (HasDragRegion())
- {
- totalMs = GetTotalSelectionTime(selectedFirstOffset, selectedLastOffset);
- }
- else
- {
- totalMs = GetTotalSelectionTime(selectedFrameOffsets);
- }
- string timeForSelectedFrames = ToDisplayUnits(totalMs, true, 0);
- string timeForSelectedFramesClamped = ToDisplayUnits(totalMs, true, 1);
- string selectionAreaString = string.Format("\n\nTotal time for {0} selected frames\n{1} ({2})", selectedCount, timeForSelectedFrames, timeForSelectedFramesClamped);
- Color selectedControl = GUI.skin.settings.selectionColor;
- if (IsGraphActive())
- {
- m_2D.DrawBox(xStart, yStart, width, height, selectedControl);
- }
- //xStart -= 1f;
- yStart += 1f;
- width -= 1f;
- height -= 1f;
- m_2D.DrawFilledBox(xStart, yStart, width, height, m_ColorBarBackground);
- RegenerateBars(xStart, yStart, width, height, yRange);
- foreach (BarData bar in m_Bars)
- {
- bool inSelectionRegion = InSelectedRegion(bar.startDataOffset, bar.endDataOffset, selectedFirstOffset, selectedLastOffset, frameOffsetToSelectionIndex, subsetSelected);
- if (inSelectionRegion)
- {
- m_2D.DrawFilledBox(bar.x, bar.y, bar.w, height, m_ColorBarBackgroundSelected);
- }
- }
- if (m_GlobalSettings.showFrameLines)
- {
- ShowFrameLines(xStart, yStart, yRange, width, height);
- }
- ProfileAnalysis analysisData = analysis;
- bool full = false;
- if (fullAnalysis != null)
- {
- analysisData = fullAnalysis;
- full = true;
- }
- MarkerData selectedMarker = (m_GlobalSettings.showSelectedMarker && analysisData != null) ? analysisData.GetMarkerByName(selectedMarkerName) : null;
- foreach (BarData bar in m_Bars)
- {
- bool inSelectionRegion = InSelectedRegion(bar.startDataOffset, bar.endDataOffset, selectedFirstOffset, selectedLastOffset, frameOffsetToSelectionIndex, subsetSelected);
- if (inSelectionRegion)
- {
- m_2D.DrawFilledBox(bar.x, bar.y, bar.w, bar.h, m_ColorBarSelected);
- }
- else
- {
- m_2D.DrawFilledBox(bar.x, bar.y, bar.w, bar.h, m_ColorBar);
- }
- // Show where its been clamped
- if (bar.yMax > yRange)
- {
- m_2D.DrawFilledBox(bar.x, bar.y + height, 1, kOverrunHeight, m_ColorBarOutOfRange);
- }
- if (analysisData != null && (full || !m_Dragging))
- {
- // Analysis is just on the subset
- if (m_GlobalSettings.showThreads)
- {
- Profiler.BeginSample("FrameTimeGraph.ShowThreads");
- ShowThreads(height, yRange, bar, full,
- analysisData.GetThreads(), subsetSelected, selectedFirstOffset, selectedLastOffset,
- offsetToIndexMapping, frameOffsetToSelectionIndex);
- Profiler.EndSample();
- }
- if (m_GlobalSettings.showSelectedMarker)
- {
- // Analysis is just on the subset (unless we have full analysis data)
- ShowSelectedMarker(height, yRange, bar, full, selectedMarker, subsetSelected, selectedFirstOffset, selectedLastOffset,
- offsetToIndexMapping, frameOffsetToSelectionIndex);
- }
- }
- }
- m_2D.DrawEnd();
- if (m_GlobalSettings.showFrameLines && m_GlobalSettings.showFrameLineText)
- {
- ShowFrameLinesText(rect, xStart, yStart, yRange, width, height, subsetSelected, selectedFirstOffset, selectedLastOffset);
- }
- foreach (BarData bar in m_Bars)
- {
- bool inSelectionRegion = InSelectedRegion(bar.startDataOffset, bar.endDataOffset, selectedFirstOffset, selectedLastOffset, frameOffsetToSelectionIndex, subsetSelected);
- // Draw tooltip for bar (or 1 pixel segment of bar)
- {
- int barStartIndex = offsetToDisplayMapping + m_Values[bar.startDataOffset].frameOffset;
- int barEndIndex = offsetToDisplayMapping + m_Values[bar.endDataOffset].frameOffset;
- string tooltip;
- if (barStartIndex == barEndIndex)
- tooltip = string.Format("Frame {0}\n{1}{2}", barStartIndex, ToDisplayUnits(bar.yMax, true), detailsString);
- else
- tooltip = string.Format("Frame {0}-{1}\n{2} max\n{3} min{4}", barStartIndex, barEndIndex, ToDisplayUnits(bar.yMax, true), ToDisplayUnits(bar.yMin, true), detailsString);
- if (inSelectionRegion)
- tooltip += selectionAreaString;
- GUI.Label(new Rect(rect.x + bar.x, rect.y + 5, bar.w, height), new GUIContent("", tooltip));
- }
- }
- }
- GUI.enabled = lastEnabled;
- if (showAxis)
- {
- int zoomedSelectedFirstOffset = selectedFirstOffset;
- int zoomedSelectedLastOffset = selectedLastOffset;
- int zoomedSelectedCount = selectedCount;
- if (m_Zoomed)
- {
- if (selectedFirstOffset > endOffset || selectedLastOffset < startOffset)
- {
- zoomedSelectedCount = 0;
- }
- else
- {
- // Clamp selection range to zoom range
- zoomedSelectedFirstOffset = ClampToRange(selectedFirstOffset, startOffset, endOffset);
- zoomedSelectedLastOffset = ClampToRange(selectedLastOffset, startOffset, endOffset);
- if (HasDragRegion())
- {
- zoomedSelectedCount = 1 + (zoomedSelectedLastOffset - zoomedSelectedFirstOffset);
- }
- else
- {
- zoomedSelectedCount = 0;
- foreach (var offset in selectedFrameOffsets)
- {
- if (offset >= startOffset && offset <= endOffset)
- {
- zoomedSelectedCount++;
- }
- }
- }
- }
- }
- ShowAxis(rect, xStart, width, startOffset, endOffset, zoomedSelectedFirstOffset, zoomedSelectedLastOffset, zoomedSelectedCount, selectedCount, yMax, totalDataSize, offsetToDisplayMapping);
- }
- GUI.enabled = enabled;
- if (rect.Contains(current.mousePosition) && current.type == EventType.ContextClick)
- {
- var analytic = ProfileAnalyzerAnalytics.BeginAnalytic();
- ShowContextMenu(subsetSelected, selectedCount);
- current.Use();
- ProfileAnalyzerAnalytics.SendUIVisibilityEvent(ProfileAnalyzerAnalytics.UIVisibility.FrameTimeContextMenu, analytic.GetDurationInSeconds(), true);
- }
- GUI.enabled = lastEnabled;
- Profiler.EndSample();
- }
- void ShowThreads(float height, float yRange, BarData bar, bool full,
- List<ThreadData> threads, bool subsetSelected, int selectedFirstOffset, int selectedLastOffset,
- int offsetToIndexMapping, Dictionary<int, int> frameOffsetToSelectionIndex)
- {
- float max = float.MinValue;
- bool selected = false;
- for (int dataOffset = bar.startDataOffset; dataOffset <= bar.endDataOffset; dataOffset++)
- {
- int frameOffset = m_Values[dataOffset].frameOffset;
- if (!full && !frameOffsetToSelectionIndex.ContainsKey(frameOffset))
- continue;
- float threadMs = 0f;
- foreach (var thread in threads)
- {
- int frameIndex = offsetToIndexMapping + frameOffset;
- var frame = thread.GetFrame(frameIndex);
- if (frame == null)
- continue;
- float ms = frame.Value.ms;
- if (ms > threadMs)
- threadMs = ms;
- }
- if (threadMs > max)
- max = threadMs;
- if (m_Dragging)
- {
- if (frameOffset >= selectedFirstOffset && frameOffset <= selectedLastOffset)
- selected = true;
- }
- else if (subsetSelected)
- {
- if (frameOffsetToSelectionIndex.ContainsKey(frameOffset))
- selected = true;
- }
- }
- if (full || selected)
- {
- // Clamp to frame time (these values can be time summed over multiple threads)
- if (max > bar.yMax)
- max = bar.yMax;
- float maxClamped = Math.Min(max, yRange);
- float h = height * maxClamped / yRange;
- m_2D.DrawFilledBox(bar.x, bar.y, bar.w, h, selected ? m_ColorBarThreadsSelected : m_ColorBarThreads);
- // Show where its been clamped
- if (max > yRange)
- {
- m_2D.DrawFilledBox(bar.x, bar.y + height, bar.w, kOverrunHeight, m_ColorBarThreadsOutOfRange);
- }
- }
- }
- void ShowSelectedMarker(float height, float yRange, BarData bar, bool full,
- MarkerData selectedMarker, bool subsetSelected, int selectedFirstOffset, int selectedLastOffset,
- int offsetToIndexMapping, Dictionary<int, int> frameOffsetToSelectionIndex)
- {
- float max = 0f;
- bool selected = false;
- if (selectedMarker != null)
- {
- for (int dataOffset = bar.startDataOffset; dataOffset <= bar.endDataOffset; dataOffset++)
- {
- int frameOffset = m_Values[dataOffset].frameOffset;
- if (!full && !frameOffsetToSelectionIndex.ContainsKey(frameOffset))
- continue;
- float ms = selectedMarker.GetFrameMs(offsetToIndexMapping + frameOffset);
- if (ms > max)
- max = ms;
- if (m_Dragging)
- {
- if (frameOffset >= selectedFirstOffset && frameOffset <= selectedLastOffset)
- selected = true;
- }
- else if (subsetSelected)
- {
- if (frameOffsetToSelectionIndex.ContainsKey(frameOffset))
- selected = true;
- }
- }
- }
- if (full || selected)
- {
- // Clamp to frame time (these values can be tiem summed over multiple threads)
- if (max > bar.yMax)
- max = bar.yMax;
- float maxClamped = Math.Min(max, yRange);
- float h = height * maxClamped / yRange;
- m_2D.DrawFilledBox(bar.x, bar.y, bar.w, h, selected ? m_ColorBarMarkerSelected : m_ColorBarMarker);
- if (max > 0f)
- {
- // we start the bar lower so that very small markers still show up.
- m_2D.DrawFilledBox(bar.x, bar.y - kOverrunHeight, bar.w, kOverrunHeight, m_ColorBarMarkerOutOfRange);
- }
- // Show where its been clamped
- if (max > yRange)
- {
- m_2D.DrawFilledBox(bar.x, bar.y + height, bar.w, kOverrunHeight, m_ColorBarMarkerOutOfRange);
- }
- }
- }
- void ShowFrameLinesText(Rect rect, float xStart, float yStart, float yRange, float width, float height, bool subsetSelected, int selectedFirstOffset, int selectedLastOffset)
- {
- int totalDataSize = m_Values.Count;
- float y = yStart;
- float msSegment = 1000f / 60f;
- int lines = (int)(yRange / msSegment);
- int step = 1;
- for (int line = 1; line <= lines; line += step, step *= 2)
- {
- float ms = line * msSegment;
- float h = height * ms / yRange;
- int edgePad = 3;
- if (h >= (height / 4) && h < (height - GUI.skin.label.lineHeight))
- {
- GUIContent content = new GUIContent(ToDisplayUnits((float)Math.Floor(ms), true, 0));
- Vector2 size = EditorStyles.miniTextField.CalcSize(content);
- bool left = true;
- if (subsetSelected)
- {
- float x = GetXForDataOffset(selectedFirstOffset, (int)width, totalDataSize);
- float x2 = GetXForDataOffset(selectedLastOffset + 1, (int)width, totalDataSize);
- // text would overlap selection so move it if that prevents overlap
- if (left)
- {
- if (x < (size.x + edgePad) && x2 < (width - (size.x + edgePad)))
- left = false;
- }
- else
- {
- if (x > (size.x + edgePad) && x2 > (width - (size.x + edgePad)))
- left = true;
- }
- }
- Rect r;
- if (left)
- r = new Rect(rect.x + (xStart + edgePad), (rect.y - y) + (height - h), size.x, EditorStyles.miniTextField.lineHeight);
- else
- r = new Rect(rect.x + (xStart + width) - (size.x + edgePad), (rect.y - y) + (height - h), size.x, EditorStyles.miniTextField.lineHeight);
- GUI.Label(r, content, EditorStyles.miniTextField);
- }
- }
- }
- void ShowSelectionMenuItem(bool subsetSelected, GenericMenu menu, GUIContent style, bool state, GenericMenu.MenuFunction func)
- {
- if (subsetSelected)
- menu.AddItem(style, state, func);
- else
- menu.AddDisabledItem(style);
- }
- void ShowContextMenu(bool subsetSelected, int selectionCount)
- {
- GenericMenu menu = new GenericMenu();
- bool showselectionOptions = subsetSelected || ((m_PairedWithFrameTimeGraph != null) && m_PairedWithFrameTimeGraph.HasSubsetSelected());
- ShowSelectionMenuItem(showselectionOptions || selectionCount == 0, menu, Styles.menuItemSelectAll, false, () => SelectAll());
- ShowSelectionMenuItem(showselectionOptions || selectionCount == m_Values.Count, menu, Styles.menuItemClearSelection, false, () => ClearSelection());
- menu.AddItem(Styles.menuItemInvertSelection, false, () => InvertSelection());
- menu.AddItem(Styles.menuItemSelectMin, false, () => SelectMin());
- menu.AddItem(Styles.menuItemSelectMax, false, () => SelectMax());
- menu.AddItem(Styles.menuItemSelectMedian, false, () => SelectMedian());
- menu.AddSeparator("");
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectPrevious, false, () => SelectPrevious(1));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectNext, false, () => SelectNext(1));
- menu.AddSeparator("");
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectGrow, false, () => SelectGrow(1));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectShrink, false, () => SelectShrink(1));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectGrowLeft, false, () => SelectGrowLeft(1));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectGrowRight, false, () => SelectGrowRight(1));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectShrinkLeft, false, () => SelectShrinkLeft(1));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectShrinkRight, false, () => SelectShrinkRight(1));
- menu.AddSeparator("");
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectGrowFast, false, () => SelectGrow(10));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectShrinkFast, false, () => SelectShrink(10));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectGrowLeftFast, false, () => SelectGrowLeft(10));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectGrowRightFast, false, () => SelectGrowRight(10));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectShrinkLeftFast, false, () => SelectShrinkLeft(10));
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemSelectShrinkRightFast, false, () => SelectShrinkRight(10));
- menu.AddSeparator("");
- ShowSelectionMenuItem(showselectionOptions, menu, Styles.menuItemZoomSelection, false, () => ZoomSelection());
- ShowSelectionMenuItem(m_Zoomed, menu, Styles.menuItemZoomAll, false, () => ZoomAll());
- menu.AddSeparator("");
- menu.AddItem(Styles.menuItemShowSelectedMarker, m_GlobalSettings.showSelectedMarker, () => ToggleShowSelectedMarker());
- menu.AddItem(Styles.menuItemShowThreads, m_GlobalSettings.showThreads, () => ToggleShowThreads());
- menu.AddItem(Styles.menuItemShowFrameLines, m_GlobalSettings.showFrameLines, () => ToggleShowFrameLines());
- //menu.AddItem(Styles.menuItemShowFrameLineText, m_GlobalSettings.showFrameLineText, () => ToggleShowFrameLinesText());
- menu.AddSeparator("");
- menu.AddItem(Styles.menuItemShowOrderedByFrameDuration, m_GlobalSettings.showOrderedByFrameDuration, () => ToggleShowOrderedByFrameDuration());
- menu.ShowAsContext();
- }
- string GetYMaxText(float value)
- {
- return ToDisplayUnits(value, true, 0);
- }
- void DrawYAxisRangeSelector(Rect rect, float yMax)
- {
- string yMaxText = GetYMaxText(yMax);
- List<GUIContent> yAxisOptions = new List<GUIContent>();
- var graphScaleUnits = ToDisplayUnits(1000f / 60f, true, 0);
- yAxisOptions.Add(new GUIContent(graphScaleUnits, string.Format("Graph Scale : {0} is equivalent to 60Hz or 60FPS.", graphScaleUnits)));
- graphScaleUnits = ToDisplayUnits(1000f / 30f, true, 0);
- yAxisOptions.Add(new GUIContent(graphScaleUnits, string.Format("Graph Scale : {0} is equivalent to 30Hz or 30FPS.", graphScaleUnits)));
- graphScaleUnits = ToDisplayUnits(1000f / 15f, true, 0);
- yAxisOptions.Add(new GUIContent(graphScaleUnits, string.Format("Graph Scale : {0} is equivalent to 15Hz or 15FPS.", graphScaleUnits)));
- yAxisOptions.Add(new GUIContent(yMaxText, "Graph Scale : Max frame time from data"));
- float width = 0;
- foreach (var content in yAxisOptions)
- {
- Vector2 size = EditorStyles.popup.CalcSize(content);
- if (size.x > width)
- width = size.x;
- }
- // Use smaller width if text is shorter
- int margin = 2;
- width = Math.Min(width + margin, rect.width);
- // Shift right to right align
- rect.x += (rect.width - width);
- rect.x -= margin;
- rect.width = width;
- s_YAxisMode = (AxisMode)EditorGUI.Popup(rect, (int)s_YAxisMode, yAxisOptions.ToArray());
- }
- void ShowAxis(Rect rect, float xStart, float width, int startOffset, int endOffset, int selectedFirstOffset, int selectedLastOffset, int selectedCount, int totalSelectedCount, float yMax, int totalDataSize, int offsetToDisplayMapping)
- {
- GUIStyle leftAlignStyle = new GUIStyle(GUI.skin.label);
- leftAlignStyle.padding = new RectOffset(leftAlignStyle.padding.left, leftAlignStyle.padding.right, 0, 0);
- leftAlignStyle.alignment = TextAnchor.MiddleLeft;
- GUIStyle rightAlignStyle = new GUIStyle(GUI.skin.label);
- rightAlignStyle.padding = new RectOffset(rightAlignStyle.padding.left, rightAlignStyle.padding.right, 0, 0);
- rightAlignStyle.alignment = TextAnchor.MiddleRight;
- // y axis
- float h = GUI.skin.label.lineHeight;
- float y = rect.y + ((rect.height - 1) - h);
- DrawYAxisRangeSelector(new Rect(rect.x, rect.y, kXAxisWidth, h), yMax);
- string yMinText = ToDisplayUnits(0, true);
- GUI.Label(new Rect(rect.x, y - h, kXAxisWidth, h), yMinText, rightAlignStyle);
- // x axis
- rect.x += xStart;
- leftAlignStyle.padding = new RectOffset(0, 0, leftAlignStyle.padding.top, leftAlignStyle.padding.bottom);
- rightAlignStyle.padding = new RectOffset(0, 0, rightAlignStyle.padding.top, rightAlignStyle.padding.bottom);
- int startIndex = offsetToDisplayMapping + startOffset;
- string startIndexText = string.Format("{0}", startIndex);
- GUIContent startIndexContent = new GUIContent(startIndexText);
- Vector2 startIndexSize = GUI.skin.label.CalcSize(startIndexContent);
- bool drawStart = !m_GlobalSettings.showOrderedByFrameDuration;
- int endIndex = offsetToDisplayMapping + endOffset;
- string endIndexText = string.Format("{0}", endIndex);
- GUIContent endIndexContent = new GUIContent(endIndexText);
- Vector2 endIndexSize = GUI.skin.label.CalcSize(endIndexContent);
- bool drawEnd = !m_GlobalSettings.showOrderedByFrameDuration;
- // Show selection frame values (if space for them)
- if (totalSelectedCount > 0)
- {
- if (selectedCount == 0)
- {
- // If we have no selection then adjust 'selection start/end to span whole view so the count display is centred)
- selectedFirstOffset = startOffset;
- selectedLastOffset = endOffset;
- }
- int selectedFirstX = GetXForDataOffset(selectedFirstOffset, (int)width, totalDataSize);
- int selectedLastX = GetXForDataOffset(selectedLastOffset + 1, (int)width, totalDataSize); // last + 1 so right hand side of the bbar
- int selectedRangeWidth = 1 + (selectedLastX - selectedFirstX);
- int selectedFirstIndex = offsetToDisplayMapping + selectedFirstOffset;
- int selectedLastIndex = offsetToDisplayMapping + selectedLastOffset;
- string selectionCountText;
- if (totalSelectedCount != selectedCount)
- selectionCountText = string.Format("[{0} of {1}]", selectedCount, totalSelectedCount);
- else
- selectionCountText = string.Format("[{0}]", selectedCount);
- string selectionRangeText;
- if (selectedCount > 1)
- {
- if (m_GlobalSettings.showOrderedByFrameDuration)
- selectionRangeText = selectionCountText;
- else
- selectionRangeText = string.Format("{0} {1} {2}", selectedFirstIndex, selectionCountText, selectedLastIndex);
- }
- else
- selectionRangeText = string.Format("{0} {1}", selectedFirstIndex, selectionCountText);
- string tooltip = string.Format("{0} frames in selection", selectedCount);
- if (totalSelectedCount != selectedCount)
- {
- tooltip = string.Format("{0} frames in zoomed selection\n{1} frames in overall selection", selectedCount, totalSelectedCount);
- }
- GUIContent selectionRangeTextContent = new GUIContent(selectionRangeText, tooltip);
- Vector2 selectionRangeTextSize = GUI.skin.label.CalcSize(selectionRangeTextContent);
- if ((selectedRangeWidth > selectionRangeTextSize.x && selectedCount > 1) || selectedCount == 0)
- {
- // Selection width is larger than the text so we can split the text
- string selectedFirstIndexText = string.Format("{0}", selectedFirstIndex);
- GUIContent selectedFirstIndexContent = new GUIContent(selectedFirstIndexText);
- Vector2 selectedFirstIndexSize = GUI.skin.label.CalcSize(selectedFirstIndexContent);
- if (m_GlobalSettings.showOrderedByFrameDuration)
- selectedFirstIndexSize.x = 0;
- string selectedLastIndexText = string.Format("{0}", selectedLastIndex);
- GUIContent selectedLastIndexContent = new GUIContent(selectedLastIndexText);
- Vector2 selectedLastIndexSize = GUI.skin.label.CalcSize(selectedLastIndexContent);
- if (m_GlobalSettings.showOrderedByFrameDuration)
- selectedLastIndexSize.x = 0;
- GUIContent selectedCountContent = new GUIContent(selectionCountText, tooltip);
- Vector2 selectedCountSize = GUI.skin.label.CalcSize(selectedCountContent);
- Rect rFirst = new Rect(rect.x + selectedFirstX, y, selectedFirstIndexSize.x, selectedFirstIndexSize.y);
- GUI.Label(rFirst, selectedFirstIndexContent);
- Rect rLast = new Rect(rect.x + selectedLastX - selectedLastIndexSize.x, y, selectedLastIndexSize.x, selectedLastIndexSize.y);
- GUI.Label(rLast, selectedLastIndexContent);
- float mid = selectedFirstX + ((selectedLastX - selectedFirstX) / 2);
- Rect rCount = new Rect(rect.x + mid - (selectedCountSize.x / 2), y, selectedCountSize.x, selectedCountSize.y);
- GUI.Label(rCount, selectedCountContent);
- if (selectedFirstX < startIndexSize.x)
- {
- // would overlap with start text
- drawStart = false;
- }
- if (selectedLastX > ((width - 1) - endIndexSize.x))
- {
- // would overlap with end text
- drawEnd = false;
- }
- }
- else
- {
- int mid = (selectedFirstX + (selectedRangeWidth / 2));
- int selectionTextX = mid - (int)(selectionRangeTextSize.x / 2);
- selectionTextX = ClampToRange(selectionTextX, 0, (int)((width - 1) - selectionRangeTextSize.x));
- Rect rangeRect = new Rect(rect.x + selectionTextX, y, selectionRangeTextSize.x, selectionRangeTextSize.y);
- GUI.Label(rangeRect, selectionRangeTextContent);
- if (selectionTextX < startIndexSize.x)
- {
- // would overlap with start text
- drawStart = false;
- }
- if ((selectionTextX + selectionRangeTextSize.x) > ((width - 1) - endIndexSize.x))
- {
- // would overlap with end text
- drawEnd = false;
- }
- }
- }
- // Show start and end values
- if (drawStart)
- {
- Rect leftRect = new Rect(rect.x, y, startIndexSize.x, startIndexSize.y);
- GUI.Label(leftRect, startIndexContent, leftAlignStyle);
- }
- if (drawEnd)
- {
- Rect rightRect = new Rect(rect.x + ((width - 1) - endIndexSize.x), y, endIndexSize.x, endIndexSize.y);
- GUI.Label(rightRect, endIndexContent, rightAlignStyle);
- }
- }
- void ClearSelection(bool effectPaired = true)
- {
- int dataLength = m_Values.Count;
- bool singleControlAction = true; // As we need the frame range to be unique to each data set
- CallSetRange(-1, -1, 0, singleControlAction, FrameTimeGraph.State.DragComplete);
- // Disable zoom
- m_Zoomed = false;
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.ClearSelection(false);
- }
- void SelectAll(bool effectPaired = true)
- {
- int dataLength = m_Values.Count;
- bool singleControlAction = true; // As we need the frame range to be unique to each data set
- CallSetRange(0, dataLength - 1, 0, singleControlAction, FrameTimeGraph.State.DragComplete);
- // Disable zoom
- m_Zoomed = false;
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectAll(false);
- }
- void InvertSelection(bool effectPaired = true)
- {
- int dataLength = m_Values.Count;
- Dictionary<int, int> frameOffsetToSelectionIndex = new Dictionary<int, int>();
- for (int i = 0; i < m_CurrentSelection.Count; i++)
- {
- int frameOffset = m_CurrentSelection[i];
- frameOffsetToSelectionIndex[frameOffset] = i;
- }
- m_CurrentSelection.Clear();
- for (int frameIndex = 0; frameIndex < dataLength; frameIndex++)
- {
- if (!frameOffsetToSelectionIndex.ContainsKey(frameIndex))
- m_CurrentSelection.Add(frameIndex);
- }
- m_SetRange(m_CurrentSelection, 1, FrameTimeGraph.State.DragComplete);
- // Disable zoom
- m_Zoomed = false;
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.InvertSelection(false);
- }
- void ZoomSelection(bool effectPaired = true)
- {
- m_Zoomed = true;
- m_ZoomStartOffset = m_CurrentSelectionFirstDataOffset;
- m_ZoomEndOffset = m_CurrentSelectionLastDataOffset;
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.ZoomSelection(false);
- }
- void ZoomAll(bool effectPaired = true)
- {
- m_Zoomed = false;
- int frames = m_Values.Count;
- m_ZoomStartOffset = 0;
- m_ZoomEndOffset = frames - 1;
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.ZoomAll(false);
- }
- void SelectMin(bool effectPaired = true)
- {
- int dataLength = m_Values.Count;
- if (dataLength <= 0)
- return;
- int minDataOffset = 0;
- float msMin = m_Values[0].ms;
- for (int dataOffset = 0; dataOffset < dataLength; dataOffset++)
- {
- float ms = m_Values[dataOffset].ms;
- if (ms < msMin)
- {
- msMin = ms;
- minDataOffset = dataOffset;
- }
- }
- bool singleControlAction = true;
- CallSetRange(minDataOffset, minDataOffset, 1, singleControlAction, State.DragComplete); // act like single click, so we select frame
- //CallSetRange(minDataOffset, minDataOffset, 2, singleControlAction, State.DragComplete); // act like double click, so we jump to the frame
- m_Zoomed = false;
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectMin(false);
- }
- void SelectMax(bool effectPaired = true)
- {
- int dataLength = m_Values.Count;
- if (dataLength <= 0)
- return;
- int maxDataOffset = 0;
- float msMax = m_Values[0].ms;
- for (int dataOffset = 0; dataOffset < dataLength; dataOffset++)
- {
- float ms = m_Values[dataOffset].ms;
- if (ms > msMax)
- {
- msMax = ms;
- maxDataOffset = dataOffset;
- }
- }
- bool singleControlAction = true;
- CallSetRange(maxDataOffset, maxDataOffset, 1, singleControlAction, State.DragComplete); // act like single click, so we select frame
- //CallSetRange(maxDataOffset, maxDataOffset, 2, singleControlAction, State.DragComplete); // act like double click, so we jump to the frame
- m_Zoomed = false;
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectMax(false);
- }
- float GetPercentageOffset(List<Data> data, float percent, out int outputFrameOffset)
- {
- int index = (int)((data.Count - 1) * percent / 100);
- outputFrameOffset = data[index].frameOffset;
- // True median is half of the sum of the middle 2 frames for an even count. However this would be a value never recorded so we avoid that.
- return data[index].ms;
- }
- void SelectMedian(bool effectPaired = true)
- {
- int dataLength = m_Values.Count;
- if (dataLength <= 0)
- return;
- List<Data> sortedValues = new List<Data>();
- foreach (var value in m_Values)
- {
- Data data = new Data(value.ms, value.frameOffset);
- sortedValues.Add(data);
- }
- // If ms value is the same then order by frame offset
- sortedValues.Sort((a, b) => { int compare = a.ms.CompareTo(b.ms); return compare == 0 ? a.frameOffset.CompareTo(b.frameOffset) : compare; });
- int medianFrameOffset = 0;
- GetPercentageOffset(sortedValues, 50, out medianFrameOffset);
- int medianDataOffset = m_FrameOffsetToDataOffsetMapping[medianFrameOffset];
- bool singleControlAction = true;
- CallSetRange(medianDataOffset, medianDataOffset, 1, singleControlAction, State.DragComplete); // act like single click, so we select frame
- //CallSetRange(medianDataOffset, medianDataOffset, 2, singleControlAction, State.DragComplete); // act like double click, so we jump to the frame
- m_Zoomed = false;
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectMedian(false);
- }
- public void SelectPrevious(int step, bool effectPaired = true)
- {
- int clicks = 1;
- bool singleClickAction = true;
- MoveSelectedRange(-step, clicks, singleClickAction, State.DragComplete);
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectPrevious(step, false);
- }
- public void SelectNext(int step, bool effectPaired = true)
- {
- int clicks = 1;
- bool singleClickAction = true;
- MoveSelectedRange(step, clicks, singleClickAction, State.DragComplete);
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectNext(step, false);
- }
- public void SelectGrow(int step, bool effectPaired = true)
- {
- int clicks = 1;
- bool singleClickAction = true;
- ResizeSelectedRange(-step, step, clicks, singleClickAction, State.DragComplete);
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectGrow(step, false);
- }
- public void SelectGrowLeft(int step, bool effectPaired = true)
- {
- int clicks = 1;
- bool singleClickAction = true;
- ResizeSelectedRange(-step, 0, clicks, singleClickAction, State.DragComplete);
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectGrowLeft(step, false);
- }
- public void SelectGrowRight(int step, bool effectPaired = true)
- {
- int clicks = 1;
- bool singleClickAction = true;
- ResizeSelectedRange(0, step, clicks, singleClickAction, State.DragComplete);
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectGrowRight(step, false);
- }
- public void SelectShrink(int step, bool effectPaired = true)
- {
- int clicks = 1;
- bool singleClickAction = true;
- ResizeSelectedRange(step, -step, clicks, singleClickAction, State.DragComplete);
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectShrink(step, false);
- }
- public void SelectShrinkLeft(int step, bool effectPaired = true)
- {
- int clicks = 1;
- bool singleClickAction = true;
- ResizeSelectedRange(step, 0, clicks, singleClickAction, State.DragComplete);
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectShrinkLeft(step, false);
- }
- public void SelectShrinkRight(int step, bool effectPaired = true)
- {
- int clicks = 1;
- bool singleClickAction = true;
- ResizeSelectedRange(0, -step, clicks, singleClickAction, State.DragComplete);
- if (m_PairedWithFrameTimeGraph != null && effectPaired)
- m_PairedWithFrameTimeGraph.SelectShrinkRight(step, false);
- }
- public void ToggleShowThreads()
- {
- m_GlobalSettings.showThreads ^= true;
- }
- public void ToggleShowSelectedMarker()
- {
- m_GlobalSettings.showSelectedMarker ^= true;
- }
- public void ToggleShowFrameLines()
- {
- m_GlobalSettings.showFrameLines ^= true;
- }
- public void ToggleShowFrameLinesText()
- {
- m_GlobalSettings.showFrameLineText ^= true;
- }
- public void ToggleShowOrderedByFrameDuration()
- {
- m_GlobalSettings.showOrderedByFrameDuration ^= true;
- SetData(m_Values); // Update order
- if (m_PairedWithFrameTimeGraph != null)
- {
- m_PairedWithFrameTimeGraph.SetData(m_PairedWithFrameTimeGraph.m_Values); // Update order
- }
- }
- internal struct SelectedRangeState
- {
- public int currentSelectionFirstDataOffset;
- public int currentSelectionLastDataOffset;
- public List<int> lastSelectedFrameOffsets;
- }
- void MoveSelectedRange(int offset, int clickCount, bool singleControlAction, State inputStatus)
- {
- MoveSelectedRange(offset, clickCount, singleControlAction, inputStatus, new SelectedRangeState()
- {
- currentSelectionFirstDataOffset = m_CurrentSelectionFirstDataOffset,
- currentSelectionLastDataOffset = m_CurrentSelectionLastDataOffset,
- lastSelectedFrameOffsets = m_LastSelectedFrameOffsets,
- });
- }
- internal void MoveSelectedRange(int offset, int clickCount, bool singleControlAction, State inputStatus, SelectedRangeState selectedRange)
- {
- var currentSelectionFirstDataOffset = selectedRange.currentSelectionFirstDataOffset;
- var currentSelectionLastDataOffset = selectedRange.currentSelectionLastDataOffset;
- var lastSelectedFrameOffsets = selectedRange.lastSelectedFrameOffsets;
- if (offset < 0)
- {
- // Clamp offset to graph lower bound.
- if (currentSelectionFirstDataOffset + offset < 0)
- {
- offset = -currentSelectionFirstDataOffset;
- }
- }
- else
- {
- // Clamp offset to graph upper bound.
- if (currentSelectionLastDataOffset + offset >= m_Values.Count)
- {
- offset = (m_Values.Count - 1) - currentSelectionLastDataOffset;
- }
- }
- // Offset selection.
- List<int> selected = new List<int>();
- foreach (int selectedFrameOffset in lastSelectedFrameOffsets)
- {
- var selectedDataOffset = m_FrameOffsetToDataOffsetMapping[selectedFrameOffset];
- var newDataOffset = selectedDataOffset + offset;
- if (newDataOffset >= 0 && newDataOffset < m_Values.Count)
- {
- var newFrameOffset = m_Values[newDataOffset].frameOffset;
- if (!selected.Contains(newFrameOffset))
- {
- selected.Add(newFrameOffset);
- }
- }
- }
- // Sort selection in frame index order.
- selected.Sort();
- m_SetRange(selected, clickCount, inputStatus);
- }
- void ResizeSelectedRange(int leftOffset, int rightOffset, int clickCount, bool singleControlAction, State inputState)
- {
- ResizeSelectedRange(leftOffset, rightOffset, clickCount, singleControlAction, inputState, new SelectedRangeState()
- {
- currentSelectionFirstDataOffset = m_CurrentSelectionFirstDataOffset,
- currentSelectionLastDataOffset = m_CurrentSelectionLastDataOffset,
- lastSelectedFrameOffsets = m_LastSelectedFrameOffsets,
- });
- }
- internal void ResizeSelectedRange(int leftOffset, int rightOffset, int clickCount, bool singleControlAction, State inputState, SelectedRangeState selectedRange)
- {
- const int k_InvalidDataOffset = -1;
- var currentSelectionFirstDataOffset = selectedRange.currentSelectionFirstDataOffset;
- var currentSelectionLastDataOffset = selectedRange.currentSelectionLastDataOffset;
- var lastSelectedFrameOffsets = selectedRange.lastSelectedFrameOffsets;
- // Clamp left offset to lower graph bound.
- bool isGrowingLeft = leftOffset < 0;
- if (isGrowingLeft && currentSelectionFirstDataOffset + leftOffset < 0)
- {
- leftOffset = -currentSelectionFirstDataOffset;
- }
- // Clamp right offset to upper graph bound.
- bool isGrowingRight = rightOffset > 0;
- if (isGrowingRight && currentSelectionLastDataOffset + rightOffset > (m_Values.Count - 1))
- {
- rightOffset = (m_Values.Count - 1) - currentSelectionLastDataOffset;
- }
- int selectionStartDataOffset = k_InvalidDataOffset;
- List<int> selected = new List<int>(lastSelectedFrameOffsets);
- for (int dataOffset = 0; dataOffset < m_Values.Count; ++dataOffset)
- {
- var frameOffset = m_Values[dataOffset].frameOffset;
- if (selectionStartDataOffset == k_InvalidDataOffset)
- {
- // Find selection start.
- if (lastSelectedFrameOffsets.Contains(frameOffset))
- {
- selectionStartDataOffset = dataOffset;
- }
- }
- else
- {
- // Find selection end.
- bool isSelected = lastSelectedFrameOffsets.Contains(frameOffset);
- if (!isSelected || dataOffset == (m_Values.Count - 1))
- {
- int selectionEndDataOffset;
- // If we reached the last index and it is selected, this index is the selection end. Otherwise, the previous index is the last selected.
- bool isLastIndex = dataOffset == (m_Values.Count - 1);
- if (isLastIndex && isSelected)
- {
- selectionEndDataOffset = dataOffset;
- }
- else
- {
- selectionEndDataOffset = dataOffset - 1;
- }
- int newSelectionStartDataOffset = Mathf.Clamp(selectionStartDataOffset + leftOffset, 0, m_Values.Count - 1);
- int newSelectionEndDataOffset = Mathf.Clamp(selectionEndDataOffset + rightOffset, 0, m_Values.Count - 1);
- // Enforce a minimum selection width.
- if (newSelectionEndDataOffset < newSelectionStartDataOffset)
- {
- var maximumOffset = (selectionEndDataOffset - selectionStartDataOffset) * 0.5f;
- var adjustedLeftOffset = Mathf.CeilToInt(maximumOffset);
- newSelectionStartDataOffset = Mathf.Clamp(selectionStartDataOffset + adjustedLeftOffset, 0, m_Values.Count - 1);
- var adjustedRightOffset = -Mathf.FloorToInt(maximumOffset);
- newSelectionEndDataOffset = Mathf.Clamp(selectionEndDataOffset + adjustedRightOffset, 0, m_Values.Count - 1);
- }
- if (selectionStartDataOffset != newSelectionStartDataOffset)
- {
- // Resize from left edge.
- int startDataOffset = Mathf.Min(selectionStartDataOffset, newSelectionStartDataOffset);
- int endDataOffset = Mathf.Max(selectionStartDataOffset, newSelectionStartDataOffset);
- MoveSelectionEdge(startDataOffset, endDataOffset, isGrowingLeft, ref selected);
- }
- if (selectionEndDataOffset != newSelectionEndDataOffset)
- {
- // Resize from right edge (iterate backwards).
- int startDataOffset = Mathf.Max(selectionEndDataOffset, newSelectionEndDataOffset);
- int endDataOffset = Mathf.Min(selectionEndDataOffset, newSelectionEndDataOffset);
- MoveSelectionEdge(startDataOffset, endDataOffset, isGrowingRight, ref selected);
- }
- // Reset to find next selection.
- selectionStartDataOffset = k_InvalidDataOffset;
- }
- }
- }
- // Sort selection in frame index order.
- selected.Sort();
- m_SetRange(selected, clickCount, inputState);
- }
- void MoveSelectionEdge(int startDataOffset, int endDataOffset, bool isGrowingFromEdge, ref List<int> selection)
- {
- var direction = (startDataOffset >= endDataOffset) ? -1 : 1;
- for (int dataOffset = startDataOffset; dataOffset != endDataOffset; dataOffset += direction)
- {
- var frameOffset = m_Values[dataOffset].frameOffset;
- var indexInSelection = selection.IndexOf(frameOffset);
- if (isGrowingFromEdge)
- {
- if (indexInSelection == -1)
- {
- selection.Add(frameOffset);
- }
- }
- else
- {
- if (indexInSelection != -1)
- {
- selection.RemoveAt(indexInSelection);
- }
- }
- }
- }
- }
- }
|