mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 02:36:14 +00:00
提交Unity 联机Pro
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using System;
|
||||
using Services;
|
||||
using SRF;
|
||||
using SRF.UI;
|
||||
using SRF.UI.Layout;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
[RequireComponent(typeof (RectTransform))]
|
||||
public class ConsoleEntryView : SRMonoBehaviourEx, IVirtualView
|
||||
{
|
||||
public const string ConsoleBlobInfo = "Console_Info_Blob";
|
||||
public const string ConsoleBlobWarning = "Console_Warning_Blob";
|
||||
public const string ConsoleBlobError = "Console_Error_Blob";
|
||||
private int _count;
|
||||
private bool _hasCount;
|
||||
private ConsoleEntry _prevData;
|
||||
private RectTransform _rectTransform;
|
||||
|
||||
[RequiredField] public Text Count;
|
||||
|
||||
[RequiredField] public CanvasGroup CountContainer;
|
||||
|
||||
[RequiredField] public StyleComponent ImageStyle;
|
||||
|
||||
[RequiredField] public Text Message;
|
||||
|
||||
[RequiredField] public Text StackTrace;
|
||||
|
||||
public void SetDataContext(object data)
|
||||
{
|
||||
var msg = data as ConsoleEntry;
|
||||
|
||||
if (msg == null)
|
||||
{
|
||||
throw new Exception("Data should be a ConsoleEntry");
|
||||
}
|
||||
|
||||
// Always check for updates on "Count", as it can change
|
||||
if (msg.Count > 1)
|
||||
{
|
||||
if (!_hasCount)
|
||||
{
|
||||
CountContainer.alpha = 1f;
|
||||
_hasCount = true;
|
||||
}
|
||||
|
||||
if (msg.Count != _count)
|
||||
{
|
||||
Count.text = Internal.SRDebuggerUtil.GetNumberString(msg.Count, 999, "999+");
|
||||
_count = msg.Count;
|
||||
}
|
||||
}
|
||||
else if (_hasCount)
|
||||
{
|
||||
CountContainer.alpha = 0f;
|
||||
_hasCount = false;
|
||||
}
|
||||
|
||||
// Only update everything else if data context has changed, not just for an update
|
||||
if (msg == _prevData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_prevData = msg;
|
||||
|
||||
Message.text = msg.MessagePreview;
|
||||
StackTrace.text = msg.StackTracePreview;
|
||||
|
||||
if (string.IsNullOrEmpty(StackTrace.text))
|
||||
{
|
||||
Message.rectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Bottom, 2,
|
||||
_rectTransform.rect.height - 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
Message.rectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Bottom, 12,
|
||||
_rectTransform.rect.height - 14);
|
||||
}
|
||||
|
||||
switch (msg.LogType)
|
||||
{
|
||||
case LogType.Log:
|
||||
ImageStyle.StyleKey = ConsoleBlobInfo;
|
||||
break;
|
||||
|
||||
case LogType.Warning:
|
||||
ImageStyle.StyleKey = ConsoleBlobWarning;
|
||||
break;
|
||||
|
||||
case LogType.Exception:
|
||||
case LogType.Assert:
|
||||
case LogType.Error:
|
||||
ImageStyle.StyleKey = ConsoleBlobError;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
_rectTransform = CachedTransform as RectTransform;
|
||||
CountContainer.alpha = 0f;
|
||||
|
||||
Message.supportRichText = Settings.Instance.RichTextInConsole;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c214ec24a4baf1a4f828768a9795f241
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,196 @@
|
||||
|
||||
#pragma warning disable 169
|
||||
#pragma warning disable 649
|
||||
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Internal;
|
||||
using Services;
|
||||
using SRF;
|
||||
using SRF.UI.Layout;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ConsoleLogControl : SRMonoBehaviourEx
|
||||
{
|
||||
[RequiredField] [SerializeField] private VirtualVerticalLayoutGroup _consoleScrollLayoutGroup;
|
||||
|
||||
[RequiredField] [SerializeField] private ScrollRect _consoleScrollRect;
|
||||
|
||||
private bool _isDirty;
|
||||
private Vector2? _scrollPosition;
|
||||
private bool _showErrors = true;
|
||||
private bool _showInfo = true;
|
||||
private bool _showWarnings = true;
|
||||
public Action<ConsoleEntry> SelectedItemChanged;
|
||||
private string _filter;
|
||||
|
||||
public bool ShowErrors
|
||||
{
|
||||
get { return _showErrors; }
|
||||
set
|
||||
{
|
||||
_showErrors = value;
|
||||
SetIsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowWarnings
|
||||
{
|
||||
get { return _showWarnings; }
|
||||
set
|
||||
{
|
||||
_showWarnings = value;
|
||||
SetIsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowInfo
|
||||
{
|
||||
get { return _showInfo; }
|
||||
set
|
||||
{
|
||||
_showInfo = value;
|
||||
SetIsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public bool EnableSelection
|
||||
{
|
||||
get { return _consoleScrollLayoutGroup.EnableSelection; }
|
||||
set { _consoleScrollLayoutGroup.EnableSelection = value; }
|
||||
}
|
||||
|
||||
public string Filter
|
||||
{
|
||||
get { return _filter; }
|
||||
set {
|
||||
if (_filter != value)
|
||||
{
|
||||
_filter = value;
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
_consoleScrollLayoutGroup.SelectedItemChanged.AddListener(OnSelectedItemChanged);
|
||||
Service.Console.Updated += ConsoleOnUpdated;
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
SetIsDirty();
|
||||
StartCoroutine(ScrollToBottom());
|
||||
}
|
||||
|
||||
IEnumerator ScrollToBottom()
|
||||
{
|
||||
yield return new WaitForEndOfFrame();
|
||||
yield return new WaitForEndOfFrame();
|
||||
yield return new WaitForEndOfFrame();
|
||||
_scrollPosition = new Vector2(0,0);
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
if (Service.Console != null)
|
||||
{
|
||||
Service.Console.Updated -= ConsoleOnUpdated;
|
||||
}
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
private void OnSelectedItemChanged(object arg0)
|
||||
{
|
||||
var entry = arg0 as ConsoleEntry;
|
||||
|
||||
if (SelectedItemChanged != null)
|
||||
{
|
||||
SelectedItemChanged(entry);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (_scrollPosition.HasValue)
|
||||
{
|
||||
_consoleScrollRect.normalizedPosition = _scrollPosition.Value;
|
||||
_scrollPosition = null;
|
||||
}
|
||||
|
||||
if (_isDirty)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private void Refresh()
|
||||
{
|
||||
if (_consoleScrollRect.normalizedPosition.y < 0.01f)
|
||||
{
|
||||
_scrollPosition = _consoleScrollRect.normalizedPosition;
|
||||
}
|
||||
|
||||
_consoleScrollLayoutGroup.ClearItems();
|
||||
|
||||
var entries = Service.Console.Entries;
|
||||
|
||||
for (var i = 0; i < entries.Count; i++)
|
||||
{
|
||||
var e = entries[i];
|
||||
|
||||
if ((e.LogType == LogType.Error || e.LogType == LogType.Exception || e.LogType == LogType.Assert) &&
|
||||
!ShowErrors)
|
||||
{
|
||||
if (e == _consoleScrollLayoutGroup.SelectedItem) _consoleScrollLayoutGroup.SelectedItem = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.LogType == LogType.Warning && !ShowWarnings)
|
||||
{
|
||||
if (e == _consoleScrollLayoutGroup.SelectedItem) _consoleScrollLayoutGroup.SelectedItem = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.LogType == LogType.Log && !ShowInfo)
|
||||
{
|
||||
if (e == _consoleScrollLayoutGroup.SelectedItem) _consoleScrollLayoutGroup.SelectedItem = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Filter))
|
||||
{
|
||||
if (e.Message.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) < 0)
|
||||
{
|
||||
if (e == _consoleScrollLayoutGroup.SelectedItem) _consoleScrollLayoutGroup.SelectedItem = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
_consoleScrollLayoutGroup.AddItem(e);
|
||||
}
|
||||
|
||||
_isDirty = false;
|
||||
}
|
||||
|
||||
private void SetIsDirty()
|
||||
{
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
private void ConsoleOnUpdated(IConsoleService console)
|
||||
{
|
||||
SetIsDirty();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 413376b74a5948a4db9e0a5c9c002724
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5fd2859be59fd34c83def152a20f905
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
@@ -0,0 +1,52 @@
|
||||
namespace SRDebugger.UI.Controls.Data
|
||||
{
|
||||
using System;
|
||||
using SRF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ActionControl : OptionsControlBase
|
||||
{
|
||||
private SRF.Helpers.MethodReference _method;
|
||||
|
||||
[RequiredField] public UnityEngine.UI.Button Button;
|
||||
|
||||
[RequiredField] public Text Title;
|
||||
|
||||
public SRF.Helpers.MethodReference Method
|
||||
{
|
||||
get { return _method; }
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
Button.onClick.AddListener(ButtonOnClick);
|
||||
}
|
||||
|
||||
private void ButtonOnClick()
|
||||
{
|
||||
if (_method == null)
|
||||
{
|
||||
Debug.LogWarning("[SRDebugger.Options] No method set for action control", this);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_method.Invoke(null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("[SRDebugger] Exception thrown while executing action.");
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMethod(string methodName, SRF.Helpers.MethodReference method)
|
||||
{
|
||||
_method = method;
|
||||
Title.text = methodName;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c637c8d0d16d024fa920dda64fb38db
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,44 @@
|
||||
namespace SRDebugger.UI.Controls.Data
|
||||
{
|
||||
using System;
|
||||
using SRF;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class BoolControl : DataBoundControl
|
||||
{
|
||||
[RequiredField] public Text Title;
|
||||
|
||||
[RequiredField] public Toggle Toggle;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
Toggle.onValueChanged.AddListener(ToggleOnValueChanged);
|
||||
}
|
||||
|
||||
private void ToggleOnValueChanged(bool isOn)
|
||||
{
|
||||
UpdateValue(isOn);
|
||||
}
|
||||
|
||||
protected override void OnBind(string propertyName, Type t)
|
||||
{
|
||||
base.OnBind(propertyName, t);
|
||||
|
||||
Title.text = propertyName;
|
||||
|
||||
Toggle.interactable = !IsReadOnly;
|
||||
}
|
||||
|
||||
protected override void OnValueUpdated(object newValue)
|
||||
{
|
||||
var value = (bool) newValue;
|
||||
Toggle.isOn = value;
|
||||
}
|
||||
|
||||
public override bool CanBind(Type type, bool isReadOnly)
|
||||
{
|
||||
return type == typeof (bool);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 645dcae76b625be40b595e4bbc27abb6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,131 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using SRF.Helpers;
|
||||
|
||||
public abstract class DataBoundControl : OptionsControlBase
|
||||
{
|
||||
private bool _hasStarted;
|
||||
private bool _isReadOnly;
|
||||
private object _prevValue;
|
||||
private SRF.Helpers.PropertyReference _prop;
|
||||
|
||||
public SRF.Helpers.PropertyReference Property
|
||||
{
|
||||
get { return _prop; }
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return _isReadOnly; }
|
||||
}
|
||||
|
||||
public string PropertyName { get; private set; }
|
||||
|
||||
#region Data Binding
|
||||
|
||||
public void Bind(string propertyName, SRF.Helpers.PropertyReference prop)
|
||||
{
|
||||
PropertyName = propertyName;
|
||||
_prop = prop;
|
||||
|
||||
_isReadOnly = !prop.CanWrite;
|
||||
|
||||
prop.ValueChanged += OnValueChanged;
|
||||
|
||||
OnBind(propertyName, prop.PropertyType);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void OnValueChanged(PropertyReference property)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
protected void UpdateValue(object newValue)
|
||||
{
|
||||
if (newValue == _prevValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsReadOnly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_prop.SetValue(newValue);
|
||||
_prevValue = newValue;
|
||||
}
|
||||
|
||||
public override void Refresh()
|
||||
{
|
||||
if (_prop == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var currentValue = _prop.GetValue();
|
||||
|
||||
if (currentValue != _prevValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
OnValueUpdated(currentValue);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("[SROptions] Error refreshing binding.");
|
||||
Debug.LogException(e);
|
||||
}
|
||||
}
|
||||
|
||||
_prevValue = currentValue;
|
||||
}
|
||||
|
||||
protected virtual void OnBind(string propertyName, Type t) {}
|
||||
protected abstract void OnValueUpdated(object newValue);
|
||||
|
||||
public abstract bool CanBind(Type type, bool isReadOnly);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
Refresh();
|
||||
_hasStarted = true;
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
if (_hasStarted)
|
||||
{
|
||||
if (_prop != null)
|
||||
{
|
||||
_prop.ValueChanged += OnValueChanged;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
if (_prop != null)
|
||||
{
|
||||
_prop.ValueChanged -= OnValueChanged;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f319c80d34ef2e4590641a136c82f1e
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,109 @@
|
||||
// ReSharper disable once RedundantUsingDirective
|
||||
using System.Reflection;
|
||||
|
||||
namespace SRDebugger.UI.Controls.Data
|
||||
{
|
||||
using System;
|
||||
using SRF;
|
||||
using SRF.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class EnumControl : DataBoundControl
|
||||
{
|
||||
private object _lastValue;
|
||||
private string[] _names;
|
||||
private Array _values;
|
||||
|
||||
[RequiredField] public LayoutElement ContentLayoutElement;
|
||||
|
||||
public GameObject[] DisableOnReadOnly;
|
||||
|
||||
[RequiredField] public SRSpinner Spinner;
|
||||
|
||||
[RequiredField] public Text Title;
|
||||
|
||||
[RequiredField] public Text Value;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
}
|
||||
|
||||
protected override void OnBind(string propertyName, Type t)
|
||||
{
|
||||
base.OnBind(propertyName, t);
|
||||
|
||||
Title.text = propertyName;
|
||||
|
||||
Spinner.interactable = !IsReadOnly;
|
||||
|
||||
if (DisableOnReadOnly != null)
|
||||
{
|
||||
foreach (var child in DisableOnReadOnly)
|
||||
{
|
||||
child.SetActive(!IsReadOnly);
|
||||
}
|
||||
}
|
||||
|
||||
_names = Enum.GetNames(t);
|
||||
_values = Enum.GetValues(t);
|
||||
|
||||
var longestName = "";
|
||||
|
||||
for (var i = 0; i < _names.Length; i++)
|
||||
{
|
||||
if (_names[i].Length > longestName.Length)
|
||||
{
|
||||
longestName = _names[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (_names.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Set preferred width of content to the largest possible value size
|
||||
|
||||
var width = Value.cachedTextGeneratorForLayout.GetPreferredWidth(longestName,
|
||||
Value.GetGenerationSettings(new Vector2(float.MaxValue, Value.preferredHeight)));
|
||||
|
||||
ContentLayoutElement.preferredWidth = width;
|
||||
}
|
||||
|
||||
protected override void OnValueUpdated(object newValue)
|
||||
{
|
||||
_lastValue = newValue;
|
||||
Value.text = newValue.ToString();
|
||||
LayoutRebuilder.MarkLayoutForRebuild(GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
public override bool CanBind(Type type, bool isReadOnly)
|
||||
{
|
||||
#if NETFX_CORE
|
||||
return type.GetTypeInfo().IsEnum;
|
||||
#else
|
||||
return type.IsEnum;
|
||||
#endif
|
||||
}
|
||||
|
||||
private void SetIndex(int i)
|
||||
{
|
||||
UpdateValue(_values.GetValue(i));
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public void GoToNext()
|
||||
{
|
||||
var currentIndex = Array.IndexOf(_values, _lastValue);
|
||||
SetIndex(SRMath.Wrap(_values.Length, currentIndex + 1));
|
||||
}
|
||||
|
||||
public void GoToPrevious()
|
||||
{
|
||||
var currentIndex = Array.IndexOf(_values, _lastValue);
|
||||
SetIndex(SRMath.Wrap(_values.Length, currentIndex - 1));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b7f14311f0b3f442b273192dc8ffe4d
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,200 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace SRDebugger.UI.Controls.Data
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SRF;
|
||||
using SRF.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class NumberControl : DataBoundControl
|
||||
{
|
||||
private static readonly Type[] IntegerTypes =
|
||||
{
|
||||
typeof (int), typeof (short), typeof (byte), typeof (sbyte), typeof (uint), typeof (ushort)
|
||||
};
|
||||
|
||||
private static readonly Type[] DecimalTypes =
|
||||
{
|
||||
typeof (float), typeof (double)
|
||||
};
|
||||
|
||||
public static readonly Dictionary<Type, ValueRange> ValueRanges = new Dictionary<Type, ValueRange>
|
||||
{
|
||||
{typeof (int), new ValueRange {MaxValue = int.MaxValue, MinValue = int.MinValue}},
|
||||
{typeof (short), new ValueRange {MaxValue = short.MaxValue, MinValue = short.MinValue}},
|
||||
{typeof (byte), new ValueRange {MaxValue = byte.MaxValue, MinValue = byte.MinValue}},
|
||||
{typeof (sbyte), new ValueRange {MaxValue = sbyte.MaxValue, MinValue = sbyte.MinValue}},
|
||||
{typeof (uint), new ValueRange {MaxValue = uint.MaxValue, MinValue = uint.MinValue}},
|
||||
{typeof (ushort), new ValueRange {MaxValue = ushort.MaxValue, MinValue = ushort.MinValue}},
|
||||
{typeof (float), new ValueRange {MaxValue = float.MaxValue, MinValue = float.MinValue}},
|
||||
{typeof (double), new ValueRange {MaxValue = double.MaxValue, MinValue = double.MinValue}}
|
||||
};
|
||||
|
||||
private string _lastValue;
|
||||
private Type _type;
|
||||
public GameObject[] DisableOnReadOnly;
|
||||
public SRNumberButton DownNumberButton;
|
||||
|
||||
[RequiredField] public SRNumberSpinner NumberSpinner;
|
||||
|
||||
[RequiredField] public Text Title;
|
||||
|
||||
public SRNumberButton UpNumberButton;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
NumberSpinner.onEndEdit.AddListener(OnValueChanged);
|
||||
}
|
||||
|
||||
private void OnValueChanged(string newValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
var num = Convert.ChangeType(newValue, _type, CultureInfo.InvariantCulture);
|
||||
UpdateValue(num);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
NumberSpinner.text = _lastValue;
|
||||
}
|
||||
|
||||
LayoutRebuilder.MarkLayoutForRebuild(GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
protected override void OnBind(string propertyName, Type t)
|
||||
{
|
||||
base.OnBind(propertyName, t);
|
||||
Title.text = propertyName;
|
||||
|
||||
if (IsIntegerType(t))
|
||||
{
|
||||
NumberSpinner.contentType = InputField.ContentType.IntegerNumber;
|
||||
}
|
||||
else if (IsDecimalType(t))
|
||||
{
|
||||
NumberSpinner.contentType = InputField.ContentType.DecimalNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Type must be one of expected types", "t");
|
||||
}
|
||||
|
||||
var rangeAttrib = Property.GetAttribute<NumberRangeAttribute>();
|
||||
|
||||
NumberSpinner.MaxValue = GetMaxValue(t);
|
||||
NumberSpinner.MinValue = GetMinValue(t);
|
||||
|
||||
if (rangeAttrib != null)
|
||||
{
|
||||
NumberSpinner.MaxValue = Math.Min(rangeAttrib.Max, NumberSpinner.MaxValue);
|
||||
NumberSpinner.MinValue = Math.Max(rangeAttrib.Min, NumberSpinner.MinValue);
|
||||
}
|
||||
|
||||
var incrementAttribute = Property.GetAttribute<IncrementAttribute>();
|
||||
|
||||
if (incrementAttribute != null)
|
||||
{
|
||||
if (UpNumberButton != null)
|
||||
{
|
||||
UpNumberButton.Amount = incrementAttribute.Increment;
|
||||
}
|
||||
|
||||
if (DownNumberButton != null)
|
||||
{
|
||||
DownNumberButton.Amount = -incrementAttribute.Increment;
|
||||
}
|
||||
}
|
||||
|
||||
_type = t;
|
||||
|
||||
NumberSpinner.interactable = !IsReadOnly;
|
||||
|
||||
if (DisableOnReadOnly != null)
|
||||
{
|
||||
foreach (var childControl in DisableOnReadOnly)
|
||||
{
|
||||
childControl.SetActive(!IsReadOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnValueUpdated(object newValue)
|
||||
{
|
||||
var value = Convert.ToDecimal(newValue, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (value != _lastValue)
|
||||
{
|
||||
NumberSpinner.text = value;
|
||||
}
|
||||
|
||||
_lastValue = value;
|
||||
}
|
||||
|
||||
public override bool CanBind(Type type, bool isReadOnly)
|
||||
{
|
||||
return IsDecimalType(type) || IsIntegerType(type);
|
||||
}
|
||||
|
||||
protected static bool IsIntegerType(Type t)
|
||||
{
|
||||
for (var i = 0; i < IntegerTypes.Length; i++)
|
||||
{
|
||||
if (IntegerTypes[i] == t)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static bool IsDecimalType(Type t)
|
||||
{
|
||||
for (var i = 0; i < DecimalTypes.Length; i++)
|
||||
{
|
||||
if (DecimalTypes[i] == t)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected double GetMaxValue(Type t)
|
||||
{
|
||||
ValueRange value;
|
||||
if (ValueRanges.TryGetValue(t, out value))
|
||||
{
|
||||
return value.MaxValue;
|
||||
}
|
||||
|
||||
Debug.LogWarning("[NumberControl] No MaxValue stored for type {0}".Fmt(t));
|
||||
|
||||
return double.MaxValue;
|
||||
}
|
||||
|
||||
protected double GetMinValue(Type t)
|
||||
{
|
||||
ValueRange value;
|
||||
if (ValueRanges.TryGetValue(t, out value))
|
||||
{
|
||||
return value.MinValue;
|
||||
}
|
||||
|
||||
Debug.LogWarning("[NumberControl] No MinValue stored for type {0}".Fmt(t));
|
||||
|
||||
return double.MinValue;
|
||||
}
|
||||
|
||||
public struct ValueRange
|
||||
{
|
||||
public double MaxValue;
|
||||
public double MinValue;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a6d9f7214a7c5e4b868bfc520d92799
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,74 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using Internal;
|
||||
using SRF;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public abstract class OptionsControlBase : SRMonoBehaviourEx
|
||||
{
|
||||
private bool _selectionModeEnabled;
|
||||
|
||||
[RequiredField] public Toggle SelectionModeToggle;
|
||||
|
||||
public OptionDefinition Option;
|
||||
|
||||
public bool SelectionModeEnabled
|
||||
{
|
||||
get { return _selectionModeEnabled; }
|
||||
|
||||
set
|
||||
{
|
||||
if (value == _selectionModeEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_selectionModeEnabled = value;
|
||||
|
||||
SelectionModeToggle.gameObject.SetActive(_selectionModeEnabled);
|
||||
|
||||
if (SelectionModeToggle.graphic != null)
|
||||
{
|
||||
SelectionModeToggle.graphic.CrossFadeAlpha(IsSelected ? _selectionModeEnabled ? 1.0f : 0.2f : 0f, 0,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get { return SelectionModeToggle.isOn; }
|
||||
set
|
||||
{
|
||||
SelectionModeToggle.isOn = value;
|
||||
|
||||
if (SelectionModeToggle.graphic != null)
|
||||
{
|
||||
SelectionModeToggle.graphic.CrossFadeAlpha(value ? _selectionModeEnabled ? 1.0f : 0.2f : 0f, 0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
IsSelected = false;
|
||||
SelectionModeToggle.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
// Reapply selection indicator alpha (is reset when disabled / reenabled)
|
||||
if (SelectionModeToggle.graphic != null)
|
||||
{
|
||||
SelectionModeToggle.graphic.CrossFadeAlpha(IsSelected ? _selectionModeEnabled ? 1.0f : 0.2f : 0f, 0,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Refresh() {}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff04c6750fdb3b744ac19818a2425666
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,36 @@
|
||||
namespace SRDebugger.UI.Controls.Data
|
||||
{
|
||||
using System;
|
||||
using SRF;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ReadOnlyControl : DataBoundControl
|
||||
{
|
||||
[RequiredField]
|
||||
public Text ValueText;
|
||||
|
||||
[RequiredField]
|
||||
public Text Title;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
}
|
||||
|
||||
protected override void OnBind(string propertyName, Type t)
|
||||
{
|
||||
base.OnBind(propertyName, t);
|
||||
Title.text = propertyName;
|
||||
}
|
||||
|
||||
protected override void OnValueUpdated(object newValue)
|
||||
{
|
||||
ValueText.text = Convert.ToString(newValue);
|
||||
}
|
||||
|
||||
public override bool CanBind(Type type, bool isReadOnly)
|
||||
{
|
||||
return type == typeof(string) && isReadOnly;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41b5dbc85a74ae84dbb6c6685e1151fc
|
||||
timeCreated: 1466683332
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,47 @@
|
||||
namespace SRDebugger.UI.Controls.Data
|
||||
{
|
||||
using System;
|
||||
using SRF;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class StringControl : DataBoundControl
|
||||
{
|
||||
[RequiredField] public InputField InputField;
|
||||
|
||||
[RequiredField] public Text Title;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
#if UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
|
||||
InputField.onValueChange.AddListener(OnValueChanged);
|
||||
#else
|
||||
InputField.onValueChanged.AddListener(OnValueChanged);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void OnValueChanged(string newValue)
|
||||
{
|
||||
UpdateValue(newValue);
|
||||
}
|
||||
|
||||
protected override void OnBind(string propertyName, Type t)
|
||||
{
|
||||
base.OnBind(propertyName, t);
|
||||
Title.text = propertyName;
|
||||
InputField.text = "";
|
||||
InputField.interactable = !IsReadOnly;
|
||||
}
|
||||
|
||||
protected override void OnValueUpdated(object newValue)
|
||||
{
|
||||
var value = newValue == null ? "" : (string) newValue;
|
||||
InputField.text = value;
|
||||
}
|
||||
|
||||
public override bool CanBind(Type type, bool isReadOnly)
|
||||
{
|
||||
return type == typeof (string) && !isReadOnly;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 019f81638c7cf1f438569f1ca9def175
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,12 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using SRF;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class InfoBlock : SRMonoBehaviourEx
|
||||
{
|
||||
[RequiredField] public Text Content;
|
||||
|
||||
[RequiredField] public Text Title;
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3214a2a17debe0c489148429ec9a37b2
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,30 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public class MultiTapButton : UnityEngine.UI.Button
|
||||
{
|
||||
private float _lastTap;
|
||||
private int _tapCount;
|
||||
public int RequiredTapCount = 3;
|
||||
public float ResetTime = 0.5f;
|
||||
|
||||
public override void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (Time.unscaledTime - _lastTap > ResetTime)
|
||||
{
|
||||
_tapCount = 0;
|
||||
}
|
||||
|
||||
_lastTap = Time.unscaledTime;
|
||||
_tapCount++;
|
||||
|
||||
if (_tapCount == RequiredTapCount)
|
||||
{
|
||||
base.OnPointerClick(eventData);
|
||||
_tapCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abc57d317f579f2459ba7317f386ecf3
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,214 @@
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using SRF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public delegate void PinEntryControlCallback(IList<int> result, bool didCancel);
|
||||
|
||||
public class PinEntryControl : SRMonoBehaviourEx
|
||||
{
|
||||
private bool _isVisible = true;
|
||||
private List<int> _numbers = new List<int>(4);
|
||||
|
||||
[RequiredField] public Image Background;
|
||||
|
||||
public bool CanCancel = true;
|
||||
|
||||
[RequiredField] public UnityEngine.UI.Button CancelButton;
|
||||
|
||||
[RequiredField] public Text CancelButtonText;
|
||||
|
||||
[RequiredField] public CanvasGroup CanvasGroup;
|
||||
|
||||
[RequiredField] public Animator DotAnimator;
|
||||
|
||||
public UnityEngine.UI.Button[] NumberButtons;
|
||||
public Toggle[] NumberDots;
|
||||
|
||||
[RequiredField] public Text PromptText;
|
||||
|
||||
public event PinEntryControlCallback Complete;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
for (var i = 0; i < NumberButtons.Length; i++)
|
||||
{
|
||||
var number = i;
|
||||
|
||||
NumberButtons[i].onClick.AddListener(() => { PushNumber(number); });
|
||||
}
|
||||
|
||||
CancelButton.onClick.AddListener(CancelButtonPressed);
|
||||
|
||||
RefreshState();
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
Keyboard.current.onTextInput += HandleCharacter;
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
Keyboard.current.onTextInput -= HandleCharacter;
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!_isVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
bool delete = Keyboard.current.deleteKey.wasPressedThisFrame || Keyboard.current.backspaceKey.wasPressedThisFrame;
|
||||
#else
|
||||
bool delete = (Input.GetKeyDown(KeyCode.Backspace) || Input.GetKeyDown(KeyCode.Delete));
|
||||
#endif
|
||||
|
||||
if (_numbers.Count > 0 && delete)
|
||||
{
|
||||
_numbers.PopLast();
|
||||
RefreshState();
|
||||
}
|
||||
|
||||
#if !ENABLE_INPUT_SYSTEM
|
||||
var input = Input.inputString;
|
||||
|
||||
for (var i = 0; i < input.Length; i++)
|
||||
{
|
||||
HandleCharacter(input[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void HandleCharacter(char i)
|
||||
{
|
||||
if (!_isVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!char.IsNumber(i))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var num = (int) char.GetNumericValue(i);
|
||||
|
||||
if (num > 9 || num < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PushNumber(num);
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
CanvasGroup.alpha = 1f;
|
||||
CanvasGroup.blocksRaycasts = CanvasGroup.interactable = true;
|
||||
_isVisible = true;
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
CanvasGroup.alpha = 0f;
|
||||
CanvasGroup.blocksRaycasts = CanvasGroup.interactable = false;
|
||||
_isVisible = false;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_numbers.Clear();
|
||||
RefreshState();
|
||||
}
|
||||
|
||||
public void PlayInvalidCodeAnimation()
|
||||
{
|
||||
DotAnimator.SetTrigger("Invalid");
|
||||
}
|
||||
|
||||
protected void OnComplete()
|
||||
{
|
||||
if (Complete != null)
|
||||
{
|
||||
Complete(new ReadOnlyCollection<int>(_numbers), false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnCancel()
|
||||
{
|
||||
if (Complete != null)
|
||||
{
|
||||
Complete(new int[] {}, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelButtonPressed()
|
||||
{
|
||||
if (_numbers.Count > 0)
|
||||
{
|
||||
_numbers.PopLast();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnCancel();
|
||||
}
|
||||
|
||||
RefreshState();
|
||||
}
|
||||
|
||||
public void PushNumber(int number)
|
||||
{
|
||||
if (_numbers.Count >= 4)
|
||||
{
|
||||
Debug.LogWarning("[PinEntry] Expected 4 numbers");
|
||||
return;
|
||||
}
|
||||
|
||||
_numbers.Add(number);
|
||||
|
||||
if (_numbers.Count >= 4)
|
||||
{
|
||||
OnComplete();
|
||||
}
|
||||
|
||||
RefreshState();
|
||||
}
|
||||
|
||||
private void RefreshState()
|
||||
{
|
||||
for (var i = 0; i < NumberDots.Length; i++)
|
||||
{
|
||||
NumberDots[i].isOn = i < _numbers.Count;
|
||||
}
|
||||
|
||||
if (_numbers.Count > 0)
|
||||
{
|
||||
CancelButtonText.text = "Delete";
|
||||
}
|
||||
else
|
||||
{
|
||||
CancelButtonText.text = CanCancel ? "Cancel" : "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac5725a9566ed324c98b66c6cb03c5cf
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de55705b2748e684483766cb59b84390
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
@@ -0,0 +1,38 @@
|
||||
namespace SRDebugger.UI
|
||||
{
|
||||
using Services;
|
||||
using SRF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ProfilerFPSLabel : SRMonoBehaviourEx
|
||||
{
|
||||
private float _nextUpdate;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (Time.realtimeSinceStartup > _nextUpdate)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private void Refresh()
|
||||
{
|
||||
_text.text = "FPS: {0:0.00}".Fmt(1f/_profilerService.AverageFrameTime);
|
||||
|
||||
_nextUpdate = Time.realtimeSinceStartup + UpdateFrequency;
|
||||
}
|
||||
#pragma warning disable 649
|
||||
|
||||
[Import] private IProfilerService _profilerService;
|
||||
|
||||
public float UpdateFrequency = 1f;
|
||||
|
||||
[RequiredField] [SerializeField] private Text _text;
|
||||
|
||||
#pragma warning restore 649
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85621644eaef06f44835068498590190
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,79 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using SRF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_5_5_OR_NEWER
|
||||
using UnityEngine.Profiling;
|
||||
#endif
|
||||
|
||||
public class ProfilerMemoryBlock : SRMonoBehaviourEx
|
||||
{
|
||||
private float _lastRefresh;
|
||||
|
||||
[RequiredField] public Text CurrentUsedText;
|
||||
|
||||
[RequiredField] public Slider Slider;
|
||||
|
||||
[RequiredField] public Text TotalAllocatedText;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
TriggerRefresh();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (SRDebug.Instance.IsDebugPanelVisible && (Time.realtimeSinceStartup - _lastRefresh > 1f))
|
||||
{
|
||||
TriggerRefresh();
|
||||
_lastRefresh = Time.realtimeSinceStartup;
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerRefresh()
|
||||
{
|
||||
long max;
|
||||
long current;
|
||||
|
||||
#if UNITY_5_6_OR_NEWER
|
||||
max = Profiler.GetTotalReservedMemoryLong();
|
||||
current = Profiler.GetTotalAllocatedMemoryLong();
|
||||
#else
|
||||
max = Profiler.GetTotalReservedMemory();
|
||||
current = Profiler.GetTotalAllocatedMemory();
|
||||
#endif
|
||||
|
||||
var maxMb = (max >> 10);
|
||||
maxMb /= 1024; // On new line to fix il2cpp
|
||||
|
||||
var currentMb = (current >> 10);
|
||||
currentMb /= 1024;
|
||||
|
||||
Slider.maxValue = maxMb;
|
||||
Slider.value = currentMb;
|
||||
|
||||
TotalAllocatedText.text = "Reserved: <color=#FFFFFF>{0}</color>MB".Fmt(maxMb);
|
||||
CurrentUsedText.text = "<color=#FFFFFF>{0}</color>MB".Fmt(currentMb);
|
||||
}
|
||||
|
||||
public void TriggerCleanup()
|
||||
{
|
||||
StartCoroutine(CleanUp());
|
||||
}
|
||||
|
||||
private IEnumerator CleanUp()
|
||||
{
|
||||
GC.Collect();
|
||||
yield return Resources.UnloadUnusedAssets();
|
||||
GC.Collect();
|
||||
|
||||
TriggerRefresh();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 445cb6d0a347a0542a38dd652e9ba01b
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,91 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using System;
|
||||
using SRF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_5_5_OR_NEWER
|
||||
using UnityEngine.Profiling;
|
||||
#endif
|
||||
|
||||
public class ProfilerMonoBlock : SRMonoBehaviourEx
|
||||
{
|
||||
private float _lastRefresh;
|
||||
|
||||
[RequiredField]
|
||||
public Text CurrentUsedText;
|
||||
|
||||
[RequiredField]
|
||||
public GameObject NotSupportedMessage;
|
||||
|
||||
[RequiredField]
|
||||
public Slider Slider;
|
||||
|
||||
[RequiredField]
|
||||
public Text TotalAllocatedText;
|
||||
private bool _isSupported;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
#if UNITY_5_6_OR_NEWER
|
||||
_isSupported = Profiler.GetMonoUsedSizeLong() > 0;
|
||||
#else
|
||||
_isSupported = Profiler.GetMonoUsedSize() > 0;
|
||||
#endif
|
||||
|
||||
NotSupportedMessage.SetActive(!_isSupported);
|
||||
CurrentUsedText.gameObject.SetActive(_isSupported);
|
||||
|
||||
TriggerRefresh();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (SRDebug.Instance.IsDebugPanelVisible && (Time.realtimeSinceStartup - _lastRefresh > 1f))
|
||||
{
|
||||
TriggerRefresh();
|
||||
_lastRefresh = Time.realtimeSinceStartup;
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerRefresh()
|
||||
{
|
||||
long max;
|
||||
long current;
|
||||
|
||||
#if UNITY_5_6_OR_NEWER
|
||||
max = _isSupported ? Profiler.GetMonoHeapSizeLong() : GC.GetTotalMemory(false);
|
||||
current = Profiler.GetMonoUsedSizeLong();
|
||||
#else
|
||||
max = _isSupported ? Profiler.GetMonoHeapSize() : GC.GetTotalMemory(false);
|
||||
current = Profiler.GetMonoUsedSize();
|
||||
#endif
|
||||
|
||||
var maxMb = (max >> 10);
|
||||
maxMb /= 1024; // On new line to workaround IL2CPP bug
|
||||
|
||||
var currentMb = (current >> 10);
|
||||
currentMb /= 1024;
|
||||
|
||||
Slider.maxValue = maxMb;
|
||||
Slider.value = currentMb;
|
||||
|
||||
TotalAllocatedText.text = "Total: <color=#FFFFFF>{0}</color>MB".Fmt(maxMb);
|
||||
|
||||
if (currentMb > 0)
|
||||
{
|
||||
CurrentUsedText.text = "<color=#FFFFFF>{0}</color>MB".Fmt(currentMb);
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerCollection()
|
||||
{
|
||||
GC.Collect();
|
||||
TriggerRefresh();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fff10238b625f545b2d88c80d4cf9d4
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,73 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using Internal;
|
||||
using SRF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_5_5_OR_NEWER
|
||||
using UnityEngine.Profiling;
|
||||
#endif
|
||||
|
||||
public class ProfilerEnableControl : SRMonoBehaviourEx
|
||||
{
|
||||
private bool _previousState;
|
||||
[RequiredField] public Text ButtonText;
|
||||
[RequiredField] public UnityEngine.UI.Button EnableButton;
|
||||
[RequiredField] public Text Text;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
if (!Profiler.supported)
|
||||
{
|
||||
Text.text = SRDebugStrings.Current.Profiler_NotSupported;
|
||||
EnableButton.gameObject.SetActive(false);
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Application.HasProLicense())
|
||||
{
|
||||
Text.text = SRDebugStrings.Current.Profiler_NoProInfo;
|
||||
EnableButton.gameObject.SetActive(false);
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateLabels();
|
||||
}
|
||||
|
||||
protected void UpdateLabels()
|
||||
{
|
||||
if (!Profiler.enabled)
|
||||
{
|
||||
Text.text = SRDebugStrings.Current.Profiler_EnableProfilerInfo;
|
||||
ButtonText.text = "Enable";
|
||||
}
|
||||
else
|
||||
{
|
||||
Text.text = SRDebugStrings.Current.Profiler_DisableProfilerInfo;
|
||||
ButtonText.text = "Disable";
|
||||
}
|
||||
|
||||
_previousState = Profiler.enabled;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (Profiler.enabled != _previousState)
|
||||
{
|
||||
UpdateLabels();
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleProfiler()
|
||||
{
|
||||
Debug.Log("Toggle Profiler");
|
||||
Profiler.enabled = !Profiler.enabled;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04ad714fc337b334687c4aedb49873e9
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,51 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using SRF;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
[RequireComponent(typeof (RectTransform))]
|
||||
public class ProfilerGraphAxisLabel : SRMonoBehaviourEx
|
||||
{
|
||||
private float _prevFrameTime;
|
||||
private float? _queuedFrameTime;
|
||||
private float _yPosition;
|
||||
|
||||
[RequiredField] public Text Text;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (_queuedFrameTime.HasValue)
|
||||
{
|
||||
SetValueInternal(_queuedFrameTime.Value);
|
||||
_queuedFrameTime = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetValue(float frameTime, float yPosition)
|
||||
{
|
||||
if (_prevFrameTime == frameTime && _yPosition == yPosition)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_queuedFrameTime = frameTime;
|
||||
_yPosition = yPosition;
|
||||
}
|
||||
|
||||
private void SetValueInternal(float frameTime)
|
||||
{
|
||||
_prevFrameTime = frameTime;
|
||||
|
||||
var ms = Mathf.FloorToInt(frameTime*1000);
|
||||
var fps = Mathf.RoundToInt(1f/frameTime);
|
||||
|
||||
Text.text = "{0}ms ({1}FPS)".Fmt(ms, fps);
|
||||
|
||||
var r = (RectTransform) CachedTransform;
|
||||
r.anchoredPosition = new Vector2(r.rect.width*0.5f + 10f, _yPosition);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4694d7052fd506340ba6cad9f8a10f1b
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,550 @@
|
||||
//#define LOGGING
|
||||
|
||||
#if UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1
|
||||
#define LEGACY_UI
|
||||
#endif
|
||||
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Services;
|
||||
using SRF;
|
||||
using SRF.Service;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof (RectTransform))]
|
||||
[RequireComponent(typeof (CanvasRenderer))]
|
||||
public class ProfilerGraphControl : Graphic
|
||||
{
|
||||
public enum VerticalAlignments
|
||||
{
|
||||
Top,
|
||||
Bottom
|
||||
}
|
||||
|
||||
public VerticalAlignments VerticalAlignment = VerticalAlignments.Bottom;
|
||||
|
||||
private static readonly float[] ScaleSteps =
|
||||
{
|
||||
1f/200f,
|
||||
1f/160f,
|
||||
1f/120f,
|
||||
1f/100f,
|
||||
1f/60f,
|
||||
1f/30f,
|
||||
1f/20f,
|
||||
1f/12f,
|
||||
1f/6f
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Resize the y-axis to fit the nearest useful fps value
|
||||
/// </summary>
|
||||
public bool FloatingScale;
|
||||
|
||||
/// <summary>
|
||||
/// If not using FloatingScale, use the target FPS set by Application.targetFrameRate for TargetFps
|
||||
/// </summary>
|
||||
public bool TargetFpsUseApplication;
|
||||
|
||||
/// <summary>
|
||||
/// Toggle drawing of the various axes
|
||||
/// </summary>
|
||||
public bool DrawAxes = true;
|
||||
|
||||
/// <summary>
|
||||
/// If FloatingScale is disabled, use this value to determine y-axis
|
||||
/// </summary>
|
||||
public int TargetFps = 60;
|
||||
|
||||
public bool Clip = true;
|
||||
|
||||
public const float DataPointMargin = 2f;
|
||||
public const float DataPointVerticalMargin = 2f;
|
||||
|
||||
public const float DataPointWidth = 4f;
|
||||
|
||||
public int VerticalPadding = 10;
|
||||
|
||||
public const int LineCount = 3;
|
||||
|
||||
public Color[] LineColours = new Color[0];
|
||||
|
||||
private IProfilerService _profilerService;
|
||||
|
||||
private ProfilerGraphAxisLabel[] _axisLabels;
|
||||
|
||||
private Rect _clipBounds;
|
||||
|
||||
#if LEGACY_UI
|
||||
private List<UIVertex> _vbo;
|
||||
#else
|
||||
private readonly List<Vector3> _meshVertices = new List<Vector3>();
|
||||
private readonly List<Color32> _meshVertexColors = new List<Color32>();
|
||||
private readonly List<int> _meshTriangles = new List<int>();
|
||||
#endif
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_profilerService = SRServiceManager.GetService<IProfilerService>();
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
}
|
||||
|
||||
protected void Update()
|
||||
{
|
||||
SetVerticesDirty();
|
||||
}
|
||||
|
||||
#if LEGACY_UI
|
||||
protected override void OnFillVBO(List<UIVertex> vbo)
|
||||
#else
|
||||
[System.ObsoleteAttribute]
|
||||
protected override void OnPopulateMesh(Mesh m)
|
||||
#endif
|
||||
{
|
||||
#if LEGACY_UI
|
||||
_vbo = vbo;
|
||||
#else
|
||||
_meshVertices.Clear();
|
||||
_meshVertexColors.Clear();
|
||||
_meshTriangles.Clear();
|
||||
#endif
|
||||
|
||||
#if LOGGING
|
||||
if(!Application.isPlaying)
|
||||
Debug.Log("Draw");
|
||||
#endif
|
||||
|
||||
var graphWidth = rectTransform.rect.width;
|
||||
var graphHeight = rectTransform.rect.height;
|
||||
|
||||
_clipBounds = new Rect(0, 0, graphWidth, graphHeight);
|
||||
|
||||
var targetFps = TargetFps;
|
||||
|
||||
if (Application.isPlaying && TargetFpsUseApplication && Application.targetFrameRate > 0)
|
||||
{
|
||||
targetFps = Application.targetFrameRate;
|
||||
}
|
||||
|
||||
var maxValue = 1f/targetFps;
|
||||
|
||||
// Holds the index of the nearest 'useful' FPS step
|
||||
var fpsStep = -1;
|
||||
|
||||
var maxFrameTime = FloatingScale ? CalculateMaxFrameTime() : 1f/targetFps;
|
||||
|
||||
if (FloatingScale)
|
||||
{
|
||||
for (var i = 0; i < ScaleSteps.Length; i++)
|
||||
{
|
||||
var step = ScaleSteps[i];
|
||||
|
||||
if (maxFrameTime < step*1.1f)
|
||||
{
|
||||
maxValue = step;
|
||||
fpsStep = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back on the largest one
|
||||
if (fpsStep < 0)
|
||||
{
|
||||
fpsStep = ScaleSteps.Length - 1;
|
||||
maxValue = ScaleSteps[fpsStep];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search for the next scale step after the user-provided step
|
||||
for (var i = 0; i < ScaleSteps.Length; i++)
|
||||
{
|
||||
var step = ScaleSteps[i];
|
||||
|
||||
if (maxFrameTime > step)
|
||||
{
|
||||
fpsStep = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var verticalScale = (graphHeight - (VerticalPadding*2))/maxValue;
|
||||
|
||||
// Number of data points that can fit into the graph space
|
||||
var availableDataPoints = CalculateVisibleDataPointCount();
|
||||
|
||||
// Reallocate vertex array if insufficient length (or not yet created)
|
||||
var sampleCount = GetFrameBufferCurrentSize();
|
||||
|
||||
for (var i = 0; i < sampleCount; i++)
|
||||
{
|
||||
// Break loop if all visible data points have been drawn
|
||||
if (i >= availableDataPoints)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// When using right-alignment, read from the end of the profiler buffer
|
||||
var frame = GetFrame(sampleCount - i - 1);
|
||||
|
||||
// Left-hand x coord
|
||||
var lx = graphWidth - DataPointWidth*i - DataPointWidth - graphWidth/2f;
|
||||
|
||||
DrawDataPoint(lx, verticalScale, frame);
|
||||
}
|
||||
|
||||
if (DrawAxes)
|
||||
{
|
||||
if (!FloatingScale)
|
||||
{
|
||||
DrawAxis(maxValue, maxValue*verticalScale, GetAxisLabel(0));
|
||||
}
|
||||
|
||||
var axisCount = 2;
|
||||
var j = 0;
|
||||
|
||||
if (!FloatingScale)
|
||||
{
|
||||
j++;
|
||||
}
|
||||
|
||||
for (var i = fpsStep; i >= 0; --i)
|
||||
{
|
||||
if (j >= axisCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
DrawAxis(ScaleSteps[i], ScaleSteps[i]*verticalScale, GetAxisLabel(j));
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
#if !LEGACY_UI
|
||||
|
||||
m.Clear();
|
||||
m.SetVertices(_meshVertices);
|
||||
m.SetColors(_meshVertexColors);
|
||||
m.SetTriangles(_meshTriangles, 0);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
protected void DrawDataPoint(float xPosition, float verticalScale, ProfilerFrame frame)
|
||||
{
|
||||
// Right-hand x-coord
|
||||
var rx = Mathf.Min(_clipBounds.width/2f, xPosition + DataPointWidth - DataPointMargin);
|
||||
|
||||
var currentLineHeight = 0f;
|
||||
|
||||
for (var j = 0; j < LineCount; j++)
|
||||
{
|
||||
var lineIndex = j;
|
||||
|
||||
var value = 0f;
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
value = (float) frame.UpdateTime;
|
||||
}
|
||||
else if (j == 1)
|
||||
{
|
||||
value = (float) frame.RenderTime;
|
||||
}
|
||||
else if (j == 2)
|
||||
{
|
||||
value = (float) frame.OtherTime;
|
||||
}
|
||||
|
||||
value *= verticalScale;
|
||||
|
||||
if (value.ApproxZero() || value - DataPointVerticalMargin*2f < 0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Lower y-coord
|
||||
var ly = currentLineHeight + DataPointVerticalMargin - rectTransform.rect.height/2f;
|
||||
|
||||
if (VerticalAlignment == VerticalAlignments.Top)
|
||||
{
|
||||
ly = rectTransform.rect.height/2f - currentLineHeight - DataPointVerticalMargin;
|
||||
}
|
||||
|
||||
// Upper y-coord
|
||||
var uy = ly + value - DataPointVerticalMargin;
|
||||
|
||||
if (VerticalAlignment == VerticalAlignments.Top)
|
||||
{
|
||||
uy = ly - value + DataPointVerticalMargin;
|
||||
}
|
||||
|
||||
var c = LineColours[lineIndex];
|
||||
|
||||
AddRect(new Vector3(Mathf.Max(-_clipBounds.width/2f, xPosition), ly),
|
||||
new Vector3(Mathf.Max(-_clipBounds.width/2f, xPosition), uy), new Vector3(rx, uy),
|
||||
new Vector3(rx, ly), c);
|
||||
|
||||
currentLineHeight += value;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawAxis(float frameTime, float yPosition, ProfilerGraphAxisLabel label)
|
||||
{
|
||||
#if LOGGING
|
||||
if(!Application.isPlaying)
|
||||
Debug.Log("Draw Axis: {0}".Fmt(yPosition));
|
||||
#endif
|
||||
|
||||
var lx = -rectTransform.rect.width*0.5f;
|
||||
var rx = -lx;
|
||||
|
||||
var uy = yPosition - rectTransform.rect.height*0.5f + 0.5f;
|
||||
var ly = yPosition - rectTransform.rect.height*0.5f - 0.5f;
|
||||
|
||||
var c = new Color(1f, 1f, 1f, 0.4f);
|
||||
|
||||
AddRect(new Vector3(lx, ly), new Vector3(lx, uy), new Vector3(rx, uy), new Vector3(rx, ly), c);
|
||||
|
||||
if (label != null)
|
||||
{
|
||||
label.SetValue(frameTime, yPosition);
|
||||
}
|
||||
}
|
||||
|
||||
protected void AddRect(Vector3 tl, Vector3 tr, Vector3 bl, Vector3 br, Color c)
|
||||
{
|
||||
#if LEGACY_UI
|
||||
|
||||
var v = UIVertex.simpleVert;
|
||||
v.color = c;
|
||||
|
||||
v.position = tl;
|
||||
_vbo.Add(v);
|
||||
|
||||
v.position = tr;
|
||||
_vbo.Add(v);
|
||||
|
||||
v.position = bl;
|
||||
_vbo.Add(v);
|
||||
|
||||
v.position = br;
|
||||
_vbo.Add(v);
|
||||
|
||||
#else
|
||||
|
||||
// New UI system uses triangles
|
||||
|
||||
_meshVertices.Add(tl);
|
||||
_meshVertices.Add(tr);
|
||||
_meshVertices.Add(bl);
|
||||
_meshVertices.Add(br);
|
||||
|
||||
_meshTriangles.Add(_meshVertices.Count - 4); // tl
|
||||
_meshTriangles.Add(_meshVertices.Count - 3); // tr
|
||||
_meshTriangles.Add(_meshVertices.Count - 1); // br
|
||||
|
||||
_meshTriangles.Add(_meshVertices.Count - 2); // bl
|
||||
_meshTriangles.Add(_meshVertices.Count - 1); // br
|
||||
_meshTriangles.Add(_meshVertices.Count - 3); // tr
|
||||
|
||||
_meshVertexColors.Add(c);
|
||||
_meshVertexColors.Add(c);
|
||||
_meshVertexColors.Add(c);
|
||||
_meshVertexColors.Add(c);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
protected ProfilerFrame GetFrame(int i)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return TestData[i];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return _profilerService.FrameBuffer[i];
|
||||
}
|
||||
|
||||
protected int CalculateVisibleDataPointCount()
|
||||
{
|
||||
return Mathf.RoundToInt(rectTransform.rect.width/DataPointWidth);
|
||||
}
|
||||
|
||||
protected int GetFrameBufferCurrentSize()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return TestData.Length;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return _profilerService.FrameBuffer.Count;
|
||||
}
|
||||
|
||||
protected int GetFrameBufferMaxSize()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return TestData.Length;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return _profilerService.FrameBuffer.Capacity;
|
||||
}
|
||||
|
||||
protected float CalculateMaxFrameTime()
|
||||
{
|
||||
var frameCount = GetFrameBufferCurrentSize();
|
||||
var c = Mathf.Min(CalculateVisibleDataPointCount(), frameCount);
|
||||
|
||||
var max = 0d;
|
||||
|
||||
for (var i = 0; i < c; i++)
|
||||
{
|
||||
var frameNumber = frameCount - i - 1;
|
||||
|
||||
var t = GetFrame(frameNumber);
|
||||
|
||||
if (t.FrameTime > max)
|
||||
{
|
||||
max = t.FrameTime;
|
||||
}
|
||||
}
|
||||
|
||||
return (float) max;
|
||||
}
|
||||
|
||||
private ProfilerGraphAxisLabel GetAxisLabel(int index)
|
||||
{
|
||||
if (_axisLabels == null || !Application.isPlaying)
|
||||
{
|
||||
_axisLabels = GetComponentsInChildren<ProfilerGraphAxisLabel>();
|
||||
}
|
||||
|
||||
if (_axisLabels.Length > index)
|
||||
{
|
||||
return _axisLabels[index];
|
||||
}
|
||||
|
||||
Debug.LogWarning("[SRDebugger.Profiler] Not enough axis labels in pool");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#region Editor Only test data
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
private ProfilerFrame[] TestData
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_testData == null)
|
||||
{
|
||||
_testData = GenerateSampleData();
|
||||
}
|
||||
|
||||
return _testData;
|
||||
}
|
||||
}
|
||||
|
||||
private ProfilerFrame[] _testData;
|
||||
|
||||
protected static ProfilerFrame[] GenerateSampleData()
|
||||
{
|
||||
var sampleCount = 200;
|
||||
|
||||
var data = new ProfilerFrame[sampleCount];
|
||||
|
||||
for (var i = 0; i < sampleCount; i++)
|
||||
{
|
||||
var frame = new ProfilerFrame();
|
||||
|
||||
for (var j = 0; j < 3; j++)
|
||||
{
|
||||
var v = 0d;
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
v = Mathf.PerlinNoise(i/200f, 0);
|
||||
}
|
||||
else if (j == 1)
|
||||
{
|
||||
v = Mathf.PerlinNoise(0, i/200f);
|
||||
}
|
||||
else
|
||||
{
|
||||
v = Random.Range(0, 1f);
|
||||
}
|
||||
|
||||
v *= (1f/60f)*0.333f;
|
||||
|
||||
// Simulate spikes
|
||||
if (Random.value > 0.8f)
|
||||
{
|
||||
v *= Random.Range(1.2f, 1.8f);
|
||||
}
|
||||
|
||||
if (j == 2)
|
||||
{
|
||||
v *= 0.1f;
|
||||
}
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
frame.UpdateTime = v;
|
||||
}
|
||||
else if (j == 1)
|
||||
{
|
||||
frame.RenderTime = v;
|
||||
}
|
||||
else if (j == 2)
|
||||
{
|
||||
frame.FrameTime = frame.RenderTime + frame.UpdateTime + v;
|
||||
}
|
||||
}
|
||||
|
||||
data[i] = frame;
|
||||
}
|
||||
|
||||
data[0] = new ProfilerFrame
|
||||
{
|
||||
FrameTime = 0.005,
|
||||
RenderTime = 0.005,
|
||||
UpdateTime = 0.005
|
||||
};
|
||||
|
||||
data[sampleCount - 1] = new ProfilerFrame
|
||||
{
|
||||
FrameTime = 1d/60d,
|
||||
RenderTime = 0.007,
|
||||
UpdateTime = 0.007
|
||||
};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5812a284a856b743b4f54c6a4637061
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
@@ -0,0 +1,26 @@
|
||||
namespace SRDebugger.UI.Controls
|
||||
{
|
||||
using SRF;
|
||||
using SRF.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class SRTabButton : SRMonoBehaviourEx
|
||||
{
|
||||
[RequiredField] public Behaviour ActiveToggle;
|
||||
|
||||
[RequiredField] public UnityEngine.UI.Button Button;
|
||||
|
||||
[RequiredField] public RectTransform ExtraContentContainer;
|
||||
|
||||
[RequiredField] public StyleComponent IconStyleComponent;
|
||||
|
||||
[RequiredField] public Text TitleText;
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get { return ActiveToggle.enabled; }
|
||||
set { ActiveToggle.enabled = value; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2e81b40d04e8e440bb9659057db98c8
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
Reference in New Issue
Block a user