This commit is contained in:
DCFApixels 2025-03-21 14:32:50 +08:00
parent 2642510c89
commit f068c22661
9 changed files with 227 additions and 45 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 69f2abf8b8744c840b2da7f8988b3f8d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,8 @@
using System; using DCFApixels.DragonECS.Unity.Internal;
using System;
using System.Reflection;
using Unity.Profiling; using Unity.Profiling;
using UnityEditor;
using UnityEngine; using UnityEngine;
#region [InitializeOnLoad] #region [InitializeOnLoad]
@ -12,14 +15,12 @@ namespace DCFApixels.DragonECS
} }
#endif #endif
#endregion #endregion
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
// Методы юнитевского Debug и ProfilerMarker потоко безопасны // Методы юнитевского Debug и ProfilerMarker потоко безопасны
public partial class UnityDebugService : DebugService public partial class UnityDebugService : DebugService
{ {
private ProfilerMarker[] _profilerMarkers = new ProfilerMarker[64]; private ProfilerMarker[] _profilerMarkers = new ProfilerMarker[64];
static UnityDebugService() static UnityDebugService()
{ {
Activate(); Activate();
@ -29,6 +30,27 @@ namespace DCFApixels.DragonECS
if (Instance.GetType() == typeof(UnityDebugService)) { return; } if (Instance.GetType() == typeof(UnityDebugService)) { return; }
Set<UnityDebugService>(); Set<UnityDebugService>();
} }
protected override void OnEnableBaseService(DebugService oldService)
{
EditorGUI.hyperLinkClicked -= EditorGUI_hyperLinkClicked;
EditorGUI.hyperLinkClicked += EditorGUI_hyperLinkClicked;
Application.logMessageReceived -= Application_logMessageReceived;
Application.logMessageReceived += Application_logMessageReceived;
}
protected override void OnDisableBaseService(DebugService nextService)
{
Application.logMessageReceived -= Application_logMessageReceived;
EditorGUI.hyperLinkClicked -= EditorGUI_hyperLinkClicked;
}
private void EditorGUI_hyperLinkClicked(EditorWindow editor, HyperLinkClickedEventArgs args)
{
throw new NotImplementedException();
}
private void Application_logMessageReceived(string logString, string stackTrace, LogType type)
{
}
protected override DebugService CreateThreadInstance() protected override DebugService CreateThreadInstance()
{ {

View File

@ -0,0 +1,119 @@
#if UNITY_EDITOR
using System;
using System.Reflection;
using System.Threading;
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Internal
{
internal class UnityDebugServiceStorage : ScriptableSingleton<UnityDebugServiceStorage>
{
private static readonly MethodInfo _getLogsCountMethod;
public static readonly bool IsSupportAutoLingks;
static UnityDebugServiceStorage()
{
var logEntriesType = typeof(EditorWindow).Assembly.GetType("UnityEditor.LogEntries");
if (logEntriesType != null)
{
_getLogsCountMethod = logEntriesType.GetMethod("GetCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
IsSupportAutoLingks = _getLogsCountMethod != null;
EditorGUI.hyperLinkClicked -= EditorGUI_hyperLinkClicked;
Application.logMessageReceived -= Application_logMessageReceived;
_consoleLogCounter = -1;
if (IsSupportAutoLingks)
{
EditorGUI.hyperLinkClicked += EditorGUI_hyperLinkClicked;
Application.logMessageReceived += Application_logMessageReceived;
_consoleLogCounter = GetConsoleLogCount();
}
}
public UnityDebugServiceStorage() { }
private const int IntervalChecksTicksThreshold = 100;
private static int _consoleLogCounter;
private static int _intervalChecksTicks = 0;
private static StructList<string> _recycledIndexes;
private static StructList<LogEntry> _logEntries;
private static object _lock = new object();
private static void EditorGUI_hyperLinkClicked(EditorWindow window, HyperLinkClickedEventArgs args)
{
throw new NotImplementedException();
}
private static void Application_logMessageReceived(string logString, string stackTrace, LogType type)
{
if (_intervalChecksTicks >= IntervalChecksTicksThreshold ||
_logEntries.Count >= _logEntries.Capacity - 1)
{
CheckConsoleClean();
_intervalChecksTicks = 0;
}
_logEntries.Add(new LogEntry(logString, stackTrace));
Interlocked.Increment(ref _consoleLogCounter);
Interlocked.Increment(ref _intervalChecksTicks);
}
private static bool CheckConsoleClean()
{
int currentCount = GetConsoleLogCount();
if (_consoleLogCounter > currentCount)
{
error
_consoleLogCounter = currentCount;
return true;
}
return false;
}
private static int GetConsoleLogCount()
{
return (int)_getLogsCountMethod.Invoke(null, null);
}
private static string CreateIndexedLink(int index)
{
return $"<a href=\"{index}\">∆</a> ";
}
//multi thread access.
public static string GetHyperLink()
{
return instance.GetHyperLink_Internal();
}
public string GetHyperLink_Internal()
{
string hyperLink;
if (_recycledIndexes.Count > 0)
{
hyperLink = _recycledIndexes.Dequeue();
}
else
{
hyperLink = CreateIndexedLink(_logEntries.Count);
}
return hyperLink;
}
private readonly struct LogEntry
{
public readonly string LogString;
public readonly string StackTrace;
public LogEntry(string logString, string stackTrace)
{
LogString = logString;
StackTrace = stackTrace;
}
}
}
}
#endif

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8666cb6c75b076c41910acbe59d258af

View File

@ -72,58 +72,31 @@ namespace DCFApixels.DragonECS.Unity.Internal
} }
} }
internal static class ArrayUtility internal static class DragonArrayUtility
{ {
private static int GetHighBitNumber(uint bits) public static int NextPow2(int v)
{
if (bits == 0)
{
return -1;
}
int bit = 0;
if ((bits & 0xFFFF0000) != 0)
{
bits >>= 16;
bit |= 16;
}
if ((bits & 0xFF00) != 0)
{
bits >>= 8;
bit |= 8;
}
if ((bits & 0xF0) != 0)
{
bits >>= 4;
bit |= 4;
}
if ((bits & 0xC) != 0)
{
bits >>= 2;
bit |= 2;
}
if ((bits & 0x2) != 0)
{
bit |= 1;
}
return bit;
}
public static int NormalizeSizeToPowerOfTwo(int minSize)
{ {
unchecked unchecked
{ {
return 1 << (GetHighBitNumber((uint)minSize - 1u) + 1); v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
return ++v;
} }
} }
public static int NormalizeSizeToPowerOfTwo_ClampOverflow(int minSize) public static int NextPow2_ClampOverflow(int v)
{ {
unchecked unchecked
{ {
int hibit = (GetHighBitNumber((uint)minSize - 1u) + 1); const int NO_SIGN_HIBIT = 0x40000000;
if (hibit >= 32) if ((v & NO_SIGN_HIBIT) != 0)
{ {
return int.MaxValue; return int.MaxValue;
} }
return 1 << hibit; return NextPow2(v);
} }
} }
public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1) public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1)

View File

@ -432,6 +432,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
} }
else if (current.type == EventType.MouseDown && current.clickCount >= 2) else if (current.type == EventType.MouseDown && current.clickCount >= 2)
{ {
//UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(); //TODO
AssetDatabase.OpenAsset(script); AssetDatabase.OpenAsset(script);
} }
} }

