mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-11-11 08:38:45 +00:00
提交Unity 联机Pro
This commit is contained in:
16
JNFrame2/Assets/Plugins/SRDebugger/Scripts/Internal/Api.cs
Normal file
16
JNFrame2/Assets/Plugins/SRDebugger/Scripts/Internal/Api.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
public static class SRDebugApi
|
||||
{
|
||||
|
||||
#if !UNITY_EDITOR
|
||||
public const string Protocol = "https://";
|
||||
#else
|
||||
public const string Protocol = "http://";
|
||||
#endif
|
||||
|
||||
public const string EndPoint = Protocol + "srdebugger.stompyrobot.uk";
|
||||
|
||||
public const string BugReportEndPoint = EndPoint + "/report/submit";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a0f930eb7b829c40a5ba3024eed594d
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,96 @@
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using SRF;
|
||||
|
||||
public static class SRDebugApiUtil
|
||||
{
|
||||
public static string ParseErrorException(WebException ex)
|
||||
{
|
||||
if (ex.Response == null)
|
||||
{
|
||||
return ex.Message;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var response = ReadResponseStream(ex.Response);
|
||||
|
||||
return ParseErrorResponse(response);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ParseErrorResponse(string response, string fallback = "Unexpected Response")
|
||||
{
|
||||
try
|
||||
{
|
||||
var jsonTable = (Dictionary<string, object>) Json.Deserialize(response);
|
||||
|
||||
var error = "";
|
||||
|
||||
error += jsonTable["errorMessage"];
|
||||
|
||||
object value;
|
||||
|
||||
if (jsonTable.TryGetValue("errors", out value) && value is IList<object>)
|
||||
{
|
||||
var errors = value as IList<object>;
|
||||
|
||||
foreach (var e in errors)
|
||||
{
|
||||
error += "\n";
|
||||
error += e;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (response.Contains("<html>"))
|
||||
{
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR || (!NETFX_CORE && !UNITY_WINRT)
|
||||
|
||||
public static bool ReadResponse(HttpWebRequest request, out string result)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = request.GetResponse();
|
||||
result = ReadResponseStream(response);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
result = ParseErrorException(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public static string ReadResponseStream(WebResponse stream)
|
||||
{
|
||||
using (var responseSteam = stream.GetResponseStream())
|
||||
{
|
||||
using (var streamReader = new StreamReader(responseSteam))
|
||||
{
|
||||
return streamReader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f41e06622aa4979458cf59f1a355095a
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,189 @@
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using SRF;
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
class BugReportApi : MonoBehaviour
|
||||
{
|
||||
private string _apiKey;
|
||||
private BugReport _bugReport;
|
||||
private bool _isBusy;
|
||||
|
||||
private UnityWebRequest _webRequest;
|
||||
private Action<BugReportSubmitResult> _onComplete;
|
||||
private IProgress<float> _progress;
|
||||
|
||||
public static void Submit(BugReport report, string apiKey, Action<BugReportSubmitResult> onComplete, IProgress<float> progress)
|
||||
{
|
||||
var go = new GameObject("BugReportApi");
|
||||
go.transform.parent = Hierarchy.Get("SRDebugger");
|
||||
|
||||
var bugReportApi = go.AddComponent<BugReportApi>();
|
||||
bugReportApi.Init(report, apiKey, onComplete, progress);
|
||||
bugReportApi.StartCoroutine(bugReportApi.Submit());
|
||||
}
|
||||
|
||||
private void Init(BugReport report, string apiKey, Action<BugReportSubmitResult> onComplete, IProgress<float> progress)
|
||||
{
|
||||
_bugReport = report;
|
||||
_apiKey = apiKey;
|
||||
_onComplete = onComplete;
|
||||
_progress = progress;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (_isBusy && _webRequest != null)
|
||||
{
|
||||
_progress.Report(_webRequest.uploadProgress);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator Submit()
|
||||
{
|
||||
if (_isBusy)
|
||||
{
|
||||
throw new InvalidOperationException("BugReportApi is already sending a bug report");
|
||||
}
|
||||
|
||||
// Reset state
|
||||
_isBusy = true;
|
||||
_webRequest = null;
|
||||
|
||||
string json;
|
||||
byte[] jsonBytes;
|
||||
|
||||
try
|
||||
{
|
||||
json = BuildJsonRequest(_bugReport);
|
||||
jsonBytes = Encoding.UTF8.GetBytes(json);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
SetCompletionState(BugReportSubmitResult.Error("Error building bug report."));
|
||||
yield break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
const string jsonContentType = "application/json";
|
||||
|
||||
_webRequest = new UnityWebRequest(SRDebugApi.BugReportEndPoint, UnityWebRequest.kHttpVerbPOST,
|
||||
new DownloadHandlerBuffer(), new UploadHandlerRaw(jsonBytes)
|
||||
{
|
||||
contentType = jsonContentType
|
||||
});
|
||||
_webRequest.SetRequestHeader("Accept", jsonContentType);
|
||||
_webRequest.SetRequestHeader("X-ApiKey", _apiKey);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
|
||||
if (_webRequest != null)
|
||||
{
|
||||
_webRequest.Dispose();
|
||||
_webRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (_webRequest == null)
|
||||
{
|
||||
SetCompletionState(BugReportSubmitResult.Error("Error building bug report request."));
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return _webRequest.SendWebRequest();
|
||||
|
||||
#if UNITY_2018 || UNITY_2019
|
||||
bool isError = _webRequest.isNetworkError;
|
||||
#else
|
||||
bool isError = _webRequest.result == UnityWebRequest.Result.ConnectionError || _webRequest.result == UnityWebRequest.Result.DataProcessingError;
|
||||
#endif
|
||||
|
||||
if (isError)
|
||||
{
|
||||
SetCompletionState(BugReportSubmitResult.Error("Request Error: " + _webRequest.error));
|
||||
_webRequest.Dispose();
|
||||
yield break;
|
||||
}
|
||||
|
||||
long responseCode = _webRequest.responseCode;
|
||||
var responseJson = _webRequest.downloadHandler.text;
|
||||
|
||||
_webRequest.Dispose();
|
||||
|
||||
if (responseCode != 200)
|
||||
{
|
||||
SetCompletionState(BugReportSubmitResult.Error("Server: " + SRDebugApiUtil.ParseErrorResponse(responseJson, "Unknown response from server")));
|
||||
yield break;
|
||||
}
|
||||
|
||||
SetCompletionState(BugReportSubmitResult.Success);
|
||||
}
|
||||
|
||||
private void SetCompletionState(BugReportSubmitResult result)
|
||||
{
|
||||
_bugReport.ScreenshotData = null; // Clear the heaviest data in case something holds onto it
|
||||
_isBusy = false;
|
||||
|
||||
if (!result.IsSuccessful)
|
||||
{
|
||||
Debug.LogError("Bug Reporter Error: " + result.ErrorMessage);
|
||||
}
|
||||
|
||||
Destroy(gameObject);
|
||||
_onComplete(result);
|
||||
}
|
||||
|
||||
private static string BuildJsonRequest(BugReport report)
|
||||
{
|
||||
var ht = new Hashtable();
|
||||
|
||||
ht.Add("userEmail", report.Email);
|
||||
ht.Add("userDescription", report.UserDescription);
|
||||
|
||||
ht.Add("console", CreateConsoleDump());
|
||||
ht.Add("systemInformation", report.SystemInformation);
|
||||
ht.Add("applicationIdentifier", Application.identifier);
|
||||
|
||||
if (report.ScreenshotData != null)
|
||||
{
|
||||
ht.Add("screenshot", Convert.ToBase64String(report.ScreenshotData));
|
||||
}
|
||||
var json = Json.Serialize(ht);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
private static List<List<string>> CreateConsoleDump()
|
||||
{
|
||||
var consoleLog = Service.Console.AllEntries;
|
||||
var list = new List<List<string>>(consoleLog.Count);
|
||||
|
||||
foreach (var consoleEntry in consoleLog)
|
||||
{
|
||||
var entry = new List<string>(5);
|
||||
|
||||
entry.Add(consoleEntry.LogType.ToString());
|
||||
entry.Add(consoleEntry.Message);
|
||||
entry.Add(consoleEntry.StackTrace);
|
||||
|
||||
if (consoleEntry.Count > 1)
|
||||
{
|
||||
entry.Add(consoleEntry.Count.ToString());
|
||||
}
|
||||
|
||||
list.Add(entry);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfdfb4c8f27446b4d8aa88d3980f4c50
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
public class BugReportScreenshotUtil
|
||||
{
|
||||
public static byte[] ScreenshotData;
|
||||
|
||||
public static IEnumerator ScreenshotCaptureCo()
|
||||
{
|
||||
if (ScreenshotData != null)
|
||||
{
|
||||
Debug.LogWarning("[SRDebugger] Warning, overriding existing screenshot data.");
|
||||
}
|
||||
|
||||
yield return new WaitForEndOfFrame();
|
||||
|
||||
var tex = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
|
||||
|
||||
tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
|
||||
tex.Apply();
|
||||
|
||||
ScreenshotData = tex.EncodeToPNG();
|
||||
|
||||
Object.Destroy(tex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52ead462624dc0c4d80e12ce55109a26
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
----------------------------------------------------------------------------
|
||||
"THE BEER-WARE LICENSE" (Revision 42):
|
||||
Joao Portela wrote this file. As long as you retain this notice you
|
||||
can do whatever you want with this stuff. If we meet some day, and you think
|
||||
this stuff is worth it, you can buy me a beer in return.
|
||||
Joao Portela
|
||||
--------------------------------------------------------------------------
|
||||
* https://github.com/joaoportela/CircullarBuffer-CSharp
|
||||
*/
|
||||
|
||||
namespace SRDebugger
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Circular buffer.
|
||||
/// When writting to a full buffer:
|
||||
/// PushBack -> removes this[0] / Front()
|
||||
/// PushFront -> removes this[Size-1] / Back()
|
||||
/// this implementation is inspired by
|
||||
/// http://www.boost.org/doc/libs/1_53_0/libs/circular_buffer/doc/circular_buffer.html
|
||||
/// because I liked their interface.
|
||||
/// </summary>
|
||||
public class CircularBuffer<T> : IEnumerable<T>, IReadOnlyList<T>
|
||||
{
|
||||
private readonly T[] _buffer;
|
||||
|
||||
/// <summary>
|
||||
/// The _end. Index after the last element in the buffer.
|
||||
/// </summary>
|
||||
private int _end;
|
||||
|
||||
/// <summary>
|
||||
/// The _size. Buffer size.
|
||||
/// </summary>
|
||||
private int _count;
|
||||
|
||||
/// <summary>
|
||||
/// The _start. Index of the first element in buffer.
|
||||
/// </summary>
|
||||
private int _start;
|
||||
|
||||
public CircularBuffer(int capacity)
|
||||
: this(capacity, new T[] {}) {}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CircularBuffer{T}" /> class.
|
||||
/// </summary>
|
||||
/// <param name='capacity'>
|
||||
/// Buffer capacity. Must be positive.
|
||||
/// </param>
|
||||
/// <param name='items'>
|
||||
/// Items to fill buffer with. Items length must be less than capacity.
|
||||
/// Sugestion: use Skip(x).Take(y).ToArray() to build this argument from
|
||||
/// any enumerable.
|
||||
/// </param>
|
||||
public CircularBuffer(int capacity, T[] items)
|
||||
{
|
||||
if (capacity < 1)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Circular buffer cannot have negative or zero capacity.", "capacity");
|
||||
}
|
||||
if (items == null)
|
||||
{
|
||||
throw new ArgumentNullException("items");
|
||||
}
|
||||
if (items.Length > capacity)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Too many items to fit circular buffer", "items");
|
||||
}
|
||||
|
||||
_buffer = new T[capacity];
|
||||
|
||||
Array.Copy(items, _buffer, items.Length);
|
||||
_count = items.Length;
|
||||
|
||||
_start = 0;
|
||||
_end = _count == capacity ? 0 : _count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum capacity of the buffer. Elements pushed into the buffer after
|
||||
/// maximum capacity is reached (IsFull = true), will remove an element.
|
||||
/// </summary>
|
||||
public int Capacity
|
||||
{
|
||||
get { return _buffer.Length; }
|
||||
}
|
||||
|
||||
public bool IsFull
|
||||
{
|
||||
get { return Count == Capacity; }
|
||||
}
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get { return Count == 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current buffer size (the number of elements that the buffer has).
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return _count; }
|
||||
}
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
throw new IndexOutOfRangeException(string.Format("Cannot access index {0}. Buffer is empty", index));
|
||||
}
|
||||
if (index >= _count)
|
||||
{
|
||||
throw new IndexOutOfRangeException(string.Format("Cannot access index {0}. Buffer size is {1}",
|
||||
index, _count));
|
||||
}
|
||||
var actualIndex = InternalIndex(index);
|
||||
return _buffer[actualIndex];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
throw new IndexOutOfRangeException(string.Format("Cannot access index {0}. Buffer is empty", index));
|
||||
}
|
||||
if (index >= _count)
|
||||
{
|
||||
throw new IndexOutOfRangeException(string.Format("Cannot access index {0}. Buffer size is {1}",
|
||||
index, _count));
|
||||
}
|
||||
var actualIndex = InternalIndex(index);
|
||||
_buffer[actualIndex] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_count = 0;
|
||||
_start = 0;
|
||||
_end = 0;
|
||||
}
|
||||
|
||||
#region IEnumerable<T> implementation
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
var segments = new ArraySegment<T>[2] {ArrayOne(), ArrayTwo()};
|
||||
foreach (var segment in segments)
|
||||
{
|
||||
for (var i = 0; i < segment.Count; i++)
|
||||
{
|
||||
yield return segment.Array[segment.Offset + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEnumerable implementation
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IList<T> implementation
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Element at the front of the buffer - this[0].
|
||||
/// </summary>
|
||||
/// <returns>The value of the element of type T at the front of the buffer.</returns>
|
||||
public T Front()
|
||||
{
|
||||
ThrowIfEmpty();
|
||||
return _buffer[_start];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Element at the back of the buffer - this[Size - 1].
|
||||
/// </summary>
|
||||
/// <returns>The value of the element of type T at the back of the buffer.</returns>
|
||||
public T Back()
|
||||
{
|
||||
ThrowIfEmpty();
|
||||
return _buffer[(_end != 0 ? _end : _count) - 1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pushes a new element to the back of the buffer. Back()/this[Size-1]
|
||||
/// will now return this element.
|
||||
/// When the buffer is full, the element at Front()/this[0] will be
|
||||
/// popped to allow for this new element to fit.
|
||||
/// </summary>
|
||||
/// <param name="item">Item to push to the back of the buffer</param>
|
||||
public void PushBack(T item)
|
||||
{
|
||||
if (IsFull)
|
||||
{
|
||||
_buffer[_end] = item;
|
||||
Increment(ref _end);
|
||||
_start = _end;
|
||||
}
|
||||
else
|
||||
{
|
||||
_buffer[_end] = item;
|
||||
Increment(ref _end);
|
||||
++_count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pushes a new element to the front of the buffer. Front()/this[0]
|
||||
/// will now return this element.
|
||||
/// When the buffer is full, the element at Back()/this[Size-1] will be
|
||||
/// popped to allow for this new element to fit.
|
||||
/// </summary>
|
||||
/// <param name="item">Item to push to the front of the buffer</param>
|
||||
public void PushFront(T item)
|
||||
{
|
||||
if (IsFull)
|
||||
{
|
||||
Decrement(ref _start);
|
||||
_end = _start;
|
||||
_buffer[_start] = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
Decrement(ref _start);
|
||||
_buffer[_start] = item;
|
||||
++_count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the element at the back of the buffer. Decreassing the
|
||||
/// Buffer size by 1.
|
||||
/// </summary>
|
||||
public void PopBack()
|
||||
{
|
||||
ThrowIfEmpty("Cannot take elements from an empty buffer.");
|
||||
Decrement(ref _end);
|
||||
_buffer[_end] = default(T);
|
||||
--_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the element at the front of the buffer. Decreassing the
|
||||
/// Buffer size by 1.
|
||||
/// </summary>
|
||||
public void PopFront()
|
||||
{
|
||||
ThrowIfEmpty("Cannot take elements from an empty buffer.");
|
||||
_buffer[_start] = default(T);
|
||||
Increment(ref _start);
|
||||
--_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the buffer contents to an array, acording to the logical
|
||||
/// contents of the buffer (i.e. independent of the internal
|
||||
/// order/contents)
|
||||
/// </summary>
|
||||
/// <returns>A new array with a copy of the buffer contents.</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
var newArray = new T[Count];
|
||||
var newArrayOffset = 0;
|
||||
var segments = new ArraySegment<T>[2] {ArrayOne(), ArrayTwo()};
|
||||
foreach (var segment in segments)
|
||||
{
|
||||
Array.Copy(segment.Array, segment.Offset, newArray, newArrayOffset, segment.Count);
|
||||
newArrayOffset += segment.Count;
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
|
||||
private void ThrowIfEmpty(string message = "Cannot access an empty buffer.")
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increments the provided index variable by one, wrapping
|
||||
/// around if necessary.
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
private void Increment(ref int index)
|
||||
{
|
||||
if (++index == Capacity)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrements the provided index variable by one, wrapping
|
||||
/// around if necessary.
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
private void Decrement(ref int index)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
index = Capacity;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the index in the argument to an index in <code>_buffer</code>
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The transformed index.
|
||||
/// </returns>
|
||||
/// <param name='index'>
|
||||
/// External index.
|
||||
/// </param>
|
||||
private int InternalIndex(int index)
|
||||
{
|
||||
return _start + (index < (Capacity - _start) ? index : index - Capacity);
|
||||
}
|
||||
|
||||
// doing ArrayOne and ArrayTwo methods returning ArraySegment<T> as seen here:
|
||||
// http://www.boost.org/doc/libs/1_37_0/libs/circular_buffer/doc/circular_buffer.html#classboost_1_1circular__buffer_1957cccdcb0c4ef7d80a34a990065818d
|
||||
// http://www.boost.org/doc/libs/1_37_0/libs/circular_buffer/doc/circular_buffer.html#classboost_1_1circular__buffer_1f5081a54afbc2dfc1a7fb20329df7d5b
|
||||
// should help a lot with the code.
|
||||
|
||||
#region Array items easy access.
|
||||
|
||||
// The array is composed by at most two non-contiguous segments,
|
||||
// the next two methods allow easy access to those.
|
||||
|
||||
private ArraySegment<T> ArrayOne()
|
||||
{
|
||||
if (_start <= _end)
|
||||
{
|
||||
return new ArraySegment<T>(_buffer, _start, _end - _start);
|
||||
}
|
||||
return new ArraySegment<T>(_buffer, _start, _buffer.Length - _start);
|
||||
}
|
||||
|
||||
private ArraySegment<T> ArrayTwo()
|
||||
{
|
||||
if (_start < _end)
|
||||
{
|
||||
return new ArraySegment<T>(_buffer, _end, 0);
|
||||
}
|
||||
return new ArraySegment<T>(_buffer, 0, _end);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39fd981a95abcb647a9c6ecd52007e71
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
* This file has been deleted.
|
||||
* This empty file is left here to ensure it is properly overwritten when importing a new version of the package over an old version.
|
||||
*/
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f809cd2d9d5ae074cbecca0ab4d472b6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using SRF;
|
||||
using SRF.Service;
|
||||
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// The default bug report handler - this submits to the SRDebugger API using the API key configured in the SRDebugger
|
||||
/// settings window.
|
||||
/// </summary>
|
||||
internal class InternalBugReporterHandler : IBugReporterHandler
|
||||
{
|
||||
public bool IsUsable
|
||||
{
|
||||
get { return Settings.Instance.EnableBugReporter && !string.IsNullOrWhiteSpace(Settings.Instance.ApiKey); }
|
||||
}
|
||||
|
||||
public void Submit(BugReport report, Action<BugReportSubmitResult> onComplete, IProgress<float> progress)
|
||||
{
|
||||
BugReportApi.Submit(report, Settings.Instance.ApiKey, onComplete, progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f424b0a8b303d9843b15a6bf70ebf4ea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SRF.Service;
|
||||
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Workaround for the debug panel not being initialized on startup.
|
||||
/// SROptions needs to register itself but not cause auto-initialization.
|
||||
/// This class buffers requests to register contains until there is a handler in place to deal with them.
|
||||
/// Once the handler is in place, all buffered requests are passed in and future requests invoke the handler directly.
|
||||
/// </summary>
|
||||
[Service(typeof(InternalOptionsRegistry))]
|
||||
public sealed class InternalOptionsRegistry
|
||||
{
|
||||
private List<object> _registeredContainers = new List<object>();
|
||||
private Action<object> _handler;
|
||||
|
||||
public void AddOptionContainer(object obj)
|
||||
{
|
||||
if (_handler != null)
|
||||
{
|
||||
_handler(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
_registeredContainers.Add(obj);
|
||||
}
|
||||
|
||||
public void SetHandler(Action<object> action)
|
||||
{
|
||||
_handler = action;
|
||||
|
||||
foreach (object o in _registeredContainers)
|
||||
{
|
||||
_handler(o);
|
||||
}
|
||||
|
||||
_registeredContainers = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12f482545d1833a4e823d79898cb46ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,174 @@
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SRF;
|
||||
using UI.Controls;
|
||||
using UI.Controls.Data;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
public static class OptionControlFactory
|
||||
{
|
||||
private static IList<DataBoundControl> _dataControlPrefabs;
|
||||
private static ActionControl _actionControlPrefab;
|
||||
|
||||
private static readonly Dictionary<OptionType, DataBoundControl> TypeCache = new Dictionary<OptionType, DataBoundControl>();
|
||||
|
||||
public static bool CanCreateControl(OptionDefinition from)
|
||||
{
|
||||
PopulateDataControlPrefabs();
|
||||
if (from.Property != null)
|
||||
{
|
||||
return TryGetDataControlPrefab(from) != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _actionControlPrefab != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a control from an <c>OptionDefinition</c>, optionally providing <paramref name="categoryPrefix" /> to remove
|
||||
/// the category name from the start of the control.
|
||||
/// </summary>
|
||||
/// <param name="from"></param>
|
||||
/// <param name="categoryPrefix"></param>
|
||||
/// <returns></returns>
|
||||
public static OptionsControlBase CreateControl(OptionDefinition from, string categoryPrefix = null)
|
||||
{
|
||||
PopulateDataControlPrefabs();
|
||||
|
||||
if (from.Property != null)
|
||||
{
|
||||
return CreateDataControl(from, categoryPrefix);
|
||||
}
|
||||
|
||||
if (from.Method != null)
|
||||
{
|
||||
return CreateActionControl(from, categoryPrefix);
|
||||
}
|
||||
|
||||
throw new Exception("OptionDefinition did not contain property or method.");
|
||||
}
|
||||
|
||||
private static void PopulateDataControlPrefabs()
|
||||
{
|
||||
if (_dataControlPrefabs == null)
|
||||
{
|
||||
_dataControlPrefabs = Resources.LoadAll<DataBoundControl>(SRDebugPaths.DataControlsResourcesPath);
|
||||
}
|
||||
|
||||
if (_actionControlPrefab == null)
|
||||
{
|
||||
_actionControlPrefab =
|
||||
Resources.LoadAll<ActionControl>(SRDebugPaths.DataControlsResourcesPath).FirstOrDefault();
|
||||
}
|
||||
|
||||
if (_actionControlPrefab == null)
|
||||
{
|
||||
Debug.LogError("[SRDebugger.Options] Cannot find ActionControl prefab.");
|
||||
}
|
||||
}
|
||||
|
||||
private static ActionControl CreateActionControl(OptionDefinition from, string categoryPrefix = null)
|
||||
{
|
||||
var control = SRInstantiate.Instantiate(_actionControlPrefab);
|
||||
|
||||
if (control == null)
|
||||
{
|
||||
Debug.LogWarning("[SRDebugger.OptionsTab] Error creating action control from prefab");
|
||||
return null;
|
||||
}
|
||||
|
||||
control.SetMethod(from.Name, from.Method);
|
||||
control.Option = from;
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
private static DataBoundControl CreateDataControl(OptionDefinition from, string categoryPrefix = null)
|
||||
{
|
||||
var prefab = TryGetDataControlPrefab(from);
|
||||
|
||||
if (prefab == null)
|
||||
{
|
||||
Debug.LogWarning(
|
||||
"[SRDebugger.OptionsTab] Can't find data control for type {0}".Fmt(from.Property.PropertyType));
|
||||
return null;
|
||||
}
|
||||
|
||||
var instance = SRInstantiate.Instantiate(prefab);
|
||||
|
||||
try
|
||||
{
|
||||
var n = from.Name;
|
||||
|
||||
// Remove category name from the start of the property name
|
||||
if (!string.IsNullOrEmpty(categoryPrefix) && n.StartsWith(categoryPrefix))
|
||||
{
|
||||
n = n.Substring(categoryPrefix.Length);
|
||||
}
|
||||
|
||||
instance.Bind(n, from.Property);
|
||||
instance.Option = from;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("[SRDebugger.Options] Error binding to property {0}".Fmt(from.Name));
|
||||
Debug.LogException(e);
|
||||
|
||||
Object.Destroy(instance);
|
||||
instance = null;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static DataBoundControl TryGetDataControlPrefab(OptionDefinition from)
|
||||
{
|
||||
OptionType type = new OptionType(@from.Property.PropertyType, !@from.Property.CanWrite);
|
||||
|
||||
DataBoundControl control;
|
||||
if (!TypeCache.TryGetValue(type, out control))
|
||||
{
|
||||
control = _dataControlPrefabs.FirstOrDefault(p =>
|
||||
p.CanBind(@from.Property.PropertyType, !@from.Property.CanWrite));
|
||||
TypeCache.Add(type, control);
|
||||
}
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
private struct OptionType
|
||||
{
|
||||
public readonly Type Type;
|
||||
public readonly bool IsReadyOnly;
|
||||
|
||||
public OptionType(Type type, bool isReadyOnly)
|
||||
{
|
||||
Type = type;
|
||||
IsReadyOnly = isReadyOnly;
|
||||
}
|
||||
|
||||
public bool Equals(OptionType other)
|
||||
{
|
||||
return Equals(Type, other.Type) && IsReadyOnly == other.IsReadyOnly;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is OptionType other && Equals(other);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return ((Type != null ? Type.GetHashCode() : 0) * 397) ^ IsReadyOnly.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d6e807b7446052409d51e03ab38cfae
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using SRF.Helpers;
|
||||
|
||||
namespace SRDebugger
|
||||
{
|
||||
/// <summary>
|
||||
/// Class describing how an option should be presented within the options panel.
|
||||
/// </summary>
|
||||
public sealed class OptionDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Display-name for the option.
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The category that this option should be placed within.
|
||||
/// </summary>
|
||||
public string Category { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sort order within the category. Order is low to high, (options with lower SortPriority will appear before
|
||||
/// options with higher SortPriority).
|
||||
/// </summary>
|
||||
public int SortPriority { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this option is a method that should be invoked.
|
||||
/// </summary>
|
||||
public bool IsMethod
|
||||
{
|
||||
get { return Method != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether this option is a property that has a value.
|
||||
/// </summary>
|
||||
public bool IsProperty
|
||||
{
|
||||
get { return Property != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The underlying method for this OptionDefinition.
|
||||
/// Can be null if <see cref="IsMethod"/> is false.
|
||||
/// </summary>
|
||||
public SRF.Helpers.MethodReference Method { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The underlying property for this OptionDefinition.
|
||||
/// Can be null if <see cref="IsProperty"/> is false.
|
||||
/// </summary>
|
||||
public SRF.Helpers.PropertyReference Property { get; private set; }
|
||||
|
||||
private OptionDefinition(string name, string category, int sortPriority)
|
||||
{
|
||||
Name = name;
|
||||
Category = category;
|
||||
SortPriority = sortPriority;
|
||||
}
|
||||
|
||||
public OptionDefinition(string name, string category, int sortPriority, SRF.Helpers.MethodReference method)
|
||||
: this(name, category, sortPriority)
|
||||
{
|
||||
Method = method;
|
||||
}
|
||||
|
||||
public OptionDefinition(string name, string category, int sortPriority, SRF.Helpers.PropertyReference property)
|
||||
: this(name, category, sortPriority)
|
||||
{
|
||||
Property = property;
|
||||
}
|
||||
|
||||
public static OptionDefinition FromMethod(string name, Action callback, string category = "Default", int sortPriority = 0)
|
||||
{
|
||||
return new OptionDefinition(name, category, sortPriority, callback);;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an option definition from a setter and getter lambda.
|
||||
/// </summary>
|
||||
/// <param name="name">Name to display in options menu.</param>
|
||||
/// <param name="getter">Method to get the current value of the property.</param>
|
||||
/// <param name="setter">Method to set the value of the property (can be null if read-only)</param>
|
||||
/// <param name="category">Category to display the option in.</param>
|
||||
/// <param name="sortPriority">Sort priority to arrange the option within the category.</param>
|
||||
/// <returns>The created option definition.</returns>
|
||||
public static OptionDefinition Create<T>(string name, Func<T> getter, Action<T> setter = null, string category = "Default", int sortPriority = 0)
|
||||
{
|
||||
return new OptionDefinition(name, category, sortPriority, PropertyReference.FromLambda(getter, setter));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6fb9bd71eceb4145a013bb7fe025c01
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
14
JNFrame2/Assets/Plugins/SRDebugger/Scripts/Internal/Paths.cs
Normal file
14
JNFrame2/Assets/Plugins/SRDebugger/Scripts/Internal/Paths.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
public static class SRDebugPaths
|
||||
{
|
||||
public const string DataControlsResourcesPath = "SRDebugger/UI/Prefabs/Options";
|
||||
public const string TriggerPrefabPath = "SRDebugger/UI/Prefabs/Trigger";
|
||||
public const string DebugPanelPrefabPath = "SRDebugger/UI/Prefabs/DebugPanel";
|
||||
public const string PinnedUIPrefabPath = "SRDebugger/UI/Prefabs/PinnedUI";
|
||||
public const string DockConsolePrefabPath = "SRDebugger/UI/Prefabs/DockConsole";
|
||||
public const string PinEntryPrefabPath = "SRDebugger/UI/Prefabs/PinEntry";
|
||||
public const string BugReportPopoverPath = "SRDebugger/UI/Prefabs/BugReportPopover";
|
||||
public const string BugReportSheetPath = "SRDebugger/UI/Prefabs/BugReportSheet";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 487af04ceed59b6409168c2d466c2f73
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,73 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
|
||||
namespace SRDebugger.Scripts.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Behaviour that supports SRDebugger reloading itself after a script recompile is detected.
|
||||
/// </summary>
|
||||
public class SRScriptRecompileHelper : MonoBehaviour
|
||||
{
|
||||
private static SRScriptRecompileHelper _instance;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
public static void Initialize()
|
||||
{
|
||||
if (_instance != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var go = new GameObject("SRDebugger Script Recompile Helper (Editor Only)");
|
||||
DontDestroyOnLoad(go);
|
||||
go.hideFlags = HideFlags.DontSave | HideFlags.HideInHierarchy;
|
||||
go.AddComponent<SRScriptRecompileHelper>();
|
||||
}
|
||||
|
||||
private bool _hasEnabled;
|
||||
private bool _srdebuggerHasInitialized;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if(_instance != null)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
_instance = this;
|
||||
|
||||
// Don't take any action on the first OnEnable()
|
||||
if (!_hasEnabled)
|
||||
{
|
||||
_hasEnabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Next OnEnable() will be due to script reload.
|
||||
AutoInitialize.OnLoadBeforeScene();
|
||||
|
||||
if (_srdebuggerHasInitialized)
|
||||
{
|
||||
Debug.Log("[SRScriptRecompileHelper] Restoring SRDebugger after script reload.", this);
|
||||
SRDebug.Init();
|
||||
}
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
// Destroy this object when leaving play mode (otherwise it will linger and a new instance will be created next time play mode is entered).
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
public static void SetHasInitialized()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
_instance._srdebuggerHasInitialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5cb2b7903b1672544b02d628ac0c1dfd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 24000
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
122
JNFrame2/Assets/Plugins/SRDebugger/Scripts/Internal/Service.cs
Normal file
122
JNFrame2/Assets/Plugins/SRDebugger/Scripts/Internal/Service.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
using Services;
|
||||
using SRF.Service;
|
||||
|
||||
public static class Service
|
||||
{
|
||||
private static IConsoleService _consoleService;
|
||||
private static IDebugPanelService _debugPanelService;
|
||||
private static IDebugTriggerService _debugTriggerService;
|
||||
private static IPinnedUIService _pinnedUiService;
|
||||
private static IDebugCameraService _debugCameraService;
|
||||
private static IOptionsService _optionsService;
|
||||
private static IDockConsoleService _dockConsoleService;
|
||||
|
||||
#if UNITY_EDITOR && ((!UNITY_2017 && !UNITY_2018 && !UNITY_2019) || UNITY_2019_3_OR_NEWER)
|
||||
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
public static void RuntimeInitialize()
|
||||
{
|
||||
// Clear service references at startup in case of "enter play mode without domain reload"
|
||||
_consoleService = null;
|
||||
_debugPanelService = null;
|
||||
_debugTriggerService = null;
|
||||
_pinnedUiService = null;
|
||||
_debugCameraService = null;
|
||||
_optionsService = null;
|
||||
_dockConsoleService = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
public static IConsoleService Console
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_consoleService == null)
|
||||
{
|
||||
_consoleService = SRServiceManager.GetService<IConsoleService>();
|
||||
}
|
||||
|
||||
return _consoleService;
|
||||
}
|
||||
}
|
||||
|
||||
public static IDockConsoleService DockConsole
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dockConsoleService == null)
|
||||
{
|
||||
_dockConsoleService = SRServiceManager.GetService<IDockConsoleService>();
|
||||
}
|
||||
|
||||
return _dockConsoleService;
|
||||
}
|
||||
}
|
||||
|
||||
public static IDebugPanelService Panel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_debugPanelService == null)
|
||||
{
|
||||
_debugPanelService = SRServiceManager.GetService<IDebugPanelService>();
|
||||
}
|
||||
|
||||
return _debugPanelService;
|
||||
}
|
||||
}
|
||||
|
||||
public static IDebugTriggerService Trigger
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_debugTriggerService == null)
|
||||
{
|
||||
_debugTriggerService = SRServiceManager.GetService<IDebugTriggerService>();
|
||||
}
|
||||
|
||||
return _debugTriggerService;
|
||||
}
|
||||
}
|
||||
|
||||
public static IPinnedUIService PinnedUI
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_pinnedUiService == null)
|
||||
{
|
||||
_pinnedUiService = SRServiceManager.GetService<IPinnedUIService>();
|
||||
}
|
||||
|
||||
return _pinnedUiService;
|
||||
}
|
||||
}
|
||||
|
||||
public static IDebugCameraService DebugCamera
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_debugCameraService == null)
|
||||
{
|
||||
_debugCameraService = SRServiceManager.GetService<IDebugCameraService>();
|
||||
}
|
||||
|
||||
return _debugCameraService;
|
||||
}
|
||||
}
|
||||
|
||||
public static IOptionsService Options
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_optionsService == null)
|
||||
{
|
||||
_optionsService = SRServiceManager.GetService<IOptionsService>();
|
||||
}
|
||||
|
||||
return _optionsService;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe213cfca7e22e844abfd16c258dd08e
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
public class SRDebugStrings
|
||||
{
|
||||
public static readonly SRDebugStrings Current = new SRDebugStrings();
|
||||
public readonly string Console_MessageTruncated = "-- Message Truncated --";
|
||||
public readonly string Console_NoStackTrace = "-- No Stack Trace Available --";
|
||||
public readonly string PinEntryPrompt = "Enter code to open debug panel";
|
||||
|
||||
public readonly string Profiler_DisableProfilerInfo =
|
||||
"Unity profiler is currently <b>enabled</b>. Disable to improve performance.";
|
||||
|
||||
public readonly string Profiler_EnableProfilerInfo =
|
||||
"Unity profiler is currently <b>disabled</b>. Enable to show more information.";
|
||||
|
||||
public readonly string Profiler_NoProInfo =
|
||||
"Unity profiler is currently <b>disabled</b>. Unity Pro is required to enable it.";
|
||||
|
||||
public readonly string Profiler_NotSupported = "Unity profiler is <b>not supported</b> in this build.";
|
||||
|
||||
public readonly string ProfilerCameraListenerHelp =
|
||||
"This behaviour is attached by the SRDebugger profiler to calculate render times.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34bc872e688c2eb4ca1794728e6ff4fd
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
233
JNFrame2/Assets/Plugins/SRDebugger/Scripts/Internal/Util.cs
Normal file
233
JNFrame2/Assets/Plugins/SRDebugger/Scripts/Internal/Util.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace SRDebugger.Internal
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using SRF.Helpers;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public static class SRDebuggerUtil
|
||||
{
|
||||
public static bool IsMobilePlatform
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Application.isMobilePlatform)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (Application.platform)
|
||||
{
|
||||
#if UNITY_5 || UNITY_5_3_OR_NEWER
|
||||
case RuntimePlatform.WSAPlayerARM:
|
||||
case RuntimePlatform.WSAPlayerX64:
|
||||
case RuntimePlatform.WSAPlayerX86:
|
||||
#else
|
||||
case RuntimePlatform.MetroPlayerARM:
|
||||
case RuntimePlatform.MetroPlayerX64:
|
||||
case RuntimePlatform.MetroPlayerX86:
|
||||
#endif
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If no event system exists, create one
|
||||
/// </summary>
|
||||
/// <returns>True if the event system was created as a result of this call</returns>
|
||||
public static bool EnsureEventSystemExists()
|
||||
{
|
||||
if (!Settings.Instance.EnableEventSystemGeneration)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (EventSystem.current != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var e = Object.FindObjectOfType<EventSystem>();
|
||||
|
||||
// Check if EventSystem is in the scene but not registered yet
|
||||
if (e != null && e.gameObject.activeSelf && e.enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.LogWarning("[SRDebugger] No EventSystem found in scene - creating a default one. Disable this behaviour in Window -> SRDebugger -> Settings Window -> Advanced)");
|
||||
|
||||
CreateDefaultEventSystem();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void CreateDefaultEventSystem()
|
||||
{
|
||||
var go = new GameObject("EventSystem (Created by SRDebugger, disable in Window -> SRDebugger -> Settings Window -> Advanced)");
|
||||
go.AddComponent<EventSystem>();
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM && ENABLE_LEGACY_INPUT_MANAGER
|
||||
switch (Settings.Instance.UIInputMode)
|
||||
{
|
||||
case Settings.UIModes.NewInputSystem:
|
||||
AddInputSystem(go);
|
||||
Debug.LogWarning("[SRDebugger] Automatically generated EventSystem is using Unity Input System (can be changed to use Legacy Input in Window -> SRDebugger -> Settings Window -> Advanced)");
|
||||
break;
|
||||
case Settings.UIModes.LegacyInputSystem:
|
||||
AddLegacyInputSystem(go);
|
||||
Debug.LogWarning("[SRDebugger] Automatically generated EventSystem is using Legacy Input (can be changed to use Unity Input System in Window -> SRDebugger -> Settings Window -> Advanced)");
|
||||
break;
|
||||
}
|
||||
#elif ENABLE_INPUT_SYSTEM
|
||||
AddInputSystem(go);
|
||||
#elif ENABLE_LEGACY_INPUT_MANAGER || (!ENABLE_INPUT_SYSTEM && !UNITY_2019_3_OR_NEWER)
|
||||
AddLegacyInputSystem(go);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
private static void AddInputSystem(GameObject go)
|
||||
{
|
||||
go.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
|
||||
|
||||
// Disable/re-enable to force some initialization.
|
||||
// fix for input not being recognized until component is toggled off then on
|
||||
go.SetActive(false);
|
||||
go.SetActive(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER || (!ENABLE_INPUT_SYSTEM && !UNITY_2019_3_OR_NEWER)
|
||||
private static void AddLegacyInputSystem(GameObject go)
|
||||
{
|
||||
go.AddComponent<StandaloneInputModule>();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Scan <paramref name="obj" /> for valid options and return a collection of them.
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static List<OptionDefinition> ScanForOptions(object obj)
|
||||
{
|
||||
var options = new List<OptionDefinition>();
|
||||
|
||||
#if NETFX_CORE
|
||||
var members = obj.GetType().GetTypeInfo().DeclaredMembers;
|
||||
#else
|
||||
|
||||
var members =
|
||||
obj.GetType().GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty |
|
||||
BindingFlags.SetProperty | BindingFlags.InvokeMethod);
|
||||
|
||||
#endif
|
||||
|
||||
var ignoreAssembly = typeof(MonoBehaviour).Assembly;
|
||||
|
||||
foreach (var memberInfo in members)
|
||||
{
|
||||
// Skip any properties that are from built-in Unity types (e.g. Behaviour, MonoBehaviour)
|
||||
if (memberInfo.DeclaringType != null && memberInfo.DeclaringType.Assembly == ignoreAssembly)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var browsable = memberInfo.GetCustomAttribute<BrowsableAttribute>();
|
||||
if (browsable != null)
|
||||
{
|
||||
if (!browsable.Browsable)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find user-specified category name from attribute
|
||||
var categoryAttribute = SRReflection.GetAttribute<CategoryAttribute>(memberInfo);
|
||||
var category = categoryAttribute == null ? "Default" : categoryAttribute.Category;
|
||||
|
||||
// Find user-specified sorting priority from attribute
|
||||
var sortAttribute = SRReflection.GetAttribute<SortAttribute>(memberInfo);
|
||||
var sortPriority = sortAttribute == null ? 0 : sortAttribute.SortPriority;
|
||||
|
||||
// Find user-specified display name from attribute
|
||||
var nameAttribute = SRReflection.GetAttribute<DisplayNameAttribute>(memberInfo);
|
||||
var name = nameAttribute == null ? memberInfo.Name : nameAttribute.DisplayName;
|
||||
|
||||
if (memberInfo is PropertyInfo)
|
||||
{
|
||||
var propertyInfo = memberInfo as PropertyInfo;
|
||||
|
||||
// Only allow properties with public read/write
|
||||
#if NETFX_CORE
|
||||
if(propertyInfo.GetMethod == null)
|
||||
continue;
|
||||
|
||||
// Ignore static members
|
||||
if (propertyInfo.GetMethod.IsStatic)
|
||||
continue;
|
||||
#else
|
||||
if (propertyInfo.GetGetMethod() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore static members
|
||||
if ((propertyInfo.GetGetMethod().Attributes & MethodAttributes.Static) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
options.Add(new OptionDefinition(name, category, sortPriority,
|
||||
new SRF.Helpers.PropertyReference(obj, propertyInfo)));
|
||||
}
|
||||
else if (memberInfo is MethodInfo)
|
||||
{
|
||||
var methodInfo = memberInfo as MethodInfo;
|
||||
|
||||
if (methodInfo.IsStatic)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip methods with parameters or non-void return type
|
||||
if (methodInfo.ReturnType != typeof (void) || methodInfo.GetParameters().Length > 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
options.Add(new OptionDefinition(name, category, sortPriority,
|
||||
new SRF.Helpers.MethodReference(obj, methodInfo)));
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public static string GetNumberString(int value, int max, string exceedsMaxString)
|
||||
{
|
||||
if (value >= max)
|
||||
{
|
||||
return exceedsMaxString;
|
||||
}
|
||||
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
public static void ConfigureCanvas(Canvas canvas)
|
||||
{
|
||||
if (Settings.Instance.UseDebugCamera)
|
||||
{
|
||||
canvas.worldCamera = Service.DebugCamera.Camera;
|
||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e0f09d4b116f524381461f865525607
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
Reference in New Issue
Block a user