mirror of
https://github.com/AnnulusGames/Alchemy.git
synced 2025-01-22 08:18:51 -05:00
commit
9033088ee3
@ -14,6 +14,8 @@ namespace Alchemy.Editor.Elements
|
||||
/// </summary>
|
||||
public sealed class GenericField : VisualElement
|
||||
{
|
||||
const string CreateButtonText = "Create...";
|
||||
|
||||
public GenericField(object obj, Type type, string label, int depth, bool isDelayed = false)
|
||||
{
|
||||
Build(obj, type, label, depth, isDelayed);
|
||||
@ -25,6 +27,7 @@ namespace Alchemy.Editor.Elements
|
||||
if (depth > InspectorHelper.MaxDepth) return;
|
||||
Clear();
|
||||
|
||||
// Add [Create...] button
|
||||
if (obj == null && !typeof(UnityEngine.Object).IsAssignableFrom(type))
|
||||
{
|
||||
var nullLabelElement = new VisualElement()
|
||||
@ -46,7 +49,19 @@ namespace Alchemy.Editor.Elements
|
||||
});
|
||||
|
||||
// TODO: support polymorphism
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
if (type == typeof(string))
|
||||
{
|
||||
nullLabelElement.Add(new Button(() =>
|
||||
{
|
||||
var instance = "";
|
||||
Build(instance, type, label, depth, isDelayed);
|
||||
OnValueChanged?.Invoke(instance);
|
||||
})
|
||||
{
|
||||
text = CreateButtonText
|
||||
});
|
||||
}
|
||||
else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) // nullable
|
||||
{
|
||||
nullLabelElement.Add(new Button(() =>
|
||||
{
|
||||
@ -55,7 +70,7 @@ namespace Alchemy.Editor.Elements
|
||||
OnValueChanged?.Invoke(instance);
|
||||
})
|
||||
{
|
||||
text = "Create..."
|
||||
text = CreateButtonText
|
||||
});
|
||||
}
|
||||
else if (TypeHelper.HasDefaultConstructor(type))
|
||||
@ -67,7 +82,7 @@ namespace Alchemy.Editor.Elements
|
||||
OnValueChanged?.Invoke(instance);
|
||||
})
|
||||
{
|
||||
text = "Create..."
|
||||
text = CreateButtonText
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -232,7 +232,8 @@ namespace Alchemy.Editor.Internal
|
||||
}
|
||||
|
||||
#if ALCHEMY_SUPPORT_SERIALIZATION
|
||||
if (serializedObject.targetObject.GetType().HasCustomAttribute<AlchemySerializeAttribute>() &&
|
||||
if (serializedObject.targetObject != null &&
|
||||
serializedObject.targetObject.GetType().HasCustomAttribute<AlchemySerializeAttribute>() &&
|
||||
memberInfo.HasCustomAttribute<AlchemySerializeFieldAttribute>())
|
||||
{
|
||||
var element = default(VisualElement);
|
||||
|
@ -23,7 +23,7 @@ namespace Alchemy.Editor.Internal
|
||||
if (fieldInfo == null) return null;
|
||||
if (fieldInfo.IsStatic)
|
||||
{
|
||||
Expression body = Expression.Convert(Expression.MakeMemberAccess(null, fieldInfo), typeof(object));
|
||||
var body = Expression.Convert(Expression.MakeMemberAccess(null, fieldInfo), typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(body).Compile();
|
||||
return _ => lambda();
|
||||
}
|
||||
@ -31,7 +31,7 @@ namespace Alchemy.Editor.Internal
|
||||
{
|
||||
var objParam = Expression.Parameter(typeof(object), "obj");
|
||||
var tParam = Expression.Convert(objParam, fieldInfo.DeclaringType);
|
||||
Expression body = Expression.Convert(Expression.MakeMemberAccess(tParam, fieldInfo), typeof(object));
|
||||
var body = Expression.Convert(Expression.MakeMemberAccess(tParam, fieldInfo), typeof(object));
|
||||
return Expression.Lambda<Func<object, object>>(body, objParam).Compile();
|
||||
}
|
||||
return null;
|
||||
@ -42,7 +42,7 @@ namespace Alchemy.Editor.Internal
|
||||
if (propertyInfo == null) return null;
|
||||
if (propertyInfo.GetGetMethod(true).IsStatic)
|
||||
{
|
||||
Expression body = Expression.Convert(Expression.MakeMemberAccess(null, propertyInfo), typeof(object));
|
||||
var body = Expression.Convert(Expression.MakeMemberAccess(null, propertyInfo), typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(body).Compile();
|
||||
return _ => lambda();
|
||||
}
|
||||
@ -50,7 +50,7 @@ namespace Alchemy.Editor.Internal
|
||||
{
|
||||
var objParam = Expression.Parameter(typeof(object), "obj");
|
||||
var tParam = Expression.Convert(objParam, propertyInfo.DeclaringType);
|
||||
Expression body = Expression.Convert(Expression.MakeMemberAccess(tParam, propertyInfo), typeof(object));
|
||||
var body = Expression.Convert(Expression.MakeMemberAccess(tParam, propertyInfo), typeof(object));
|
||||
return Expression.Lambda<Func<object, object>>(body, objParam).Compile();
|
||||
}
|
||||
return null;
|
||||
@ -61,7 +61,7 @@ namespace Alchemy.Editor.Internal
|
||||
if (methodInfo == null) return null;
|
||||
if (methodInfo.IsStatic)
|
||||
{
|
||||
Expression body = Expression.Convert(Expression.Call(null, methodInfo), typeof(object));
|
||||
var body = Expression.Convert(Expression.Call(null, methodInfo), typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(body).Compile();
|
||||
return _ => lambda();
|
||||
}
|
||||
@ -69,7 +69,7 @@ namespace Alchemy.Editor.Internal
|
||||
{
|
||||
var objParam = Expression.Parameter(typeof(object), "obj");
|
||||
var tParam = Expression.Convert(objParam, methodInfo.DeclaringType);
|
||||
Expression body = Expression.Convert(Expression.Call(tParam, methodInfo), typeof(object));
|
||||
var body = Expression.Convert(Expression.Call(tParam, methodInfo), typeof(object));
|
||||
return Expression.Lambda<Func<object, object>>(body, objParam).Compile();
|
||||
}
|
||||
return null;
|
||||
@ -79,7 +79,7 @@ namespace Alchemy.Editor.Internal
|
||||
{
|
||||
if (!cacheGetFieldValue.TryGetValue((type, name), out var value))
|
||||
{
|
||||
FieldInfo info = type.GetField(name, bindingAttr);
|
||||
var info = type.GetField(name, bindingAttr);
|
||||
value = CreateGetter(info);
|
||||
cacheGetFieldValue.Add((type, name), value);
|
||||
}
|
||||
@ -90,7 +90,7 @@ namespace Alchemy.Editor.Internal
|
||||
{
|
||||
if (!cacheGetPropertyValue.TryGetValue((type, name), out var value))
|
||||
{
|
||||
PropertyInfo info = type.GetProperty(name, bindingAttr);
|
||||
var info = type.GetProperty(name, bindingAttr);
|
||||
value = CreateGetter(info);
|
||||
cacheGetPropertyValue.Add((type, name), value);
|
||||
}
|
||||
@ -101,95 +101,80 @@ namespace Alchemy.Editor.Internal
|
||||
{
|
||||
if (!cacheGetMethodValue.TryGetValue((type, name), out var value))
|
||||
{
|
||||
MethodInfo info = type.GetMethod(name, bindingAttr);
|
||||
var info = type.GetMethod(name, bindingAttr);
|
||||
value = CreateGetter(info);
|
||||
cacheGetMethodValue.Add((type, name), value);
|
||||
}
|
||||
return value?.Invoke(target);
|
||||
}
|
||||
|
||||
public static FieldInfo GetField(Type type, string name, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, bool inherit = false)
|
||||
public static FieldInfo GetField(Type type, string name, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, bool includingBaseNonPublic = false)
|
||||
{
|
||||
FieldInfo info;
|
||||
if (cacheFieldInfo.ContainsKey((type, name, bindingAttr, inherit)))
|
||||
if (!cacheFieldInfo.TryGetValue((type, name, bindingAttr, includingBaseNonPublic), out var info))
|
||||
{
|
||||
info = cacheFieldInfo[(type, name, bindingAttr, inherit)];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inherit)
|
||||
if (includingBaseNonPublic)
|
||||
{
|
||||
info = GetAllFieldsIncludingInherited(type, bindingAttr).FirstOrDefault(x => x.Name == name);
|
||||
info = GetAllFieldsIncludingBaseNonPublic(type, bindingAttr).FirstOrDefault(x => x.Name == name);
|
||||
}
|
||||
else
|
||||
{
|
||||
info = type.GetField(name, bindingAttr);
|
||||
}
|
||||
cacheFieldInfo.Add((type, name, bindingAttr, inherit), info);
|
||||
cacheFieldInfo.Add((type, name, bindingAttr, includingBaseNonPublic), info);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
static IEnumerable<FieldInfo> GetAllFieldsIncludingInherited(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
static IEnumerable<FieldInfo> GetAllFieldsIncludingBaseNonPublic(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
{
|
||||
if (type == null) return Enumerable.Empty<FieldInfo>();
|
||||
return type.GetFields(bindingAttr).Concat(GetAllFieldsIncludingInherited(type.BaseType));
|
||||
return type.GetFields(bindingAttr).Concat(GetAllFieldsIncludingBaseNonPublic(type.BaseType));
|
||||
}
|
||||
|
||||
public static PropertyInfo GetProperty(Type type, string name, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, bool inherit = false)
|
||||
public static PropertyInfo GetProperty(Type type, string name, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, bool includingBaseNonPublic = false)
|
||||
{
|
||||
PropertyInfo info;
|
||||
if (cachePropertyInfo.ContainsKey((type, name, bindingAttr, inherit)))
|
||||
if (!cachePropertyInfo.TryGetValue((type, name, bindingAttr, includingBaseNonPublic), out var info))
|
||||
{
|
||||
info = cachePropertyInfo[(type, name, bindingAttr, inherit)];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inherit)
|
||||
if (includingBaseNonPublic)
|
||||
{
|
||||
info = GetAllPropertiesIncludingInherited(type, bindingAttr).FirstOrDefault(x => x.Name == name);
|
||||
info = GetAllPropertiesIncludingBaseNonPublic(type, bindingAttr).FirstOrDefault(x => x.Name == name);
|
||||
}
|
||||
else
|
||||
{
|
||||
info = type.GetProperty(name, bindingAttr);
|
||||
}
|
||||
cachePropertyInfo.Add((type, name, bindingAttr, inherit), info);
|
||||
cachePropertyInfo.Add((type, name, bindingAttr, includingBaseNonPublic), info);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
static IEnumerable<PropertyInfo> GetAllPropertiesIncludingInherited(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
static IEnumerable<PropertyInfo> GetAllPropertiesIncludingBaseNonPublic(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
{
|
||||
if (type == null) return Enumerable.Empty<PropertyInfo>();
|
||||
return type.GetProperties(bindingAttr).Concat(GetAllPropertiesIncludingInherited(type.BaseType));
|
||||
return type.GetProperties(bindingAttr).Concat(GetAllPropertiesIncludingBaseNonPublic(type.BaseType));
|
||||
}
|
||||
|
||||
public static MethodInfo GetMethod(Type type, string name, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, bool inherit = false)
|
||||
public static MethodInfo GetMethod(Type type, string name, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, bool includingBaseNonPublic = false)
|
||||
{
|
||||
MethodInfo info;
|
||||
if (cacheMethodInfo.ContainsKey((type, name, bindingAttr, inherit)))
|
||||
if (!cacheMethodInfo.TryGetValue((type, name, bindingAttr, includingBaseNonPublic), out var info))
|
||||
{
|
||||
info = cacheMethodInfo[(type, name, bindingAttr, inherit)];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inherit)
|
||||
if (includingBaseNonPublic)
|
||||
{
|
||||
info = GetAllMethodsIncludingInherited(type, bindingAttr).FirstOrDefault(x => x.Name == name);
|
||||
info = GetAllMethodsIncludingBaseNonPublic(type, bindingAttr).FirstOrDefault(x => x.Name == name);
|
||||
}
|
||||
else
|
||||
{
|
||||
info = type.GetMethods(bindingAttr).Where(x => x.Name == name).FirstOrDefault();
|
||||
}
|
||||
cacheMethodInfo.Add((type, name, bindingAttr, inherit), info);
|
||||
cacheMethodInfo.Add((type, name, bindingAttr, includingBaseNonPublic), info);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
static IEnumerable<MethodInfo> GetAllMethodsIncludingInherited(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
static IEnumerable<MethodInfo> GetAllMethodsIncludingBaseNonPublic(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
{
|
||||
if (type == null) return Enumerable.Empty<MethodInfo>();
|
||||
return type.GetMethods(bindingAttr).Concat(GetAllMethodsIncludingInherited(type.BaseType));
|
||||
return type.GetMethods(bindingAttr).Concat(GetAllMethodsIncludingBaseNonPublic(type.BaseType));
|
||||
}
|
||||
|
||||
public static object GetValue(object target, string name, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, bool allowProperty = true, bool allowMethod = true)
|
||||
@ -241,32 +226,31 @@ namespace Alchemy.Editor.Internal
|
||||
return false;
|
||||
}
|
||||
|
||||
public static MemberInfo[] GetMembers(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, bool inherit = false)
|
||||
public static MemberInfo[] GetMembers(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, bool includingBaseNonPublic = false)
|
||||
{
|
||||
if (cacheAllMembers.ContainsKey((type, bindingAttr, inherit)))
|
||||
if (cacheAllMembers.TryGetValue((type, bindingAttr, includingBaseNonPublic), out var memberInfoArray))
|
||||
{
|
||||
return cacheAllMembers[(type, bindingAttr, inherit)];
|
||||
return memberInfoArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemberInfo[] memberInfos;
|
||||
if (inherit)
|
||||
if (includingBaseNonPublic)
|
||||
{
|
||||
memberInfos = GetMembersIncludingInherited(type, bindingAttr).ToArray();
|
||||
memberInfoArray = GetMembersIncludingBaseNonPublic(type, bindingAttr).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
memberInfos = type.GetMembers(bindingAttr);
|
||||
memberInfoArray = type.GetMembers(bindingAttr);
|
||||
}
|
||||
cacheAllMembers.Add((type, bindingAttr, inherit), memberInfos);
|
||||
return memberInfos;
|
||||
cacheAllMembers.Add((type, bindingAttr, includingBaseNonPublic), memberInfoArray);
|
||||
return memberInfoArray;
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<MemberInfo> GetMembersIncludingInherited(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
static IEnumerable<MemberInfo> GetMembersIncludingBaseNonPublic(Type type, BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
{
|
||||
if (type == null) return Enumerable.Empty<MemberInfo>();
|
||||
return type.GetMembers(bindingAttr).Concat(GetMembersIncludingInherited(type.BaseType));
|
||||
return type.GetMembers(bindingAttr).Concat(GetMembersIncludingBaseNonPublic(type.BaseType));
|
||||
}
|
||||
|
||||
public static object Invoke(object target, string name, params object[] parameters)
|
||||
|
@ -14,12 +14,12 @@ namespace Alchemy.Serialization.Internal
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (IsUnityObject<T>())
|
||||
if (target is UnityEngine.Object unityObject)
|
||||
{
|
||||
var index = unityObjectReferences.IndexOf(target as UnityEngine.Object);
|
||||
var index = unityObjectReferences.IndexOf(unityObject);
|
||||
if (index == -1)
|
||||
{
|
||||
unityObjectReferences.Add(target as UnityEngine.Object);
|
||||
unityObjectReferences.Add(unityObject);
|
||||
index = unityObjectReferences.Count - 1;
|
||||
}
|
||||
return index.ToString();
|
||||
@ -98,12 +98,6 @@ namespace Alchemy.Serialization.Internal
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
static bool IsUnityObject<T>()
|
||||
{
|
||||
var type = typeof(T);
|
||||
return type == typeof(UnityEngine.Object) || type.IsSubclassOf(typeof(UnityEngine.Object));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user