Compare commits

...

5 Commits

Author SHA1 Message Date
DCFApixels
d21c65742b Update package.json 2025-05-14 20:41:36 +08:00
DCFApixels
cb733e8903 Update RuntimeComponentsDrawer.cs 2025-05-14 20:31:01 +08:00
DCFApixels
64bc896457 Update RuntimeComponentsDrawer.cs 2025-05-14 20:26:17 +08:00
DCFApixels
6d0a572c80 refactoring RuntimeComponentsDrawer 2025-05-14 20:21:35 +08:00
DCFApixels
ed499de283 refactoring RuntimeComponentsDrawer 2025-05-14 20:19:40 +08:00
3 changed files with 351 additions and 293 deletions

View File

@ -8,7 +8,7 @@
"displayName": "DragonECS-Unity", "displayName": "DragonECS-Unity",
"description": "Integration with Unity for DragonECS", "description": "Integration with Unity for DragonECS",
"unity": "2021.2", "unity": "2021.2",
"version": "0.5.14", "version": "0.5.14_1",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/DCFApixels/DragonECS-Unity.git" "url": "https://github.com/DCFApixels/DragonECS-Unity.git"

View File

@ -15,7 +15,8 @@ namespace DCFApixels.DragonECS.Unity.Editors.X
{ {
internal class RuntimeComponentsDrawer internal class RuntimeComponentsDrawer
{ {
private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const BindingFlags INSTANCE_FIELD_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetRuntimeComponentReflectionCache() private static void ResetRuntimeComponentReflectionCache()
{ {
@ -28,6 +29,7 @@ namespace DCFApixels.DragonECS.Unity.Editors.X
} }
private const int RuntimeComponentsMaxDepth = 2; private const int RuntimeComponentsMaxDepth = 2;
private const int RuntimeComponentsDepthRoot = -1; private const int RuntimeComponentsDepthRoot = -1;
private static RuntimeComponentsDrawer[] _drawers; private static RuntimeComponentsDrawer[] _drawers;
private static int _runtimeComponentsDepth = RuntimeComponentsDepthRoot; private static int _runtimeComponentsDepth = RuntimeComponentsDepthRoot;
static RuntimeComponentsDrawer() static RuntimeComponentsDrawer()
@ -63,35 +65,11 @@ namespace DCFApixels.DragonECS.Unity.Editors.X
internal class RuntimeComponentReflectionCache internal class RuntimeComponentReflectionCache
{ {
public readonly Type Type; public readonly Type Type;
public readonly bool IsUnityObjectType;
public readonly bool IsUnitySerializable;
public readonly bool IsCompositeType;
public readonly bool IsUnmanaged; public readonly bool IsUnmanaged;
public readonly DrawerType DrawerType;
public readonly bool IsLeaf;
public readonly LeafType LeafPropertyType;
public enum LeafType
{
NONE = 0,
Enum,
Bool,
String,
Float,
Double,
Byte,
SByte,
Short,
UShort,
Int,
UInt,
Long,
ULong,
}
public readonly FieldInfoData[] Fields; public readonly FieldInfoData[] Fields;
private RefEditorWrapper[] _wrappers = new RefEditorWrapper[2]; private RefEditorWrapper[] _wrappers = new RefEditorWrapper[RuntimeComponentsMaxDepth];
public RefEditorWrapper GetWrapper(int depth) public RefEditorWrapper GetWrapper(int depth)
{ {
return _wrappers[depth]; return _wrappers[depth];
@ -102,87 +80,88 @@ namespace DCFApixels.DragonECS.Unity.Editors.X
Type = type; Type = type;
ResetWrappers(); ResetWrappers();
IsUnmanaged = UnsafeUtility.IsUnmanaged(type); IsUnmanaged = UnsafeUtility.IsUnmanaged(type);
IsUnityObjectType = typeof(UnityObject).IsAssignableFrom(type);
LeafPropertyType = LeafType.NONE; bool isVoideType = type == typeof(void);
IsLeaf = type.IsPrimitive || type == typeof(string) || type.IsEnum; bool isUnityObjectType = typeof(UnityObject).IsAssignableFrom(type);
bool isLeaf = isUnityObjectType || type.IsPrimitive || type == typeof(string) || type.IsEnum;
if (IsLeaf) DrawerType = DrawerType.UNDEFINED;
if(type.IsArray || isVoideType)
{
DrawerType = DrawerType.Ignored;
}
if (DrawerType == DrawerType.UNDEFINED && isLeaf)
{ {
if (type.IsEnum) if (type.IsEnum)
{ {
LeafPropertyType = LeafType.Enum; DrawerType = type.HasAttribute<FlagsAttribute>() ? DrawerType.EnumFlags : DrawerType.Enum;
}
else if (isUnityObjectType)
{
DrawerType = DrawerType.UnityObject;
} }
else if (type == typeof(bool)) else if (type == typeof(bool))
{ {
LeafPropertyType = LeafType.Bool; DrawerType = DrawerType.Bool;
} }
else if (type == typeof(string)) else if (type == typeof(string))
{ {
LeafPropertyType = LeafType.String; DrawerType = DrawerType.String;
} }
else if (type == typeof(float)) else if (type == typeof(float))
{ {
LeafPropertyType = LeafType.Float; DrawerType = DrawerType.Float;
} }
else if (type == typeof(double)) else if (type == typeof(double))
{ {
LeafPropertyType = LeafType.Double; DrawerType = DrawerType.Double;
} }
else if (type == typeof(byte)) else if (type == typeof(byte))
{ {
LeafPropertyType = LeafType.Byte; DrawerType = DrawerType.Byte;
} }
else if (type == typeof(sbyte)) else if (type == typeof(sbyte))
{ {
LeafPropertyType = LeafType.SByte; DrawerType = DrawerType.SByte;
} }
else if (type == typeof(short)) else if (type == typeof(short))
{ {
LeafPropertyType = LeafType.Short; DrawerType = DrawerType.Short;
} }
else if (type == typeof(ushort)) else if (type == typeof(ushort))
{ {
LeafPropertyType = LeafType.UShort; DrawerType = DrawerType.UShort;
} }
else if (type == typeof(int)) else if (type == typeof(int))
{ {
LeafPropertyType = LeafType.Int; DrawerType = DrawerType.Int;
} }
else if (type == typeof(uint)) else if (type == typeof(uint))
{ {
LeafPropertyType = LeafType.UInt; DrawerType = DrawerType.UInt;
} }
else if (type == typeof(long)) else if (type == typeof(long))
{ {
LeafPropertyType = LeafType.Long; DrawerType = DrawerType.Long;
} }
else if (type == typeof(ulong)) else if (type == typeof(ulong))
{ {
LeafPropertyType = LeafType.ULong; DrawerType = DrawerType.ULong;
} }
} }
if (DrawerType == DrawerType.UNDEFINED)
IsUnitySerializable =
IsUnityObjectType ||
//typeof(Array).IsAssignableFrom(type) ||
//(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) ||
//type.IsPrimitive ||
//type == typeof(string) ||
//type.IsEnum ||
(!type.IsGenericType && type.HasAttribute<System.SerializableAttribute>() && type.IsArray == false);
IsCompositeType =
type.IsPrimitive == false &&
type.IsArray == false &&
type != typeof(string);
if (type == typeof(void)) { return; }
if (IsUnitySerializable == false)
{ {
var fieldInfos = type.GetFields(fieldFlags); 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]; Fields = new FieldInfoData[fieldInfos.Length];
for (int i = 0; i < fieldInfos.Length; i++) for (int i = 0; i < fieldInfos.Length; i++)
{ {
@ -204,6 +183,7 @@ namespace DCFApixels.DragonECS.Unity.Editors.X
public readonly bool IsUnityObjectField; public readonly bool IsUnityObjectField;
public readonly bool IsPassToUnitySerialize; public readonly bool IsPassToUnitySerialize;
public readonly RuntimeComponentReflectionCache ValueTypeReflectionCache; public readonly RuntimeComponentReflectionCache ValueTypeReflectionCache;
public FieldInfoData(FieldInfo fieldInfo) public FieldInfoData(FieldInfo fieldInfo)
{ {
FieldInfo = fieldInfo; FieldInfo = fieldInfo;
@ -448,266 +428,301 @@ namespace DCFApixels.DragonECS.Unity.Editors.X
#region draw data #region draw data
private bool DrawRuntimeData(ref RuntimeComponentReflectionCache.FieldInfoData fieldInfoData, GUIContent label, ExpandMatrix expandMatrix, object data, out object outData, int depth) private bool DrawRuntimeData(ref RuntimeComponentReflectionCache.FieldInfoData fieldInfoData, GUIContent label, ExpandMatrix expandMatrix, object data, out object outData, int depth)
{ {
const int DEPTH_MAX = 64; const int DEPTH_MAX = 24;
outData = data;
Type type = data == null ? typeof(void) : data.GetType();
RuntimeComponentReflectionCache cache = fieldInfoData.GetReflectionCache(type); using (EcsGUI.CheckChanged())
bool isUnityObjectField = fieldInfoData.IsUnityObjectField;
if (isUnityObjectField == false && data == null)
{ {
EditorGUILayout.TextField(label, "Null");
return false;
}
if (depth >= DEPTH_MAX || cache == null)
{
EditorGUILayout.TextField(label, "error");
return false;
}
bool isUnityObjectType = cache.IsUnityObjectType;
ref bool isExpanded = ref expandMatrix.Down(); outData = data;
bool changed = false; object newData = data;
Type type = data == null ? typeof(void) : data.GetType();
if (cache.IsUnitySerializable == false && cache.IsCompositeType) bool isUnityObjectField = fieldInfoData.IsUnityObjectField;
{ if (isUnityObjectField == false && data == null)
GUILayout.Space(EcsGUI.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 (EcsGUI.UpIndentLevel()) EditorGUILayout.TextField(label, "Null");
{ return false;
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, depth + 1))
{
field.FieldInfo.SetValue(data, fieldData);
outData = data;
changed = true;
}
}
}
} }
}
else RuntimeComponentReflectionCache cache = fieldInfoData.GetReflectionCache(type);
{ if (depth >= DEPTH_MAX || cache == null)
Type fieldType = fieldInfoData.FieldType;
if (isUnityObjectType || isUnityObjectField)
{ {
EditorGUI.BeginChangeCheck(); EditorGUILayout.TextField(label, "error");
var uobj = UnsafeUtility.As<object, UnityObject>(ref data); return false;
}
bool isComponent = typeof(UnityComponent).IsAssignableFrom(fieldType); ref bool isExpanded = ref expandMatrix.Down();
if (isComponent) bool childElementChanged = false;
{ var eventType = Event.current.type;
uobj = EditorGUILayout.ObjectField(label, uobj, typeof(UnityObject), true);
}
else
{
uobj = EditorGUILayout.ObjectField(label, uobj, fieldType, true);
}
if (EditorGUI.EndChangeCheck()) var label2 = UnityEditorUtility.GetLabel2(cache.Type.FullName + " " + type.FullName);
{ var drawerType = cache.DrawerType;
if (isComponent && uobj is GameObject go)
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 (EcsGUI.CheckChanged())
{ {
uobj = go.GetComponent(fieldType); RefEditorWrapper wrapper = cache.GetWrapper(_runtimeComponentsDepth);
wrapper.data = data;
wrapper.SO.Update();
wrapper.IsExpanded = isExpanded;
EditorGUILayout.PropertyField(wrapper.Property, label, true);
if (EcsGUI.Changed)
{
wrapper.SO.ApplyModifiedProperties();
newData = wrapper.Data;
childElementChanged = true;
}
isExpanded = wrapper.IsExpanded;
} }
outData = uobj; break;
changed = true; case DrawerType.UnityNotSerializableComposite:
}
}
else
{
EditorGUI.BeginChangeCheck();
RefEditorWrapper wrapper = cache.GetWrapper(_runtimeComponentsDepth);
wrapper.data = data;
try GUILayout.Space(EcsGUI.Spacing);
{ var foldoutStyle = EditorStyles.foldout;
if (fieldInfoData.IsPassToUnitySerialize) Rect rect = GUILayoutUtility.GetRect(label, foldoutStyle);
//rect.xMin += EcsGUI.Indent;
isExpanded = EditorGUI.BeginFoldoutHeaderGroup(rect, isExpanded, label, foldoutStyle, null, null);
EditorGUILayout.EndFoldoutHeaderGroup();
if (isExpanded)
{ {
if (cache.IsCompositeType) using (EcsGUI.UpIndentLevel())
{ {
wrapper.SO.Update(); for (int j = 0, jMax = cache.Fields.Length; j < jMax; j++)
wrapper.IsExpanded = isExpanded;
EditorGUILayout.PropertyField(wrapper.Property, label, true);
if (GUI.changed)
{ {
wrapper.SO.ApplyModifiedProperties(); var field = cache.Fields[j];
} if (DrawRuntimeData(ref field, UnityEditorUtility.GetLabel(field.UnityFormatName), expandMatrix, field.FieldInfo.GetValue(data), out object fieldData, depth + 1))
} {
else if (cache.IsLeaf) field.FieldInfo.SetValue(data, fieldData);
{ newData = data;
var eventType = Event.current.type; childElementChanged = true;
switch (cache.LeafPropertyType) }
{
//case RuntimeComponentReflectionCache.LeafType.Enum:
// break;
case RuntimeComponentReflectionCache.LeafType.Bool:
if (eventType != EventType.Layout)
{
wrapper.data = EditorGUILayout.Toggle(label, (bool)data);
}
else
{
EditorGUILayout.Toggle(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.String:
if (eventType != EventType.Layout)
{
wrapper.data = EditorGUILayout.TextField(label, (string)data);
}
else
{
EditorGUILayout.TextField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.Float:
if (eventType != EventType.Layout)
{
wrapper.data = EditorGUILayout.FloatField(label, (float)data);
}
else
{
EditorGUILayout.FloatField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.Double:
if (eventType != EventType.Layout)
{
wrapper.data = EditorGUILayout.DoubleField(label, (double)data);
}
else
{
EditorGUILayout.DoubleField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.Byte:
if (eventType != EventType.Layout)
{
wrapper.data = (byte)EditorGUILayout.IntField(label, (byte)data);
}
else
{
EditorGUILayout.IntField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.SByte:
if (eventType != EventType.Layout)
{
wrapper.data = (sbyte)EditorGUILayout.IntField(label, (sbyte)data);
}
else
{
EditorGUILayout.IntField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.Short:
if (eventType != EventType.Layout)
{
wrapper.data = (short)EditorGUILayout.IntField(label, (short)data);
}
else
{
EditorGUILayout.IntField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.UShort:
if (eventType != EventType.Layout)
{
wrapper.data = (ushort)EditorGUILayout.IntField(label, (ushort)data);
}
else
{
EditorGUILayout.IntField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.Int:
if (eventType != EventType.Layout)
{
wrapper.data = (int)EditorGUILayout.IntField(label, (int)data);
}
else
{
EditorGUILayout.IntField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.UInt:
if (eventType != EventType.Layout)
{
wrapper.data = (uint)EditorGUILayout.IntField(label, (int)(uint)data);
}
else
{
EditorGUILayout.IntField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.Long:
if (eventType != EventType.Layout)
{
wrapper.data = EditorGUILayout.LongField(label, (long)data);
}
else
{
EditorGUILayout.LongField(label, default);
}
break;
case RuntimeComponentReflectionCache.LeafType.ULong:
if (eventType != EventType.Layout)
{
wrapper.data = (ulong)EditorGUILayout.LongField(label, (long)(ulong)data);
}
else
{
EditorGUILayout.LongField(label, default);
}
break;
default:
EditorGUILayout.LabelField(label);
break;
} }
} }
}
break;
case DrawerType.UnityObject:
using (EcsGUI.CheckChanged())
{
var uobj = UnsafeUtility.As<object, UnityObject>(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<object, Enum>(ref data);
newData = EditorGUILayout.EnumPopup(label, enumData);
} }
else else
{ {
EditorGUILayout.LabelField(label); EditorGUILayout.EnumPopup(label, default);
} }
}
catch (ArgumentException) break;
{ case DrawerType.EnumFlags:
if (Event.current.type != EventType.Repaint)
if (eventType != EventType.Layout)
{ {
throw; var enumData = UnsafeUtility.As<object, Enum>(ref data);
newData = EditorGUILayout.EnumFlagsField(label, enumData);
} }
} else
finally
{
if (EditorGUI.EndChangeCheck())
{ {
outData = wrapper.Data; EditorGUILayout.EnumFlagsField(label, default);
changed = true;
} }
isExpanded = wrapper.IsExpanded;
} 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;
}
expandMatrix.Up();
if (childElementChanged || EcsGUI.Changed)
{
outData = newData;
return true;
} }
} }
expandMatrix.Up(); return false;
return changed;
} }
#endregion #endregion
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,
}
} }
} }
#endif #endif

View File

@ -235,6 +235,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
//private static Type[] _noHiddenSerializableTypes; //private static Type[] _noHiddenSerializableTypes;
private static GUIContent _singletonIconContent = null; private static GUIContent _singletonIconContent = null;
private static GUIContent _singletonContent = null; private static GUIContent _singletonContent = null;
private static GUIContent _singleton2Content = null;
private static GUIStyle _inputFieldCenterAnhor = null; private static GUIStyle _inputFieldCenterAnhor = null;
private static Dictionary<Type, MonoScript> _scriptsAssets = new Dictionary<Type, MonoScript>(256); private static Dictionary<Type, MonoScript> _scriptsAssets = new Dictionary<Type, MonoScript>(256);
@ -440,6 +441,17 @@ namespace DCFApixels.DragonECS.Unity.Editors
_singletonIconContent.tooltip = tooltip; _singletonIconContent.tooltip = tooltip;
return _singletonIconContent; return _singletonIconContent;
} }
public static GUIContent GetLabel2(string name, string tooltip = null)
{
if (_singleton2Content == null)
{
_singleton2Content = new GUIContent();
}
_singleton2Content.text = name;
_singleton2Content.image = null;
_singleton2Content.tooltip = tooltip;
return _singleton2Content;
}
#endregion #endregion
#region GetDefaultStyle #region GetDefaultStyle
@ -517,6 +529,37 @@ namespace DCFApixels.DragonECS.Unity.Editors
return result; return result;
} }
#endregion #endregion
//private static StructList<GUIContent> _stackLabels = new StructList<GUIContent>(4);
//public static StackTempLabelScope GetStackLabel(string text, string tooltip = null)
//{
// StackTempLabelScope result = default;
// if (_stackLabels.Count <= 0)
// {
// result = new StackTempLabelScope(new GUIContent());
// }
// else
// {
// var l = _stackLabels[_stackLabels.Count - 1];
// _stackLabels.RemoveAt(_stackLabels.Count - 1);
// result = new StackTempLabelScope(l);
// }
// result.Label.text = text;
// result.Label.tooltip = tooltip;
// return result;
//}
//private static void ReturnStackLabel(GUIContent label)
//{
// _stackLabels.Add(label);
//}
//public readonly struct StackTempLabelScope : IDisposable
//{
// public readonly GUIContent Label;
// public StackTempLabelScope(GUIContent label) { Label = label; }
// public void Dispose() { ReturnStackLabel(Label); }
// public static implicit operator GUIContent(StackTempLabelScope a) { return a.Label; }
//}
} }
internal static class RuntimeComponentsUtility internal static class RuntimeComponentsUtility