diff --git a/src/Debug/Monitors/Editor/PipelineMonitorEditor.cs b/src/Debug/Monitors/Editor/PipelineMonitorEditor.cs new file mode 100644 index 0000000..ccc2bcc --- /dev/null +++ b/src/Debug/Monitors/Editor/PipelineMonitorEditor.cs @@ -0,0 +1,152 @@ +#if UNITY_EDITOR +using DCFApixels.DragonECS.RunnersCore; +using DCFApixels.DragonECS.Unity.Internal; +using System; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace DCFApixels.DragonECS.Unity.Editors +{ + [CustomEditor(typeof(PipelineMonitor))] + internal class PipelineMonitorEditor : Editor + { + private MetaColorAttribute _fakeDebugColorAttribute = new MetaColorAttribute(190, 190, 190); + private Type _debugColorAttributeType = typeof(MetaColorAttribute); + private GUIStyle _headerStyle; + private GUIStyle _interfacesStyle; + private Color _interfaceColor = new Color(0.96f, 1f, 0.16f); + + private GUIStyle systemsListStyle; + + private PipelineMonitor Target => (PipelineMonitor)target; + private bool IsShowInterfaces + { + get { return DebugMonitorPrefs.instance.IsShowInterfaces; } + set { DebugMonitorPrefs.instance.IsShowInterfaces = value; } + } + private bool IsShowHidden + { + get { return DebugMonitorPrefs.instance.IsShowHidden; } + set { DebugMonitorPrefs.instance.IsShowHidden = value; } + } + + public override void OnInspectorGUI() + { + systemsListStyle = new GUIStyle(EditorStyles.miniLabel); + systemsListStyle.wordWrap = true; + + if (Target.Pipeline == null || Target.Pipeline.IsDestoryed) + { + return; + } + if (_headerStyle == null) + { + _headerStyle = new GUIStyle(EditorStyles.boldLabel); + _interfacesStyle = new GUIStyle(EditorStyles.miniLabel); + _interfacesStyle.hover.textColor = _interfaceColor; + _interfacesStyle.focused.textColor = _interfaceColor; + _interfacesStyle.active.textColor = _interfaceColor; + _interfacesStyle.normal.textColor = _interfaceColor; + _interfacesStyle.wordWrap = true; + _headerStyle.fontSize = 28; + } + + GUILayout.Label("[Systems]", _headerStyle); + + IsShowInterfaces = EditorGUILayout.Toggle("Show Interfaces", IsShowInterfaces); + IsShowHidden = EditorGUILayout.Toggle("Show Hidden", IsShowHidden); + + GUILayout.BeginVertical(); + foreach (var item in Target.Pipeline.AllSystems) + { + DrawSystem(item); + } + GUILayout.EndVertical(); + + + GUILayout.Label("[Runners]", _headerStyle); + + GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f)); + foreach (var item in Target.Pipeline.AllRunners) + { + if (item.Key.IsInterface == false) + { + DrawRunner(item.Value); + } + } + GUILayout.EndVertical(); + } + + private void DrawSystem(IEcsProcess system) + { + if (system is SystemsLayerMarkerSystem markerSystem) + { + GUILayout.EndVertical(); + GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f)); + + GUILayout.BeginHorizontal(); + GUILayout.Label("<"); + GUILayout.Label($"{markerSystem.name}", EditorStyles.boldLabel); + GUILayout.Label(">", GUILayout.ExpandWidth(false)); + GUILayout.EndHorizontal(); + return; + } + + Type type = system.GetType(); + TypeMeta meta = type.ToMeta(); + + if (CheckIsHidden(meta)) + { + return; + } + + string name = meta.Name; + Color color = meta.Color.ToUnityColor(); + + GUILayout.BeginVertical(UnityEditorUtility.GetStyle(color, 0.2f)); + if (IsShowInterfaces) + { + GUILayout.Label(string.Join(", ", type.GetInterfaces().Select(o => o.Name)), _interfacesStyle); + } + GUILayout.Label(name, EditorStyles.boldLabel); + GUILayout.EndVertical(); + } + + private void DrawRunner(IEcsRunner runner) + { + Type type = runner.GetType(); + TypeMeta meta = type.ToMeta(); + + if (CheckIsHidden(meta)) + { + return; + } + + //Color color = (GetAttribute(type) ?? _fakeDebugColorAttribute).GetUnityColor(); + Color color = meta.Color.ToUnityColor(); + + GUILayout.BeginVertical(UnityEditorUtility.GetStyle(color, 0.2f)); + GUILayout.Label(meta.Name, EditorStyles.boldLabel); + GUILayout.Label(string.Join(", ", runner.ProcessRaw.Cast().Select(o => o.GetType().Name)), systemsListStyle); + GUILayout.EndVertical(); + } + + private TAttribute GetAttribute(Type target) where TAttribute : Attribute + { + var result = target.GetCustomAttributes(_debugColorAttributeType, false); + if (result.Length > 0) + return (TAttribute)result[0]; + return null; + } + + private bool CheckIsHidden(TypeMeta meta) + { + if (IsShowHidden) + return false; + + return meta.IsHidden; + } + } +} +#endif \ No newline at end of file diff --git a/src/Debug/Monitors/Editor/PipelineMonitorEditor.cs.meta b/src/Debug/Monitors/Editor/PipelineMonitorEditor.cs.meta new file mode 100644 index 0000000..99bc7f1 --- /dev/null +++ b/src/Debug/Monitors/Editor/PipelineMonitorEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 406298e83eb7a0b41b525c7e810c0c6f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Debug/Monitors/Editor/PipelineProcessesMonitorEditor.cs b/src/Debug/Monitors/Editor/PipelineProcessesMonitorEditor.cs new file mode 100644 index 0000000..a7606aa --- /dev/null +++ b/src/Debug/Monitors/Editor/PipelineProcessesMonitorEditor.cs @@ -0,0 +1,185 @@ +#if UNITY_EDITOR +using DCFApixels.DragonECS.Unity.Internal; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace DCFApixels.DragonECS.Unity.Editors +{ + [CustomEditor(typeof(PipelineProcessMonitor))] + internal class PipelineProcessesMonitorEditor : Editor + { + private bool _isInit = false; + private List _processesList = new List(); + private Dictionary _processeIndexes = new Dictionary(); + private Type systemInterfaceType = typeof(IEcsProcess); + private IEcsProcess[] _systems; + + private PipelineProcessMonitor Target => (PipelineProcessMonitor)target; + private bool IsShowInterfaces + { + get { return DebugMonitorPrefs.instance.IsShowInterfaces; } + set { DebugMonitorPrefs.instance.IsShowInterfaces = value; } + } + private bool IsShowHidden + { + get { return DebugMonitorPrefs.instance.IsShowHidden; } + set { DebugMonitorPrefs.instance.IsShowHidden = value; } + } + + private void Init() + { + if (_isInit) + { + return; + } + + _processesList.Clear(); + _processeIndexes.Clear(); + if (IsShowHidden) + { + _systems = Target.Pipeline.AllSystems.Where(o => o is SystemsLayerMarkerSystem == false).ToArray(); + } + else + { + _systems = Target.Pipeline.AllSystems.Where(o => o.GetMeta().IsHidden == false).ToArray(); + } + + int i = 0; + foreach (var system in _systems) + { + foreach (var interfaceType in system.GetType().GetInterfaces()) + { + TypeMeta meta = interfaceType.ToMeta(); + if (systemInterfaceType.IsAssignableFrom(interfaceType) && systemInterfaceType != interfaceType && (IsShowHidden || meta.IsHidden == false)) + { + ProcessData data; + if (!_processeIndexes.TryGetValue(interfaceType, out int index)) + { + index = _processesList.Count; + _processeIndexes.Add(interfaceType, index); + + data = new ProcessData(); + _processesList.Add(data); + + data.name = meta.Name; + data.interfaceType = interfaceType; + data.systemsBitMask = new BitMask(_systems.Length); + } + data = _processesList[index]; + data.systemsBitMask[i] = true; + } + } + i++; + } + + _isInit = true; + } + private Vector2 _position; + private Vector2 _cellsize = new Vector2(EditorGUIUtility.singleLineHeight, EditorGUIUtility.singleLineHeight); + private Vector2 _nameCellSize = new Vector2(200f, 200f); + + public override void OnInspectorGUI() + { + EditorGUI.BeginChangeCheck(); + IsShowHidden = EditorGUILayout.Toggle("Show Hidden", IsShowHidden); + if (EditorGUI.EndChangeCheck()) + { + _isInit = false; + } + + Init(); + + Rect rect; + Rect lineRect; + GUILayout.Label("", GUILayout.ExpandWidth(true), GUILayout.Height(400f)); + rect = GUILayoutUtility.GetLastRect(); + + rect.height = 400f; + + + Rect rectView = new Rect(0f, 0f, _nameCellSize.x + _cellsize.x * _processesList.Count, _nameCellSize.y + _cellsize.y * _systems.Length); + _position = GUI.BeginScrollView(rect, _position, rectView, true, true); + + List systeNames = new List(); + + var blackStyle = UnityEditorUtility.GetStyle(Color.black, 0.04f); + var whiteStyle = UnityEditorUtility.GetStyle(Color.white, 0.04f); + GUIContent label = new GUIContent(); + + + Vector2 pivod = _nameCellSize; + rect = new Rect(); + rect.y = _nameCellSize.y; + rect.width = _nameCellSize.x; + rect.height = _cellsize.x; + rect.y -= _cellsize.y; + for (int i = 0; i < _processesList.Count; i++) + { + lineRect = rect; + lineRect.y = 0f; + lineRect.x = _nameCellSize.x + _cellsize.x * i; + lineRect.width = _cellsize.x; + lineRect.height = rectView.height; + GUI.Label(lineRect, "", i % 2 == 1 ? whiteStyle : blackStyle); + + GUIUtility.RotateAroundPivot(90, pivod); + label.text = _processesList[i].name; + label.tooltip = "." + _processesList[i].name; + GUI.Label(rect, label, EditorStyles.miniBoldLabel); + GUIUtility.RotateAroundPivot(-90, pivod); + + pivod.x += _cellsize.x; + rect.x += _cellsize.x; + } + + rect = new Rect(); + rect.y = _nameCellSize.y; + rect.width = _nameCellSize.x; + rect.height = _cellsize.x; + for (int i = 0; i < _systems.Length; i++) + { + TypeMeta meta = _systems[i].GetMeta(); + string name = meta.Name; + systeNames.Add(name); + + lineRect = rect; + lineRect.width = rectView.width; + GUI.Label(lineRect, "", i % 2 == 1 ? whiteStyle : blackStyle); + + label.text = name; + label.tooltip = i + " " + name; + GUI.Label(rect, label, EditorStyles.miniBoldLabel); + rect.y += _cellsize.y; + } + + for (int x = 0; x < _processesList.Count; x++) + { + var process = _processesList[x]; + for (int y = 0; y < _systems.Length; y++) + { + string systemName = systeNames[x]; + rect = new Rect(x * _cellsize.x + _nameCellSize.x, y * _cellsize.y + _nameCellSize.y, _cellsize.x, _cellsize.y); + bool flag = process.systemsBitMask[y]; + string labeltext = flag ? "^" : " "; + label.text = labeltext; + label.tooltip = $"{process.name}-{systemName}"; + GUI.Label(rect, label); + } + } + + GUI.EndScrollView(); + } + + private class ProcessData + { + public Type interfaceType; + public string name; + public BitMask systemsBitMask; + } + } +} +#endif \ No newline at end of file diff --git a/src/Debug/Monitors/Editor/PipelineProcessesMonitorEditor.cs.meta b/src/Debug/Monitors/Editor/PipelineProcessesMonitorEditor.cs.meta new file mode 100644 index 0000000..8451072 --- /dev/null +++ b/src/Debug/Monitors/Editor/PipelineProcessesMonitorEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d3cd5a052acb5c4469a9802390bb532a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Debug/Monitors/EntityMonitor.cs b/src/Debug/Monitors/EntityMonitor.cs index 40ac57a..c3f5cbc 100644 --- a/src/Debug/Monitors/EntityMonitor.cs +++ b/src/Debug/Monitors/EntityMonitor.cs @@ -4,7 +4,7 @@ namespace DCFApixels.DragonECS.Unity.Internal { [MetaTags(MetaTags.HIDDEN)] [MetaColor(MetaColor.Gray)] - public class EntityMonitor : MonoBehaviour + internal class EntityMonitor : MonoBehaviour { private entlong _entity; public entlong Entity diff --git a/src/Debug/Monitors/PipelineMonitor.cs b/src/Debug/Monitors/PipelineMonitor.cs index c2f1c5d..b5b1774 100644 --- a/src/Debug/Monitors/PipelineMonitor.cs +++ b/src/Debug/Monitors/PipelineMonitor.cs @@ -5,7 +5,7 @@ namespace DCFApixels.DragonECS.Unity.Internal { [MetaTags(MetaTags.HIDDEN)] [MetaColor(MetaColor.Gray)] - public class PipelineMonitor : MonoBehaviour + internal class PipelineMonitor : MonoBehaviour { private EcsPipeline _pipeline; public EcsPipeline Pipeline @@ -20,9 +20,10 @@ namespace DCFApixels.DragonECS.Unity.Internal [MetaTags(MetaTags.HIDDEN)] [MetaColor(MetaColor.Gray)] - public class PipelineMonitorSystem : IEcsInit, IEcsPipelineMember, IEcsDestroy + internal class PipelineMonitorSystem : IEcsInit, IEcsPipelineMember, IEcsDestroy { private PipelineMonitor _monitor; + private PipelineProcessMonitor _processesMonitor; public EcsPipeline Pipeline { get; set; } public void Init() @@ -32,6 +33,11 @@ namespace DCFApixels.DragonECS.Unity.Internal UnityEngine.Object.DontDestroyOnLoad(_monitor); _monitor.Set(Pipeline); _monitor.gameObject.SetActive(false); + + _processesMonitor = new GameObject($"PROCESS_MATRIX").AddComponent(); + _processesMonitor.transform.SetParent(_monitor.transform); + _processesMonitor.Set(Pipeline); + _processesMonitor.gameObject.SetActive(false); } public void Destroy() diff --git a/src/Debug/Monitors/PipelineProcessMonitor.cs b/src/Debug/Monitors/PipelineProcessMonitor.cs new file mode 100644 index 0000000..3401463 --- /dev/null +++ b/src/Debug/Monitors/PipelineProcessMonitor.cs @@ -0,0 +1,19 @@ +using UnityEngine; + +namespace DCFApixels.DragonECS.Unity.Editors +{ + [MetaTags(MetaTags.HIDDEN)] + [MetaColor(MetaColor.Gray)] + internal class PipelineProcessMonitor : MonoBehaviour + { + private EcsPipeline _pipeline; + public EcsPipeline Pipeline + { + get { return _pipeline; } + } + public void Set(EcsPipeline pipeline) + { + _pipeline = pipeline; + } + } +} diff --git a/src/Debug/Monitors/PipelineProcessMonitor.cs.meta b/src/Debug/Monitors/PipelineProcessMonitor.cs.meta new file mode 100644 index 0000000..628f9be --- /dev/null +++ b/src/Debug/Monitors/PipelineProcessMonitor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2e20707e619a5b742aeb26e3eff3a9c4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Debug/Monitors/WorldMonitor.cs b/src/Debug/Monitors/WorldMonitor.cs index 5236296..0c5eca2 100644 --- a/src/Debug/Monitors/WorldMonitor.cs +++ b/src/Debug/Monitors/WorldMonitor.cs @@ -6,7 +6,7 @@ namespace DCFApixels.DragonECS.Unity.Internal { [MetaTags(MetaTags.HIDDEN)] [MetaColor(MetaColor.Gray)] - public class WorldMonitor : MonoBehaviour + internal class WorldMonitor : MonoBehaviour { private EcsWorld _world; public EcsWorld World @@ -21,7 +21,7 @@ namespace DCFApixels.DragonECS.Unity.Internal [MetaTags(MetaTags.HIDDEN)] [MetaColor(MetaColor.Gray)] - public class WorldMonitorSystem : IEcsInit, IEcsWorldEventListener, IEcsEntityEventListener + internal class WorldMonitorSystem : IEcsInit, IEcsWorldEventListener, IEcsEntityEventListener { private EcsWorld _world; private WorldMonitor _monitor; @@ -76,7 +76,7 @@ namespace DCFApixels.DragonECS.Unity.Internal private void InitNewEntity(int entityID, bool check) { - if(_monitor == null) { return; } + if (_monitor == null) { return; } ref var _entityMonitorRef = ref _entityMonitors[entityID]; if (_entityMonitorRef == null) { @@ -92,7 +92,7 @@ namespace DCFApixels.DragonECS.Unity.Internal void IEcsEntityEventListener.OnDelEntity(int entityID) { - if(_monitor == null) { return; } + if (_monitor == null) { return; } ref var _entityMonitorRef = ref _entityMonitors[entityID]; if (_entityMonitorRef != null) { diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs index 9c1b9d1..fbe62af 100644 --- a/src/Internal/Editor/EcsGUI.cs +++ b/src/Internal/Editor/EcsGUI.cs @@ -1,5 +1,4 @@ #if UNITY_EDITOR -using Codice.Client.Common.GameUI; using DCFApixels.DragonECS.Unity.Internal; using System; using System.Reflection;