mirror of
https://github.com/DCFApixels/DragonECS-Unity.git
synced 2025-09-17 17:34:34 +08:00
update runtime monitors
This commit is contained in:
parent
7f2d1cee73
commit
69e2c926e8
@ -12,6 +12,7 @@ namespace DCFApixels.DragonECS
|
||||
public abstract bool IsEmpty { get; }
|
||||
public abstract void SetRaw(EcsWorld world);
|
||||
public abstract EcsWorld GetRaw();
|
||||
public abstract EcsWorld GetCurrentWorldRaw();
|
||||
}
|
||||
[Serializable]
|
||||
public abstract class EcsWorldProvider<TWorld> : EcsWorldProviderBase where TWorld : EcsWorld
|
||||
@ -78,6 +79,10 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
public sealed override EcsWorld GetCurrentWorldRaw()
|
||||
{
|
||||
return _world;
|
||||
}
|
||||
public TWorld Get()
|
||||
{
|
||||
if (_world == null || _world.IsDestroyed)
|
||||
|
@ -23,6 +23,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
EcsWorld world = Target.GetRaw();
|
||||
GUILayout.Box($"{world.GetMeta().Name} ( {world.id} )", style, GUILayout.ExpandWidth(true));
|
||||
}
|
||||
EcsGUI.Layout.DrawWorldBaseInfo(Target.GetCurrentWorldRaw());
|
||||
|
||||
|
||||
base.OnInspectorGUI();
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
@ -1,23 +1,33 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
using DCFApixels.DragonECS.Unity.Internal;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public sealed class DebugModule : IEcsModule
|
||||
{
|
||||
public const string DEBUG_LAYER = nameof(DEBUG_LAYER);
|
||||
public EcsWorld[] _worlds;
|
||||
|
||||
public DebugModule(params EcsWorld[] worlds)
|
||||
{
|
||||
_worlds = worlds;
|
||||
}
|
||||
|
||||
void IEcsModule.Import(EcsPipeline.Builder b)
|
||||
{
|
||||
UnityDebugService.Activate();
|
||||
b.Layers.Insert(EcsConsts.POST_END_LAYER, DEBUG_LAYER);
|
||||
//b.Add(new PipelineDebugSystem(), DEBUG_LAYER);
|
||||
b.Add(new PipelineMonitorSystem(), DEBUG_LAYER);
|
||||
foreach (var world in _worlds)
|
||||
{
|
||||
//b.Add(new WorldDebugSystem(world), DEBUG_LAYER);
|
||||
b.Add(new WorldMonitorSystem(world), DEBUG_LAYER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class DebugModuleExt
|
||||
{
|
||||
public static EcsPipeline.Builder AddUnityDebug(this EcsPipeline.Builder self, params EcsWorld[] worlds)
|
||||
{
|
||||
self.AddModule(new DebugModule(worlds));
|
||||
return self;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
8
src/Debug/Monitors/Editor.meta
Normal file
8
src/Debug/Monitors/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1105324b07e39d449acceb24bdd7eb3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
20
src/Debug/Monitors/Editor/EntityMonitorEditor.cs
Normal file
20
src/Debug/Monitors/Editor/EntityMonitorEditor.cs
Normal file
@ -0,0 +1,20 @@
|
||||
#if UNITY_EDITOR
|
||||
using DCFApixels.DragonECS.Unity.Internal;
|
||||
using UnityEditor;
|
||||
|
||||
namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
[CustomEditor(typeof(EntityMonitor))]
|
||||
internal class EntityMonitorEditor : Editor
|
||||
{
|
||||
private EntityMonitor Target => (EntityMonitor)target;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
bool isAlive = Target.Entity.TryUnpack(out int id, out short gen, out EcsWorld world);
|
||||
EcsGUI.Layout.EntityBar(isAlive ? EcsGUI.EntityStatus.Alive : EcsGUI.EntityStatus.NotAlive, id, gen, world.id);
|
||||
EcsGUI.Layout.DrawRuntimeComponents(Target.Entity, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
11
src/Debug/Monitors/Editor/EntityMonitorEditor.cs.meta
Normal file
11
src/Debug/Monitors/Editor/EntityMonitorEditor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5457dbe0f53566419d37e0ee9d9c13f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
18
src/Debug/Monitors/Editor/WorldMonitorEditor.cs
Normal file
18
src/Debug/Monitors/Editor/WorldMonitorEditor.cs
Normal file
@ -0,0 +1,18 @@
|
||||
#if UNITY_EDITOR
|
||||
using DCFApixels.DragonECS.Unity.Internal;
|
||||
using UnityEditor;
|
||||
|
||||
namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
[CustomEditor(typeof(WorldMonitor))]
|
||||
internal class WorldMonitorEditor : Editor
|
||||
{
|
||||
private WorldMonitor Target => (WorldMonitor)target;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EcsGUI.Layout.DrawWorldBaseInfo(Target.World);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
11
src/Debug/Monitors/Editor/WorldMonitorEditor.cs.meta
Normal file
11
src/Debug/Monitors/Editor/WorldMonitorEditor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7aadf8c836c97694186e4b3aeb01fcce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,31 +1,19 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
namespace DCFApixels.DragonECS.Unity.Internal
|
||||
{
|
||||
[MetaTags(MetaTags.HIDDEN), MetaColor(MetaColor.Gray)]
|
||||
public class EntityMonitor : MonoBehaviour, IEcsProcess
|
||||
[MetaTags(MetaTags.HIDDEN)]
|
||||
[MetaColor(MetaColor.Gray)]
|
||||
public class EntityMonitor : MonoBehaviour
|
||||
{
|
||||
private entlong _entity;
|
||||
private int _entityID;
|
||||
private short _gen;
|
||||
private EcsWorld _world;
|
||||
|
||||
public EcsWorld World
|
||||
public entlong Entity
|
||||
{
|
||||
get { return _world; }
|
||||
get { return _entity; }
|
||||
}
|
||||
public int EntityID
|
||||
{
|
||||
get { return _entityID; }
|
||||
}
|
||||
|
||||
public EntityMonitor(entlong entity)
|
||||
public void Set(entlong entity)
|
||||
{
|
||||
_entity = entity;
|
||||
if (_entity.TryUnpack(out _entityID, out _gen, out _world))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,42 @@
|
||||
using UnityEngine;
|
||||
using DCFApixels.DragonECS.Unity.Editors;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
namespace DCFApixels.DragonECS.Unity.Internal
|
||||
{
|
||||
[MetaTags(MetaTags.HIDDEN), MetaColor(MetaColor.Gray)]
|
||||
public class PipelineMonitor : MonoBehaviour, IEcsProcess
|
||||
[MetaTags(MetaTags.HIDDEN)]
|
||||
[MetaColor(MetaColor.Gray)]
|
||||
public class PipelineMonitor : MonoBehaviour
|
||||
{
|
||||
private EcsPipeline _pipeline;
|
||||
public EcsPipeline Pipeline
|
||||
{
|
||||
get { return _pipeline; }
|
||||
}
|
||||
public void Set(EcsPipeline pipeline)
|
||||
{
|
||||
_pipeline = pipeline;
|
||||
}
|
||||
}
|
||||
|
||||
[MetaTags(MetaTags.HIDDEN)]
|
||||
[MetaColor(MetaColor.Gray)]
|
||||
public class PipelineMonitorSystem : IEcsInit, IEcsPipelineMember, IEcsDestroy
|
||||
{
|
||||
private PipelineMonitor _monitor;
|
||||
public EcsPipeline Pipeline { get; set; }
|
||||
|
||||
public void Init()
|
||||
{
|
||||
TypeMeta meta = typeof(EcsPipeline).ToMeta();
|
||||
_monitor = new GameObject($"{UnityEditorUtility.TransformToUpperName(meta.Name)}").AddComponent<PipelineMonitor>();
|
||||
UnityEngine.Object.DontDestroyOnLoad(_monitor);
|
||||
_monitor.Set(Pipeline);
|
||||
_monitor.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
UnityEngine.Object.Destroy(_monitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,108 @@
|
||||
using UnityEngine;
|
||||
using DCFApixels.DragonECS.Unity.Editors;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
namespace DCFApixels.DragonECS.Unity.Internal
|
||||
{
|
||||
[MetaTags(MetaTags.HIDDEN), MetaColor(MetaColor.Gray)]
|
||||
public class WorldMonitor : MonoBehaviour, IEcsProcess
|
||||
[MetaTags(MetaTags.HIDDEN)]
|
||||
[MetaColor(MetaColor.Gray)]
|
||||
public class WorldMonitor : MonoBehaviour
|
||||
{
|
||||
private EcsWorld _world;
|
||||
public EcsWorld World
|
||||
{
|
||||
get { return _world; }
|
||||
}
|
||||
public void Set(EcsWorld world)
|
||||
{
|
||||
_world = world;
|
||||
}
|
||||
}
|
||||
|
||||
[MetaTags(MetaTags.HIDDEN)]
|
||||
[MetaColor(MetaColor.Gray)]
|
||||
public class WorldMonitorSystem : IEcsInit, IEcsWorldEventListener, IEcsEntityEventListener
|
||||
{
|
||||
private EcsWorld _world;
|
||||
private WorldMonitor _monitor;
|
||||
private Transform _entityMonitorsPoolRoot;
|
||||
private EntityMonitor[] _entityMonitors;
|
||||
public EcsWorld World
|
||||
{
|
||||
get { return _world; }
|
||||
}
|
||||
public WorldMonitorSystem(EcsWorld world)
|
||||
{
|
||||
_world = world;
|
||||
_entityMonitors = new EntityMonitor[_world.Capacity];
|
||||
|
||||
_world.AddListener(entityEventListener: this);
|
||||
_world.AddListener(worldEventListener: this);
|
||||
}
|
||||
public void Init()
|
||||
{
|
||||
TypeMeta meta = _world.GetMeta();
|
||||
_monitor = new GameObject($"{UnityEditorUtility.TransformToUpperName(meta.Name)} ( {_world.id} )").AddComponent<WorldMonitor>();
|
||||
UnityEngine.Object.DontDestroyOnLoad(_monitor);
|
||||
_monitor.Set(_world);
|
||||
_monitor.gameObject.SetActive(false);
|
||||
|
||||
_entityMonitorsPoolRoot = new GameObject("__POOL").transform;
|
||||
_entityMonitorsPoolRoot.SetParent(_monitor.transform);
|
||||
|
||||
foreach (var e in _world.Entities)
|
||||
{
|
||||
InitNewEntity(e, false);
|
||||
}
|
||||
}
|
||||
|
||||
void IEcsWorldEventListener.OnWorldResize(int newSize)
|
||||
{
|
||||
Array.Resize(ref _entityMonitors, newSize);
|
||||
}
|
||||
void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||
void IEcsWorldEventListener.OnWorldDestroy()
|
||||
{
|
||||
UnityEngine.Object.Destroy(_monitor);
|
||||
UnityEngine.Object.Destroy(_entityMonitorsPoolRoot);
|
||||
_monitor = null;
|
||||
_entityMonitorsPoolRoot = null;
|
||||
}
|
||||
|
||||
void IEcsEntityEventListener.OnNewEntity(int entityID)
|
||||
{
|
||||
InitNewEntity(entityID, true);
|
||||
}
|
||||
|
||||
private void InitNewEntity(int entityID, bool check)
|
||||
{
|
||||
if(_monitor == null) { return; }
|
||||
ref var _entityMonitorRef = ref _entityMonitors[entityID];
|
||||
if (_entityMonitorRef == null)
|
||||
{
|
||||
_entityMonitorRef = new GameObject($"ENTITY ( {entityID} )").AddComponent<EntityMonitor>();
|
||||
}
|
||||
if (check && _entityMonitorRef.Entity.IsAlive)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
_entityMonitorRef.Set(_world.GetEntityLong(entityID));
|
||||
_entityMonitorRef.transform.SetParent(_monitor.transform);
|
||||
}
|
||||
|
||||
void IEcsEntityEventListener.OnDelEntity(int entityID)
|
||||
{
|
||||
if(_monitor == null) { return; }
|
||||
ref var _entityMonitorRef = ref _entityMonitors[entityID];
|
||||
if (_entityMonitorRef != null)
|
||||
{
|
||||
if (_entityMonitorRef.Entity.IsAlive)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
_entityMonitorRef.transform.SetParent(_entityMonitorsPoolRoot.transform);
|
||||
_entityMonitorRef.Set(_world.GetEntityLong(entityID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#if UNITY_EDITOR
|
||||
using Codice.Client.Common.GameUI;
|
||||
using DCFApixels.DragonECS.Unity.Internal;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
@ -23,6 +24,20 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
}
|
||||
}
|
||||
|
||||
public struct ContentColorScope : IDisposable
|
||||
{
|
||||
private readonly Color _oldColor;
|
||||
public ContentColorScope(Color color)
|
||||
{
|
||||
_oldColor = GUI.contentColor;
|
||||
GUI.contentColor = color;
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
GUI.contentColor = _oldColor;
|
||||
}
|
||||
}
|
||||
|
||||
internal readonly static Color GrayColor = new Color32(100, 100, 100, 255);
|
||||
internal readonly static Color GreenColor = new Color32(75, 255, 0, 255);
|
||||
internal readonly static Color RedColor = new Color32(255, 0, 75, 255);
|
||||
@ -274,6 +289,20 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
|
||||
public static class Layout
|
||||
{
|
||||
public static void DrawWorldBaseInfo(EcsWorld world)
|
||||
{
|
||||
bool isNull = world == null || world.id == 0;
|
||||
int entitesCount = isNull ? 0 : world.Count;
|
||||
int capacity = isNull ? 0 : world.Capacity;
|
||||
int leakedEntitesCount = isNull ? 0 : world.CountLeakedEntitesDebug();
|
||||
EditorGUILayout.IntField("Entities", entitesCount, EditorStyles.boldLabel);
|
||||
EditorGUILayout.IntField("Capacity", capacity, EditorStyles.boldLabel);
|
||||
Color color = leakedEntitesCount > 0 ? Color.yellow : GUI.contentColor;
|
||||
using (new ContentColorScope(color))
|
||||
{
|
||||
EditorGUILayout.IntField("Leaked Entites", leakedEntitesCount, EditorStyles.boldLabel);
|
||||
}
|
||||
}
|
||||
public static void EntityBar(EntityStatus status, int id, short gen, short world)
|
||||
{
|
||||
float width = EditorGUIUtility.currentViewWidth;
|
||||
|
@ -20,6 +20,43 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
private static GUIContent _singletonContent = null;
|
||||
|
||||
#region TransformFieldName
|
||||
public static string TransformToUpperName(string name)
|
||||
{
|
||||
if (name.Length <= 0)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
StringBuilder b = new StringBuilder();
|
||||
bool nextWorld = true;
|
||||
bool prewIsUpper = false;
|
||||
|
||||
|
||||
for (int i = 0; i < name.Length; i++)
|
||||
{
|
||||
char c = name[i];
|
||||
if (char.IsLetter(c) == false)
|
||||
{
|
||||
nextWorld = true;
|
||||
prewIsUpper = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isUpper = char.IsUpper(c);
|
||||
if (isUpper)
|
||||
{
|
||||
if (nextWorld == false && prewIsUpper == false)
|
||||
{
|
||||
b.Append('_');
|
||||
}
|
||||
}
|
||||
b.Append(char.ToUpper(c));
|
||||
nextWorld = false;
|
||||
prewIsUpper = isUpper;
|
||||
}
|
||||
|
||||
return b.ToString();
|
||||
}
|
||||
|
||||
public static string TransformFieldName(string name)
|
||||
{
|
||||
if (name.Length <= 0)
|
||||
|
Loading…
Reference in New Issue
Block a user