#if UNITY_EDITOR using DCFApixels.DragonECS.Core; 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.X { internal class RuntimeComponentsDrawer { private const BindingFlags INSTANCE_FIELD_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void ResetRuntimeComponentReflectionCache() { RefEditorWrapper.ResetStaticState(); foreach (var item in _runtimeComponentReflectionCaches) { item.Value.ResetWrappers(); } //_runtimeComponentReflectionCaches.Clear(); } private const int RuntimeComponentsMaxDepth = 2; private const int RuntimeComponentsDepthRoot = -1; private static RuntimeComponentsDrawer[] _drawers; private static int _runtimeComponentsDepth = RuntimeComponentsDepthRoot; static RuntimeComponentsDrawer() { _drawers = new RuntimeComponentsDrawer[RuntimeComponentsMaxDepth + 1]; _drawers[0] = new RuntimeComponentsDrawer(); _drawers[1] = new RuntimeComponentsDrawer(); _drawers[2] = new RuntimeComponentsDrawer(); } private List _componentPoolsBuffer = new List(64); #region Properties private static RuntimeDrawMode RuntimeDrawMode { get { return UserSettingsPrefs.instance.RuntimeDrawMode; } set { UserSettingsPrefs.instance.RuntimeDrawMode = value; } } private static bool IsShowHidden { get { return UserSettingsPrefs.instance.IsShowHidden; } set { UserSettingsPrefs.instance.IsShowHidden = value; } } private static bool IsShowRuntimeComponents { get { return UserSettingsPrefs.instance.IsShowRuntimeComponents; } set { UserSettingsPrefs.instance.IsShowRuntimeComponents = value; } } #endregion #region reflection cache internal class RuntimeComponentReflectionCache { public readonly Type Type; public readonly bool IsValueType; public readonly bool IsUnmanaged; public readonly DrawerType DrawerType; public readonly FieldInfoData[] Fields; private RefEditorWrapper[] _wrappers = new RefEditorWrapper[RuntimeComponentsMaxDepth]; public RefEditorWrapper GetWrapper(int depth) { return _wrappers[depth]; } public RuntimeComponentReflectionCache(Type type) { Type = type; ResetWrappers(); IsUnmanaged = UnsafeUtility.IsUnmanaged(type); IsValueType = type.IsValueType; bool isVoideType = type == typeof(void); bool isUnityObjectType = typeof(UnityObject).IsAssignableFrom(type); bool isLeaf = isUnityObjectType || type.IsPrimitive || type == typeof(string) || type.IsEnum; DrawerType = DrawerType.UNDEFINED; if(type.IsArray || isVoideType) { DrawerType = DrawerType.Ignored; } if (DrawerType == DrawerType.UNDEFINED && isLeaf) { if (type.IsEnum) { DrawerType = type.HasAttribute() ? DrawerType.EnumFlags : DrawerType.Enum; } else if (isUnityObjectType) { DrawerType = DrawerType.UnityObject; } else if (type == typeof(bool)) { DrawerType = DrawerType.Bool; } else if (type == typeof(string)) { DrawerType = DrawerType.String; } else if (type == typeof(float)) { DrawerType = DrawerType.Float; } else if (type == typeof(double)) { DrawerType = DrawerType.Double; } else if (type == typeof(byte)) { DrawerType = DrawerType.Byte; } else if (type == typeof(sbyte)) { DrawerType = DrawerType.SByte; } else if (type == typeof(short)) { DrawerType = DrawerType.Short; } else if (type == typeof(ushort)) { DrawerType = DrawerType.UShort; } else if (type == typeof(int)) { DrawerType = DrawerType.Int; } else if (type == typeof(uint)) { DrawerType = DrawerType.UInt; } else if (type == typeof(long)) { DrawerType = DrawerType.Long; } else if (type == typeof(ulong)) { DrawerType = DrawerType.ULong; } } if (DrawerType == DrawerType.UNDEFINED) { DrawerType = type.IsGenericType ? DrawerType.UnityNotSerializableComposite : DrawerType.UnitySerializableComposite; } if (isVoideType) { return; } if (DrawerType == DrawerType.UnityNotSerializableComposite) { var fieldInfos = type.GetFields(INSTANCE_FIELD_FLAGS); Fields = new FieldInfoData[fieldInfos.Length]; for (int i = 0; i < fieldInfos.Length; i++) { var fieldInfo = fieldInfos[i]; Fields[i] = new FieldInfoData(fieldInfo); } } } public void ResetWrappers() { _wrappers[0] = RefEditorWrapper.Take(); _wrappers[1] = RefEditorWrapper.Take(); } public readonly struct FieldInfoData { public readonly FieldInfo FieldInfo; public readonly Type FieldType; public readonly string UnityFormatName; public readonly bool IsUnityObjectField; public readonly bool IsPassToUnitySerialize; public readonly RuntimeComponentReflectionCache ValueTypeReflectionCache; public FieldInfoData(FieldInfo fieldInfo) { FieldInfo = fieldInfo; FieldType = fieldInfo.FieldType; IsUnityObjectField = typeof(UnityObject).IsAssignableFrom(fieldInfo.FieldType); UnityFormatName = UnityEditorUtility.TransformFieldName(fieldInfo.Name); IsPassToUnitySerialize = (fieldInfo.IsPublic || fieldInfo.HasAttribute() || fieldInfo.HasAttribute()) && (fieldInfo.IsInitOnly || fieldInfo.HasAttribute()) == false; ValueTypeReflectionCache = FieldType.IsValueType ? GetRuntimeComponentReflectionCache(FieldType) : null; } public FieldInfoData(FieldInfo fieldInfo, Type fieldType, string unityFormatName, bool isPassToSerialize = true) { FieldInfo = fieldInfo; FieldType = fieldType; UnityFormatName = unityFormatName; IsUnityObjectField = typeof(UnityObject).IsAssignableFrom(fieldType); IsPassToUnitySerialize = isPassToSerialize; ValueTypeReflectionCache = FieldType.IsValueType ? GetRuntimeComponentReflectionCache(FieldType) : null; } public RuntimeComponentReflectionCache GetReflectionCache(Type type) { if (ValueTypeReflectionCache != null) { return ValueTypeReflectionCache; } return GetRuntimeComponentReflectionCache(type); } } } 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; } #endregion #region draw world component public static void DrawWorldComponents(EcsWorld world) { if (_runtimeComponentsDepth == RuntimeComponentsDepthRoot) { try { _runtimeComponentsDepth = 0; _drawers[0].DrawWorldComponents_Internal(world); } finally { _runtimeComponentsDepth = RuntimeComponentsDepthRoot; } } } private void DrawWorldComponents_Internal(EcsWorld world) { bool isNull = world == null || world.IsDestroyed || world.ID == 0; if (isNull) { return; } using (DragonGUI.Layout.BeginVertical(UnityEditorUtility.GetTransperentBlackBackgrounStyle())) { 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.GetMeta(); if (meta.IsHidden == false || IsShowHidden) { Type componentType = cmp.ComponentType; object data = cmp.GetRaw(worldID); ExpandStack expandStack = ExpandStack.Take(componentType); float padding = EditorGUIUtility.standardVerticalSpacing; Rect optionButton = GUILayoutUtility.GetLastRect(); optionButton.yMin = optionButton.yMax; optionButton.yMax += DragonGUI.HeadIconsRect.height; optionButton.xMin = optionButton.xMax - 64; optionButton.center += Vector2.up * padding * 2f; //Canceling isExpanded if (DragonGUI.ClickTest(optionButton)) { ref bool isExpanded = ref expandStack.Down(); isExpanded = !isExpanded; } Color panelColor = DragonGUI.SelectPanelColor(meta, index, total); using (DragonGUI.Layout.BeginVertical(panelColor.SetAlpha(EscEditorConsts.MetaBlockFillStyle_Alpha))) { //Edit script button if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script)) { optionButton = DragonGUI.HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); DragonGUI.ScriptAssetButton(optionButton, script); } //Description icon if (string.IsNullOrEmpty(meta.Description.Text) == false) { optionButton = DragonGUI.HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); DragonGUI.DescriptionIcon(optionButton, meta.Description.Text); } RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name); if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandStack, data, out object resultData, 0)) { cmp.SetRaw(worldID, resultData); } } } } } } #endregion #region draw entity component public static void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout, bool isRoot) { if (isRoot) { _runtimeComponentsDepth = RuntimeComponentsDepthRoot; } _runtimeComponentsDepth++; try { _drawers[_runtimeComponentsDepth].DrawRuntimeComponents(entityID, world, isWithFoldout); } finally { _runtimeComponentsDepth--; if (_runtimeComponentsDepth < RuntimeComponentsDepthRoot) { _runtimeComponentsDepth = RuntimeComponentsDepthRoot; } } } private void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout) { using (DragonGUI.Layout.BeginVertical(UnityEditorUtility.GetTransperentBlackBackgrounStyle())) using (DragonGUI.SetIndentLevel(0)) { if (_runtimeComponentsDepth >= RuntimeComponentsMaxDepth) { GUILayout.Label("Max depth for inspecting components at runtime"); return; } if (isWithFoldout) { IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout); EditorGUILayout.EndFoldoutHeaderGroup(); } if (isWithFoldout == false || IsShowRuntimeComponents) { if (DragonGUI.Layout.AddComponentButtons(out Rect dropDownRect)) { RuntimeComponentsUtility.GetAddComponentGenericMenu(world).Open(dropDownRect, entityID); } using (DragonGUI.Layout.BeginVertical(Color.white.SetAlpha(0.066f))) { IsShowHidden = EditorGUILayout.Toggle("Show Hidden", IsShowHidden); RuntimeDrawMode = (RuntimeDrawMode)EditorGUILayout.EnumPopup("Draw Mode", selected: RuntimeDrawMode); } world.GetComponentPoolsFor(entityID, _componentPoolsBuffer); for (int i = 0; i < _componentPoolsBuffer.Count; i++) { var pool = _componentPoolsBuffer[i]; if (pool.ComponentType.IsValueType) { DrawRuntimeValueComponent(entityID, pool, 9, i); } else { DrawRuntimeClassComponent(entityID, pool, 9, i); } } } } } private struct DrawRuntimeCompoentnsCahce : IEcsWorldComponent { public EcsWorld World; public Record[] Records; void IEcsWorldComponent.Init(ref DrawRuntimeCompoentnsCahce component, EcsWorld world) { component.World = world; component.Records = new Record[world.Count]; } void IEcsWorldComponent.OnDestroy(ref DrawRuntimeCompoentnsCahce component, EcsWorld world) { } public ref Record GetFor(int componentTypeID) { if(componentTypeID >= Records.Length) { var newSize = DragonArrayUtility.NextPow2(componentTypeID + 1); Array.Resize(ref Records, newSize); } ref var result = ref Records[componentTypeID]; if(result.IsInit == false && World.TryFindPoolInstance(componentTypeID, out var pool)) { var componentType = pool.ComponentType; result.Meta = componentType.GetMeta(); result.ExpandStack = ExpandStack.Take(componentType); result.FieldInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, result.Meta.Name); if (ScriptsCache.TryGetScriptAsset(result.Meta, out result.ScriptReference) == false) { result.ScriptReference = null; } result.IsInit = true; } return ref result; } public struct Record { public bool IsInit; public TypeMeta Meta; public ExpandStack ExpandStack; public RuntimeComponentReflectionCache.FieldInfoData FieldInfoData; public MonoScript ScriptReference; } } private void DrawRuntimeValueComponent(int entityID, IEcsPool pool, int total, int index) { ref var cache = ref pool.World.Get().GetFor(pool.ComponentTypeID); var meta = cache.Meta; if (meta.IsHidden == false || IsShowHidden) { float padding = EditorGUIUtility.standardVerticalSpacing; Rect optionButton = GUILayoutUtility.GetLastRect(); optionButton.yMin = optionButton.yMax; optionButton.yMax += DragonGUI.HeadIconsRect.height; optionButton.xMin = optionButton.xMax - 64; optionButton.center += Vector2.up * padding * 2f; Color fillColor = Color.clear; Color backColor = Color.clear; if (Event.current.type == EventType.Repaint) { switch (UserSettingsPrefs.instance.MetaBlockRectStyle) { default: case MetaBlockRectStyle.Clean: { backColor = Color.white.SetAlpha(EscEditorConsts.MetaBlockCleanStyle_Alpha); } break; case MetaBlockRectStyle.Edge: { backColor = Color.white.SetAlpha(EscEditorConsts.MetaBlockCleanStyle_Alpha); fillColor = DragonGUI.SelectPanelColor(meta, index, total) .SetAlpha(EscEditorConsts.MetaBlockEdgeStyle_Alpha); } break; case MetaBlockRectStyle.Fill: { backColor = DragonGUI.SelectPanelColor(meta, index, total) .Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE) .SetAlpha(EscEditorConsts.MetaBlockFillStyle_Alpha); } break; } } using (DragonGUI.Layout.BeginVertical(UnityEditorUtility.GetWhiteStyle(), backColor)) { using (DragonGUI.Layout.BeginVertical(UnityEditorUtility.GetWhiteEdge4Style(), fillColor)) { //Close button optionButton.xMin = optionButton.xMax - DragonGUI.HeadIconsRect.width; if (DragonGUI.CloseButton(optionButton)) { pool.Del(entityID); return; } //Edit script button if (cache.ScriptReference != null) { optionButton = DragonGUI.HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); DragonGUI.ScriptAssetButton(optionButton, cache.ScriptReference); } //Description icon if (string.IsNullOrEmpty(meta.Description.Text) == false) { optionButton = DragonGUI.HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); DragonGUI.DescriptionIcon(optionButton, meta.Description.Text); } ref bool peakExpand = ref cache.ExpandStack.Peek(); var label = UnityEditorUtility.GetLabel(meta.Name); if (peakExpand) { object data = pool.GetRaw(entityID); if (DrawRuntimeData(ref cache.FieldInfoData, label, cache.ExpandStack, data, out object resultData, 0)) { pool.SetRaw(entityID, resultData); } } else { var foldoutStyle = EditorStyles.foldout; Rect rect = GUILayoutUtility.GetRect(label, foldoutStyle); peakExpand = EditorGUI.BeginFoldoutHeaderGroup(rect, false, label, foldoutStyle, null, null); EditorGUILayout.EndFoldoutHeaderGroup(); } } } } } private void DrawRuntimeClassComponent(int entityID, IEcsPool pool, int total, int index) { object data = pool.GetRaw(entityID); Type componentType = data.GetType(); var meta = componentType.GetMeta(); if (meta.IsHidden == false || IsShowHidden) { ExpandStack expandStack = ExpandStack.Take(componentType); float padding = EditorGUIUtility.standardVerticalSpacing; Rect optionButton = GUILayoutUtility.GetLastRect(); optionButton.yMin = optionButton.yMax; optionButton.yMax += DragonGUI.HeadIconsRect.height; optionButton.xMin = optionButton.xMax - 64; optionButton.center += Vector2.up * padding * 2f; Color fillColor = Color.clear; Color backColor = Color.clear; if (Event.current.type == EventType.Repaint) { switch (UserSettingsPrefs.instance.MetaBlockRectStyle) { default: case MetaBlockRectStyle.Clean: { backColor = Color.white.SetAlpha(EscEditorConsts.MetaBlockCleanStyle_Alpha); } break; case MetaBlockRectStyle.Edge: { backColor = Color.white.SetAlpha(EscEditorConsts.MetaBlockCleanStyle_Alpha); fillColor = DragonGUI.SelectPanelColor(meta, index, total) .SetAlpha(EscEditorConsts.MetaBlockEdgeStyle_Alpha); } break; case MetaBlockRectStyle.Fill: { backColor = DragonGUI.SelectPanelColor(meta, index, total) .Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE) .SetAlpha(EscEditorConsts.MetaBlockFillStyle_Alpha); } break; } } using (DragonGUI.Layout.BeginVertical(UnityEditorUtility.GetWhiteStyle(), backColor)) { using (DragonGUI.Layout.BeginVertical(UnityEditorUtility.GetWhiteEdge4Style(), fillColor)) { //Close button optionButton.xMin = optionButton.xMax - DragonGUI.HeadIconsRect.width; if (DragonGUI.CloseButton(optionButton)) { pool.Del(entityID); return; } //Edit script button if (ScriptsCache.TryGetScriptAsset(meta, out MonoScript script)) { optionButton = DragonGUI.HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); DragonGUI.ScriptAssetButton(optionButton, script); } //Description icon if (string.IsNullOrEmpty(meta.Description.Text) == false) { optionButton = DragonGUI.HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); DragonGUI.DescriptionIcon(optionButton, meta.Description.Text); } RuntimeComponentReflectionCache.FieldInfoData componentInfoData = new RuntimeComponentReflectionCache.FieldInfoData(null, componentType, meta.Name); if (DrawRuntimeData(ref componentInfoData, UnityEditorUtility.GetLabel(meta.Name), expandStack, data, out object resultData, 0)) { pool.SetRaw(entityID, resultData); } } } } } #endregion #region draw data private bool DrawRuntimeData(ref RuntimeComponentReflectionCache.FieldInfoData fieldInfoData, GUIContent label, ExpandStack expandStack, object data, out object outData, int depth) { const int DEPTH_MAX = 24; using (DragonGUI.CheckChanged()) { outData = data; object newData = data; Type type = data == null ? typeof(void) : data.GetType(); bool isUnityObjectField = fieldInfoData.IsUnityObjectField; if (isUnityObjectField == false && data == null) { EditorGUILayout.TextField(label, "Null"); return false; } var reflectionCache = fieldInfoData.GetReflectionCache(type); if (depth >= DEPTH_MAX || reflectionCache == null) { EditorGUILayout.TextField(label, "error"); return false; } ref bool isExpanded = ref expandStack.Down(); bool childElementChanged = false; var eventType = Event.current.type; var label2 = "-"; var drawerType = reflectionCache.DrawerType; if (isUnityObjectField) { drawerType = DrawerType.UnityObject; } switch (drawerType) { case DrawerType.UNDEFINED: { EditorGUILayout.LabelField(label, label2); } break; case DrawerType.Ignored: { EditorGUILayout.LabelField(label, label2); } break; case DrawerType.UnitySerializableComposite: { using (DragonGUI.CheckChanged()) { RefEditorWrapper wrapper = reflectionCache.GetWrapper(_runtimeComponentsDepth); wrapper.data = data; wrapper.SO.Update(); wrapper.IsExpanded = isExpanded; EditorGUILayout.PropertyField(wrapper.Property, label, true); if (DragonGUI.Changed) { wrapper.SO.ApplyModifiedProperties(); newData = wrapper.Data; childElementChanged = true; } isExpanded = wrapper.IsExpanded; } } break; case DrawerType.UnityNotSerializableComposite: { GUILayout.Space(DragonGUI.Spacing); var foldoutStyle = EditorStyles.foldout; Rect rect = GUILayoutUtility.GetRect(label, foldoutStyle); //rect.xMin += EcsGUI.Indent; isExpanded = EditorGUI.BeginFoldoutHeaderGroup(rect, isExpanded, label, foldoutStyle, null, null); EditorGUILayout.EndFoldoutHeaderGroup(); if (isExpanded) { using (DragonGUI.UpIndentLevel()) { for (int j = 0, jMax = reflectionCache.Fields.Length; j < jMax; j++) { var field = reflectionCache.Fields[j]; if (DrawRuntimeData(ref field, UnityEditorUtility.GetLabel(field.UnityFormatName), expandStack, field.FieldInfo.GetValue(data), out object fieldData, depth + 1)) { field.FieldInfo.SetValue(data, fieldData); newData = data; childElementChanged = true; } } } } } break; case DrawerType.UnityObject: { using (DragonGUI.CheckChanged()) { var uobj = UnsafeUtility.As(ref data); bool isComponent = typeof(UnityComponent).IsAssignableFrom(fieldInfoData.FieldType); var newuobj = EditorGUILayout.ObjectField(label, uobj, fieldInfoData.FieldType, true); if (uobj != newuobj) { if (isComponent && newuobj is GameObject go) { newuobj = go.GetComponent(fieldInfoData.FieldType); } newData = newuobj; childElementChanged = true; } } } break; case DrawerType.Enum: { if (eventType != EventType.Layout) { var enumData = UnsafeUtility.As(ref data); newData = EditorGUILayout.EnumPopup(label, enumData); } else { EditorGUILayout.EnumPopup(label, default); } } break; case DrawerType.EnumFlags: { if (eventType != EventType.Layout) { var enumData = UnsafeUtility.As(ref data); newData = EditorGUILayout.EnumFlagsField(label, enumData); } else { EditorGUILayout.EnumFlagsField(label, default); } } break; case DrawerType.Bool: { if (eventType != EventType.Layout) { newData = EditorGUILayout.Toggle(label, (bool)data); } else { EditorGUILayout.Toggle(label, default); } } break; case DrawerType.String: { if (eventType != EventType.Layout) { newData = EditorGUILayout.TextField(label, (string)data); } else { EditorGUILayout.TextField(label, default); } } break; case DrawerType.Float: { if (eventType != EventType.Layout) { newData = EditorGUILayout.FloatField(label, (float)data); } else { EditorGUILayout.FloatField(label, default); } } break; case DrawerType.Double: { if (eventType != EventType.Layout) { newData = EditorGUILayout.DoubleField(label, (double)data); } else { EditorGUILayout.DoubleField(label, default); } } break; case DrawerType.Byte: { if (eventType != EventType.Layout) { newData = (byte)EditorGUILayout.IntField(label, (byte)data); } else { EditorGUILayout.IntField(label, default); } } break; case DrawerType.SByte: { if (eventType != EventType.Layout) { newData = (sbyte)EditorGUILayout.IntField(label, (sbyte)data); } else { EditorGUILayout.IntField(label, default); } } break; case DrawerType.Short: { if (eventType != EventType.Layout) { newData = (short)EditorGUILayout.IntField(label, (short)data); } else { EditorGUILayout.IntField(label, default); } } break; case DrawerType.UShort: { if (eventType != EventType.Layout) { newData = (ushort)EditorGUILayout.IntField(label, (ushort)data); } else { EditorGUILayout.IntField(label, default); } } break; case DrawerType.Int: { if (eventType != EventType.Layout) { newData = (int)EditorGUILayout.IntField(label, (int)data); } else { EditorGUILayout.IntField(label, default); } } break; case DrawerType.UInt: { if (eventType != EventType.Layout) { newData = (uint)EditorGUILayout.IntField(label, (int)(uint)data); } else { EditorGUILayout.IntField(label, default); } } break; case DrawerType.Long: { if (eventType != EventType.Layout) { newData = EditorGUILayout.LongField(label, (long)data); } else { EditorGUILayout.LongField(label, default); } } break; case DrawerType.ULong: { if (eventType != EventType.Layout) { newData = (ulong)EditorGUILayout.LongField(label, (long)(ulong)data); } else { EditorGUILayout.LongField(label, default); } } break; default: { EditorGUILayout.LabelField(label, label2); } break; } expandStack.Up(); if (childElementChanged || DragonGUI.Changed) { outData = newData; return true; } } return false; } public enum DrawerType { UNDEFINED = 0, Ignored, // Composite UnitySerializableComposite, UnityNotSerializableComposite, // Leaft types UnityObject, Enum, EnumFlags, Bool, String, Float, Double, Byte, SByte, Short, UShort, Int, UInt, Long, ULong, } #endregion } } #endif