internal static void DrawVerticalLine(int frame, ChartViewData cdata, Rect r, Color color1, Color color2, float widthFactor) { if (Event.current.type != EventType.Repaint) { return; } frame -= cdata.chartDomainOffset; if (frame < 0) { return; } Vector2 domain = cdata.GetDataDomain(); float domainSize = domain.y - domain.x; HandleUtility.ApplyWireMaterial(); GL.Begin(GL.QUADS); GL.Color(color1); GL.Vertex3(r.x + r.width / domainSize * frame, r.y + 1, 0); GL.Vertex3(r.x + r.width / domainSize * frame + r.width / domainSize, r.y + 1, 0); GL.Color(color2); GL.Vertex3(r.x + r.width / domainSize * frame + r.width / domainSize, r.yMax, 0); GL.Vertex3(r.x + r.width / domainSize * frame, r.yMax, 0); GL.End(); }
internal static void DrawVerticalLine(int frame, ChartViewData cdata, Rect r, Color color, float minWidth, float maxWidth = 0) { if (Event.current.type != EventType.Repaint) { return; } frame -= cdata.chartDomainOffset; if (frame < 0) { return; } Vector2 domain = cdata.GetDataDomain(); float domainSize = domain.y - domain.x; float lineWidth = Mathf.Max(minWidth, r.width / domainSize); if (maxWidth > 0) { lineWidth = Mathf.Min(maxWidth, lineWidth); } HandleUtility.ApplyWireMaterial(); GL.Begin(GL.QUADS); GL.Color(color); GL.Vertex3(r.x + r.width / domainSize * frame, r.y + 1, 0); GL.Vertex3(r.x + r.width / domainSize * frame + lineWidth, r.y + 1, 0); GL.Vertex3(r.x + r.width / domainSize * frame + lineWidth, r.yMax, 0); GL.Vertex3(r.x + r.width / domainSize * frame, r.yMax, 0); GL.End(); }
private void DrawSelectedFrame(int selectedFrame, ChartViewData cdata, Rect r) { if (cdata.firstSelectableFrame != -1 && selectedFrame - cdata.firstSelectableFrame >= 0) { DrawVerticalLine(selectedFrame, cdata, r, Styles.selectedFrameColor, 1.0f); } }
private void DrawChartStacked(int selectedFrame, ChartViewData cdata, Rect r, bool chartActive) { HandleUtility.ApplyWireMaterial(); Vector2 domain = cdata.GetDataDomain(); int numSamples = (int)(domain.y - domain.x); if (numSamples <= 0) { return; } if (m_StackedSampleSums == null || m_StackedSampleSums.Length < numSamples) { m_StackedSampleSums = new float[numSamples]; } for (int i = 0; i < numSamples; ++i) { m_StackedSampleSums[i] = 0f; } for (int i = 0; i < cdata.numSeries; i++) { if (cdata.hasOverlay) { DrawChartItemStackedOverlay(r, i, cdata, m_StackedSampleSums); } DrawChartItemStacked(r, i, cdata, m_StackedSampleSums); } DrawOverlayBoxes(cdata, r, chartActive); DrawSelectedFrame(selectedFrame, cdata, r); DrawGridStacked(r, cdata); DrawLabels(r, cdata, selectedFrame, ChartType.StackedFill); // Show selected property name //@TODO: not the best place to put this code. if (!cdata.hasOverlay) { return; } string selectedName = ProfilerDriver.selectedPropertyPath; if (selectedName.Length > 0) { int selectedNameBegin = selectedName.LastIndexOf('/'); if (selectedNameBegin != -1) { selectedName = selectedName.Substring(selectedNameBegin + 1); } GUIContent content = EditorGUIUtility.TempContent("Selected: " + selectedName); Vector2 size = EditorStyles.whiteBoldLabel.CalcSize(content); EditorGUI.DropShadowLabel(new Rect(r.x + r.width - size.x - 3.0f, r.y + 3.0f, size.x, size.y), content, Styles.selectedLabel); } }
private int DoFrameSelectionDrag(float x, Rect r, ChartViewData cdata, int len) { int frame = Mathf.RoundToInt((x - r.x) / r.width * len - 0.5f); GUI.changed = true; return(Mathf.Clamp(frame + cdata.chartDomainOffset, cdata.firstSelectableFrame, cdata.chartDomainOffset + len)); }
private void DrawOverlayBoxes(ChartViewData cdata, Rect r, bool chartActive) { if (Event.current.type == EventType.Repaint && cdata.dataAvailable != null) { r.height += 2; r.y -= 1; int lastFrameWithData = 0; int frameDataLength = cdata.dataAvailable.Length; for (int frame = 0; frame < frameDataLength; frame++) { bool hasDataForFrame = cdata.dataAvailable[frame]; if (hasDataForFrame) { if (lastFrameWithData < frame - 1) { DrawOverlayBox(r, lastFrameWithData, frame, frameDataLength, chartActive, Styles.noDataOverlayBox); } lastFrameWithData = frame; } } if (lastFrameWithData < frameDataLength - 1) { DrawOverlayBox(r, lastFrameWithData, frameDataLength - 1, frameDataLength, chartActive, Styles.noDataOverlayBox); } } }
private void LoadChartsSettings(ChartViewData cdata) { if (!string.IsNullOrEmpty(this.m_ChartSettingsName)) { string @string = EditorPrefs.GetString(this.m_ChartSettingsName + "Order"); if (!string.IsNullOrEmpty(@string)) { try { string[] array = @string.Split(new char[] { ',' }); if (array.Length == cdata.numSeries) { for (int i = 0; i < cdata.numSeries; i++) { cdata.order[i] = int.Parse(array[i]); } } } catch (FormatException) { } } @string = EditorPrefs.GetString(this.m_ChartSettingsName + "Visible"); for (int j = 0; j < cdata.numSeries; j++) { if (j < @string.Length && @string[j] == '0') { cdata.series[j].enabled = false; } } } }
private void DrawGridStacked(Rect r, ChartViewData cdata) { if (Event.current.type != EventType.Repaint || cdata.grid == null || cdata.gridLabels == null) { return; } GL.Begin(GL.LINES); GL.Color(new Color(1, 1, 1, 0.2f)); float rangeScale = cdata.series[0].rangeAxis.sqrMagnitude == 0f ? 0f : 1f / (cdata.series[0].rangeAxis.y - cdata.series[0].rangeAxis.x) * r.height; float rectBottom = r.y + r.height; for (int i = 0; i < cdata.grid.Length; ++i) { float y = rectBottom - (cdata.grid[i] - cdata.series[0].rangeAxis.x) * rangeScale; if (y > r.y) { GL.Vertex3(r.x + 80, y, 0.0f); GL.Vertex3(r.x + r.width, y, 0.0f); } } GL.End(); for (int i = 0; i < cdata.grid.Length; ++i) { float y = rectBottom - (cdata.grid[i] - cdata.series[0].rangeAxis.x) * rangeScale; if (y > r.y) { DoLabel(r.x + 5, y - 12, cdata.gridLabels[i], 0.0f); } } }
private void DrawChartItemLine(Rect r, ChartViewData cdata, int index) { ChartSeriesViewData chartSeriesViewData = cdata.series[index]; if (chartSeriesViewData.enabled) { if (this.m_LineDrawingPoints == null || chartSeriesViewData.numDataPoints > this.m_LineDrawingPoints.Length) { this.m_LineDrawingPoints = new Vector3[chartSeriesViewData.numDataPoints]; } Vector2 dataDomain = cdata.GetDataDomain(); float num = dataDomain.y - dataDomain.x; if (num > 0f) { float num2 = 1f / num * r.width; float num3 = (cdata.series[index].rangeAxis.sqrMagnitude != 0f) ? (1f / (cdata.series[index].rangeAxis.y - cdata.series[index].rangeAxis.x) * r.height) : 0f; float num4 = r.y + r.height; for (int i = 0; i < chartSeriesViewData.numDataPoints; i++) { this.m_LineDrawingPoints[i].Set((chartSeriesViewData.xValues[i] - dataDomain.x) * num2 + r.x, num4 - (chartSeriesViewData.yValues[i] - chartSeriesViewData.rangeAxis.x) * num3, 0f); } using (new Handles.DrawingScope(cdata.series[index].color)) { Handles.DrawAAPolyLine(2f, chartSeriesViewData.numDataPoints, this.m_LineDrawingPoints); } } } }
private void DrawChartItemStackedOverlay(Rect r, int index, ChartViewData cdata, float[] stackedSampleSums) { Vector2 dataDomain = cdata.GetDataDomain(); int num = (int)(dataDomain.y - dataDomain.x); float num2 = r.width / (float)num; int num3 = cdata.order[index]; if (cdata.series[num3].enabled) { Color color = cdata.series[num3].color; GL.Begin(5); float num4 = r.x + num2 * 0.5f; float num5 = (cdata.series[0].rangeAxis.sqrMagnitude != 0f) ? (1f / (cdata.series[0].rangeAxis.y - cdata.series[0].rangeAxis.x) * r.height) : 0f; float num6 = r.y + r.height; int i = 0; while (i < num) { float num7 = num6 - stackedSampleSums[i]; float num8 = cdata.overlays[num3].yValues[i]; if (num8 != -1f) { float num9 = (num8 - cdata.series[0].rangeAxis.x) * num5; GL.Color(color); GL.Vertex3(num4, num7 - num9, 0f); GL.Vertex3(num4, num7, 0f); } i++; num4 += num2; } GL.End(); } }
private void DrawGridStacked(Rect r, ChartViewData cdata) { if (Event.current.type == EventType.Repaint && cdata.grid != null && cdata.gridLabels != null) { GL.Begin(1); GL.Color(new Color(1f, 1f, 1f, 0.2f)); float num = (cdata.series[0].rangeAxis.sqrMagnitude != 0f) ? (1f / (cdata.series[0].rangeAxis.y - cdata.series[0].rangeAxis.x) * r.height) : 0f; float num2 = r.y + r.height; for (int i = 0; i < cdata.grid.Length; i++) { float num3 = num2 - (cdata.grid[i] - cdata.series[0].rangeAxis.x) * num; if (num3 > r.y) { GL.Vertex3(r.x + 80f, num3, 0f); GL.Vertex3(r.x + r.width, num3, 0f); } } GL.End(); for (int j = 0; j < cdata.grid.Length; j++) { float num4 = num2 - (cdata.grid[j] - cdata.series[0].rangeAxis.x) * num; if (num4 > r.y) { Chart.DoLabel(r.x + 5f, num4 - 8f, cdata.gridLabels[j], 0f); } } } }
private void LoadChartsSettings(ChartViewData cdata) { if (string.IsNullOrEmpty(m_ChartSettingsName)) { return; } var str = EditorPrefs.GetString(m_ChartSettingsName + "Order"); if (!string.IsNullOrEmpty(str)) { try { var values = str.Split(','); if (values.Length == cdata.numSeries) { for (var i = 0; i < cdata.numSeries; i++) { cdata.order[i] = int.Parse(values[i]); } } } catch (FormatException) {} } str = EditorPrefs.GetString(m_ChartSettingsName + "Visible"); for (var i = 0; i < cdata.numSeries; i++) { if (i < str.Length && str[i] == '0') { cdata.series[i].enabled = false; } } }
public int DoGUI(Chart.ChartType type, int selectedFrame, ChartViewData cdata, bool active) { int result; if (cdata == null) { result = selectedFrame; } else { this.m_chartControlID = GUIUtility.GetControlID(Chart.s_ChartHash, FocusType.Keyboard); GUILayoutOption gUILayoutOption = GUILayout.MinHeight(Math.Max(5f + (float)((cdata.numSeries + 1) * 11) + 38f, 130f)); Rect rect = GUILayoutUtility.GetRect(GUIContent.none, Chart.Styles.background, new GUILayoutOption[] { gUILayoutOption }); Rect rect2 = rect; rect2.x += 180f; rect2.width -= 180f; Event current = Event.current; EventType typeForControl = current.GetTypeForControl(this.m_chartControlID); if (typeForControl == EventType.MouseDown && rect.Contains(current.mousePosition) && this.selected != null) { this.selected(this); } if (this.m_DragItemIndex == -1) { selectedFrame = this.HandleFrameSelectionEvents(selectedFrame, this.m_chartControlID, rect2, cdata); } Rect position = rect2; position.x -= 180f; position.width = 180f; this.DoLegendGUI(position, type, cdata, typeForControl, active); if (current.type == EventType.Repaint && GUIClip.visibleRect.Overlaps(rect)) { Chart.Styles.rightPane.Draw(rect2, false, false, active, false); if (this.m_NotSupportedWarning == null) { rect2.height -= 1f; if (type == Chart.ChartType.StackedFill) { this.DrawChartStacked(selectedFrame, cdata, rect2); } else { this.DrawChartLine(selectedFrame, cdata, rect2); } } else { Rect position2 = rect2; position2.x += 59.4f; position2.y += 43f; GUI.Label(position2, this.m_NotSupportedWarning, EditorStyles.boldLabel); } } result = selectedFrame; } return(result); }
protected virtual void DoLegendGUI(Rect position, Chart.ChartType type, ChartViewData cdata, EventType evtType, bool active) { if (Event.current.type == EventType.Repaint) { Chart.Styles.legendBackground.Draw(position, GUIContent.none, false, false, active, false); } Rect rect = position; GUIContent content = this.legendHeaderLabel ?? GUIContent.none; rect.height = Chart.Styles.legendHeaderLabel.CalcSize(content).y; GUI.Label(rect, content, Chart.Styles.legendHeaderLabel); position.yMin += rect.height; position.xMin += 5f; position.xMax -= 5f; this.DoSeriesList(position, this.m_chartControlID, type, cdata); Rect position2 = rect; position2.xMax -= (float)Chart.Styles.legendHeaderLabel.padding.right; position2.xMin = position2.xMax - 13f; position2.yMin += (float)Chart.Styles.legendHeaderLabel.padding.top; position2.yMax = position2.yMin + 13f; if (GUI.Button(position2, GUIContent.none, Chart.Styles.closeButton) && this.closed != null) { this.closed(this); } }
protected virtual void DoLegendGUI(Rect position, ChartType type, ChartViewData cdata, EventType evtType, bool active) { if (Event.current.type == EventType.Repaint) { Styles.legendBackground.Draw(position, GUIContent.none, false, false, active, false); } Rect headerRect = position; GUIContent headerLabel = legendHeaderLabel ?? GUIContent.none; headerRect.height = Styles.legendHeaderLabel.CalcSize(headerLabel).y; GUI.Label(headerRect, headerLabel, Styles.legendHeaderLabel); position.yMin += headerRect.height; position.xMin += kLabelOffset; position.xMax -= kLabelOffset; DoSeriesList(position, m_chartControlID, type, cdata); Rect closeButtonRect = headerRect; closeButtonRect.xMax -= Styles.legendHeaderLabel.padding.right; closeButtonRect.xMin = closeButtonRect.xMax - kCloseButtonSize - kCloseButtonXOffset; closeButtonRect.yMin += Styles.legendHeaderLabel.padding.top; closeButtonRect.yMax = closeButtonRect.yMin + kCloseButtonSize; if (GUI.Button(closeButtonRect, GUIContent.none, Styles.closeButton) && closed != null) { closed(this); } }
public int DoGUI(ChartType type, int selectedFrame, ChartViewData cdata, bool active) { if (cdata == null) { return(selectedFrame); } m_chartControlID = GUIUtility.GetControlID(s_ChartHash, FocusType.Keyboard); var chartHeight = GUILayout.MinHeight( Math.Max(kLabelOffset + ((cdata.numSeries + 1) * kLabelHeight) + kDistFromTopToFirstLabel, kChartMinHeight) ); Rect chartRect = GUILayoutUtility.GetRect(GUIContent.none, Styles.background, chartHeight); Rect r = chartRect; r.x += kSideWidth; r.width -= kSideWidth; Event evt = Event.current; EventType evtType = evt.GetTypeForControl(m_chartControlID); if (evtType == EventType.MouseDown && chartRect.Contains(evt.mousePosition) && selected != null) { ChartSelected(); } // if we are not dragging labels, handle graph frame selection if (m_DragItemIndex == -1) { selectedFrame = HandleFrameSelectionEvents(selectedFrame, m_chartControlID, r, cdata); } Rect sideRect = r; sideRect.x -= kSideWidth; sideRect.width = kSideWidth; DoLegendGUI(sideRect, type, cdata, evtType, active); // Drawing the chart is expensive, so only draw it when it is visible if (evt.type == EventType.Repaint && GUIClip.visibleRect.Overlaps(chartRect)) { Styles.rightPane.Draw(r, false, false, active, false); r.height -= 1.0f; // do not draw the bottom pixel if (type == ChartType.StackedFill) { DrawChartStacked(selectedFrame, cdata, r, active); } else { DrawChartLine(selectedFrame, cdata, r, active); } } return(selectedFrame); }
protected void SaveChartsSettingsEnabled(ChartViewData cdata) { string text = string.Empty; for (int i = 0; i < cdata.numSeries; i++) { text += ((!cdata.series[i].enabled) ? '0' : '1'); } EditorPrefs.SetString(this.m_ChartSettingsName + "Visible", text); }
protected void SaveChartsSettingsEnabled(ChartViewData cdata) { var str = string.Empty; for (var i = 0; i < cdata.numSeries; i++) { str += cdata.series[i].enabled ? '1' : '0'; } EditorPrefs.SetString(m_ChartSettingsName + "Visible", str); }
public ProfilerChart(ProfilerArea area, Chart.ChartType type, float dataScale, int seriesCount) { base.labelRange = new Vector2(Mathf.Epsilon, float.PositiveInfinity); this.m_Area = area; this.m_Type = type; this.m_DataScale = dataScale; this.m_Data = new ChartViewData(); this.m_Series = new ChartSeriesViewData[seriesCount]; this.m_Active = this.ReadActiveState(); this.ApplyActiveState(); }
protected override void DoLegendGUI(Rect position, Chart.ChartType type, ChartViewData cdata, EventType evtType, bool active) { Rect position2 = position; position2.xMin = position2.xMax - (float)ProfilerChart.performanceWarning.image.width; position2.yMin = position2.yMax - (float)ProfilerChart.performanceWarning.image.height; base.DoLegendGUI(position, type, cdata, evtType, active); if (this.m_Area == ProfilerArea.GPU) { GUI.Label(position2, ProfilerChart.performanceWarning); } }
public ProfilerChart(ProfilerArea area, Chart.ChartType type, float dataScale, int seriesCount) : base() { labelRange = new Vector2(Mathf.Epsilon, Mathf.Infinity); graphRange = new Vector2(Mathf.Epsilon, Mathf.Infinity); m_Area = area; m_Type = type; m_DataScale = dataScale; m_Data = new ChartViewData(); m_Series = new ChartSeriesViewData[seriesCount]; m_Active = ReadActiveState(); ApplyActiveState(); }
private void DrawChartLine(int selectedFrame, ChartViewData cdata, Rect r) { for (int i = 0; i < cdata.numSeries; i++) { this.DrawChartItemLine(r, cdata, i); } if (cdata.maxValue > 0f) { this.DrawMaxValueScale(cdata, r); } this.DrawSelectedFrame(selectedFrame, cdata, r); this.DrawLabels(r, cdata, selectedFrame, Chart.ChartType.Line); }
private int MoveSelectedFrame(int selectedFrame, ChartViewData cdata, int direction) { Vector2 domain = cdata.GetDataDomain(); int length = (int)(domain.y - domain.x); int newSelectedFrame = selectedFrame + direction; if (newSelectedFrame < cdata.firstSelectableFrame || newSelectedFrame > cdata.chartDomainOffset + length) { return(selectedFrame); } return(newSelectedFrame); }
private void DrawChartItemStacked(Rect r, int index, ChartViewData cdata, float[] stackedSampleSums) { Vector2 domain = cdata.GetDataDomain(); int numSamples = (int)(domain.y - domain.x); float step = r.width / numSamples; index = cdata.order[index]; if (!cdata.series[index].enabled) { return; } Color color = cdata.series[index].color; if (cdata.hasOverlay) { color *= s_OverlayBackgroundDimFactor; } GL.Begin(GL.TRIANGLE_STRIP); float x = r.x + step * 0.5f; float rangeScale = cdata.series[0].rangeAxis.sqrMagnitude == 0f ? 0f : 1f / (cdata.series[0].rangeAxis.y - cdata.series[0].rangeAxis.x) * r.height; float rectBottom = r.y + r.height; for (int i = 0; i < numSamples; i++, x += step) { float y = rectBottom - stackedSampleSums[i]; var serie = cdata.series[index]; float value = serie.yValues[i] * serie.yScale; if (value == -1f) { continue; } float val = (value - cdata.series[0].rangeAxis.x) * rangeScale; if (y - val < r.yMin) { val = y - r.yMin; // Clamp the values to be inside drawrect } GL.Color(color); GL.Vertex3(x, y - val, 0f); // clip chart top GL.Vertex3(x, y, 0f); stackedSampleSums[i] += val; } GL.End(); }
protected override void DoLegendGUI(Rect position, ChartType type, ChartViewData cdata, EventType evtType, bool active) { Rect warningIconRect = position; warningIconRect.xMin = warningIconRect.xMax - performanceWarning.image.width; warningIconRect.yMin = warningIconRect.yMax - performanceWarning.image.height; base.DoLegendGUI(position, type, cdata, evtType, active); if (m_Area == ProfilerArea.GPU) { GUI.Label(warningIconRect, performanceWarning); } }
protected override void DoLegendGUI(Rect position, ChartType type, ChartViewData cdata, EventType evtType, bool active) { base.DoLegendGUI(position, type, cdata, evtType, active); if (m_Area == ProfilerArea.GPU) { const float rightMmargin = 2f; const float topMargin = 4f; const float iconSize = 16f; var padding = GUISkin.current.label.padding; float width = iconSize + padding.horizontal; GUI.Label(new Rect(position.xMax - width - rightMmargin, position.y + topMargin, width, iconSize + padding.vertical), performanceWarning); } }
private void SaveChartsSettingsOrder(ChartViewData cdata) { if (!string.IsNullOrEmpty(this.m_ChartSettingsName)) { string text = string.Empty; for (int i = 0; i < cdata.numSeries; i++) { if (text.Length != 0) { text += ","; } text += cdata.order[i]; } EditorPrefs.SetString(this.m_ChartSettingsName + "Order", text); } }
void DrawOverlayBoxes(ChartViewData cdata, Rect r, bool chartActive) { m_cachedFramesWithSeparatorLines.Clear(); if (Event.current.type == EventType.Repaint && cdata.dataAvailable != null) { r.height += 1; int lastFrameBeforeStatisticsAvailabilityChanged = 0; int lastStatisticsState = 1; int frameDataLength = cdata.dataAvailable.Length; for (int frame = 0; frame < frameDataLength; frame++) { bool hasDataForFrame = (cdata.dataAvailable[frame] & ChartViewData.dataAvailableBit) == ChartViewData.dataAvailableBit; if (hasDataForFrame) { if (lastFrameBeforeStatisticsAvailabilityChanged < frame - 1) { DrawOverlayBox(r, lastFrameBeforeStatisticsAvailabilityChanged, frame, frameDataLength, chartActive, Styles.noDataOverlayBox, lastStatisticsState); } lastStatisticsState = ChartViewData.dataAvailableBit; lastFrameBeforeStatisticsAvailabilityChanged = frame; } else if (lastStatisticsState != cdata.dataAvailable[frame]) { // Not bitwise comparison because this here just checks that the previous frame didn't just contain normal available data if (lastStatisticsState != ChartViewData.dataAvailableBit) { // a new reason for missing data has started here, flush out the old one DrawOverlayBox(r, lastFrameBeforeStatisticsAvailabilityChanged, frame, frameDataLength, chartActive, Styles.noDataOverlayBox, lastStatisticsState); m_cachedFramesWithSeparatorLines.Add(frame + cdata.chartDomainOffset); } lastFrameBeforeStatisticsAvailabilityChanged = frame; lastStatisticsState = cdata.dataAvailable[frame]; } } if (lastFrameBeforeStatisticsAvailabilityChanged < frameDataLength - 1) { DrawOverlayBox(r, lastFrameBeforeStatisticsAvailabilityChanged, frameDataLength - 1, frameDataLength, chartActive, Styles.noDataOverlayBox, lastStatisticsState); } } foreach (var frame in m_cachedFramesWithSeparatorLines) { DrawVerticalLine(frame, cdata, r, Styles.noDataSeparatorColor, 1f, 1f); } }
private int MoveSelectedFrame(int selectedFrame, ChartViewData cdata, int direction) { Vector2 dataDomain = cdata.GetDataDomain(); int num = (int)(dataDomain.y - dataDomain.x); int num2 = selectedFrame + direction; int result; if (num2 < cdata.firstSelectableFrame || num2 > cdata.chartDomainOffset + num) { result = selectedFrame; } else { result = num2; } return(result); }
private void DrawChartLine(int selectedFrame, ChartViewData cdata, Rect r, bool chartActive) { for (int i = 0; i < cdata.numSeries; i++) { DrawChartItemLine(r, cdata, i); } if (cdata.maxValue > 0) { DrawMaxValueScale(cdata, r); } DrawOverlayBoxes(cdata, r, chartActive); DrawSelectedFrame(selectedFrame, cdata, r); DrawLabels(r, cdata, selectedFrame, ChartType.Line); }