You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
7.1 KiB
189 lines
7.1 KiB
9 years ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Reflection;
|
||
|
using System.Text.RegularExpressions;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace UnityTest
|
||
|
{
|
||
|
[Serializable]
|
||
|
public class PropertyResolver
|
||
|
{
|
||
|
public string[] ExcludedFieldNames { get; set; }
|
||
|
public Type[] ExcludedTypes { get; set; }
|
||
|
public Type[] AllowedTypes { get; set; }
|
||
|
|
||
|
public PropertyResolver()
|
||
|
{
|
||
|
ExcludedFieldNames = new string[] { };
|
||
|
ExcludedTypes = new Type[] { };
|
||
|
AllowedTypes = new Type[] { };
|
||
|
}
|
||
|
|
||
|
public IList<string> GetFieldsAndPropertiesUnderPath(GameObject go, string propertPath)
|
||
|
{
|
||
|
propertPath = propertPath.Trim();
|
||
|
if (!PropertyPathIsValid(propertPath))
|
||
|
{
|
||
|
throw new ArgumentException("Incorrect property path: " + propertPath);
|
||
|
}
|
||
|
|
||
|
var idx = propertPath.LastIndexOf('.');
|
||
|
|
||
|
if (idx < 0)
|
||
|
{
|
||
|
var components = GetFieldsAndPropertiesFromGameObject(go, 2, null);
|
||
|
return components;
|
||
|
}
|
||
|
|
||
|
var propertyToSearch = propertPath;
|
||
|
Type type;
|
||
|
if (MemberResolver.TryGetMemberType(go, propertyToSearch, out type))
|
||
|
{
|
||
|
idx = propertPath.Length - 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
propertyToSearch = propertPath.Substring(0, idx);
|
||
|
if (!MemberResolver.TryGetMemberType(go, propertyToSearch, out type))
|
||
|
{
|
||
|
var components = GetFieldsAndPropertiesFromGameObject(go, 2, null);
|
||
|
return components.Where(s => s.StartsWith(propertPath.Substring(idx + 1))).ToArray();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var resultList = new List<string>();
|
||
|
var path = "";
|
||
|
if (propertyToSearch.EndsWith("."))
|
||
|
propertyToSearch = propertyToSearch.Substring(0, propertyToSearch.Length - 1);
|
||
|
foreach (var c in propertyToSearch)
|
||
|
{
|
||
|
if (c == '.')
|
||
|
resultList.Add(path);
|
||
|
path += c;
|
||
|
}
|
||
|
resultList.Add(path);
|
||
|
foreach (var prop in type.GetProperties().Where(info => info.GetIndexParameters().Length == 0))
|
||
|
{
|
||
|
if (prop.Name.StartsWith(propertPath.Substring(idx + 1)))
|
||
|
resultList.Add(propertyToSearch + "." + prop.Name);
|
||
|
}
|
||
|
foreach (var prop in type.GetFields())
|
||
|
{
|
||
|
if (prop.Name.StartsWith(propertPath.Substring(idx + 1)))
|
||
|
resultList.Add(propertyToSearch + "." + prop.Name);
|
||
|
}
|
||
|
return resultList.ToArray();
|
||
|
}
|
||
|
|
||
|
internal bool PropertyPathIsValid(string propertPath)
|
||
|
{
|
||
|
if (propertPath.StartsWith("."))
|
||
|
return false;
|
||
|
if (propertPath.IndexOf("..") >= 0)
|
||
|
return false;
|
||
|
if (Regex.IsMatch(propertPath, @"\s"))
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public IList<string> GetFieldsAndPropertiesFromGameObject(GameObject gameObject, int depthOfSearch, string extendPath)
|
||
|
{
|
||
|
if (depthOfSearch < 1) throw new ArgumentOutOfRangeException("depthOfSearch has to be greater than 0");
|
||
|
|
||
|
var goVals = GetPropertiesAndFieldsFromType(typeof(GameObject),
|
||
|
depthOfSearch - 1).Select(s => "gameObject." + s);
|
||
|
|
||
|
var result = new List<string>();
|
||
|
if (AllowedTypes == null || !AllowedTypes.Any() || AllowedTypes.Contains(typeof(GameObject)))
|
||
|
result.Add("gameObject");
|
||
|
result.AddRange(goVals);
|
||
|
|
||
|
foreach (var componentType in GetAllComponents(gameObject))
|
||
|
{
|
||
|
if (AllowedTypes == null || !AllowedTypes.Any() || AllowedTypes.Any(t => t.IsAssignableFrom(componentType)))
|
||
|
result.Add(componentType.Name);
|
||
|
|
||
|
if (depthOfSearch > 1)
|
||
|
{
|
||
|
var vals = GetPropertiesAndFieldsFromType(componentType, depthOfSearch - 1);
|
||
|
var valsFullName = vals.Select(s => componentType.Name + "." + s);
|
||
|
result.AddRange(valsFullName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!string.IsNullOrEmpty(extendPath))
|
||
|
{
|
||
|
var memberResolver = new MemberResolver(gameObject, extendPath);
|
||
|
var pathType = memberResolver.GetMemberType();
|
||
|
var vals = GetPropertiesAndFieldsFromType(pathType, depthOfSearch - 1);
|
||
|
var valsFullName = vals.Select(s => extendPath + "." + s);
|
||
|
result.AddRange(valsFullName);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
private string[] GetPropertiesAndFieldsFromType(Type type, int level)
|
||
|
{
|
||
|
level--;
|
||
|
|
||
|
var result = new List<string>();
|
||
|
var fields = new List<MemberInfo>();
|
||
|
fields.AddRange(type.GetFields().Where(f => !Attribute.IsDefined(f, typeof(ObsoleteAttribute))).ToArray());
|
||
|
fields.AddRange(type.GetProperties().Where(info => info.GetIndexParameters().Length == 0 && !Attribute.IsDefined(info, typeof(ObsoleteAttribute))).ToArray());
|
||
|
|
||
|
foreach (var member in fields)
|
||
|
{
|
||
|
var memberType = GetMemberFieldType(member);
|
||
|
var memberTypeName = memberType.Name;
|
||
|
|
||
|
if (AllowedTypes == null
|
||
|
|| !AllowedTypes.Any()
|
||
|
|| (AllowedTypes.Any(t => t.IsAssignableFrom(memberType)) && !ExcludedFieldNames.Contains(memberTypeName)))
|
||
|
{
|
||
|
result.Add(member.Name);
|
||
|
}
|
||
|
|
||
|
if (level > 0 && IsTypeOrNameNotExcluded(memberType, memberTypeName))
|
||
|
{
|
||
|
var vals = GetPropertiesAndFieldsFromType(memberType, level);
|
||
|
var valsFullName = vals.Select(s => member.Name + "." + s);
|
||
|
result.AddRange(valsFullName);
|
||
|
}
|
||
|
}
|
||
|
return result.ToArray();
|
||
|
}
|
||
|
|
||
|
private Type GetMemberFieldType(MemberInfo info)
|
||
|
{
|
||
|
if (info.MemberType == MemberTypes.Property)
|
||
|
return (info as PropertyInfo).PropertyType;
|
||
|
if (info.MemberType == MemberTypes.Field)
|
||
|
return (info as FieldInfo).FieldType;
|
||
|
throw new Exception("Only properties and fields are allowed");
|
||
|
}
|
||
|
|
||
|
internal Type[] GetAllComponents(GameObject gameObject)
|
||
|
{
|
||
|
var result = new List<Type>();
|
||
|
var components = gameObject.GetComponents(typeof(Component));
|
||
|
foreach (var component in components)
|
||
|
{
|
||
|
var componentType = component.GetType();
|
||
|
if (IsTypeOrNameNotExcluded(componentType, null))
|
||
|
{
|
||
|
result.Add(componentType);
|
||
|
}
|
||
|
}
|
||
|
return result.ToArray();
|
||
|
}
|
||
|
|
||
|
private bool IsTypeOrNameNotExcluded(Type memberType, string memberTypeName)
|
||
|
{
|
||
|
return !ExcludedTypes.Contains(memberType) && !ExcludedFieldNames.Contains(memberTypeName);
|
||
|
}
|
||
|
}
|
||
|
}
|