simple editor optimization

This commit is contained in:
Mikhail 2024-11-08 15:21:13 +08:00
parent 9a78a38c72
commit 5bc8e9f0a5
4 changed files with 144 additions and 38 deletions

View File

@ -12,6 +12,7 @@ namespace DCFApixels.DragonECS
[MetaDescription(EcsConsts.AUTHOR, "This component is automatically added if an entity is connected to one of the EcsEntityConnect. It also contains a reference to the connected EcsEntityConnect.")] [MetaDescription(EcsConsts.AUTHOR, "This component is automatically added if an entity is connected to one of the EcsEntityConnect. It also contains a reference to the connected EcsEntityConnect.")]
[MetaID("14AC6B239201C6A60337AF3384D237E7")] [MetaID("14AC6B239201C6A60337AF3384D237E7")]
[MetaTags(MetaTags.ENGINE_MEMBER)] [MetaTags(MetaTags.ENGINE_MEMBER)]
[System.Serializable]
public readonly struct GameObjectConnect : IEcsComponent, IEcsComponentLifecycle<GameObjectConnect> public readonly struct GameObjectConnect : IEcsComponent, IEcsComponentLifecycle<GameObjectConnect>
{ {
public readonly EcsEntityConnect Connect; public readonly EcsEntityConnect Connect;

View File

@ -2,10 +2,14 @@
using DCFApixels.DragonECS.Unity.Internal; using DCFApixels.DragonECS.Unity.Internal;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
//using System.Drawing;
using System.Reflection; using System.Reflection;
using Unity.Collections.LowLevel.Unsafe;
using UnityEditor; using UnityEditor;
using UnityEditor.IMGUI.Controls; using UnityEditor.IMGUI.Controls;
using UnityEngine; using UnityEngine;
using Color = UnityEngine.Color;
using UnityComponent = UnityEngine.Component; using UnityComponent = UnityEngine.Component;
using UnityObject = UnityEngine.Object; using UnityObject = UnityEngine.Object;
@ -1146,8 +1150,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
private static List<IEcsPool> _componentPoolsBuffer; private static List<IEcsPool> _componentPoolsBuffer;
public static void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout = true) public static void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout = true)
{ {
using (BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f)))
using (EcsGUI.Layout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f)))
{ {
if (isWithFoldout) if (isWithFoldout)
{ {
@ -1170,10 +1173,10 @@ namespace DCFApixels.DragonECS.Unity.Editors
} }
world.GetComponentPoolsFor(entityID, _componentPoolsBuffer); world.GetComponentPoolsFor(entityID, _componentPoolsBuffer);
int i = 0; int i = 0;
int iMax = _componentPoolsBuffer.Count; //int iMax = _componentPoolsBuffer.Count;
foreach (var componentPool in _componentPoolsBuffer) foreach (var componentPool in _componentPoolsBuffer)
{ {
DrawRuntimeComponent(entityID, componentPool, iMax, i++); DrawRuntimeComponent(entityID, componentPool, 9, i++);
} }
} }
} }
@ -1183,9 +1186,10 @@ namespace DCFApixels.DragonECS.Unity.Editors
var meta = pool.ComponentType.ToMeta(); var meta = pool.ComponentType.ToMeta();
if (meta.IsHidden == false || IsShowHidden) if (meta.IsHidden == false || IsShowHidden)
{ {
Type componentType = pool.ComponentType;
object data = pool.GetRaw(entityID); object data = pool.GetRaw(entityID);
Type componentType = pool.ComponentType;
ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType); ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType);
float padding = EditorGUIUtility.standardVerticalSpacing; float padding = EditorGUIUtility.standardVerticalSpacing;
@ -1201,8 +1205,8 @@ namespace DCFApixels.DragonECS.Unity.Editors
isExpanded = !isExpanded; isExpanded = !isExpanded;
} }
Color panelColor = SelectPanelColor(meta, index, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE).SetAlpha(EscEditorConsts.COMPONENT_DRAWER_ALPHA); Color panelColor = SelectPanelColor(meta, index, total);
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor)); GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA));
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
//Close button //Close button
@ -1225,8 +1229,8 @@ namespace DCFApixels.DragonECS.Unity.Editors
DescriptionIcon(optionButton, meta.Description.Text); DescriptionIcon(optionButton, meta.Description.Text);
} }
RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name);
if (DrawRuntimeData(componentType, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData)) if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData))
{ {
pool.SetRaw(entityID, resultData); pool.SetRaw(entityID, resultData);
} }
@ -1234,24 +1238,98 @@ namespace DCFApixels.DragonECS.Unity.Editors
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
} }
[InitializeOnLoadMethod]
private static void ResetRuntimeComponentReflectionCache()
{
_runtimeComponentReflectionCaches.Clear();
}
private class RuntimeComponentReflectionCache
{
public readonly Type Type;
private static bool DrawRuntimeData(Type fieldType, GUIContent label, ExpandMatrix expandMatrix, object data, out object outData) public readonly bool IsUnityObjectType;
public readonly bool IsUnitySerializable;
public readonly bool IsUnmanaged;
public readonly FieldInfoData[] Fields;
public readonly RefEditorWrapper Wrapper;
public RuntimeComponentReflectionCache(Type type)
{
Type = type;
IsUnmanaged = UnsafeUtility.IsUnmanaged(type);
IsUnityObjectType = typeof(UnityObject).IsAssignableFrom(type);
IsUnitySerializable = IsUnityObjectType || (!type.IsGenericType && type.IsSerializable);
Wrapper = RefEditorWrapper.Take();
if (type == typeof(void)) { return; }
if (IsUnitySerializable == false)
{
var fs = type.GetFields(fieldFlags);
Fields = new FieldInfoData[fs.Length];
for (int i = 0; i < fs.Length; i++)
{
var f = fs[i];
Fields[i] = new FieldInfoData(f);
}
}
}
public readonly struct FieldInfoData
{
public readonly FieldInfo FieldInfo;
public readonly Type FieldType;
public readonly string UnityFormatName;
public readonly bool IsUnityObjectField;
public FieldInfoData(FieldInfo fieldInfo)
{
FieldInfo = fieldInfo;
FieldType = fieldInfo.FieldType;
IsUnityObjectField = typeof(UnityObject).IsAssignableFrom(fieldInfo.FieldType);
UnityFormatName = UnityEditorUtility.TransformFieldName(fieldInfo.Name);
}
public FieldInfoData(FieldInfo fieldInfo, Type fieldType, string unityFormatName)
{
FieldInfo = fieldInfo;
FieldType = fieldType;
UnityFormatName = unityFormatName;
IsUnityObjectField = typeof(UnityObject).IsAssignableFrom(fieldType);
}
}
}
private static Dictionary<Type, RuntimeComponentReflectionCache> _runtimeComponentReflectionCaches = new Dictionary<Type, RuntimeComponentReflectionCache>();
private static RuntimeComponentReflectionCache GetRuntimeComponentReflectionCache(Type type)
{
if (_runtimeComponentReflectionCaches.TryGetValue(type, out RuntimeComponentReflectionCache result) == false)
{
result = new RuntimeComponentReflectionCache(type);
_runtimeComponentReflectionCaches.Add(type, result);
}
return result;
}
private static bool DrawRuntimeData(ref RuntimeComponentReflectionCache.FieldInfoData fieldInfoData, GUIContent label, ExpandMatrix expandMatrix, object data, out object outData)
{ {
outData = data; outData = data;
Type type = data == null ? typeof(void) : data.GetType(); Type type = data == null ? typeof(void) : data.GetType();
bool isUnityObject = typeof(UnityObject).IsAssignableFrom(fieldType); RuntimeComponentReflectionCache cache = GetRuntimeComponentReflectionCache(type);
if (isUnityObject == false && data == null) bool isUnityObjectField = fieldInfoData.IsUnityObjectField;
if (isUnityObjectField == false && data == null)
{ {
EditorGUILayout.TextField(label, "Null"); EditorGUILayout.TextField(label, "Null");
return false; return false;
} }
bool isUnityObjectType = cache.IsUnityObjectType;
ref bool isExpanded = ref expandMatrix.Down(); ref bool isExpanded = ref expandMatrix.Down();
bool changed = false; bool changed = false;
outData = data;
if (isUnityObject == false && (type.IsGenericType || !type.IsSerializable))
if (cache.IsUnitySerializable == false)
{ {
isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(isExpanded, label, EditorStyles.foldout); isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(isExpanded, label, EditorStyles.foldout);
EditorGUILayout.EndFoldoutHeaderGroup(); EditorGUILayout.EndFoldoutHeaderGroup();
@ -1260,12 +1338,12 @@ namespace DCFApixels.DragonECS.Unity.Editors
{ {
using (UpIndentLevel()) using (UpIndentLevel())
{ {
foreach (var field in type.GetFields(fieldFlags)) for (int j = 0, jMax = cache.Fields.Length; j < jMax; j++)
{ {
GUIContent subLabel = UnityEditorUtility.GetLabel(UnityEditorUtility.TransformFieldName(field.Name)); var field = cache.Fields[j];
if (DrawRuntimeData(field.FieldType, subLabel, expandMatrix, field.GetValue(data), out object fieldData)) if (DrawRuntimeData(ref field, UnityEditorUtility.GetLabel(field.UnityFormatName), expandMatrix, field.FieldInfo.GetValue(data), out object fieldData))
{ {
field.SetValue(data, fieldData); field.FieldInfo.SetValue(data, fieldData);
outData = data; outData = data;
changed = true; changed = true;
} }
@ -1275,10 +1353,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
} }
else else
{ {
if (isUnityObject) Type fieldType = fieldInfoData.FieldType;
if (isUnityObjectType || isUnityObjectField)
{ {
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
var uobj = (UnityObject)data; var uobj = UnsafeUtility.As<object, UnityObject>(ref data);
bool isComponent = typeof(UnityComponent).IsAssignableFrom(fieldType); bool isComponent = typeof(UnityComponent).IsAssignableFrom(fieldType);
if (isComponent) if (isComponent)
@ -1289,13 +1368,14 @@ namespace DCFApixels.DragonECS.Unity.Editors
{ {
uobj = EditorGUILayout.ObjectField(label, uobj, fieldType, true); uobj = EditorGUILayout.ObjectField(label, uobj, fieldType, true);
} }
if (isComponent && uobj is GameObject go)
{
uobj = go.GetComponent(fieldType);
}
if (EditorGUI.EndChangeCheck()) if (EditorGUI.EndChangeCheck())
{ {
if (isComponent && uobj is GameObject go)
{
uobj = go.GetComponent(fieldType);
}
outData = uobj; outData = uobj;
changed = true; changed = true;
} }
@ -1303,19 +1383,34 @@ namespace DCFApixels.DragonECS.Unity.Editors
else else
{ {
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
WrapperBase w = RefEditorWrapper.Take(data); //WrapperBase wrapper = RefEditorWrapper.Take(data);
w.IsExpanded = isExpanded; RefEditorWrapper wrapper = cache.Wrapper;
EditorGUILayout.PropertyField(w.Property, label, true);
isExpanded = w.IsExpanded; wrapper.data = data;
wrapper.SO.Update();
wrapper.IsExpanded = isExpanded;
try
{
EditorGUILayout.PropertyField(wrapper.Property, label, true);
}
catch (ArgumentException)
{
if (Event.current.type != EventType.Repaint)
{
throw;
}
}
if (EditorGUI.EndChangeCheck()) if (EditorGUI.EndChangeCheck())
{ {
w.SO.ApplyModifiedProperties(); isExpanded = wrapper.IsExpanded;
outData = w.Data; wrapper.SO.ApplyModifiedProperties();
outData = wrapper.Data;
changed = true; changed = true;
} }
w.Release(); //wrapper.Release();
} }
} }

View File

@ -25,6 +25,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
private bool _isStaticInit = false; private bool _isStaticInit = false;
private bool _isInit = false; private bool _isInit = false;
public bool AutoChechChanges = true;
protected float OneLineHeight protected float OneLineHeight
{ {
get => EditorGUIUtility.singleLineHeight; get => EditorGUIUtility.singleLineHeight;
@ -70,12 +71,20 @@ namespace DCFApixels.DragonECS.Unity.Editors
public sealed override void OnInspectorGUI() public sealed override void OnInspectorGUI()
{ {
using (EcsGUI.CheckChanged(serializedObject)) if (AutoChechChanges)
{ {
StaticInit(); using (EcsGUI.CheckChanged(serializedObject))
Init(); {
DrawCustom(); StaticInit();
Init();
DrawCustom();
}
return;
} }
StaticInit();
Init();
DrawCustom();
} }
protected abstract void DrawCustom(); protected abstract void DrawCustom();

View File

@ -20,6 +20,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
internal abstract class WrapperBase<TSelf> : WrapperBase internal abstract class WrapperBase<TSelf> : WrapperBase
where TSelf : WrapperBase<TSelf> where TSelf : WrapperBase<TSelf>
{ {
private SerializedObject _so; private SerializedObject _so;
private SerializedProperty _property; private SerializedProperty _property;
@ -28,19 +29,19 @@ namespace DCFApixels.DragonECS.Unity.Editors
private static Stack<TSelf> _wrappers = new Stack<TSelf>(); private static Stack<TSelf> _wrappers = new Stack<TSelf>();
public override bool IsExpanded public sealed override bool IsExpanded
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return Property.isExpanded; } get { return Property.isExpanded; }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
set { Property.isExpanded = value; } set { Property.isExpanded = value; }
} }
public override SerializedObject SO public sealed override SerializedObject SO
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _so; } get { return _so; }
} }
public override SerializedProperty Property public sealed override SerializedProperty Property
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _property; } get { return _property; }