View File

@ -3,13 +3,18 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Internal namespace DCFApixels.DragonECS.Unity.Internal
{ {
[Serializable]
[DebuggerDisplay("Count: {Count}")] [DebuggerDisplay("Count: {Count}")]
internal struct StructList<T> internal struct StructList<T>
{ {
[SerializeField]
internal T[] _items; internal T[] _items;
[SerializeField]
internal int _count; internal int _count;
public IEnumerable<T> Enumerable public IEnumerable<T> Enumerable
@ -39,7 +44,7 @@ namespace DCFApixels.DragonECS.Unity.Internal
set set
{ {
if (value <= _items.Length) { return; } if (value <= _items.Length) { return; }
value = ArrayUtility.NormalizeSizeToPowerOfTwo(value); value = DragonArrayUtility.NextPow2(value);
Array.Resize(ref _items, value); Array.Resize(ref _items, value);
} }
} }
@ -66,7 +71,7 @@ namespace DCFApixels.DragonECS.Unity.Internal
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public StructList(int capacity) public StructList(int capacity)
{ {
_items = new T[ArrayUtility.NormalizeSizeToPowerOfTwo(capacity)]; _items = new T[DragonArrayUtility.NextPow2(capacity)];
_count = 0; _count = 0;
} }
@ -92,6 +97,24 @@ namespace DCFApixels.DragonECS.Unity.Internal
_items[idnex2] = tmp; _items[idnex2] = tmp;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T FastDequeue()
{
#if DEBUG
if (_count <= 0) { Throw.ArgumentOutOfRange(); }
#endif
return ref _items[--_count];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T Dequeue()
{
#if DEBUG
if (_count <= 0) { Throw.ArgumentOutOfRange(); }
#endif
T result = _items[--_count];
_items[_count] = default;
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FastRemoveAt(int index) public void FastRemoveAt(int index)
{ {
#if DEBUG #if DEBUG
@ -178,4 +201,38 @@ namespace DCFApixels.DragonECS.Unity.Internal
return _items; return _items;
} }
} }
internal static class StructListExt
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Add_MultiAccess<T>(this ref StructList<T> self, T item)
{
var index = Interlocked.Increment(ref self._count);
index -= 1;
if (index >= self._items.Length)
{
lock (self._items)
{
if (index >= self._items.Length)
{
Array.Resize(ref self._items, self._items.Length << 1);
}
}
}
self._items[index] = item;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryDequeue_MultiAccess<T>(this ref StructList<T> self, T item)
{
var index = Interlocked.Increment(ref self._count);
#if DEBUG
if (_count <= 0) { Throw.ArgumentOutOfRange(); }
#endif
T result = _items[--_count];
_items[_count] = default;
return result;
}
}
} }