mirror of
https://github.com/DCFApixels/DragonECS-Unity.git
synced 2025-09-18 18:14:35 +08:00
update? add runtime component editing
This commit is contained in:
parent
ebfaf5bc98
commit
84445bfb7c
@ -91,7 +91,6 @@ namespace DCFApixels.DragonECS
|
||||
#if UNITY_EDITOR
|
||||
namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(EcsEntityConnect))]
|
||||
@ -127,7 +126,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
DrawTemplates();
|
||||
|
||||
DrawButtons();
|
||||
DrawComponents();
|
||||
DrawComponents(targets);
|
||||
}
|
||||
private void DrawTop()
|
||||
{
|
||||
@ -179,9 +178,16 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.TextField(idRect, "-");
|
||||
EditorGUI.TextField(genRect, "-");
|
||||
EditorGUI.TextField(worldRect, "-");
|
||||
//Color defColor = GUI.contentColor;
|
||||
//Color c = defColor;
|
||||
//c.a = 0.55f;
|
||||
//GUI.contentColor = c;
|
||||
GUI.enabled = false;
|
||||
EditorGUI.TextField(idRect, "Entity ID");
|
||||
EditorGUI.TextField(genRect, "Gen");
|
||||
EditorGUI.TextField(worldRect, "World ID");
|
||||
GUI.enabled = true;
|
||||
//GUI.contentColor = defColor;
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,13 +223,22 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawComponents()
|
||||
private void DrawComponents(EcsEntityConnect[] targets)
|
||||
{
|
||||
if (IsMultipleTargets)
|
||||
{
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
{
|
||||
if (targets[i].IsConected == true)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Multiple component editing is not available.", MessageType.Warning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Target.IsConected)
|
||||
{
|
||||
List<object> comps = new List<object>();
|
||||
Target.World.GetComponents(Target.Entity.ID, comps);
|
||||
GUILayout.TextArea(string.Join("\r\n", comps));
|
||||
EcsGUI.Layout.DrawComponents(Target.Entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
{
|
||||
public const string DEBUG_LAYER = nameof(DEBUG_LAYER);
|
||||
public EcsWorld[] _worlds;
|
||||
|
||||
public DebugModule(params EcsWorld[] worlds)
|
||||
{
|
||||
_worlds = worlds;
|
||||
@ -12,10 +13,10 @@
|
||||
void IEcsModule.Import(EcsPipeline.Builder b)
|
||||
{
|
||||
b.Layers.Insert(EcsConsts.POST_END_LAYER, DEBUG_LAYER);
|
||||
b.Add(new PipelineDebugSystem(), DEBUG_LAYER);
|
||||
//b.Add(new PipelineDebugSystem(), DEBUG_LAYER);
|
||||
foreach (var world in _worlds)
|
||||
{
|
||||
b.Add(new WorldDebugSystem(world), DEBUG_LAYER);
|
||||
//b.Add(new WorldDebugSystem(world), DEBUG_LAYER);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ using UnityEditor;
|
||||
|
||||
namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
[FilePath("DragonECS/DebugMonitorPrefs.prefs", FilePathAttribute.Location.ProjectFolder)]
|
||||
[FilePath(EcsConsts.FRAMEWORK_NAME + "/" + nameof(DebugMonitorPrefs) + ".prefs", FilePathAttribute.Location.ProjectFolder)]
|
||||
public class DebugMonitorPrefs : ScriptableSingleton<DebugMonitorPrefs>
|
||||
{
|
||||
private bool _isShowInterfaces = false;
|
||||
@ -34,7 +34,6 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
Save(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,190 +0,0 @@
|
||||
#if UNITY_EDITOR
|
||||
using DCFApixels.DragonECS.Unity.Internal;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
public static class EcsGUI
|
||||
{
|
||||
private static GUIStyle _grayStyle;
|
||||
private static GUIStyle _greenStyle;
|
||||
private static GUIStyle _redStyle;
|
||||
private static GUILayoutOption[] _defaultParams;
|
||||
|
||||
private static bool _isInit = false;
|
||||
private static void Init()
|
||||
{
|
||||
if (_isInit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_defaultParams = new GUILayoutOption[] { GUILayout.ExpandWidth(true) };
|
||||
_grayStyle = EcsEditor.GetStyle(new Color32(100, 100, 100, 100));
|
||||
_greenStyle = EcsEditor.GetStyle(new Color32(75, 255, 0, 100));
|
||||
_redStyle = EcsEditor.GetStyle(new Color32(255, 0, 75, 100));
|
||||
_isInit = true;
|
||||
}
|
||||
|
||||
|
||||
private const string CONNECTED = "Connected";
|
||||
private const string NOT_CONNECTED = "Not connected";
|
||||
private const string UNDETERMINED_CONNECTED = "---";
|
||||
public static void DrawConnectStatus(Rect position, bool status)
|
||||
{
|
||||
Init();
|
||||
if (status)
|
||||
{
|
||||
GUI.Box(position, CONNECTED, _greenStyle);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.Box(position, NOT_CONNECTED, _redStyle);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawUndeterminedConnectStatus(Rect position)
|
||||
{
|
||||
Init();
|
||||
GUI.Box(position, UNDETERMINED_CONNECTED, _grayStyle);
|
||||
}
|
||||
public static class Layout
|
||||
{
|
||||
public static void DrawConnectStatus(bool status, params GUILayoutOption[] options)
|
||||
{
|
||||
Init();
|
||||
if(options == null || options.Length <= 0)
|
||||
{
|
||||
options = _defaultParams;
|
||||
}
|
||||
if (status)
|
||||
{
|
||||
GUILayout.Box(CONNECTED, _greenStyle, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Box(NOT_CONNECTED, _redStyle, options);
|
||||
}
|
||||
}
|
||||
public static void DrawUndeterminedConnectStatus(params GUILayoutOption[] options)
|
||||
{
|
||||
Init();
|
||||
if (options == null || options.Length <= 0)
|
||||
{
|
||||
options = _defaultParams;
|
||||
}
|
||||
GUILayout.Box(UNDETERMINED_CONNECTED, _grayStyle, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
[InitializeOnLoad]
|
||||
public static class EcsEditor
|
||||
{
|
||||
static EcsEditor()
|
||||
{
|
||||
colorBoxeStyles = new SparseArray<GUIStyle>();
|
||||
}
|
||||
private static SparseArray<GUIStyle> colorBoxeStyles = new SparseArray<GUIStyle>();
|
||||
public static GUIStyle GetStyle(Color color, float alphaMultiplier)
|
||||
{
|
||||
color.a *= alphaMultiplier;
|
||||
return GetStyle(color);
|
||||
}
|
||||
public static GUIStyle GetStyle(Color32 color32)
|
||||
{
|
||||
int colorCode = new Color32Union(color32).colorCode;
|
||||
if (colorBoxeStyles.TryGetValue(colorCode, out GUIStyle style))
|
||||
{
|
||||
if (style == null || style.normal.background == null)
|
||||
{
|
||||
style = CreateStyle(color32, colorCode);
|
||||
colorBoxeStyles[colorCode] = style;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
style = CreateStyle(color32, colorCode);
|
||||
colorBoxeStyles.Add(colorCode, style);
|
||||
return style;
|
||||
}
|
||||
private static GUIStyle CreateStyle(Color32 color32, int colorCode)
|
||||
{
|
||||
GUIStyle result = new GUIStyle(GUI.skin.box);
|
||||
Color componentColor = color32;
|
||||
Texture2D texture2D = CreateTexture(2, 2, componentColor);
|
||||
result.hover.background = texture2D;
|
||||
result.focused.background = texture2D;
|
||||
result.active.background = texture2D;
|
||||
result.normal.background = texture2D;
|
||||
return result;
|
||||
}
|
||||
private static Texture2D CreateTexture(int width, int height, Color color)
|
||||
{
|
||||
var pixels = new Color[width * height];
|
||||
for (var i = 0; i < pixels.Length; ++i)
|
||||
pixels[i] = color;
|
||||
|
||||
var result = new Texture2D(width, height);
|
||||
result.SetPixels(pixels);
|
||||
result.Apply();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string GetGenericName(Type type) => EcsDebugUtility.GetGenericTypeName(type);
|
||||
|
||||
public static string GetName<T>() => GetName(typeof(T));
|
||||
public static string GetName(Type type) => EcsDebugUtility.GetName(type);
|
||||
|
||||
public static string GetDescription<T>() => GetDescription(typeof(T));
|
||||
public static string GetDescription(Type type) => EcsDebugUtility.GetDescription(type);
|
||||
|
||||
#region Utils
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
|
||||
private readonly ref struct Color32Union
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public readonly int colorCode;
|
||||
[FieldOffset(0)]
|
||||
public readonly byte r;
|
||||
[FieldOffset(1)]
|
||||
public readonly byte g;
|
||||
[FieldOffset(2)]
|
||||
public readonly byte b;
|
||||
[FieldOffset(3)]
|
||||
public readonly byte a;
|
||||
public Color32Union(byte r, byte g, byte b, byte a) : this()
|
||||
{
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
this.a = a;
|
||||
}
|
||||
public Color32Union(Color32 color) : this()
|
||||
{
|
||||
r = color.r;
|
||||
g = color.g;
|
||||
b = color.b;
|
||||
a = color.a;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class ReflectionExtensions
|
||||
{
|
||||
public static bool TryGetAttribute<T>(this MemberInfo self, out T attrbiute) where T : Attribute
|
||||
{
|
||||
attrbiute = self.GetCustomAttribute<T>();
|
||||
return attrbiute != null;
|
||||
}
|
||||
public static bool HasAttribute<T>(this MemberInfo self) where T : Attribute
|
||||
{
|
||||
return self.GetCustomAttribute<T>() != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a124aa9f464ff79439c89b52281215d3
|
||||
guid: 8b7186fd57cbf9c42b4759c49920a688
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
31
src/Debug/Monitors/EntityMonitor.cs
Normal file
31
src/Debug/Monitors/EntityMonitor.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[MetaTags(MetaTags.HIDDEN), MetaColor(MetaColor.Gray)]
|
||||
public class EntityMonitor : MonoBehaviour, IEcsProcess
|
||||
{
|
||||
private entlong _entity;
|
||||
private int _entityID;
|
||||
private short _gen;
|
||||
private EcsWorld _world;
|
||||
|
||||
public EcsWorld World
|
||||
{
|
||||
get { return _world; }
|
||||
}
|
||||
public int EntityID
|
||||
{
|
||||
get { return _entityID; }
|
||||
}
|
||||
|
||||
public EntityMonitor(entlong entity)
|
||||
{
|
||||
_entity = entity;
|
||||
if (_entity.TryUnpack(out _entityID, out _gen, out _world))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1caa902906afea3409fc63ed94cbbc11
|
||||
guid: b3c51f9f4aa13e74fbb4339f8c1746d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
9
src/Debug/Monitors/PipelineMonitor.cs
Normal file
9
src/Debug/Monitors/PipelineMonitor.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[MetaTags(MetaTags.HIDDEN), MetaColor(MetaColor.Gray)]
|
||||
public class PipelineMonitor : MonoBehaviour, IEcsProcess
|
||||
{
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d36835beef2392f40854af962ff47472
|
||||
guid: 03154a226ad86e24ebfa4faf43da8310
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
9
src/Debug/Monitors/WorldMonitor.cs
Normal file
9
src/Debug/Monitors/WorldMonitor.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[MetaTags(MetaTags.HIDDEN), MetaColor(MetaColor.Gray)]
|
||||
public class WorldMonitor : MonoBehaviour, IEcsProcess
|
||||
{
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b7b4bd406553d64589aa4e085d4ff28
|
||||
guid: 3d65916dbb4c8f74cb5239c5bbf7ba31
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@ -1,17 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace DCFApixels.DragonECS.Unity.Debug
|
||||
{
|
||||
public class DebugMonitorBase : MonoBehaviour
|
||||
{
|
||||
internal string monitorName;
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
DontDestroyOnLoad(this.gameObject);
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,341 +0,0 @@
|
||||
using DCFApixels.DragonECS.Unity.Debug;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[MetaTags(MetaTags.HIDDEN), MetaColor(MetaColor.Gray)]
|
||||
public class PipelineDebugSystem : IEcsPreInit, IEcsPipelineMember
|
||||
{
|
||||
public EcsPipeline Pipeline { get; set; }
|
||||
private string _monitorName;
|
||||
public PipelineDebugSystem(string monitorName = "Pipeline")
|
||||
{
|
||||
_monitorName = monitorName;
|
||||
}
|
||||
|
||||
void IEcsPreInit.PreInit()
|
||||
{
|
||||
PipelineDebugMonitor monitor = new GameObject(EcsConsts.DEBUG_PREFIX + _monitorName).AddComponent<PipelineDebugMonitor>();
|
||||
monitor.source = this;
|
||||
monitor.pipeline = Pipeline;
|
||||
monitor.monitorName = _monitorName;
|
||||
|
||||
PipelineProcessesDebugMonitor processesMonitor = new GameObject(EcsConsts.DEBUG_PREFIX + "Processes Matrix").AddComponent<PipelineProcessesDebugMonitor>();
|
||||
processesMonitor.transform.parent = monitor.transform;
|
||||
processesMonitor.source = this;
|
||||
processesMonitor.pipeline = Pipeline;
|
||||
processesMonitor.monitorName = "Processes Matrix";
|
||||
|
||||
//foreach (var item in pipeline.AllSystems) //Вырезано пока не сделаю TODO в SystemDebugMonitor
|
||||
//{
|
||||
// DebugNameAttribute debugName = item.GetType().GetCustomAttribute<DebugNameAttribute>();
|
||||
// string name = debugName == null ? item.GetType().Name : debugName.name;
|
||||
// SystemDebugMonitor.CreateMonitor(monitor.transform, item, name);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
public class PipelineDebugMonitor : DebugMonitorBase
|
||||
{
|
||||
internal PipelineDebugSystem source;
|
||||
internal EcsPipeline pipeline;
|
||||
}
|
||||
|
||||
public class PipelineProcessesDebugMonitor : DebugMonitorBase
|
||||
{
|
||||
internal PipelineDebugSystem source;
|
||||
internal EcsPipeline pipeline;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
using DCFApixels.DragonECS.RunnersCore;
|
||||
using DCFApixels.DragonECS.Unity.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(PipelineDebugMonitor))]
|
||||
public class PipelineDebugMonitorEditor : 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 PipelineDebugMonitor Target => (PipelineDebugMonitor)target;
|
||||
|
||||
|
||||
private GUIStyle systemsListStyle;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
systemsListStyle = new GUIStyle(EditorStyles.miniLabel);
|
||||
systemsListStyle.wordWrap = true;
|
||||
|
||||
if (Target.source == null)
|
||||
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);
|
||||
|
||||
DebugMonitorPrefs.instance.IsShowInterfaces = EditorGUILayout.Toggle("Show Interfaces", DebugMonitorPrefs.instance.IsShowInterfaces);
|
||||
DebugMonitorPrefs.instance.IsShowHidden = EditorGUILayout.Toggle("Show Hidden", DebugMonitorPrefs.instance.IsShowHidden);
|
||||
|
||||
GUILayout.BeginVertical();
|
||||
foreach (var item in Target.pipeline.AllSystems)
|
||||
{
|
||||
DrawSystem(item);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
|
||||
GUILayout.Label("[Runners]", _headerStyle);
|
||||
|
||||
GUILayout.BeginVertical(EcsEditor.GetStyle(Color.black, 0.2f));
|
||||
foreach (var item in Target.pipeline.AllRunners)
|
||||
{
|
||||
DrawRunner(item.Value);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void DrawSystem(IEcsProcess system)
|
||||
{
|
||||
if (system is SystemsLayerMarkerSystem markerSystem)
|
||||
{
|
||||
GUILayout.EndVertical();
|
||||
GUILayout.BeginVertical(EcsEditor.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();
|
||||
|
||||
if (CheckIsHidden(type))
|
||||
return;
|
||||
|
||||
string name = EcsEditor.GetGenericName(type);
|
||||
//Color color = (GetAttribute<DebugColorAttribute>(type) ?? _fakeDebugColorAttribute).GetUnityColor();
|
||||
Color color = EcsDebugUtility.GetColor(type).ToUnityColor();
|
||||
|
||||
GUILayout.BeginVertical(EcsEditor.GetStyle(color, 0.2f));
|
||||
if (DebugMonitorPrefs.instance.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();
|
||||
if (CheckIsHidden(type))
|
||||
return;
|
||||
|
||||
//Color color = (GetAttribute<DebugColorAttribute>(type) ?? _fakeDebugColorAttribute).GetUnityColor();
|
||||
Color color = EcsDebugUtility.GetColor(type).ToUnityColor();
|
||||
|
||||
GUILayout.BeginVertical(EcsEditor.GetStyle(color, 0.2f));
|
||||
GUILayout.Label(EcsEditor.GetGenericName(type), EditorStyles.boldLabel);
|
||||
GUILayout.Label(string.Join(", ", runner.ProcessRaw.Cast<object>().Select(o => o.GetType().Name)), systemsListStyle);
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private TAttribute GetAttribute<TAttribute>(Type target) where TAttribute : Attribute
|
||||
{
|
||||
var result = target.GetCustomAttributes(_debugColorAttributeType, false);
|
||||
if (result.Length > 0)
|
||||
return (TAttribute)result[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool CheckIsHidden(Type target)
|
||||
{
|
||||
if (DebugMonitorPrefs.instance.IsShowHidden)
|
||||
return false;
|
||||
return target.GetCustomAttribute<DebugHideAttribute>() != null;
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(PipelineProcessesDebugMonitor))]
|
||||
public class PipelineProcessesDebugMonitorEditor : Editor
|
||||
{
|
||||
private bool _isInit = false;
|
||||
private List<ProcessData> _processesList = new List<ProcessData>();
|
||||
private Dictionary<Type, int> _processeIndexes = new Dictionary<Type, int>();
|
||||
|
||||
private PipelineProcessesDebugMonitor Target => (PipelineProcessesDebugMonitor)target;
|
||||
private Type systemInterfaceType = typeof(IEcsProcess);
|
||||
|
||||
private IEcsProcess[] _systems;
|
||||
private void Init()
|
||||
{
|
||||
if (_isInit)
|
||||
return;
|
||||
bool showHidden = DebugMonitorPrefs.instance.IsShowHidden;
|
||||
_processesList.Clear();
|
||||
_processeIndexes.Clear();
|
||||
if (showHidden)
|
||||
_systems = Target.pipeline.AllSystems.Where(o => o is SystemsLayerMarkerSystem == false).ToArray();
|
||||
else
|
||||
_systems = Target.pipeline.AllSystems.Where(o => o.GetType().GetCustomAttribute<DebugHideAttribute>() == null).ToArray();
|
||||
|
||||
int i = 0;
|
||||
foreach (var system in _systems)
|
||||
{
|
||||
foreach (var intr in system.GetType().GetInterfaces())
|
||||
{
|
||||
if (systemInterfaceType.IsAssignableFrom(intr) && systemInterfaceType != intr && (showHidden || intr.GetCustomAttribute<DebugHideAttribute>() == null))
|
||||
{
|
||||
ProcessData data;
|
||||
if (!_processeIndexes.TryGetValue(intr, out int index))
|
||||
{
|
||||
index = _processesList.Count;
|
||||
_processeIndexes.Add(intr, index);
|
||||
|
||||
data = new ProcessData();
|
||||
_processesList.Add(data);
|
||||
|
||||
data.name = EcsEditor.GetGenericName(intr);
|
||||
data.interfaceType = intr;
|
||||
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();
|
||||
DebugMonitorPrefs.instance.IsShowHidden = EditorGUILayout.Toggle("Show Hidden", DebugMonitorPrefs.instance.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<string> systeNames = new List<string>();
|
||||
|
||||
var blackStyle = EcsEditor.GetStyle(Color.black, 0.04f);
|
||||
var whiteStyle = EcsEditor.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);
|
||||
//GUIContent label = new GUIContent(_processesList[i].name, "." + _processesList[i].name);
|
||||
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;
|
||||
}
|
||||
|
||||
//GUIUtility.RotateAroundPivot(-90, _nameCellSize);
|
||||
rect = new Rect();
|
||||
rect.y = _nameCellSize.y;
|
||||
rect.width = _nameCellSize.x;
|
||||
rect.height = _cellsize.x;
|
||||
for (int i = 0; i < _systems.Length; i++)
|
||||
{
|
||||
string name = EcsEditor.GetGenericName(_systems[i].GetType());
|
||||
systeNames.Add(name);
|
||||
|
||||
lineRect = rect;
|
||||
lineRect.width = rectView.width;
|
||||
GUI.Label(lineRect, "", i % 2 == 1 ? whiteStyle : blackStyle);
|
||||
|
||||
// GUIContent label = new GUIContent(name, i + " " + name);
|
||||
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.Label(rect, lable, flag ? whiteStyle : blackStyle);
|
||||
// GUI.Label(rect, label, EditorStyles.helpBox);
|
||||
}
|
||||
}
|
||||
|
||||
GUI.EndScrollView();
|
||||
}
|
||||
|
||||
private class ProcessData
|
||||
{
|
||||
public Type interfaceType;
|
||||
public string name;
|
||||
public BitMask systemsBitMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,177 +0,0 @@
|
||||
using DCFApixels.DragonECS.Unity.Debug;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[MetaTags(MetaTags.HIDDEN), MetaColor(MetaColor.Gray)]
|
||||
public class WorldDebugSystem : IEcsRun
|
||||
{
|
||||
private string _monitorName;
|
||||
private EcsWorld _ecsWorld;
|
||||
|
||||
public WorldDebugSystem(EcsWorld ecsWorld, string monitorName = null)
|
||||
{
|
||||
_monitorName = monitorName;
|
||||
if (string.IsNullOrEmpty(_monitorName)) _monitorName = ecsWorld.GetType().Name;
|
||||
_ecsWorld = ecsWorld;
|
||||
WorldDebugMonitor monitor = new GameObject(EcsConsts.DEBUG_PREFIX + _monitorName).AddComponent<WorldDebugMonitor>();
|
||||
WorldPoolsMonitor poolsmonitor = new GameObject(EcsConsts.DEBUG_PREFIX + "Pools").AddComponent<WorldPoolsMonitor>();
|
||||
poolsmonitor.transform.SetParent(monitor.transform);
|
||||
|
||||
monitor.source = this;
|
||||
monitor.world = _ecsWorld;
|
||||
monitor.monitorName = _monitorName;
|
||||
|
||||
poolsmonitor.source = this;
|
||||
poolsmonitor.world = _ecsWorld;
|
||||
poolsmonitor.monitorName = "pools";
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class WorldDebugMonitor : DebugMonitorBase
|
||||
{
|
||||
internal WorldDebugSystem source;
|
||||
internal EcsWorld world;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace Editors
|
||||
{
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(WorldDebugMonitor))]
|
||||
public class WorldDebugMonitorEditor : Editor
|
||||
{
|
||||
private WorldDebugMonitor Target => (WorldDebugMonitor)target;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
GUILayout.Label($"Size: {Target.world.Capacity}");
|
||||
GUILayout.Label($"Total entities: {Target.world.Count}");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
public class WorldPoolsMonitor : DebugMonitorBase
|
||||
{
|
||||
internal WorldDebugSystem source;
|
||||
internal EcsWorld world;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(WorldPoolsMonitor))]
|
||||
public class WorldPoolsMonitorEditor : Editor
|
||||
{
|
||||
private static Vector2 _poolBlockMinSize = new Vector2(80, 160);
|
||||
private static Vector2 _poolProgressBasrSize = _poolBlockMinSize * new Vector2(1f, 0.8f);
|
||||
|
||||
private WorldPoolsMonitor Target => (WorldPoolsMonitor)target;
|
||||
|
||||
private Vector2 _scroll;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
_scroll = GUILayout.BeginScrollView(_scroll, GUILayout.Height(800f));
|
||||
|
||||
var pools = Target.world.AllPools.ToArray().Where(o => !o.IsNullOrDummy()).OfType<IEcsPool>();
|
||||
|
||||
GUILayout.Label("", GUILayout.ExpandWidth(true));
|
||||
|
||||
float width = GUILayoutUtility.GetLastRect().width;
|
||||
|
||||
Vector3 newPoolBlockSize = _poolBlockMinSize;
|
||||
int widthCount = Mathf.Max(1, Mathf.Min((Mathf.FloorToInt(width / _poolBlockMinSize.x)), pools.Count()));
|
||||
newPoolBlockSize.x = width / widthCount;
|
||||
|
||||
int x = -1, y = 0;
|
||||
foreach (var pool in pools)
|
||||
{
|
||||
if (++x >= widthCount)
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
|
||||
DrawPoolBlock(pool, new Rect(newPoolBlockSize.x * x, newPoolBlockSize.y * y, newPoolBlockSize.x, newPoolBlockSize.y));
|
||||
}
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
/// Äåôîëòíûé öâåò äëÿ ïóëà: new Color(0.3f, 1f, 0f, 1f);
|
||||
|
||||
private void DrawPoolBlock(IEcsPool pool, Rect position)
|
||||
{
|
||||
var meta = pool.GetMeta();
|
||||
|
||||
int count = pool.Count;
|
||||
int capacity = pool.Capacity < 0 ? count : pool.Capacity;
|
||||
|
||||
Color defaultContentColor = GUI.contentColor;
|
||||
GUI.contentColor = Color.black * 0.925f;
|
||||
|
||||
position = AddMargin(position, 1f, 1f);
|
||||
|
||||
EditorGUI.DrawRect(position, Color.black * 0.16f);
|
||||
|
||||
Rect progressBar = new Rect(Vector2.zero, _poolProgressBasrSize);
|
||||
progressBar.width = position.width;
|
||||
progressBar.center = position.center - Vector2.up * _poolBlockMinSize.y * 0.09f;
|
||||
|
||||
Color mainColor = meta.Color.ToUnityColor();
|
||||
Color backgroundColor = mainColor * 0.3f + Color.white * 0.2f;
|
||||
|
||||
EditorGUI.DrawRect(progressBar, backgroundColor);
|
||||
|
||||
progressBar.yMin = progressBar.yMax - ((float)count / capacity) * progressBar.height;
|
||||
|
||||
GUIStyle textStyle0 = new GUIStyle(EditorStyles.miniBoldLabel);
|
||||
textStyle0.alignment = TextAnchor.MiddleCenter;
|
||||
|
||||
Color foregroundColor = mainColor;
|
||||
EditorGUI.DrawRect(progressBar, foregroundColor);
|
||||
GUI.Label(progressBar, count.ToString(), textStyle0);
|
||||
|
||||
GUIStyle textStyle1 = new GUIStyle(EditorStyles.miniBoldLabel);
|
||||
textStyle1.alignment = TextAnchor.UpperCenter;
|
||||
GUI.Label(AddMargin(position, 3f, 3f), "Total\r\n" + capacity, textStyle1);
|
||||
|
||||
GUI.contentColor = defaultContentColor;
|
||||
GUIStyle textStyle2 = new GUIStyle(EditorStyles.miniBoldLabel);
|
||||
textStyle2.wordWrap = true;
|
||||
textStyle2.alignment = TextAnchor.LowerCenter;
|
||||
string name = EcsEditor.GetGenericName(pool.ComponentType);
|
||||
GUIContent label = new GUIContent(name, $"{name} e:{count}");
|
||||
GUI.Label(AddMargin(position, -10f, 3f), label, textStyle2);
|
||||
|
||||
}
|
||||
|
||||
private Rect AddMargin(Rect rect, Vector2 value)
|
||||
{
|
||||
return AddMargin(rect, value.x, value.y);
|
||||
}
|
||||
private Rect AddMargin(Rect rect, float x, float y)
|
||||
{
|
||||
rect.yMax -= y;
|
||||
rect.yMin += y;
|
||||
rect.xMax -= x;
|
||||
rect.xMin += x;
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
8
src/Editor.meta
Normal file
8
src/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ff185425dcbca44f820bfc6c564d1d2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
365
src/Editor/EditorUtility.cs
Normal file
365
src/Editor/EditorUtility.cs
Normal file
@ -0,0 +1,365 @@
|
||||
#if UNITY_EDITOR
|
||||
using DCFApixels.DragonECS.Unity.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
internal class WrapperBase<TSelf> : ScriptableObject
|
||||
where TSelf : WrapperBase<TSelf>
|
||||
{
|
||||
private SerializedObject _so;
|
||||
private SerializedProperty _property;
|
||||
|
||||
private bool _isReleased = false;
|
||||
private static Stack<TSelf> _wrappers = new Stack<TSelf>();
|
||||
|
||||
public SerializedObject SO
|
||||
{
|
||||
get { return _so; }
|
||||
}
|
||||
public SerializedProperty Property
|
||||
{
|
||||
get { return _property; }
|
||||
}
|
||||
|
||||
public static TSelf Take()
|
||||
{
|
||||
TSelf result;
|
||||
if (_wrappers.Count <= 0)
|
||||
{
|
||||
result = CreateInstance<TSelf>();
|
||||
result._so = new SerializedObject(result);
|
||||
result._property = result._so.FindProperty("data");
|
||||
}
|
||||
else
|
||||
{
|
||||
result = _wrappers.Pop();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static void Release(TSelf wrapper)
|
||||
{
|
||||
if (wrapper._isReleased)
|
||||
{
|
||||
return;
|
||||
}
|
||||
wrapper._isReleased = true;
|
||||
_wrappers.Push(wrapper);
|
||||
}
|
||||
}
|
||||
internal class RefEditorWrapper : WrapperBase<RefEditorWrapper>
|
||||
{
|
||||
[SerializeReference]
|
||||
public object data;
|
||||
}
|
||||
internal class UnityObjEditorWrapper : WrapperBase<UnityObjEditorWrapper>
|
||||
{
|
||||
[SerializeField]
|
||||
public UnityEngine.Object data;
|
||||
}
|
||||
|
||||
public static class EcsGUI
|
||||
{
|
||||
private static Color _grayColor = new Color32(100, 100, 100, 100);
|
||||
private static Color _greenColor = new Color32(75, 255, 0, 100);
|
||||
private static Color _redColor = new Color32(255, 0, 75, 100);
|
||||
|
||||
private static GUIStyle _grayStyle;
|
||||
private static GUIStyle _greenStyle;
|
||||
private static GUIStyle _redStyle;
|
||||
private static GUILayoutOption[] _defaultParams;
|
||||
|
||||
private static bool _isInit = false;
|
||||
|
||||
private static void Init()
|
||||
{
|
||||
if (_isInit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_defaultParams = new GUILayoutOption[] { GUILayout.ExpandWidth(true) };
|
||||
_grayStyle = EcsEditor.GetStyle(_grayColor);
|
||||
_greenStyle = EcsEditor.GetStyle(_greenColor);
|
||||
_redStyle = EcsEditor.GetStyle(_redColor);
|
||||
_isInit = true;
|
||||
}
|
||||
|
||||
|
||||
private const string CONNECTED = "Connected";
|
||||
private const string NOT_CONNECTED = "Not connected";
|
||||
private const string UNDETERMINED_CONNECTED = "---";
|
||||
public static void DrawConnectStatus(Rect position, bool status)
|
||||
{
|
||||
Init();
|
||||
if (status)
|
||||
{
|
||||
GUI.Box(position, CONNECTED, _greenStyle);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.Box(position, NOT_CONNECTED, _redStyle);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawUndeterminedConnectStatus(Rect position)
|
||||
{
|
||||
Init();
|
||||
GUI.Box(position, UNDETERMINED_CONNECTED, _grayStyle);
|
||||
}
|
||||
|
||||
public static class Layout
|
||||
{
|
||||
public static void DrawConnectStatus(bool status, params GUILayoutOption[] options)
|
||||
{
|
||||
Init();
|
||||
if (options == null || options.Length <= 0)
|
||||
{
|
||||
options = _defaultParams;
|
||||
}
|
||||
GUILayout.Box("", options);
|
||||
Rect lastRect = GUILayoutUtility.GetLastRect();
|
||||
if (status)
|
||||
{
|
||||
Color color = _greenColor;
|
||||
color.a = 0.6f;
|
||||
EditorGUI.DrawRect(lastRect, color);
|
||||
GUI.Box(lastRect, CONNECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
Color color = _redColor;
|
||||
color.a = 0.6f;
|
||||
EditorGUI.DrawRect(lastRect, color);
|
||||
GUI.Box(lastRect, NOT_CONNECTED);
|
||||
}
|
||||
}
|
||||
public static void DrawUndeterminedConnectStatus(params GUILayoutOption[] options)
|
||||
{
|
||||
Init();
|
||||
if (options == null || options.Length <= 0)
|
||||
{
|
||||
options = _defaultParams;
|
||||
}
|
||||
GUILayout.Box(UNDETERMINED_CONNECTED, _grayStyle, options);
|
||||
}
|
||||
public static void DrawComponents(entlong entity)
|
||||
{
|
||||
if (entity.TryUnpack(out int entityID, out EcsWorld world))
|
||||
{
|
||||
DrawComponents(entityID, world);
|
||||
}
|
||||
}
|
||||
public static void DrawComponents(int entityID, EcsWorld world)
|
||||
{
|
||||
var componentTypeIDs = world.GetComponentTypeIDs(entityID);
|
||||
|
||||
foreach (var componentTypeID in componentTypeIDs)
|
||||
{
|
||||
var pool = world.GetPool(componentTypeID);
|
||||
{
|
||||
DrawComponent(entityID, world, pool);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
private static void DrawComponent(int entityID, EcsWorld world, IEcsPool pool)
|
||||
{
|
||||
object data = pool.GetRaw(entityID);
|
||||
var meta = data.GetMeta();
|
||||
|
||||
Color panelColor = meta.Color.ToUnityColor();
|
||||
GUILayout.BeginVertical(EcsEditor.GetStyle(panelColor, 0.22f));
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
bool changed = DrawData(pool.ComponentType, data, out object resultData);
|
||||
|
||||
if (changed)
|
||||
{
|
||||
pool.SetRaw(entityID, resultData);
|
||||
}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
|
||||
Rect lineRect = GUILayoutUtility.GetLastRect();
|
||||
lineRect.y = lineRect.yMax;
|
||||
lineRect.height = 3f;
|
||||
Color rectColor = panelColor;
|
||||
rectColor.a = 0.34f;
|
||||
EditorGUI.DrawRect(lineRect, rectColor);
|
||||
|
||||
GUILayout.Space(2f);
|
||||
}
|
||||
|
||||
private static bool DrawData(Type fieldType, object data, out object outData)
|
||||
{
|
||||
var meta = data.GetMeta();
|
||||
GUIContent label = new GUIContent(meta.Name);
|
||||
|
||||
Type type = data.GetType();
|
||||
var uobj = data as UnityEngine.Object;
|
||||
if (uobj == false && type.IsGenericType)
|
||||
{
|
||||
bool result = false;
|
||||
foreach (var field in type.GetFields(fieldFlags))
|
||||
{
|
||||
if (DrawData(field.FieldType, field.GetValue(data), out object fieldData))
|
||||
{
|
||||
field.SetValue(data, fieldData);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
outData = data;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uobj == null)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
var w = RefEditorWrapper.Take();
|
||||
w.data = data;
|
||||
w.SO.Update();
|
||||
|
||||
EditorGUILayout.PropertyField(w.Property, true);
|
||||
RefEditorWrapper.Release(w);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
w.SO.ApplyModifiedProperties();
|
||||
outData = w.data;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
var w = UnityObjEditorWrapper.Take();
|
||||
w.data = uobj;
|
||||
w.SO.Update();
|
||||
|
||||
EditorGUILayout.PropertyField(w.Property, true);
|
||||
UnityObjEditorWrapper.Release(w);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
w.SO.ApplyModifiedProperties();
|
||||
outData = uobj;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
outData = data;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[InitializeOnLoad]
|
||||
public static class EcsEditor
|
||||
{
|
||||
static EcsEditor()
|
||||
{
|
||||
colorBoxeStyles = new SparseArray<GUIStyle>();
|
||||
}
|
||||
private static SparseArray<GUIStyle> colorBoxeStyles = new SparseArray<GUIStyle>();
|
||||
public static GUIStyle GetStyle(Color color, float alphaMultiplier)
|
||||
{
|
||||
color.a *= alphaMultiplier;
|
||||
return GetStyle(color);
|
||||
}
|
||||
public static GUIStyle GetStyle(Color32 color32)
|
||||
{
|
||||
int colorCode = new Color32Union(color32).colorCode;
|
||||
if (colorBoxeStyles.TryGetValue(colorCode, out GUIStyle style))
|
||||
{
|
||||
if (style == null || style.normal.background == null)
|
||||
{
|
||||
style = CreateStyle(color32, colorCode);
|
||||
colorBoxeStyles[colorCode] = style;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
style = CreateStyle(color32, colorCode);
|
||||
colorBoxeStyles.Add(colorCode, style);
|
||||
return style;
|
||||
}
|
||||
private static GUIStyle CreateStyle(Color32 color32, int colorCode)
|
||||
{
|
||||
GUIStyle result = new GUIStyle(GUI.skin.box);
|
||||
Color componentColor = color32;
|
||||
Texture2D texture2D = CreateTexture(2, 2, componentColor);
|
||||
result.hover.background = texture2D;
|
||||
result.focused.background = texture2D;
|
||||
result.active.background = texture2D;
|
||||
result.normal.background = texture2D;
|
||||
return result;
|
||||
}
|
||||
private static Texture2D CreateTexture(int width, int height, Color color)
|
||||
{
|
||||
var pixels = new Color[width * height];
|
||||
for (var i = 0; i < pixels.Length; ++i)
|
||||
pixels[i] = color;
|
||||
|
||||
var result = new Texture2D(width, height);
|
||||
result.SetPixels(pixels);
|
||||
result.Apply();
|
||||
return result;
|
||||
}
|
||||
|
||||
#region Utils
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
|
||||
private readonly ref struct Color32Union
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public readonly int colorCode;
|
||||
[FieldOffset(0)]
|
||||
public readonly byte r;
|
||||
[FieldOffset(1)]
|
||||
public readonly byte g;
|
||||
[FieldOffset(2)]
|
||||
public readonly byte b;
|
||||
[FieldOffset(3)]
|
||||
public readonly byte a;
|
||||
public Color32Union(byte r, byte g, byte b, byte a) : this()
|
||||
{
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
this.a = a;
|
||||
}
|
||||
public Color32Union(Color32 color) : this()
|
||||
{
|
||||
r = color.r;
|
||||
g = color.g;
|
||||
b = color.b;
|
||||
a = color.a;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class ReflectionExtensions
|
||||
{
|
||||
public static bool TryGetAttribute<T>(this MemberInfo self, out T attrbiute) where T : Attribute
|
||||
{
|
||||
attrbiute = self.GetCustomAttribute<T>();
|
||||
return attrbiute != null;
|
||||
}
|
||||
public static bool HasAttribute<T>(this MemberInfo self) where T : Attribute
|
||||
{
|
||||
return self.GetCustomAttribute<T>() != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
25
src/Editor/FieldDrawerInfo.cs
Normal file
25
src/Editor/FieldDrawerInfo.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace DCFApixels.DragonECS.Unity.Editors
|
||||
{
|
||||
public struct FieldDrawerInfo
|
||||
{
|
||||
private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
public Type type;
|
||||
public object data;
|
||||
public FieldInfo[] fields;
|
||||
public FieldDrawerInfo(object data)
|
||||
{
|
||||
type = data.GetType();
|
||||
this.data = data;
|
||||
fields = type.GetFields(fieldFlags);
|
||||
}
|
||||
public void Set(object data)
|
||||
{
|
||||
type = data.GetType();
|
||||
this.data = data;
|
||||
fields = type.GetFields(fieldFlags);
|
||||
}
|
||||
}
|
||||
}
|
11
src/Editor/FieldDrawerInfo.cs.meta
Normal file
11
src/Editor/FieldDrawerInfo.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9047f4ae8f7a24c4d8b053ffeeb259f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -192,7 +192,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
|
||||
GUILayout.Label("", GUILayout.Width(removeButtonRect.width));
|
||||
|
||||
if (GUI.Button(removeButtonRect, "x", removeButtonStyle))
|
||||
{
|
||||
OnRemoveComponentAt(index);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(description))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user