mirror of
https://github.com/Cardidi/ca2d-unity-toolkit.git
synced 2025-12-20 01:06:03 +08:00
Add some basic features of this toolkit.
feat: Logg was almost done. fix: Some impossible call was fixed in UnityObjectWarp.cs feat: Boxing<T> was force to unbox by explicit cast operator.
This commit is contained in:
parent
91c24b27e8
commit
0315862527
@ -7,28 +7,43 @@ namespace Ca2d.Toolkit
|
|||||||
|
|
||||||
public static class AsDisposableExtension
|
public static class AsDisposableExtension
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Convert an <see cref="System.Action"/> to a IDisposable callback.
|
||||||
|
/// </summary>
|
||||||
public static AsDisposable AsDisposable(Action callback)
|
public static AsDisposable AsDisposable(Action callback)
|
||||||
{
|
{
|
||||||
return new AsDisposable(callback);
|
return new AsDisposable(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert an <see cref="System.Action"/> to a IDisposable callback.
|
||||||
|
/// </summary>
|
||||||
public static AsAsyncDisposable AsAsyncDisposable(Func<UniTask> callback)
|
public static AsAsyncDisposable AsAsyncDisposable(Func<UniTask> callback)
|
||||||
{
|
{
|
||||||
return new AsAsyncDisposable(callback);
|
return new AsAsyncDisposable(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert an <see cref="System.Action"/> to a IDisposable callback in chain style.
|
||||||
|
/// </summary>
|
||||||
public static AsDisposable<T> AsDisposable<T>(this T target, Action<T> callback)
|
public static AsDisposable<T> AsDisposable<T>(this T target, Action<T> callback)
|
||||||
{
|
{
|
||||||
return new AsDisposable<T>(callback, target);
|
return new AsDisposable<T>(callback, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert an <see cref="System.Action"/> to a IDisposable callback in chain style.
|
||||||
|
/// </summary>
|
||||||
public static AsAsyncDisposable<T> AsAsyncDisposable<T>(this T target, Func<T, UniTask> callback)
|
public static AsAsyncDisposable<T> AsAsyncDisposable<T>(this T target, Func<T, UniTask> callback)
|
||||||
{
|
{
|
||||||
return new AsAsyncDisposable<T>(callback, target);
|
return new AsAsyncDisposable<T>(callback, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An operation container for <see cref="IDisposable"/>.
|
||||||
|
/// </summary>
|
||||||
public readonly struct AsDisposable : IDisposable
|
public readonly struct AsDisposable : IDisposable
|
||||||
{
|
{
|
||||||
private readonly Action m_callback;
|
private readonly Action m_callback;
|
||||||
@ -49,6 +64,10 @@ namespace Ca2d.Toolkit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An operation container for <see cref="IDisposable"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TParam">Object select source.</typeparam>
|
||||||
public readonly struct AsDisposable<TParam> : IDisposable
|
public readonly struct AsDisposable<TParam> : IDisposable
|
||||||
{
|
{
|
||||||
private readonly Action<TParam> m_callback;
|
private readonly Action<TParam> m_callback;
|
||||||
@ -73,6 +92,9 @@ namespace Ca2d.Toolkit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An operation container for <see cref="IDisposable"/>.
|
||||||
|
/// </summary>
|
||||||
public readonly struct AsAsyncDisposable : IAsyncDisposable
|
public readonly struct AsAsyncDisposable : IAsyncDisposable
|
||||||
{
|
{
|
||||||
private readonly Func<UniTask> m_callback;
|
private readonly Func<UniTask> m_callback;
|
||||||
@ -94,6 +116,10 @@ namespace Ca2d.Toolkit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An operation container for <see cref="IDisposable"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TParam">Object select source.</typeparam>
|
||||||
public readonly struct AsAsyncDisposable<TParam> : IAsyncDisposable
|
public readonly struct AsAsyncDisposable<TParam> : IAsyncDisposable
|
||||||
{
|
{
|
||||||
private readonly Func<TParam, UniTask> m_callback;
|
private readonly Func<TParam, UniTask> m_callback;
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace Ca2d.Toolkit
|
namespace Ca2d.Toolkit
|
||||||
{
|
{
|
||||||
@ -18,7 +17,7 @@ namespace Ca2d.Toolkit
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Boxing(Boxing<T> source)
|
public Boxing(Boxing<T> source)
|
||||||
{
|
{
|
||||||
m_value = source.Unbox;
|
m_value = source.m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -30,24 +29,15 @@ namespace Ca2d.Toolkit
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a empty boxing.
|
/// Create an empty boxing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Boxing()
|
public Boxing()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a copy of boxing value.
|
/// Access to the boxing value directly in reference mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public T Unbox
|
public ref T Ref => ref m_value;
|
||||||
{
|
|
||||||
get => m_value;
|
|
||||||
set => m_value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Access to the boxing value directly.
|
|
||||||
/// </summary>
|
|
||||||
public ref T Direct => ref m_value;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clean this boxing container to the default value of boxing target.
|
/// Clean this boxing container to the default value of boxing target.
|
||||||
@ -62,9 +52,9 @@ namespace Ca2d.Toolkit
|
|||||||
return m_value.ToString();
|
return m_value.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator T(Boxing<T> wrapper)
|
public static explicit operator T(Boxing<T> wrapper)
|
||||||
{
|
{
|
||||||
return wrapper.Unbox;
|
return wrapper.m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator Boxing<T>(T value)
|
public static implicit operator Boxing<T>(T value)
|
||||||
|
|||||||
43
Assets/Main/Scripts/ILoggHandler.cs
Normal file
43
Assets/Main/Scripts/ILoggHandler.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Ca2d.Toolkit
|
||||||
|
{
|
||||||
|
public enum LoggType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <para>LogType used for Errors.</para>
|
||||||
|
/// </summary>
|
||||||
|
Error,
|
||||||
|
/// <summary>
|
||||||
|
/// <para>LogType used for Asserts. (These could also indicate an error inside Unity itself.)</para>
|
||||||
|
/// </summary>
|
||||||
|
Assert,
|
||||||
|
/// <summary>
|
||||||
|
/// <para>LogType used for Warnings.</para>
|
||||||
|
/// </summary>
|
||||||
|
Warning,
|
||||||
|
/// <summary>
|
||||||
|
/// <para>LogType used for regular log messages.</para>
|
||||||
|
/// </summary>
|
||||||
|
Log,
|
||||||
|
/// <summary>
|
||||||
|
/// <para>LogType used for Exceptions.</para>
|
||||||
|
/// </summary>
|
||||||
|
Exception,
|
||||||
|
/// <summary>
|
||||||
|
/// <para>LogType used for Developers on testing.</para>
|
||||||
|
/// </summary>
|
||||||
|
Debug
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ILoggHandler : ILogHandler
|
||||||
|
{
|
||||||
|
public ILogHandler InnerLogHandler { get; }
|
||||||
|
|
||||||
|
public void LoggFormat(LoggType logType, Object context, string format, params object[] args);
|
||||||
|
|
||||||
|
public void SetLabel(string label);
|
||||||
|
|
||||||
|
public void ClearLabel();
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/Main/Scripts/ILoggHandler.cs.meta
Normal file
3
Assets/Main/Scripts/ILoggHandler.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bfec301646cc46339921f4c1c9170412
|
||||||
|
timeCreated: 1715271270
|
||||||
@ -1,497 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Ca2d.Toolkit
|
|
||||||
{
|
|
||||||
public readonly struct Log : IDisposable
|
|
||||||
{
|
|
||||||
private const string kNoLabelAndContextName = "Anonymous";
|
|
||||||
|
|
||||||
private const string kFallbackLabelName = "Fallback";
|
|
||||||
|
|
||||||
private static HashSet<int> _loopDetector = new();
|
|
||||||
|
|
||||||
private static StringBuilder _sb = new();
|
|
||||||
|
|
||||||
#region ManagedRegionOperations
|
|
||||||
|
|
||||||
private static Core _fallbackCore = new Core
|
|
||||||
{
|
|
||||||
ValidateNumber = 0,
|
|
||||||
ParentIndex = 0,
|
|
||||||
ParentValidateNumber = 0,
|
|
||||||
Context = null,
|
|
||||||
Label = kFallbackLabelName
|
|
||||||
};
|
|
||||||
|
|
||||||
private static List<Core> _core = new()
|
|
||||||
{
|
|
||||||
// This is the first element of AdvDebugCore and also as fallback options.
|
|
||||||
_fallbackCore
|
|
||||||
};
|
|
||||||
|
|
||||||
#region Allocation
|
|
||||||
|
|
||||||
private static List<Vector2Int> m_allocMap = new()
|
|
||||||
{
|
|
||||||
// The first element must be allocated.
|
|
||||||
new Vector2Int(0, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
private static bool RangeOverlap(Vector2Int a, Vector2Int b)
|
|
||||||
{
|
|
||||||
var offset = a.x - b.x;
|
|
||||||
switch (offset)
|
|
||||||
{
|
|
||||||
case < 0:
|
|
||||||
{
|
|
||||||
var o = -offset;
|
|
||||||
var lenA = a.y - a.x;
|
|
||||||
return o < lenA;
|
|
||||||
}
|
|
||||||
case > 0:
|
|
||||||
{
|
|
||||||
var o = offset;
|
|
||||||
var lenB = b.y - b.x;
|
|
||||||
return o < lenB;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static bool IsIdUsed(int id)
|
|
||||||
{
|
|
||||||
return m_allocMap.Exists(range => id >= range.x && id < range.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int GetUnusedId()
|
|
||||||
{
|
|
||||||
var alloc = m_allocMap[0].y;
|
|
||||||
if (alloc == int.MaxValue) throw new IndexOutOfRangeException("No free index can be exposed!");
|
|
||||||
return alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool AllocId(int id)
|
|
||||||
{
|
|
||||||
if (id <= 0 || id == int.MaxValue) return false;
|
|
||||||
var range = new Vector2Int(id, id + 1);
|
|
||||||
|
|
||||||
for (var i = 1; i < m_allocMap.Count; i++)
|
|
||||||
{
|
|
||||||
var r = m_allocMap[i];
|
|
||||||
var insert = i + 1;
|
|
||||||
if (m_allocMap.Count != insert && RangeOverlap(r, range)) continue;
|
|
||||||
|
|
||||||
// Get the reaction on merge.
|
|
||||||
var mergePrev = false;
|
|
||||||
var mergeNext = false;
|
|
||||||
|
|
||||||
var before = m_allocMap[insert - 1];
|
|
||||||
if (before.y == range.x) mergePrev = true;
|
|
||||||
|
|
||||||
var after = m_allocMap.Count > insert ? m_allocMap[insert] : default;
|
|
||||||
if (after.y != 0 && after.x == range.y) mergeNext = true;
|
|
||||||
|
|
||||||
if (mergePrev & mergeNext)
|
|
||||||
{
|
|
||||||
m_allocMap[insert - 1] = new Vector2Int(before.x, after.y);
|
|
||||||
m_allocMap.RemoveAt(insert);
|
|
||||||
}
|
|
||||||
else if (mergePrev)
|
|
||||||
{
|
|
||||||
m_allocMap[insert - 1] = new Vector2Int(before.x, range.y);
|
|
||||||
}
|
|
||||||
else if (mergeNext)
|
|
||||||
{
|
|
||||||
m_allocMap[insert] = new Vector2Int(range.x, after.y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_allocMap.Insert(insert, range);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool FreeId(int id)
|
|
||||||
{
|
|
||||||
if (id <= 0 || id == int.MaxValue) return false;
|
|
||||||
var range = new Vector2Int(id, id + 1);
|
|
||||||
var idx = m_allocMap.FindIndex(r => RangeOverlap(r, range));
|
|
||||||
if (idx < 0) return false;
|
|
||||||
|
|
||||||
// Get reaction on split
|
|
||||||
var insertLeft = true;
|
|
||||||
var insertRight = true;
|
|
||||||
|
|
||||||
var splitTarget = m_allocMap[id];
|
|
||||||
if (splitTarget.x == range.x) insertLeft = false;
|
|
||||||
if (splitTarget.y == range.y) insertRight = false;
|
|
||||||
|
|
||||||
if (insertLeft || insertRight)
|
|
||||||
{
|
|
||||||
if (insertLeft)
|
|
||||||
{
|
|
||||||
m_allocMap[idx] = new Vector2Int(splitTarget.x, range.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (insertRight)
|
|
||||||
{
|
|
||||||
m_allocMap.Insert(idx + 1, new Vector2Int(range.y, splitTarget.y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_allocMap.RemoveAt(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private struct Capture
|
|
||||||
{
|
|
||||||
public readonly ulong CaptureValidateNumber;
|
|
||||||
|
|
||||||
public readonly int ResourceIndex;
|
|
||||||
|
|
||||||
public object Context
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (IsValid()) return _core[ResourceIndex].Context;
|
|
||||||
return _fallbackCore.Context;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Label
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (IsValid()) return _core[ResourceIndex].Label;
|
|
||||||
return _fallbackCore.Label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryResolveParent(out Capture capture, bool includeFallback = false)
|
|
||||||
{
|
|
||||||
if (IsValid())
|
|
||||||
{
|
|
||||||
capture = new Capture(_core[ResourceIndex].ParentIndex);
|
|
||||||
if (capture.IsFallback()) return includeFallback;
|
|
||||||
return capture.CaptureValidateNumber == _core[ResourceIndex].ParentValidateNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
capture = default;
|
|
||||||
return includeFallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Capture(int idx)
|
|
||||||
{
|
|
||||||
if (idx >= _core.Count || idx <= 0)
|
|
||||||
{
|
|
||||||
CaptureValidateNumber = default;
|
|
||||||
ResourceIndex = default;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceIndex = idx;
|
|
||||||
CaptureValidateNumber = _core[idx].ValidateNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsFallback()
|
|
||||||
{
|
|
||||||
return ResourceIndex == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsValid()
|
|
||||||
{
|
|
||||||
var resIdx = ResourceIndex;
|
|
||||||
if (resIdx == 0) return true;
|
|
||||||
if (resIdx >= _core.Count || resIdx < 0) return false;
|
|
||||||
return _core[resIdx].ParentValidateNumber == CaptureValidateNumber && IsIdUsed(resIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct Core
|
|
||||||
{
|
|
||||||
public ulong ValidateNumber;
|
|
||||||
|
|
||||||
public ulong ParentValidateNumber;
|
|
||||||
|
|
||||||
public int ParentIndex;
|
|
||||||
|
|
||||||
public object Context;
|
|
||||||
|
|
||||||
public string Label;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool RequestCore(out Capture capture, string label, object context, int parentId)
|
|
||||||
{
|
|
||||||
var id = GetUnusedId();
|
|
||||||
if (AllocId(id))
|
|
||||||
{
|
|
||||||
// Make sure there has valid space to allocate.
|
|
||||||
while (_core.Count - 1 < id) _core.Add(default);
|
|
||||||
|
|
||||||
var c = _core[id];
|
|
||||||
|
|
||||||
// Set context of current Debug.
|
|
||||||
c.Context = context;
|
|
||||||
c.Label = label;
|
|
||||||
|
|
||||||
// Check is given parent id is valid and fill result.
|
|
||||||
c.ParentIndex = parentId != 0 && IsIdUsed(parentId) ? parentId : 0;
|
|
||||||
c.ParentValidateNumber = c.ParentIndex == 0 ? 0 : _core[c.ParentIndex].ValidateNumber;
|
|
||||||
|
|
||||||
_core[id] = c;
|
|
||||||
capture = new Capture(id);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
capture = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ReturnCore(Capture capture)
|
|
||||||
{
|
|
||||||
if (capture.IsFallback() || !capture.IsValid()) return false;
|
|
||||||
if (!FreeId(capture.ResourceIndex)) return false;
|
|
||||||
|
|
||||||
var core = _core[capture.ResourceIndex];
|
|
||||||
|
|
||||||
core.ValidateNumber += 1;
|
|
||||||
core.ParentValidateNumber = default;
|
|
||||||
core.ParentIndex = default;
|
|
||||||
core.Context = null;
|
|
||||||
core.Label = kFallbackLabelName;
|
|
||||||
|
|
||||||
_core[capture.ResourceIndex] = core;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ExposeValue
|
|
||||||
|
|
||||||
public bool IsFallback => m_capture.IsFallback();
|
|
||||||
|
|
||||||
public string Label => m_capture.Label;
|
|
||||||
|
|
||||||
public object Context => m_capture.Context;
|
|
||||||
|
|
||||||
public Log? Parent
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (m_capture.TryResolveParent(out var cap, false))
|
|
||||||
return new Log(cap);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Lifecircle
|
|
||||||
|
|
||||||
private readonly Capture m_capture;
|
|
||||||
|
|
||||||
private Log(Capture capture)
|
|
||||||
{
|
|
||||||
m_capture = capture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Log(Log parent = default)
|
|
||||||
{
|
|
||||||
if (!RequestCore(out var capture, kNoLabelAndContextName, null, parent.m_capture.ResourceIndex))
|
|
||||||
{
|
|
||||||
m_capture = default;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_capture = capture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Log(string label, Log parent = default)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(label)) label = kNoLabelAndContextName;
|
|
||||||
if (!RequestCore(out var capture, label, null, parent.m_capture.ResourceIndex))
|
|
||||||
{
|
|
||||||
m_capture = default;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_capture = capture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Log(object context, Log parent = default)
|
|
||||||
{
|
|
||||||
var label = context == null ? kNoLabelAndContextName : context.GetType().Name;
|
|
||||||
if (!RequestCore(out var capture, label, null, parent.m_capture.ResourceIndex))
|
|
||||||
{
|
|
||||||
m_capture = default;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_capture = capture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Log(string label, object context, Log parent = default)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(label)) label = context == null ? kNoLabelAndContextName : context.GetType().Name;
|
|
||||||
if (!RequestCore(out var capture, label, null, parent.m_capture.ResourceIndex))
|
|
||||||
{
|
|
||||||
m_capture = default;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_capture = capture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!FreeId(m_capture.ResourceIndex) || !ReturnCore(m_capture)) throw new InvalidOperationException(
|
|
||||||
"You can not trying to dispose an outdated or default AdvLogger!");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public void Debug(string text)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Info(string text)
|
|
||||||
{}
|
|
||||||
|
|
||||||
public void Warning(string text)
|
|
||||||
{}
|
|
||||||
|
|
||||||
public void Error(string text)
|
|
||||||
{}
|
|
||||||
|
|
||||||
public void Error(Exception err)
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class QLog
|
|
||||||
{
|
|
||||||
|
|
||||||
#region (string)
|
|
||||||
|
|
||||||
public static void Debug(string text)
|
|
||||||
{
|
|
||||||
default(Log).Debug(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Info(string text)
|
|
||||||
{
|
|
||||||
default(Log).Info(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Warning(string text)
|
|
||||||
{
|
|
||||||
default(Log).Warning(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Error(string text)
|
|
||||||
{
|
|
||||||
default(Log).Error(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region (string, string)
|
|
||||||
|
|
||||||
public static void Debug(string text, string label)
|
|
||||||
{
|
|
||||||
using var logger = new Log(label);
|
|
||||||
logger.Debug(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Info(string text, string label)
|
|
||||||
{
|
|
||||||
using var logger = new Log(label);
|
|
||||||
logger.Info(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Warning(string text, string label)
|
|
||||||
{
|
|
||||||
using var logger = new Log(label);
|
|
||||||
logger.Warning(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Error(string text, string label)
|
|
||||||
{
|
|
||||||
using var logger = new Log(label);
|
|
||||||
logger.Error(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region (string, object)
|
|
||||||
|
|
||||||
public static void Debug(string text, object context)
|
|
||||||
{
|
|
||||||
using var logger = new Log(context);
|
|
||||||
logger.Debug(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Info(string text, object context)
|
|
||||||
{
|
|
||||||
using var logger = new Log(context);
|
|
||||||
logger.Info(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Warning(string text, object context)
|
|
||||||
{
|
|
||||||
using var logger = new Log(context);
|
|
||||||
logger.Warning(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Error(string text, object context)
|
|
||||||
{
|
|
||||||
using var logger = new Log(context);
|
|
||||||
logger.Error(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region (string, string, object)
|
|
||||||
|
|
||||||
public static void Debug(string text, string label, object context)
|
|
||||||
{
|
|
||||||
using var logger = new Log(label, context);
|
|
||||||
logger.Info(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Info(string text, string label, object context)
|
|
||||||
{
|
|
||||||
using var logger = new Log(label, context);
|
|
||||||
logger.Info(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Warning(string text, string label, object context)
|
|
||||||
{
|
|
||||||
using var logger = new Log(label, context);
|
|
||||||
logger.Warning(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Error(string text, string label, object context)
|
|
||||||
{
|
|
||||||
using var logger = new Log(label, context);
|
|
||||||
logger.Error(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3b5d1b48628646eebc9e64c30bd93ae8
|
|
||||||
timeCreated: 1713286134
|
|
||||||
282
Assets/Main/Scripts/Logg.cs
Normal file
282
Assets/Main/Scripts/Logg.cs
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
|
namespace Ca2d.Toolkit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Alternatives to the default Unity Logger.
|
||||||
|
/// </summary>
|
||||||
|
public struct Logg
|
||||||
|
{
|
||||||
|
#region BackendConfig
|
||||||
|
|
||||||
|
// ReSharper disable once MemberCanBePrivate.Global
|
||||||
|
public const string kDefaultLoggerLevelSplit = "::";
|
||||||
|
|
||||||
|
private static ILoggHandler _backend;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Which backend will be used for logger?
|
||||||
|
/// </summary>
|
||||||
|
public static ILoggHandler Backend
|
||||||
|
{
|
||||||
|
get => _backend;
|
||||||
|
set => _backend = value ?? throw new NullReferenceException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logger level name spliter sign.
|
||||||
|
/// </summary>
|
||||||
|
public static string LoggerLevelSplit { get; set; } = kDefaultLoggerLevelSplit;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
private static readonly StringBuilder kStringBuilder = new();
|
||||||
|
|
||||||
|
private readonly bool m_useLabel;
|
||||||
|
|
||||||
|
private readonly string m_label;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a logger with first-level namespace
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ns">Namespace</param>
|
||||||
|
public Logg(string ns)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(ns))
|
||||||
|
{
|
||||||
|
m_useLabel = false;
|
||||||
|
m_label = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_useLabel = true;
|
||||||
|
m_label = ns.Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a copy of source logger.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">Source logger.</param>
|
||||||
|
public Logg(Logg source)
|
||||||
|
{
|
||||||
|
if (source.m_useLabel)
|
||||||
|
{
|
||||||
|
m_useLabel = true;
|
||||||
|
m_label = source.m_label;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_useLabel = false;
|
||||||
|
m_label = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a nested logger with given namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">Nest source.</param>
|
||||||
|
/// <param name="ns">Namespace</param>
|
||||||
|
public Logg(Logg source, string ns)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(ns))
|
||||||
|
{
|
||||||
|
if (source.m_useLabel)
|
||||||
|
{
|
||||||
|
m_useLabel = true;
|
||||||
|
m_label = source.m_label;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_useLabel = false;
|
||||||
|
m_label = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_useLabel = true;
|
||||||
|
if (source.m_useLabel)
|
||||||
|
{
|
||||||
|
kStringBuilder.Clear();
|
||||||
|
m_label = kStringBuilder.AppendJoin(LoggerLevelSplit, source.m_label, ns.Trim()).ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_label = ns.Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region EnvOverrider
|
||||||
|
|
||||||
|
private static bool _init = false;
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
private static void LoggInitEditor()
|
||||||
|
{
|
||||||
|
LoggInit();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
[RuntimeInitializeOnLoadMethod]
|
||||||
|
private static void RuntimeLoggInit()
|
||||||
|
{
|
||||||
|
LoggInit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private static void LoggInit()
|
||||||
|
{
|
||||||
|
if (!_init)
|
||||||
|
{
|
||||||
|
var prevLogHandler = UnityEngine.Debug.unityLogger.logHandler;
|
||||||
|
|
||||||
|
if (prevLogHandler is ILoggHandler)
|
||||||
|
{
|
||||||
|
prevLogHandler.LogFormat(
|
||||||
|
LogType.Warning,
|
||||||
|
null,
|
||||||
|
"Logg seems to be inited before initialize?");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var l = new LoggHandler(prevLogHandler);
|
||||||
|
_backend = l;
|
||||||
|
UnityEngine.Debug.unityLogger.logHandler = l;
|
||||||
|
prevLogHandler.LogFormat(LogType.Log, null, "##### Debug.unityLogger was taken over by Logg #####");
|
||||||
|
}
|
||||||
|
|
||||||
|
_init = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region LogMethods
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public void Format(LoggType type, Object context, string format, params object[] args)
|
||||||
|
{
|
||||||
|
if (_backend != null)
|
||||||
|
{
|
||||||
|
if (m_useLabel) _backend.SetLabel(m_label);
|
||||||
|
_backend.LoggFormat(type, context, format, args);
|
||||||
|
_backend.ClearLabel();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use fallback logger if Logg is not ready.
|
||||||
|
UnityEngine.Debug.LogFormat((LogType) type, LogOption.NoStacktrace, context, format, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public void Debug(string content, Object context = null)
|
||||||
|
{
|
||||||
|
Format(LoggType.Debug, context, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public void Info(string content, Object context = null)
|
||||||
|
{
|
||||||
|
Format(LoggType.Log, context, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public void Warning(string content, Object context = null)
|
||||||
|
{
|
||||||
|
Format(LoggType.Warning, context, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public void Error(string content, Object context = null)
|
||||||
|
{
|
||||||
|
Format(LoggType.Error, context, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public void Error(Exception err, Object context = null)
|
||||||
|
{
|
||||||
|
Format(LoggType.Exception, context, err.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Quick log API for <see cref="Logg"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class DebugLogg
|
||||||
|
{
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public static void Format(LoggType type, Object context, string format, params object[] args)
|
||||||
|
{
|
||||||
|
default(Logg).Format(type, context, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public static void Debug(string content, Object context = null)
|
||||||
|
{
|
||||||
|
default(Logg).Debug(content, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public static void Info(string content, Object context = null)
|
||||||
|
{
|
||||||
|
default(Logg).Info(content, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public static void Warning(string content, Object context = null)
|
||||||
|
{
|
||||||
|
default(Logg).Warning(content, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public static void Error(string content, Object context = null)
|
||||||
|
{
|
||||||
|
default(Logg).Error(content, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public static void Error(Exception err, Object context = null)
|
||||||
|
{
|
||||||
|
default(Logg).Error(err, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/Main/Scripts/Logg.cs.meta
Normal file
3
Assets/Main/Scripts/Logg.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 59eb97c7769441599ea2569c2f5402b8
|
||||||
|
timeCreated: 1715264700
|
||||||
102
Assets/Main/Scripts/LoggHandler.cs
Normal file
102
Assets/Main/Scripts/LoggHandler.cs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
|
namespace Ca2d.Toolkit
|
||||||
|
{
|
||||||
|
public class LoggHandler : ILoggHandler
|
||||||
|
{
|
||||||
|
private readonly ILogHandler m_innerHandle;
|
||||||
|
|
||||||
|
private readonly StringBuilder m_sb = new();
|
||||||
|
|
||||||
|
private bool m_useLabel = false;
|
||||||
|
|
||||||
|
private string m_labelText = default;
|
||||||
|
|
||||||
|
#region PassThrough
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public void LogFormat(LogType logType, Object context, string format, params object[] args)
|
||||||
|
{
|
||||||
|
LoggFormat((LoggType) logType, context, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public void LogException(Exception exception, Object context)
|
||||||
|
{
|
||||||
|
LoggFormat(LoggType.Exception, context, exception.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void GenerateLabel(StringBuilder sb, LoggType type)
|
||||||
|
{
|
||||||
|
var logTypeText = type switch
|
||||||
|
{
|
||||||
|
LoggType.Assert => "ASSERT",
|
||||||
|
LoggType.Exception => "EXCEPTION",
|
||||||
|
LoggType.Error => "Error",
|
||||||
|
LoggType.Warning => "Warning",
|
||||||
|
LoggType.Log => "Info",
|
||||||
|
_ => "Debug"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_useLabel)
|
||||||
|
{
|
||||||
|
sb.AppendFormat("[{0:yyyy-M-d HH:mm:ss}] {1} ({2}) : ", DateTime.Now, logTypeText, m_labelText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.AppendFormat("[{0:yyyy-M-d HH:mm:ss}] {1} : ", DateTime.Now, logTypeText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideInCallstack]
|
||||||
|
[DebuggerHidden]
|
||||||
|
[DebuggerStepThrough]
|
||||||
|
public void LoggFormat(LoggType logType, Object context, string format, params object[] args)
|
||||||
|
{
|
||||||
|
m_sb.Clear();
|
||||||
|
|
||||||
|
// Write label to the front
|
||||||
|
GenerateLabel(m_sb, logType);
|
||||||
|
|
||||||
|
// Write format text after front
|
||||||
|
m_sb.AppendFormat(format, args);
|
||||||
|
|
||||||
|
// Redirect Debug to Log.
|
||||||
|
LogType finalType;
|
||||||
|
if (logType == LoggType.Debug) finalType = LogType.Log;
|
||||||
|
else finalType = (LogType) logType;
|
||||||
|
|
||||||
|
// Use inner handle to write.
|
||||||
|
m_innerHandle.LogFormat(finalType, context, m_sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILogHandler InnerLogHandler => m_innerHandle;
|
||||||
|
|
||||||
|
public void SetLabel(string label)
|
||||||
|
{
|
||||||
|
m_labelText = label;
|
||||||
|
m_useLabel = label != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearLabel()
|
||||||
|
{
|
||||||
|
m_labelText = null;
|
||||||
|
m_useLabel = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoggHandler(ILogHandler innerHandle)
|
||||||
|
{
|
||||||
|
m_innerHandle = innerHandle ?? throw new ArgumentNullException(nameof(innerHandle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/Main/Scripts/LoggHandler.cs.meta
Normal file
3
Assets/Main/Scripts/LoggHandler.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f543cfba5cf04258b3ab59b75849e7a9
|
||||||
|
timeCreated: 1715271314
|
||||||
@ -2,6 +2,9 @@ using System;
|
|||||||
|
|
||||||
namespace Ca2d.Toolkit
|
namespace Ca2d.Toolkit
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// When Unity Requirements did not fit <see cref="Guard"/> wants, throw this.
|
||||||
|
/// </summary>
|
||||||
public class LoseRequirementException : Exception
|
public class LoseRequirementException : Exception
|
||||||
{
|
{
|
||||||
public Type RequiredType { get; }
|
public Type RequiredType { get; }
|
||||||
|
|||||||
@ -11,8 +11,14 @@ namespace Ca2d.Toolkit
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public struct Option<T>
|
public struct Option<T>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Is option set to fill.
|
||||||
|
/// </summary>
|
||||||
public bool Enabled;
|
public bool Enabled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Value inside of option
|
||||||
|
/// </summary>
|
||||||
public T Value;
|
public T Value;
|
||||||
|
|
||||||
public T ValueOrDefault()
|
public T ValueOrDefault()
|
||||||
|
|||||||
@ -15,16 +15,26 @@ namespace Ca2d.Toolkit
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is this warp reference to a valid target?
|
/// Is this warp reference to a valid target?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Valid => m_referencedObject is T;
|
public bool Is => m_referencedObject is T;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Trying to get the actual object of this reference.
|
/// Trying to get the actual object of this reference.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public T Object => m_referencedObject as T;
|
public T As => m_referencedObject as T;
|
||||||
|
|
||||||
public static implicit operator T(UnityObjectWarp<T> wrapper)
|
/// <summary>
|
||||||
|
/// Is this warp reference to a valid target? If this is valid, give the casting result.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsAs(out T val)
|
||||||
{
|
{
|
||||||
return wrapper.Object;
|
if (m_referencedObject is T referenced)
|
||||||
|
{
|
||||||
|
val = referenced;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user