2024-03-03 19:59:39 +08:00
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
using DCFApixels.DragonECS.Unity.Internal;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Runtime.InteropServices;
|
2024-03-03 22:46:26 +08:00
|
|
|
|
using System.Text;
|
2024-03-03 19:59:39 +08:00
|
|
|
|
using UnityEditor;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
namespace DCFApixels.DragonECS.Unity.Editors
|
|
|
|
|
{
|
2024-03-03 22:46:26 +08:00
|
|
|
|
internal static class EcsUnityEditorUtility
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-03 22:46:26 +08:00
|
|
|
|
public static string TransformFieldName(string name)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-03 22:46:26 +08:00
|
|
|
|
if (name.Length <= 0)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-03 22:46:26 +08:00
|
|
|
|
return name;
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
2024-03-03 22:46:26 +08:00
|
|
|
|
StringBuilder b = new StringBuilder();
|
|
|
|
|
bool nextWorld = true;
|
|
|
|
|
bool prewIsUpper = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < name.Length; i++)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-03 22:46:26 +08:00
|
|
|
|
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(' ');
|
2024-03-04 03:00:45 +08:00
|
|
|
|
nextWorld = true;
|
2024-03-03 22:46:26 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-04 03:00:45 +08:00
|
|
|
|
|
|
|
|
|
if (nextWorld)
|
|
|
|
|
{
|
|
|
|
|
b.Append(char.ToUpper(c));
|
|
|
|
|
}
|
2024-03-03 22:46:26 +08:00
|
|
|
|
else
|
|
|
|
|
{
|
2024-03-04 03:00:45 +08:00
|
|
|
|
b.Append(c);
|
2024-03-03 22:46:26 +08:00
|
|
|
|
}
|
2024-03-04 03:00:45 +08:00
|
|
|
|
nextWorld = false;
|
2024-03-03 22:46:26 +08:00
|
|
|
|
prewIsUpper = isUpper;
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
2024-03-03 22:46:26 +08:00
|
|
|
|
|
|
|
|
|
return b.ToString();
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-03 22:46:26 +08:00
|
|
|
|
|
2024-03-03 19:59:39 +08:00
|
|
|
|
|
2024-03-04 07:38:38 +08:00
|
|
|
|
internal static class EcsGUI
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-04 07:38:38 +08:00
|
|
|
|
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);
|
2024-03-03 19:59:39 +08:00
|
|
|
|
|
2024-03-04 08:01:49 +08:00
|
|
|
|
//private static GUILayoutOption[] _defaultParams;
|
|
|
|
|
//private static bool _isInit = false;
|
|
|
|
|
//private static void Init()
|
2024-03-04 07:38:38 +08:00
|
|
|
|
//{
|
2024-03-04 08:01:49 +08:00
|
|
|
|
// if (_isInit)
|
2024-03-04 07:38:38 +08:00
|
|
|
|
// {
|
2024-03-04 08:01:49 +08:00
|
|
|
|
// return;
|
2024-03-04 07:38:38 +08:00
|
|
|
|
// }
|
2024-03-04 08:01:49 +08:00
|
|
|
|
// _defaultParams = new GUILayoutOption[] { GUILayout.ExpandWidth(true) };
|
|
|
|
|
// _isInit = true;
|
2024-03-04 07:38:38 +08:00
|
|
|
|
//}
|
2024-03-03 19:59:39 +08:00
|
|
|
|
|
|
|
|
|
public static class Layout
|
|
|
|
|
{
|
2024-03-04 08:01:49 +08:00
|
|
|
|
private static bool IsShowHidden
|
|
|
|
|
{
|
|
|
|
|
get { return DebugMonitorPrefs.instance.IsShowHidden; }
|
|
|
|
|
set { DebugMonitorPrefs.instance.IsShowHidden = value; }
|
|
|
|
|
}
|
2024-03-04 08:21:01 +08:00
|
|
|
|
private static bool IsShowRuntimeComponents
|
|
|
|
|
{
|
|
|
|
|
get { return DebugMonitorPrefs.instance.IsShowRuntimeComponents; }
|
|
|
|
|
set { DebugMonitorPrefs.instance.IsShowRuntimeComponents = value; }
|
|
|
|
|
}
|
|
|
|
|
public static void DrawRuntimeComponents(entlong entity)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
|
|
|
|
if (entity.TryUnpack(out int entityID, out EcsWorld world))
|
|
|
|
|
{
|
2024-03-04 08:21:01 +08:00
|
|
|
|
DrawRuntimeComponents(entityID, world);
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-04 08:21:01 +08:00
|
|
|
|
public static void DrawRuntimeComponents(int entityID, EcsWorld world)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
|
|
|
|
var componentTypeIDs = world.GetComponentTypeIDs(entityID);
|
2024-03-04 08:01:49 +08:00
|
|
|
|
|
2024-03-04 07:38:38 +08:00
|
|
|
|
GUILayout.BeginVertical(EcsEditor.GetStyle(Color.black, 0.2f));
|
2024-03-04 08:01:49 +08:00
|
|
|
|
|
2024-03-04 08:21:01 +08:00
|
|
|
|
IsShowRuntimeComponents = EditorGUILayout.Foldout(IsShowRuntimeComponents, "RUNTIME COMPONENTS");
|
|
|
|
|
if (IsShowRuntimeComponents)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-04 08:21:01 +08:00
|
|
|
|
//TODO галочкаслишком чернаяя, невидно
|
|
|
|
|
IsShowHidden = EditorGUILayout.Toggle("Show Hidden", IsShowHiddens);
|
|
|
|
|
foreach (var componentTypeID in componentTypeIDs)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-04 08:21:01 +08:00
|
|
|
|
var pool = world.GetPool(componentTypeID);
|
|
|
|
|
{
|
|
|
|
|
DrawRuntimeComponent(entityID, pool);
|
|
|
|
|
}
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-04 07:38:38 +08:00
|
|
|
|
GUILayout.EndVertical();
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
|
|
|
|
private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
2024-03-04 08:21:01 +08:00
|
|
|
|
private static void DrawRuntimeComponent(int entityID, IEcsPool pool)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-04 08:01:49 +08:00
|
|
|
|
var meta = pool.ComponentType.ToMeta();
|
|
|
|
|
if (meta.IsHidden == false || IsShowHidden)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-04 08:01:49 +08:00
|
|
|
|
object data = pool.GetRaw(entityID);
|
|
|
|
|
Color panelColor = meta.Color.ToUnityColor();
|
|
|
|
|
GUILayout.BeginVertical(EcsEditor.GetStyle(panelColor, 0.22f));
|
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
|
|
|
|
|
|
Type componentType = pool.ComponentType;
|
|
|
|
|
ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType);
|
2024-03-04 08:21:01 +08:00
|
|
|
|
bool changed = DrawRuntimeData(componentType, new GUIContent(meta.Name), expandMatrix, data, out object resultData);
|
2024-03-04 08:01:49 +08:00
|
|
|
|
if (changed)
|
|
|
|
|
{
|
|
|
|
|
pool.SetRaw(entityID, resultData);
|
|
|
|
|
}
|
2024-03-03 19:59:39 +08:00
|
|
|
|
|
2024-03-04 08:01:49 +08:00
|
|
|
|
GUILayout.EndVertical();
|
|
|
|
|
GUILayout.Space(2f);
|
|
|
|
|
}
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-04 08:21:01 +08:00
|
|
|
|
private static bool DrawRuntimeData(Type fieldType, GUIContent label, ExpandMatrix expandMatrix, object data, out object outData)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
|
|
|
|
Type type = data.GetType();
|
2024-03-04 07:38:38 +08:00
|
|
|
|
UnityEngine.Object uobj = data as UnityEngine.Object;
|
2024-03-04 03:00:45 +08:00
|
|
|
|
ref bool isExpanded = ref expandMatrix.Down();
|
2024-03-04 07:38:38 +08:00
|
|
|
|
bool changed = false;
|
|
|
|
|
outData = data;
|
2024-03-03 22:46:26 +08:00
|
|
|
|
|
2024-03-04 07:38:38 +08:00
|
|
|
|
if (uobj == null && (type.IsGenericType || !type.IsSerializable))
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-04 03:00:45 +08:00
|
|
|
|
isExpanded = EditorGUILayout.Foldout(isExpanded, label);
|
|
|
|
|
|
|
|
|
|
if (isExpanded)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-03 22:46:26 +08:00
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
|
foreach (var field in type.GetFields(fieldFlags))
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-03 22:46:26 +08:00
|
|
|
|
GUIContent subLabel = new GUIContent(EcsUnityEditorUtility.TransformFieldName(field.Name));
|
2024-03-04 08:21:01 +08:00
|
|
|
|
if (DrawRuntimeData(field.FieldType, subLabel, expandMatrix, field.GetValue(data), out object fieldData))
|
2024-03-03 22:46:26 +08:00
|
|
|
|
{
|
|
|
|
|
field.SetValue(data, fieldData);
|
2024-03-04 07:38:38 +08:00
|
|
|
|
|
|
|
|
|
outData = fieldData;
|
|
|
|
|
changed = true;
|
2024-03-03 22:46:26 +08:00
|
|
|
|
}
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
2024-03-03 22:46:26 +08:00
|
|
|
|
EditorGUI.indentLevel--;
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-03-03 22:46:26 +08:00
|
|
|
|
EditorGUI.BeginChangeCheck();
|
2024-03-04 03:00:45 +08:00
|
|
|
|
WrapperBase w = uobj == null ? RefEditorWrapper.Take(data) : UnityObjEditorWrapper.Take(uobj);
|
2024-03-03 19:59:39 +08:00
|
|
|
|
|
2024-03-04 03:00:45 +08:00
|
|
|
|
w.IsExpanded = isExpanded;
|
2024-03-03 22:46:26 +08:00
|
|
|
|
EditorGUILayout.PropertyField(w.Property, label, true);
|
2024-03-04 03:00:45 +08:00
|
|
|
|
isExpanded = w.IsExpanded;
|
|
|
|
|
|
2024-03-03 22:46:26 +08:00
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
|
|
|
{
|
|
|
|
|
w.SO.ApplyModifiedProperties();
|
|
|
|
|
outData = w.Data;
|
2024-03-04 07:38:38 +08:00
|
|
|
|
changed = true;
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-04 07:38:38 +08:00
|
|
|
|
|
|
|
|
|
expandMatrix.Up();
|
|
|
|
|
return changed;
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[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
|