diff --git a/src/DebugUtils/Editor/SettingsEditor.cs b/src/DebugUtils/Editor/SettingsEditor.cs index 42ab0ed..6d63854 100644 --- a/src/DebugUtils/Editor/SettingsEditor.cs +++ b/src/DebugUtils/Editor/SettingsEditor.cs @@ -53,29 +53,25 @@ namespace DCFApixels.DragonECS.Unity.Editors //using (prefs.DisableAutoSave()) { - GUILayout.BeginHorizontal(); prefs.IsShowHidden = EditorGUILayout.ToggleLeft( UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsShowHidden)), prefs.IsShowHidden); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); prefs.IsShowInterfaces = EditorGUILayout.ToggleLeft( UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsShowInterfaces)), prefs.IsShowInterfaces); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); prefs.IsShowRuntimeComponents = EditorGUILayout.ToggleLeft( UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsShowRuntimeComponents)), prefs.IsShowRuntimeComponents); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); prefs.IsUseCustomNames = EditorGUILayout.ToggleLeft( UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsUseCustomNames)), prefs.IsUseCustomNames); - GUILayout.EndHorizontal(); + + prefs.IsFastModeRuntimeComponents = EditorGUILayout.ToggleLeft( + UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.IsFastModeRuntimeComponents)), + prefs.IsFastModeRuntimeComponents); prefs.ComponentColorMode = (ComponentColorMode)EditorGUILayout.EnumPopup(UnityEditorUtility.TransformFieldName(nameof(UserSettingsPrefs.ComponentColorMode)), prefs.ComponentColorMode); } diff --git a/src/DebugUtils/Editor/UserSettingsPrefs.cs b/src/DebugUtils/Editor/UserSettingsPrefs.cs index eb7f9cc..03a9c4c 100644 --- a/src/DebugUtils/Editor/UserSettingsPrefs.cs +++ b/src/DebugUtils/Editor/UserSettingsPrefs.cs @@ -69,6 +69,20 @@ namespace DCFApixels.DragonECS.Unity.Editors } } } + [SerializeField] + private bool _isFastModeRuntimeComponents = false; + public bool IsFastModeRuntimeComponents + { + get => _isFastModeRuntimeComponents; + set + { + if (_isFastModeRuntimeComponents != value) + { + _isFastModeRuntimeComponents = value; + AutoSave(); + } + } + } //[SerializeField] //private bool _poolsToggle = false; diff --git a/src/Internal/Editor/EcsGUI.Layout.cs b/src/Internal/Editor/EcsGUI.Layout.cs new file mode 100644 index 0000000..04dd5f0 --- /dev/null +++ b/src/Internal/Editor/EcsGUI.Layout.cs @@ -0,0 +1,502 @@ +#if UNITY_EDITOR +using DCFApixels.DragonECS.Unity.Internal; +using System; +using System.Collections.Generic; +using System.Reflection; +using Unity.Collections.LowLevel.Unsafe; +using UnityEditor; +using UnityEngine; +using Color = UnityEngine.Color; +using UnityComponent = UnityEngine.Component; +using UnityObject = UnityEngine.Object; + +namespace DCFApixels.DragonECS.Unity.Editors +{ + internal static partial class EcsGUI + { + public static partial class Layout + { + public static void ScriptAssetButton(MonoScript script, params GUILayoutOption[] options) + { + EcsGUI.ScriptAssetButton(GUILayoutUtility.GetRect(UnityEditorUtility.GetLabelTemp(), EditorStyles.miniButton, options), script); + } + + + public static void CopyMetaIDButton(string metaID, params GUILayoutOption[] options) + { + Rect r = GUILayoutUtility.GetRect(UnityEditorUtility.GetLabelTemp(), EditorStyles.miniButton, options); + var current = Event.current; + var hover = IconHoverScan(r, current); + using (new ColorScope(new Color(1f, 1f, 1f, hover ? 1f : 0.8f))) + { + DrawIcon(r, Icons.Instance.MetaIDIcon, hover ? 1f : 2f, metaID); + if (hover && current.type == EventType.MouseUp) + { + GUIUtility.systemCopyBuffer = metaID; + } + } + } + public static bool IconButton(Texture icon, params GUILayoutOption[] options) + { + bool result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), options); + DrawIcon(GUILayoutUtility.GetLastRect(), icon, 0, null); + return result; + } + public static bool IconButton(Texture icon, float iconPadding = 0, string description = null) + { + bool result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty)); + DrawIcon(GUILayoutUtility.GetLastRect(), icon, iconPadding, description); + return result; + } + public static bool IconButton(Texture icon, float iconPadding = 0, string description = null, GUIStyle style = null, params GUILayoutOption[] options) + { + bool result; + if (style == null) + { + result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), options); + } + else + { + result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), style, options); + } + DrawIcon(GUILayoutUtility.GetLastRect(), icon, iconPadding, description); + return result; + } + + public static void DrawEmptyComponentProperty(SerializedProperty property, string name, bool isDisplayEmpty) + { + EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(UnityEditorUtility.GetLabel(name), EditorStyles.label), property, name, isDisplayEmpty); + } + public static void DrawEmptyComponentProperty(SerializedProperty property, GUIContent label, bool isDisplayEmpty) + { + EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(label, EditorStyles.label), property, label, isDisplayEmpty); + } + public static void DrawWorldBaseInfo(EcsWorld world) + { + bool isNull = world == null || world.IsDestroyed || world.ID == 0; + int entitesCount = isNull ? 0 : world.Count; + int capacity = isNull ? 0 : world.Capacity; + long Version = isNull ? 0 : world.Version; + int leakedEntitesCount = isNull ? 0 : world.CountLeakedEntitesDebug(); + EditorGUILayout.IntField("Entities", entitesCount, EditorStyles.boldLabel); + EditorGUILayout.IntField("Capacity", capacity, EditorStyles.boldLabel); + EditorGUILayout.LongField("Version", Version, EditorStyles.boldLabel); + Color color = leakedEntitesCount > 0 ? Color.yellow : GUI.contentColor; + using (new ContentColorScope(color)) + { + EditorGUILayout.IntField("Leaked Entites", leakedEntitesCount, EditorStyles.boldLabel); + } + } + public static void DrawWorldComponents(EcsWorld world) + { + bool isNull = world == null || world.IsDestroyed || world.ID == 0; + if (isNull) { return; } + using (BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) + { + IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout); + EditorGUILayout.EndFoldoutHeaderGroup(); + if (IsShowRuntimeComponents == false) { return; } + + var worldID = world.ID; + var cmps = world.GetWorldComponents(); + int index = -1; + int total = 9; + foreach (var cmp in cmps) + { + index++; + var meta = cmp.ComponentType.ToMeta(); + if (meta.IsHidden == false || IsShowHidden) + { + Type componentType = cmp.ComponentType; + + object data = cmp.GetRaw(worldID); + + ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType); + + float padding = EditorGUIUtility.standardVerticalSpacing; + Rect optionButton = GUILayoutUtility.GetLastRect(); + optionButton.yMin = optionButton.yMax; + optionButton.yMax += HeadIconsRect.height; + optionButton.xMin = optionButton.xMax - 64; + optionButton.center += Vector2.up * padding * 2f; + //Canceling isExpanded + if (ClickTest(optionButton)) + { + ref bool isExpanded = ref expandMatrix.Down(); + isExpanded = !isExpanded; + } + + Color panelColor = SelectPanelColor(meta, index, total); + GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA)); + EditorGUI.BeginChangeCheck(); + + ////Close button + //optionButton.xMin = optionButton.xMax - HeadIconsRect.width; + //if (CloseButton(optionButton)) + //{ + // cmp.Del(worldID); + // return; + //} + + //Edit script button + if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script)) + { + optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); + EcsGUI.ScriptAssetButton(optionButton, script); + } + //Description icon + if (string.IsNullOrEmpty(meta.Description.Text) == false) + { + optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); + DescriptionIcon(optionButton, meta.Description.Text); + } + + RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name); + if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData)) + { + cmp.SetRaw(worldID, resultData); + } + + GUILayout.EndVertical(); + } + } + } + } + + #region entity bar + public static void EntityBarForAlive(EntityStatus status, int id, short gen, short world) + { + float width = EditorGUIUtility.currentViewWidth; + float height = EntityBarHeight; + EcsGUI.EntityBarForAlive(GUILayoutUtility.GetRect(width, height), status, id, gen, world); + } + public static void EntityBar(EntityStatus status, bool isPlaceholder, int id, short gen, short world) + { + float width = EditorGUIUtility.currentViewWidth; + float height = EntityBarHeight; + EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height), isPlaceholder, status, id, gen, world); + } + public static void EntityBar(int id, short gen, short world) + { + float width = EditorGUIUtility.currentViewWidth; + float height = EntityBarHeight; + EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height), id, gen, world); + } + public static void EntityBar() + { + float width = EditorGUIUtility.currentViewWidth; + float height = EntityBarHeight; + EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height)); + } + #endregion + + public static bool AddComponentButtons(out Rect dropDownRect) + { + return EcsGUI.AddComponentButton(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); + } + public static AddClearButton AddClearComponentButtons(out Rect dropDownRect) + { + return EcsGUI.AddClearComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); + } + public static AddClearButton AddClearSystemButtons(out Rect dropDownRect) + { + return EcsGUI.AddClearSystemButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); + } + public static void DrawRuntimeComponents(entlong entity, bool isWithFoldout = true) + { + if (entity.TryUnpackForUnityEditor(out int entityID, out _, out _, out EcsWorld world)) + { + DrawRuntimeComponents(entityID, world, isWithFoldout); + } + } + + [ThreadStatic] + private static List _componentPoolsBuffer; + public static void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout = true) + { + using (BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) + { + if (isWithFoldout) + { + IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout); + EditorGUILayout.EndFoldoutHeaderGroup(); + } + if (isWithFoldout == false || IsShowRuntimeComponents) + { + if (AddComponentButtons(out Rect dropDownRect)) + { + RuntimeComponentsUtility.GetAddComponentGenericMenu(world).Open(dropDownRect, entityID); + } + + GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true)); + IsShowHidden = EditorGUI.Toggle(GUILayoutUtility.GetLastRect(), "Show Hidden", IsShowHidden); + + if (_componentPoolsBuffer == null) + { + _componentPoolsBuffer = new List(64); + } + world.GetComponentPoolsFor(entityID, _componentPoolsBuffer); + int i = 0; + //int iMax = _componentPoolsBuffer.Count; + foreach (var componentPool in _componentPoolsBuffer) + { + DrawRuntimeComponent(entityID, componentPool, 9, i++); + } + } + } + } + private static void DrawRuntimeComponent(int entityID, IEcsPool pool, int total, int index) + { + var meta = pool.ComponentType.ToMeta(); + if (meta.IsHidden == false || IsShowHidden) + { + Type componentType = pool.ComponentType; + + object data = pool.GetRaw(entityID); + + ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType); + + float padding = EditorGUIUtility.standardVerticalSpacing; + Rect optionButton = GUILayoutUtility.GetLastRect(); + optionButton.yMin = optionButton.yMax; + optionButton.yMax += HeadIconsRect.height; + optionButton.xMin = optionButton.xMax - 64; + optionButton.center += Vector2.up * padding * 2f; + //Canceling isExpanded + if (ClickTest(optionButton)) + { + ref bool isExpanded = ref expandMatrix.Down(); + isExpanded = !isExpanded; + } + + Color panelColor = SelectPanelColor(meta, index, total); + GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA)); + EditorGUI.BeginChangeCheck(); + + //Close button + optionButton.xMin = optionButton.xMax - HeadIconsRect.width; + if (CloseButton(optionButton)) + { + pool.Del(entityID); + return; + } + //Edit script button + if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script)) + { + optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); + EcsGUI.ScriptAssetButton(optionButton, script); + } + //Description icon + if (string.IsNullOrEmpty(meta.Description.Text) == false) + { + optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); + DescriptionIcon(optionButton, meta.Description.Text); + } + + RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name); + + if (IsFastModeRuntimeComponents) + { + if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData)) + { + pool.SetRaw(entityID, resultData); + } + } + else + { + if (DrawProperty(data)) + { + pool.SetRaw(entityID, data); + } + } + + + GUILayout.EndVertical(); + } + } + + #region Default DrawRuntimeData + [InitializeOnLoadMethod] + private static void ResetRuntimeComponentReflectionCache() + { + _runtimeComponentReflectionCaches.Clear(); + } + internal class RuntimeComponentReflectionCache + { + public readonly Type Type; + + 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 _runtimeComponentReflectionCaches = new Dictionary(); + 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; + Type type = data == null ? typeof(void) : data.GetType(); + + RuntimeComponentReflectionCache cache = GetRuntimeComponentReflectionCache(type); + + bool isUnityObjectField = fieldInfoData.IsUnityObjectField; + if (isUnityObjectField == false && data == null) + { + EditorGUILayout.TextField(label, "Null"); + return false; + } + bool isUnityObjectType = cache.IsUnityObjectType; + + ref bool isExpanded = ref expandMatrix.Down(); + bool changed = false; + + + if (cache.IsUnitySerializable == false) + { + isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(isExpanded, label, EditorStyles.foldout); + EditorGUILayout.EndFoldoutHeaderGroup(); + + if (isExpanded) + { + using (UpIndentLevel()) + { + for (int j = 0, jMax = cache.Fields.Length; j < jMax; j++) + { + var field = cache.Fields[j]; + if (DrawRuntimeData(ref field, UnityEditorUtility.GetLabel(field.UnityFormatName), expandMatrix, field.FieldInfo.GetValue(data), out object fieldData)) + { + field.FieldInfo.SetValue(data, fieldData); + outData = data; + changed = true; + } + } + } + } + } + else + { + Type fieldType = fieldInfoData.FieldType; + if (isUnityObjectType || isUnityObjectField) + { + EditorGUI.BeginChangeCheck(); + var uobj = UnsafeUtility.As(ref data); + + bool isComponent = typeof(UnityComponent).IsAssignableFrom(fieldType); + if (isComponent) + { + uobj = EditorGUILayout.ObjectField(label, uobj, typeof(UnityObject), true); + } + else + { + uobj = EditorGUILayout.ObjectField(label, uobj, fieldType, true); + } + + if (EditorGUI.EndChangeCheck()) + { + if (isComponent && uobj is GameObject go) + { + uobj = go.GetComponent(fieldType); + } + + outData = uobj; + changed = true; + } + } + else + { + EditorGUI.BeginChangeCheck(); + //WrapperBase wrapper = RefEditorWrapper.Take(data); + + RefEditorWrapper wrapper = cache.Wrapper; + + 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()) + { + isExpanded = wrapper.IsExpanded; + wrapper.SO.ApplyModifiedProperties(); + outData = wrapper.Data; + changed = true; + } + //wrapper.Release(); + } + } + + expandMatrix.Up(); + return changed; + } + #endregion + } + } +} +#endif \ No newline at end of file diff --git a/src/Internal/Editor/EcsGUI.Layout.cs.meta b/src/Internal/Editor/EcsGUI.Layout.cs.meta new file mode 100644 index 0000000..f0151db --- /dev/null +++ b/src/Internal/Editor/EcsGUI.Layout.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7a7468927b696e4899e73de0866d947 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Internal/Editor/EcsGUI.RuntimeCumponents.cs b/src/Internal/Editor/EcsGUI.RuntimeCumponents.cs new file mode 100644 index 0000000..fce80f9 --- /dev/null +++ b/src/Internal/Editor/EcsGUI.RuntimeCumponents.cs @@ -0,0 +1,896 @@ +using DCFApixels.DragonECS.Unity.Internal; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using Unity.Collections.LowLevel.Unsafe; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using Color = UnityEngine.Color; +using Debug = UnityEngine.Debug; +using UnityObject = UnityEngine.Object; + +namespace DCFApixels.DragonECS.Unity.Editors +{ + internal unsafe static partial class EcsGUI + { + [StructLayout(LayoutKind.Explicit)] + private struct PtrRefUnion + { + [FieldOffset(0)] + public void* Ptr; + [FieldOffset(0)] + public object Ref; + public PtrRefUnion(void* ptr) : this() + { + Ptr = ptr; + } + } + + #region Value + private readonly unsafe struct Value + { + public readonly byte* FieldPtr; + public readonly byte* ValuePtr; + public Value(byte* fieldPtr, byte* valuePtr) + { + FieldPtr = fieldPtr; + ValuePtr = valuePtr; + } + public Value Read(in InspectorFieldInfo field) + { + return Read(in this, field.Offset, field.Flag == FieldFlag.Ref); + } + public Value Read(int fieldOffset, bool isRef) + { + return Read(in this, fieldOffset, isRef); + } + public static Value Read(in Value source, in InspectorFieldInfo field) + { + return Read(in source, field.Offset, field.Flag == FieldFlag.Ref); + } + public static Value Read(in Value source, int fieldOffset, bool isRef) + { + byte* fieldPtr = source.ValuePtr + fieldOffset; + byte* valuePtr; + if (isRef) + { + IntPtr* refPtr = (IntPtr*)fieldPtr; + valuePtr = (byte*)&refPtr; + } + else + { + valuePtr = fieldPtr; + } + return new Value(fieldPtr, valuePtr); + } + public ref T AsValue() where T : struct + { +#if DEV_MODE + if (FieldPtr != ValuePtr) { throw new Exception(); } +#endif + return ref UnsafeUtility.AsRef(FieldPtr); + } + public T AsRef() where T : class + { +#if DEV_MODE + if (FieldPtr == ValuePtr) { throw new Exception(); } +#endif + + //ref IntPtr p = ref UnsafeUtility.AsRef(ValuePtr); + //byte* pp = (byte*)p; + // + //Union union = default; + ////union.Ptr = ValuePtr; // ValuePtr это какраз и есть реф + //union.Ptr = pp; // ValuePtr это какраз и есть реф + ////object result = union.Ref; + // + //object result = UnsafeUtility.As(ref p); + //return (T)result; + + PtrRefUnion union = default; + union.Ptr = ValuePtr; // ValuePtr это какраз и есть реф + object result = union.Ref; + return (T)result; + } + public object AsRef() + { + return AsRef(); + } + } + #endregion + + #region FieldValueProcessor + private abstract class FieldValueProcessor + { + private static readonly Dictionary _processors = new Dictionary(); + private static readonly StructFieldValueProcessor _defaultProcessor = new StructFieldValueProcessor(); + static FieldValueProcessor() + { + _processors.Clear(); + _defaultProcessor._valueInfo = InspectorTypeInfo.Get(typeof(object)); + _processors.Add(typeof(object), _defaultProcessor); + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + foreach (var processorType in assembly.GetTypes()) + { + if (processorType.IsGenericType == false && + processorType.IsAbstract == false && + typeof(FieldValueProcessor).IsAssignableFrom(processorType) && + processorType != typeof(StructFieldValueProcessor)) + { + var processor = (FieldValueProcessor)Activator.CreateInstance(processorType); + processor._valueInfo = InspectorTypeInfo.Get(processor.ProcessedType); + _processors.Add(processor.ProcessedType, processor); + } + } + } + } + public static FieldValueProcessor GetProcessor(Type type) + { + if(type == null) + { + throw new ArgumentNullException("type"); + } + + if (_processors == null) + { + throw new Exception("_processors == null"); + } + if (_processors.TryGetValue(type, out FieldValueProcessor processor) == false) + { + FieldValueProcessor otherProcessor; + if (type.IsValueType) + { + otherProcessor = _defaultProcessor; + } + else + { + otherProcessor = GetProcessor(type.BaseType); + } + + processor = (FieldValueProcessor)otherProcessor.MemberwiseClone(); + processor._valueInfo = InspectorTypeInfo.Get(type); + _processors.Add(type, processor); + } + return processor; + } + + + private InspectorTypeInfo _valueInfo; + public InspectorTypeInfo ValueInfo + { + get { return _valueInfo; } + } + public bool IsDefault + { + get { return this == _defaultProcessor; } + } + public abstract Type ProcessedType { get; } + public abstract float GetHeight(in InspectorFieldInfo field, in Value value); + public abstract void Draw(Rect rect, in InspectorFieldInfo field, in Value value); + + public override string ToString() + { + if(_valueInfo == null) + { + return "ERROR"; + } + return _valueInfo.Type.Name + " " + GetType().Name; + } + } + private class StructFieldValueProcessor : FieldValueProcessor + { + public override Type ProcessedType { get { return typeof(object); } } + public override float GetHeight(in InspectorFieldInfo field, in Value value) + { + float result = GetPropertyHeight(field, ValueInfo, value); + Debug.Log("GetHeight: " + result + " : " + ValueInfo.Type + " : " + ValueInfo.Fields + " : " + ValueInfo.IsNull); + return result; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value value) + { + Debug.Log("Draw: " + ValueInfo.Type + " : " + ValueInfo.Fields + " : " + ValueInfo.IsNull); + DrawProperty(rect, field, ValueInfo, value); + } + } + private class ValueFieldValueProcessor : StructFieldValueProcessor where T : struct + { + public sealed override Type ProcessedType { get { return typeof(T); } } + public sealed override float GetHeight(in InspectorFieldInfo field, in Value value) + { + float result = GetHeight(field, value, ref value.AsValue()); + Debug.Log("GetHeight: " + result + " : " + ValueInfo.Type + " : " + ValueInfo.Fields + " : " + ValueInfo.IsNull); + return result; + } + public sealed override void Draw(Rect rect, in InspectorFieldInfo field, in Value value) + { + Debug.Log("Draw: " + ValueInfo.Type + " : " + ValueInfo.Fields + " : " + ValueInfo.IsNull); + Draw(rect, field, value, ref value.AsValue()); + } + public virtual float GetHeight(in InspectorFieldInfo field, in Value raw, ref T value) + { + return base.GetHeight(field, raw); + } + public virtual void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref T value) + { + base.Draw(rect, field, raw); + } + } + private class RefFieldValueProcessor : StructFieldValueProcessor where T : class + { + public sealed override Type ProcessedType { get { return typeof(T); } } + public sealed override float GetHeight(in InspectorFieldInfo field, in Value value) + { + float result = GetHeight(field, value, value.AsRef()); + Debug.Log("GetHeight: " + result + " : " + ValueInfo.Type + " : " + ValueInfo.Fields + " : " + ValueInfo.IsNull); + return result; + } + public sealed override void Draw(Rect rect, in InspectorFieldInfo field, in Value value) + { + Debug.Log("Draw: " + ValueInfo.Type + " : " + ValueInfo.Fields + " : " + ValueInfo.IsNull); + Draw(rect, field, value, value.AsRef()); + } + public virtual float GetHeight(in InspectorFieldInfo field, in Value raw, T value) + { + return base.GetHeight(field, raw); + } + public virtual void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, T value) + { + base.Draw(rect, field, raw); + } + } + private unsafe class ArrayFieldValueProcessor : RefFieldValueProcessor + { + private static readonly int _mappingDataOffset; + static ArrayFieldValueProcessor() + { + Array array = new int[] { 1, 2, 3 }; + ulong handle; + + byte* ptrObject = (byte*)UnsafeUtility.PinGCObjectAndGetAddress(array, out handle); + UnsafeUtility.ReleaseGCObject(handle); + byte* ptrData = (byte*)UnsafeUtility.PinGCArrayAndGetDataAddress(array, out handle); + UnsafeUtility.ReleaseGCObject(handle); + + _mappingDataOffset = (int)(ptrData - ptrObject); + } + + + private readonly ReorderableList _listDragCache; // сюда попадает _list если было вызвано событие драг енд дропа, а изначальный _listDragCache перемещается в _list + private readonly ReorderableList _list; + public ArrayFieldValueProcessor() + { + //_list.list + } + public override float GetHeight(in InspectorFieldInfo field, in Value raw, Array value) + { + //var elemType = value.GetType().GetElementType(); + //int length = value.Length; + //byte* ptr = raw.ValuePtr + _mappingDataOffset; + // + // + //_list.heigh + // + //ReorderableList l = null; + //l.onMouseDragCallback + // + //float result = 0; + //var processor = GetProcessor(elemType); + //for (int i = 0; i < length; i++) + //{ + // + //} + + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, Array value) + { + //var elemType = value.GetType().GetElementType(); + //int length = value.Length; + //byte* ptr = raw.ValuePtr + _mappingDataOffset; + // + + EditorGUI.LabelField(rect, UnityEditorUtility.GetLabel(field.Name), "Array Unsupport"); + } + } + private class SByteFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref sbyte value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref sbyte value) + { + value = (sbyte)EditorGUI.IntField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class ByteFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref byte value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref byte value) + { + value = (byte)EditorGUI.IntField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class ShortFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref short value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref short value) + { + value = (short)EditorGUI.IntField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class UShortFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref ushort value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref ushort value) + { + value = (ushort)EditorGUI.IntField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class IntFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref int value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref int value) + { + value = EditorGUI.IntField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class UIntFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref uint value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref uint value) + { + value = (uint)EditorGUI.LongField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class LongFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref long value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref long value) + { + value = EditorGUI.LongField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class ULongFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref ulong value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref ulong value) + { + value = (ulong)EditorGUI.LongField(rect, UnityEditorUtility.GetLabel(field.Name), (long)value); + } + } + private class FloatFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref float value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref float value) + { + value = EditorGUI.FloatField(rect, UnityEditorUtility.GetLabel(field.Name), (long)value); + } + } + private class DoubleFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref double value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref double value) + { + value = EditorGUI.DoubleField(rect, UnityEditorUtility.GetLabel(field.Name), (long)value); + } + } + private class CharFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref char value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref char value) + { + var result = EditorGUI.TextField(rect, UnityEditorUtility.GetLabel(field.Name), value.ToString()); + if(result.Length > 0) + { + value = result[0]; + } + value = default; + } + } + private class ColorFieldValueProcessor : ValueFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, ref Color value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, ref Color value) + { + value = EditorGUI.ColorField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class StringFieldValueProcessor : RefFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, string value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, string value) + { + value = EditorGUI.TextField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class GradientFieldValueProcessor : RefFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, Gradient value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, Gradient value) + { + value = EditorGUI.GradientField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class CurveFieldValueProcessor : RefFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, AnimationCurve value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, AnimationCurve value) + { + value = EditorGUI.CurveField(rect, UnityEditorUtility.GetLabel(field.Name), value); + } + } + private class UnityObjectFieldValueProcessor : RefFieldValueProcessor + { + public override float GetHeight(in InspectorFieldInfo field, in Value raw, UnityObject value) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + public override void Draw(Rect rect, in InspectorFieldInfo field, in Value raw, UnityObject value) + { + value = EditorGUI.ObjectField(rect, UnityEditorUtility.GetLabel(field.Name), value, ValueInfo.Type, true); + } + } + #endregion + + #region InspectorTypeInfo + private class InspectorTypeInfo + { + #region cahce + private static Dictionary _typeInfosCache = new Dictionary(); + static InspectorTypeInfo() + { + _typeInfosCache.Clear(); + } + public static InspectorTypeInfo Get(Type type) + { + if (_typeInfosCache.TryGetValue(type, out InspectorTypeInfo info) == false) + { + info = new InspectorTypeInfo(type); + _typeInfosCache.Add(type, info); + } + + return info; + } + #endregion + private struct FakeNull { } + public static readonly InspectorTypeInfo PtrTypeInfo = new InspectorTypeInfo(typeof(IntPtr)); + public static readonly InspectorTypeInfo NullTypeInfo = new InspectorTypeInfo(typeof(FakeNull)); + + public readonly Type Type; + //public readonly int Size; + public readonly InspectorFieldInfo[] Fields; + //public readonly float DefaultInspectorHegiht; + + public readonly bool IsVector; + public readonly bool IsColor; + + public bool IsNull + { + get { return this == NullTypeInfo; } + } + public bool IsPrt + { + get { return this == PtrTypeInfo; } + } + + #region Constructors + //private static StructList CnstrBuffer = new StructList(32); + private static readonly char[] VectorFields = new char[] { 'x', 'y', 'z', 'w' }; + private static readonly char[] ColorFields = new char[] { 'r', 'g', 'b', 'a' }; + public InspectorTypeInfo(Type type) + { + StructList CnstrBuffer = new StructList(32); + //if (CnstrBuffer.IsNull) + //{ + // CnstrBuffer = new StructList(32); + //} + CnstrBuffer.FastClear(); + Type = type; + //Size = UnsafeUtility.SizeOf(type); + var fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + foreach (var fieldInfo in fieldInfos) + { + InspectorFieldInfo.Union infoUniton = default; + ref InspectorFieldInfo.Constructor infocstr = ref infoUniton.Constructor; + + var fieldType = fieldInfo.FieldType; + + infocstr.FieldInfo = fieldInfo; + infocstr.Offset = UnsafeUtility.GetFieldOffset(fieldInfo); + infocstr.Name = UnityEditorUtility.TransformFieldName(fieldType.Name); + infocstr.Flag = FieldFlagUtitlity.GetFieldFlag(fieldType); + + Debug.LogWarning("Offset: " + type.Name + "." + infocstr.Name + "." + infocstr.Offset); + + + if (infocstr.Flag == FieldFlag.Struct) + { + infocstr.PreDefinedType = Get(fieldType); + } + else if (infocstr.Flag == FieldFlag.Ref) + { + infocstr.PreDefinedType = PtrTypeInfo; + } + else + { + infocstr.PreDefinedType = NullTypeInfo; + } + + CnstrBuffer.Add(infoUniton.Result); + } + + Fields = CnstrBuffer.Enumerable.ToArray(); + Array.Sort(Fields); + + int length = Fields.Length; + if (length >= 2 && length <= 3) + { + bool isCheck = true; + for (int i = 0; i < length; i++) + { + ref var field = ref Fields[i]; + + if (field.Flag == FieldFlag.Leaf && + field.PreDefinedType.Type.IsPrimitive && + char.ToLower(field.Name[0]) != VectorFields[i]) + { + isCheck = false; + break; + } + } + if (isCheck) + { + IsVector = true; + } + else + { + isCheck = true; + for (int i = 0; i < length; i++) + { + ref var field = ref Fields[i]; + if (field.Flag == FieldFlag.Leaf && + field.PreDefinedType.Type.IsPrimitive && + char.ToLower(field.Name[0]) != ColorFields[i]) + { + isCheck = false; + break; + } + } + if (isCheck) + { + IsColor = true; + } + } + } + } + #endregion + + public override string ToString() + { + return Type.Name; + } + } + #endregion + + #region InspectorFieldInfo + [StructLayout(LayoutKind.Sequential)] + private unsafe readonly struct InspectorFieldInfo : IEquatable, IComparable + { + public readonly FieldInfo FieldInfo; + public readonly InspectorTypeInfo PreDefinedType; + public readonly string Name; + public readonly int Offset; + public readonly FieldFlag Flag; + + public int CompareTo(InspectorFieldInfo other) + { + return other.Offset - Offset; + } + public bool Equals(InspectorFieldInfo other) + { + return EqualityComparer.Default.Equals(this, other); + } + [StructLayout(LayoutKind.Sequential)] + public unsafe struct Constructor + { + public FieldInfo FieldInfo; + public InspectorTypeInfo PreDefinedType; + public string Name; + public int Offset; + public FieldFlag Flag; + public override string ToString() { return Name; } + } + [StructLayout(LayoutKind.Explicit)] + public struct Union + { + [FieldOffset(0)] + public Constructor Constructor; + [FieldOffset(0)] + public InspectorFieldInfo Result; + } + public override string ToString() { return Name; } + } + private static class FieldFlagUtitlity + { + private static readonly HashSet _cantDisplayedTypes = new HashSet() + { + typeof(IntPtr), + typeof(UIntPtr), + }; + private static readonly HashSet _leafTypes = new HashSet() + { + typeof(string), + typeof(AnimationCurve), + typeof(Gradient), + typeof(LayerMask), + typeof(Color), + }; + public static FieldFlag GetFieldFlag(Type fieldType) + { + if (fieldType.IsPointer || _cantDisplayedTypes.Contains(fieldType)) + { + return FieldFlag.CantDisplayed; + } + if (fieldType.IsClass || fieldType.IsInterface) + { + return FieldFlag.Ref; + } + if (fieldType.IsPrimitive || fieldType.IsEnum || _leafTypes.Contains(fieldType)) + { + return FieldFlag.Leaf; + } + return FieldFlag.Struct; + } + public static bool IsValueField(FieldFlag flag) + { + return flag == FieldFlag.Leaf || flag == FieldFlag.Struct; + } + public static bool IsCanDisplayed(FieldFlag flag) + { + return flag != FieldFlag.None && flag != FieldFlag.CantDisplayed; + } + } + private enum FieldFlag : byte + { + None = 0, + CantDisplayed, + Leaf, + Struct, + Ref, + } + private unsafe static bool FastDrawRuntimeData(void* data, InspectorTypeInfo cache) + { + throw new NotImplementedException(); + } + #endregion + + private static void DrawProperty(Rect rect, in InspectorFieldInfo field, InspectorTypeInfo valueInfo, in Value value) + { + if (field.Flag == FieldFlag.Leaf) + { + EditorGUI.LabelField(rect, UnityEditorUtility.GetLabel(field.Name)); + return; + } + float y = rect.y; + float height = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + Rect subRect = rect; + subRect.y = y; + subRect.height = height - EditorGUIUtility.standardVerticalSpacing; + y += height; + + EditorGUI.LabelField(subRect, field.Name); + + using (UpIndentLevel()) + { + foreach (var subField in valueInfo.Fields) + { + if (FieldFlagUtitlity.IsCanDisplayed(subField.Flag) == false) { continue; } + + var subValue = value.Read(subField); + Type subValueType; + + switch (subField.Flag) + { + case FieldFlag.Leaf: + case FieldFlag.Struct: + subValueType = subField.PreDefinedType.Type; + break; + case FieldFlag.Ref: + var obj = subValue.AsRef(); + subValueType = obj.GetType(); + break; + case FieldFlag.None: + case FieldFlag.CantDisplayed: + default: + subValueType = null; + break; + } + + if (subValueType == null) { continue; } + + var processor = FieldValueProcessor.GetProcessor(subValueType); + height = processor.GetHeight(subField, subValue); + subRect = rect; + subRect.y = y; + subRect.height = height - EditorGUIUtility.standardVerticalSpacing; + y += height; + + if (subField.Flag == FieldFlag.Struct && processor.IsDefault) + { + if (subField.PreDefinedType.IsVector) + { + float defLabelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = 14f; + subRect.xMin += EditorGUIUtility.labelWidth; + var vectorFields = subField.PreDefinedType.Fields; + var widthOne = subRect.width / vectorFields.Length; + foreach (var vectorField in vectorFields) + { + var vectorFieldProcessor = FieldValueProcessor.GetProcessor(vectorField.PreDefinedType.Type); + vectorFieldProcessor.Draw(subRect, vectorField, subValue.Read(vectorField)); + } + EditorGUIUtility.labelWidth = defLabelWidth; + } + //else if (subField.PreDefinedType.IsColor) + //{ + // EditorGUI.ColorField(subRect, ); + //} + } + + processor.Draw(subRect, subField, subValue); + } + } + } + private static float GetPropertyHeight(in InspectorFieldInfo field, InspectorTypeInfo valueInfo, in Value value) + { + float result = 0; + if (field.Flag == FieldFlag.Leaf) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + + Debug.Log(string.Join("\r\n", valueInfo.Fields)); + + foreach (var subField in valueInfo.Fields) + { + if (FieldFlagUtitlity.IsCanDisplayed(subField.Flag) == false) { continue; } + + var subValue = value.Read(subField); + Type subValueType; + + switch (subField.Flag) + { + case FieldFlag.None: + case FieldFlag.CantDisplayed: + default: + subValueType = null; + break; + case FieldFlag.Leaf: + case FieldFlag.Struct: + subValueType = subField.PreDefinedType.Type; + break; + case FieldFlag.Ref: + var obj = subValue.AsRef(); + subValueType = obj.GetType(); + break; + } + + if (subValueType == null) { continue; } + + var processor = FieldValueProcessor.GetProcessor(subValueType); + if (subField.Flag == FieldFlag.Struct && processor.IsDefault) + { + if (subField.PreDefinedType.IsVector) + //if (subField.PreDefinedType.IsVector || subField.PreDefinedType.IsColor) + { + return EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + } + } + result += EditorGUIUtility.currentViewWidth + EditorGUIUtility.standardVerticalSpacing; + result += processor.GetHeight(subField, subValue); + } + return result; + } + + public static unsafe partial class Layout + { + private static bool DrawProperty(object data) + { + Debug.LogWarning("--------------------------------------------"); + EditorGUI.BeginChangeCheck(); + Type type = data.GetType(); + byte* ptr = (byte*)UnsafeUtility.PinGCObjectAndGetAddress(data, out ulong gcHandle); + + try + { + InspectorTypeInfo inspectorTypeInfo = InspectorTypeInfo.Get(type); + Value value = new Value(null, ptr); + +#if DEV_MODE + if (data is GameObjectConnect goc) + { + byte* ptrX = (byte*)UnsafeUtility.PinGCObjectAndGetAddress(goc.Connect, out ulong gcHandleX); + UnsafeUtility.ReleaseGCObject(gcHandleX); + + var fieldX = inspectorTypeInfo.Fields[0]; + + Value valueX = value.Read(fieldX); + byte* ptrX2 = valueX.ValuePtr; + + PtrRefUnion u = default; + u.Ref = goc.Connect; + + + Debug.Log((IntPtr)ptrX + " " + (IntPtr)ptrX2); + } +#endif + + + InspectorFieldInfo f = default; + float h = GetPropertyHeight(in f, inspectorTypeInfo, in value); + var r = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, h); + EcsGUI.DrawProperty(r, in f, inspectorTypeInfo, in value); + + + UnsafeUtility.ReleaseGCObject(gcHandle); + } + catch (Exception) + { + UnsafeUtility.ReleaseGCObject(gcHandle); + throw; + } + + + return EditorGUI.EndChangeCheck(); + } + + } + } +} diff --git a/src/Internal/Editor/EcsGUI.RuntimeCumponents.cs.meta b/src/Internal/Editor/EcsGUI.RuntimeCumponents.cs.meta new file mode 100644 index 0000000..a8c426f --- /dev/null +++ b/src/Internal/Editor/EcsGUI.RuntimeCumponents.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b50e8a16e06a37438743ce90a39f93d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs index 8dac123..954a4d6 100644 --- a/src/Internal/Editor/EcsGUI.cs +++ b/src/Internal/Editor/EcsGUI.cs @@ -2,18 +2,11 @@ using DCFApixels.DragonECS.Unity.Internal; using System; using System.Collections.Generic; - - -//using System.Drawing; using System.Reflection; -using System.Runtime.InteropServices; -using Unity.Collections.LowLevel.Unsafe; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; using Color = UnityEngine.Color; -using UnityComponent = UnityEngine.Component; -using UnityObject = UnityEngine.Object; namespace DCFApixels.DragonECS.Unity.Editors { @@ -24,7 +17,10 @@ namespace DCFApixels.DragonECS.Unity.Editors private static bool _changed = false; private static bool _delayedChanged = false; - public static int ChangedCounter => _changedCounter; + public static int ChangedCounter + { + get { return _changedCounter; } + } public static bool Changed { get @@ -275,6 +271,7 @@ namespace DCFApixels.DragonECS.Unity.Editors public static float EntityBarHeight => EditorGUIUtility.singleLineHeight + 3f; private static float indent => (float)EditorGUI.indentLevel * 15f; + private static float indentLevel => EditorGUI.indentLevel; #region Properties private static ComponentColorMode AutoColorMode @@ -292,6 +289,11 @@ namespace DCFApixels.DragonECS.Unity.Editors get { return UserSettingsPrefs.instance.IsShowRuntimeComponents; } set { UserSettingsPrefs.instance.IsShowRuntimeComponents = value; } } + private static bool IsFastModeRuntimeComponents + { + get { return UserSettingsPrefs.instance.IsFastModeRuntimeComponents; } + set { UserSettingsPrefs.instance.IsFastModeRuntimeComponents = value; } + } private static float OneLineHeight { get => EditorGUIUtility.singleLineHeight; @@ -1009,766 +1011,8 @@ namespace DCFApixels.DragonECS.Unity.Editors _currentProperty = property; GetReferenceDropDown(sortedPredicateTypes, sortedWithOutTypes).Show(position); } - #endregion - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - public static partial class Layout - { - public static void ScriptAssetButton(MonoScript script, params GUILayoutOption[] options) - { - EcsGUI.ScriptAssetButton(GUILayoutUtility.GetRect(UnityEditorUtility.GetLabelTemp(), EditorStyles.miniButton, options), script); - } - - - public static void CopyMetaIDButton(string metaID, params GUILayoutOption[] options) - { - Rect r = GUILayoutUtility.GetRect(UnityEditorUtility.GetLabelTemp(), EditorStyles.miniButton, options); - var current = Event.current; - var hover = IconHoverScan(r, current); - using (new ColorScope(new Color(1f, 1f, 1f, hover ? 1f : 0.8f))) - { - DrawIcon(r, Icons.Instance.MetaIDIcon, hover ? 1f : 2f, metaID); - if (hover && current.type == EventType.MouseUp) - { - GUIUtility.systemCopyBuffer = metaID; - } - } - } - public static bool IconButton(Texture icon, params GUILayoutOption[] options) - { - bool result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), options); - DrawIcon(GUILayoutUtility.GetLastRect(), icon, 0, null); - return result; - } - public static bool IconButton(Texture icon, float iconPadding = 0, string description = null) - { - bool result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty)); - DrawIcon(GUILayoutUtility.GetLastRect(), icon, iconPadding, description); - return result; - } - public static bool IconButton(Texture icon, float iconPadding = 0, string description = null, GUIStyle style = null, params GUILayoutOption[] options) - { - bool result; - if (style == null) - { - result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), options); - } - else - { - result = GUILayout.Button(UnityEditorUtility.GetLabel(string.Empty), style, options); - } - DrawIcon(GUILayoutUtility.GetLastRect(), icon, iconPadding, description); - return result; - } - - public static void DrawEmptyComponentProperty(SerializedProperty property, string name, bool isDisplayEmpty) - { - EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(UnityEditorUtility.GetLabel(name), EditorStyles.label), property, name, isDisplayEmpty); - } - public static void DrawEmptyComponentProperty(SerializedProperty property, GUIContent label, bool isDisplayEmpty) - { - EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(label, EditorStyles.label), property, label, isDisplayEmpty); - } - public static void DrawWorldBaseInfo(EcsWorld world) - { - bool isNull = world == null || world.IsDestroyed || world.ID == 0; - int entitesCount = isNull ? 0 : world.Count; - int capacity = isNull ? 0 : world.Capacity; - long Version = isNull ? 0 : world.Version; - int leakedEntitesCount = isNull ? 0 : world.CountLeakedEntitesDebug(); - EditorGUILayout.IntField("Entities", entitesCount, EditorStyles.boldLabel); - EditorGUILayout.IntField("Capacity", capacity, EditorStyles.boldLabel); - EditorGUILayout.LongField("Version", Version, EditorStyles.boldLabel); - Color color = leakedEntitesCount > 0 ? Color.yellow : GUI.contentColor; - using (new ContentColorScope(color)) - { - EditorGUILayout.IntField("Leaked Entites", leakedEntitesCount, EditorStyles.boldLabel); - } - } - public static void DrawWorldComponents(EcsWorld world) - { - bool isNull = world == null || world.IsDestroyed || world.ID == 0; - if (isNull) { return; } - using (BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) - { - IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout); - EditorGUILayout.EndFoldoutHeaderGroup(); - if (IsShowRuntimeComponents == false) { return; } - - var worldID = world.ID; - var cmps = world.GetWorldComponents(); - int index = -1; - int total = 9; - foreach (var cmp in cmps) - { - index++; - var meta = cmp.ComponentType.ToMeta(); - if (meta.IsHidden == false || IsShowHidden) - { - Type componentType = cmp.ComponentType; - - object data = cmp.GetRaw(worldID); - - ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType); - - float padding = EditorGUIUtility.standardVerticalSpacing; - Rect optionButton = GUILayoutUtility.GetLastRect(); - optionButton.yMin = optionButton.yMax; - optionButton.yMax += HeadIconsRect.height; - optionButton.xMin = optionButton.xMax - 64; - optionButton.center += Vector2.up * padding * 2f; - //Canceling isExpanded - if (ClickTest(optionButton)) - { - ref bool isExpanded = ref expandMatrix.Down(); - isExpanded = !isExpanded; - } - - Color panelColor = SelectPanelColor(meta, index, total); - GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA)); - EditorGUI.BeginChangeCheck(); - - ////Close button - //optionButton.xMin = optionButton.xMax - HeadIconsRect.width; - //if (CloseButton(optionButton)) - //{ - // cmp.Del(worldID); - // return; - //} - - //Edit script button - if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script)) - { - optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); - EcsGUI.ScriptAssetButton(optionButton, script); - } - //Description icon - if (string.IsNullOrEmpty(meta.Description.Text) == false) - { - optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); - DescriptionIcon(optionButton, meta.Description.Text); - } - - RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name); - if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData)) - { - cmp.SetRaw(worldID, resultData); - } - - GUILayout.EndVertical(); - } - } - } - } - - #region entity bar - public static void EntityBarForAlive(EntityStatus status, int id, short gen, short world) - { - float width = EditorGUIUtility.currentViewWidth; - float height = EntityBarHeight; - EcsGUI.EntityBarForAlive(GUILayoutUtility.GetRect(width, height), status, id, gen, world); - } - public static void EntityBar(EntityStatus status, bool isPlaceholder, int id, short gen, short world) - { - float width = EditorGUIUtility.currentViewWidth; - float height = EntityBarHeight; - EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height), isPlaceholder, status, id, gen, world); - } - public static void EntityBar(int id, short gen, short world) - { - float width = EditorGUIUtility.currentViewWidth; - float height = EntityBarHeight; - EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height), id, gen, world); - } - public static void EntityBar() - { - float width = EditorGUIUtility.currentViewWidth; - float height = EntityBarHeight; - EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height)); - } - #endregion - - public static bool AddComponentButtons(out Rect dropDownRect) - { - return EcsGUI.AddComponentButton(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); - } - public static AddClearButton AddClearComponentButtons(out Rect dropDownRect) - { - return EcsGUI.AddClearComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); - } - public static AddClearButton AddClearSystemButtons(out Rect dropDownRect) - { - return EcsGUI.AddClearSystemButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 24f), out dropDownRect); - } - public static void DrawRuntimeComponents(entlong entity, bool isWithFoldout = true) - { - if (entity.TryUnpackForUnityEditor(out int entityID, out _, out _, out EcsWorld world)) - { - DrawRuntimeComponents(entityID, world, isWithFoldout); - } - } - - [ThreadStatic] - private static List _componentPoolsBuffer; - public static void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout = true) - { - using (BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) - { - if (isWithFoldout) - { - IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout); - EditorGUILayout.EndFoldoutHeaderGroup(); - } - if (isWithFoldout == false || IsShowRuntimeComponents) - { - if (AddComponentButtons(out Rect dropDownRect)) - { - RuntimeComponentsUtility.GetAddComponentGenericMenu(world).Open(dropDownRect, entityID); - } - - GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true)); - IsShowHidden = EditorGUI.Toggle(GUILayoutUtility.GetLastRect(), "Show Hidden", IsShowHidden); - - if (_componentPoolsBuffer == null) - { - _componentPoolsBuffer = new List(64); - } - world.GetComponentPoolsFor(entityID, _componentPoolsBuffer); - int i = 0; - //int iMax = _componentPoolsBuffer.Count; - foreach (var componentPool in _componentPoolsBuffer) - { - DrawRuntimeComponent(entityID, componentPool, 9, i++); - } - } - } - } - private static void DrawRuntimeComponent(int entityID, IEcsPool pool, int total, int index) - { - var meta = pool.ComponentType.ToMeta(); - if (meta.IsHidden == false || IsShowHidden) - { - Type componentType = pool.ComponentType; - - object data = pool.GetRaw(entityID); - - ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType); - - float padding = EditorGUIUtility.standardVerticalSpacing; - Rect optionButton = GUILayoutUtility.GetLastRect(); - optionButton.yMin = optionButton.yMax; - optionButton.yMax += HeadIconsRect.height; - optionButton.xMin = optionButton.xMax - 64; - optionButton.center += Vector2.up * padding * 2f; - //Canceling isExpanded - if (ClickTest(optionButton)) - { - ref bool isExpanded = ref expandMatrix.Down(); - isExpanded = !isExpanded; - } - - Color panelColor = SelectPanelColor(meta, index, total); - GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA)); - EditorGUI.BeginChangeCheck(); - - //Close button - optionButton.xMin = optionButton.xMax - HeadIconsRect.width; - if (CloseButton(optionButton)) - { - pool.Del(entityID); - return; - } - //Edit script button - if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script)) - { - optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); - EcsGUI.ScriptAssetButton(optionButton, script); - } - //Description icon - if (string.IsNullOrEmpty(meta.Description.Text) == false) - { - optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); - DescriptionIcon(optionButton, meta.Description.Text); - } - - RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name); - if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData)) - { - pool.SetRaw(entityID, resultData); - } - - GUILayout.EndVertical(); - } - } - - #region Default DrawRuntimeData - [InitializeOnLoadMethod] - private static void ResetRuntimeComponentReflectionCache() - { - _runtimeComponentReflectionCaches.Clear(); - } - internal class RuntimeComponentReflectionCache - { - public readonly Type Type; - - 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 _runtimeComponentReflectionCaches = new Dictionary(); - 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; - Type type = data == null ? typeof(void) : data.GetType(); - - RuntimeComponentReflectionCache cache = GetRuntimeComponentReflectionCache(type); - - bool isUnityObjectField = fieldInfoData.IsUnityObjectField; - if (isUnityObjectField == false && data == null) - { - EditorGUILayout.TextField(label, "Null"); - return false; - } - bool isUnityObjectType = cache.IsUnityObjectType; - - ref bool isExpanded = ref expandMatrix.Down(); - bool changed = false; - - - if (cache.IsUnitySerializable == false) - { - isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(isExpanded, label, EditorStyles.foldout); - EditorGUILayout.EndFoldoutHeaderGroup(); - - if (isExpanded) - { - using (UpIndentLevel()) - { - for (int j = 0, jMax = cache.Fields.Length; j < jMax; j++) - { - var field = cache.Fields[j]; - if (DrawRuntimeData(ref field, UnityEditorUtility.GetLabel(field.UnityFormatName), expandMatrix, field.FieldInfo.GetValue(data), out object fieldData)) - { - field.FieldInfo.SetValue(data, fieldData); - outData = data; - changed = true; - } - } - } - } - } - else - { - Type fieldType = fieldInfoData.FieldType; - if (isUnityObjectType || isUnityObjectField) - { - EditorGUI.BeginChangeCheck(); - var uobj = UnsafeUtility.As(ref data); - - bool isComponent = typeof(UnityComponent).IsAssignableFrom(fieldType); - if (isComponent) - { - uobj = EditorGUILayout.ObjectField(label, uobj, typeof(UnityObject), true); - } - else - { - uobj = EditorGUILayout.ObjectField(label, uobj, fieldType, true); - } - - if (EditorGUI.EndChangeCheck()) - { - if (isComponent && uobj is GameObject go) - { - uobj = go.GetComponent(fieldType); - } - - outData = uobj; - changed = true; - } - } - else - { - EditorGUI.BeginChangeCheck(); - //WrapperBase wrapper = RefEditorWrapper.Take(data); - - RefEditorWrapper wrapper = cache.Wrapper; - - 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()) - { - isExpanded = wrapper.IsExpanded; - wrapper.SO.ApplyModifiedProperties(); - outData = wrapper.Data; - changed = true; - } - //wrapper.Release(); - } - } - - expandMatrix.Up(); - return changed; - } - #endregion - - #region FactMode DrawRuntimeData - private class InspectorTypeInfo - { - #region cahce - private static Dictionary _typeInfosCache = new Dictionary(); - public static InspectorTypeInfo Get(Type type) - { - if (_typeInfosCache.TryGetValue(type, out InspectorTypeInfo info) == false) - { - info = new InspectorTypeInfo(type); - _typeInfosCache.Add(type, info); - } - - return info; - } - #endregion - - public readonly Type Type; - public readonly InspectorFieldInfo[] Fields; - - #region Constructors - private static StructList CnstrBuffer = new StructList(32); - private static readonly char[] VectorFields = new char[] { 'x', 'y', 'z', 'w' }; - private static readonly char[] ColorFields = new char[] { 'r', 'g', 'b', 'a' }; - public InspectorTypeInfo(Type type) - { - CnstrBuffer.FastClear(); - Type = type; - var fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - foreach (var fieldInfo in fieldInfos) - { - InspectorFieldInfo.Union infoUniton = default; - ref InspectorFieldInfo.Constructor infocstr = ref infoUniton.Constructor; - - var fieldType = fieldInfo.FieldType; - - infocstr.FieldInfo = fieldInfo; - infocstr.Offset = UnsafeUtility.GetFieldOffset(fieldInfo); ; - infocstr.Size = UnsafeUtility.SizeOf(fieldType); ; - infocstr.Name = UnityEditorUtility.TransformFieldName(fieldType.Name); - infocstr.TypeID = FieldTypeIDUtitlity.GetFieldTypeIDFor(fieldType); - - #region Def custom types - if (infocstr.TypeID == FieldTypeID.Struct) - { - InspectorTypeInfo preDefinedTypeInfo = Get(fieldType); - infocstr.PreDefinedType = preDefinedTypeInfo; - int length = preDefinedTypeInfo.Fields.Length; - if (length >= 2 && length <= 3) - { - bool isCheck = true; - for (int i = 0; i < length; i++) - { - ref var field = ref preDefinedTypeInfo.Fields[i]; - if (char.ToLower(field.Name[0]) != VectorFields[i]) - { - isCheck = false; - break; - } - } - if (isCheck) - { - infocstr.TypeID = FieldTypeID.StructVector; - } - else - { - isCheck = true; - for (int i = 0; i < length; i++) - { - ref var field = ref preDefinedTypeInfo.Fields[i]; - if (char.ToLower(field.Name[0]) != ColorFields[i]) - { - isCheck = false; - break; - } - } - if (isCheck) - { - infocstr.TypeID = FieldTypeID.StructColor; - } - } - } - } - #endregion - - CnstrBuffer.Add(infoUniton.Result); - } - - Fields = CnstrBuffer.ToArray(); - Array.Sort(Fields); - } - #endregion - } - - private static class FieldTypeIDUtitlity - { - #region GetFieldTypeIDFor - public static FieldTypeID GetFieldTypeIDFor(Type type) - { - var size = UnsafeUtility.SizeOf(type); - if (type.IsClass) - { - if (typeof(UnityObject).IsAssignableFrom(type)) - { - return FieldTypeID.UnityObject; - } - if (type == typeof(string)) - { - return FieldTypeID.String; - } - if (type == typeof(AnimationCurve)) - { - return FieldTypeID.AnimationCurve; - } - if (type == typeof(Gradient)) - { - return FieldTypeID.Gradient; - } - if (type == typeof(Array)) - { - return FieldTypeID.RefArray; - } - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) - { - return FieldTypeID.RefArray; - } - - return FieldTypeID.Ref; - } - else - { - if (type.IsPrimitive) - { - if (UnsafeUtility.IsBlittable(type)) - { - switch (size) - { - case 1: - if (type == typeof(byte)) - { - return FieldTypeID.UInt; - } - if (type == typeof(sbyte)) - { - return FieldTypeID.Int; - } - break; - case 2: - if (type == typeof(ushort)) - { - return FieldTypeID.UInt; - } - if (type == typeof(short)) - { - return FieldTypeID.Int; - } - break; - case 4: - if (type == typeof(uint)) - { - return FieldTypeID.UInt; - } - if (type == typeof(int)) - { - return FieldTypeID.Int; - } - if (type == typeof(float)) - { - return FieldTypeID.Real; - } - break; - case 8: - if (type == typeof(ulong)) - { - return FieldTypeID.UInt; - } - if (type == typeof(long)) - { - return FieldTypeID.Int; - } - if (type == typeof(double)) - { - return FieldTypeID.Real; - } - break; - } - } - else - { - if (type == typeof(bool)) - { - return FieldTypeID.Bool; - } - } - } - else if (type.IsEnum) - { - return FieldTypeID.Enum; - } - - if (type == typeof(LayerMask)) - { - return FieldTypeID.LayerMask; - } - - return FieldTypeID.Struct; - } - } - #endregion - } - private enum FieldTypeID : byte - { - None = 0, - CantDisplayed, - - // leaf types - Bool, - Int, - UInt, - Real, - String, - Enum, - - UnityObject, - LayerMask, - Gradient, - AnimationCurve, - - // struct types - Struct, - Ref, - - // custom struct types - StructVector, - StructColor, - RefArray, - RefList, - } - - [StructLayout(LayoutKind.Sequential)] - private unsafe readonly struct InspectorFieldInfo : IEquatable, IComparable - { - public readonly FieldInfo FieldInfo; - public readonly InspectorTypeInfo PreDefinedType; - public readonly string Name; - public readonly int Offset; - public readonly int Size; - public readonly FieldTypeID ID; - - public int CompareTo(InspectorFieldInfo other) - { - return other.Offset - Offset; - } - public bool Equals(InspectorFieldInfo other) - { - return EqualityComparer.Default.Equals(this, other); - } - [StructLayout(LayoutKind.Sequential)] - public unsafe struct Constructor - { - public FieldInfo FieldInfo; - public InspectorTypeInfo PreDefinedType; - public string Name; - public int Offset; - public int Size; - public byte AxisCount; - public FieldTypeID TypeID; - } - [StructLayout(LayoutKind.Explicit)] - public struct Union - { - [FieldOffset(0)] - public Constructor Constructor; - [FieldOffset(0)] - public InspectorFieldInfo Result; - } - } - private unsafe static bool FastDrawRuntimeData(void* data, InspectorTypeInfo cache) - { - throw new NotImplementedException(); - } - #endregion - } +#endregion } } #endif \ No newline at end of file diff --git a/src/Internal/Icons/Color_Icon.png b/src/Internal/Icons/Color_Icon.png deleted file mode 100644 index 69278be..0000000 Binary files a/src/Internal/Icons/Color_Icon.png and /dev/null differ diff --git a/src/Internal/Icons/Color_Icon.png.meta b/src/Internal/Icons/Color_Icon.png.meta deleted file mode 100644 index cb32197..0000000 --- a/src/Internal/Icons/Color_Icon.png.meta +++ /dev/null @@ -1,122 +0,0 @@ -fileFormatVersion: 2 -guid: f6905846bdee2584393b2583d00d10f3 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMasterTextureLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 0 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 2 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/src/Internal/Icons/Gray_Icon.png b/src/Internal/Icons/Gray_Icon.png deleted file mode 100644 index 6d875a8..0000000 Binary files a/src/Internal/Icons/Gray_Icon.png and /dev/null differ diff --git a/src/Internal/Icons/Gray_Icon.png.meta b/src/Internal/Icons/Gray_Icon.png.meta deleted file mode 100644 index 7e74db9..0000000 --- a/src/Internal/Icons/Gray_Icon.png.meta +++ /dev/null @@ -1,122 +0,0 @@ -fileFormatVersion: 2 -guid: f1fe20f167697834b815161036625d65 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMasterTextureLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 0 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 2 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/src/Internal/Utils/StructList.cs b/src/Internal/Utils/StructList.cs index 83efadf..793319d 100644 --- a/src/Internal/Utils/StructList.cs +++ b/src/Internal/Utils/StructList.cs @@ -11,6 +11,22 @@ namespace DCFApixels.DragonECS.Unity.Internal { internal T[] _items; internal int _count; + + public IEnumerable Enumerable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _items.Take(_count); } + } + public bool IsNull + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _items == null; } + } + public bool IsNullOrEmpty + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _items == null || _items.Length <= 0; } + } public int Count { [MethodImpl(MethodImplOptions.AggressiveInlining)]