// -------------------------------------------------------------------------------------------------------------------- // // HiddenMonk // http://answers.unity3d.com/users/496850/hiddenmonk.html // // Johannes Deml // send@johannesdeml.com // // -------------------------------------------------------------------------------------------------------------------- namespace VRTK.Supyrb { using System; using UnityEngine; using UnityEditor; using System.Reflection; using System.Collections.Generic; using System.Linq; /// /// Extension class for SerializedProperties /// See also: http://answers.unity3d.com/questions/627090/convert-serializedproperty-to-custom-class.html /// public static class SerializedPropertyExtensions { /// /// Get the object the serialized property holds by using reflection /// /// The object type that the property contains /// /// Returns the object type T if it is the type the property actually contains public static T GetValue(this SerializedProperty property) { return GetNestedObject(property.propertyPath, GetSerializedPropertyRootComponent(property)); } /// /// Set the value of a field of the property with the type T /// /// The type of the field that is set /// The serialized property that should be set /// The new value for the specified property /// Returns if the operation was successful or failed public static bool SetValue(this SerializedProperty property, T value) { object obj = GetSerializedPropertyRootComponent(property); //Iterate to parent object of the value, necessary if it is a nested object string[] fieldStructure = property.propertyPath.Split('.'); for (int i = 0; i < fieldStructure.Length - 1; i++) { obj = GetFieldOrPropertyValue(fieldStructure[i], obj); } string fieldName = fieldStructure.Last(); return SetFieldOrPropertyValue(fieldName, obj, value); } /// /// Get the component of a serialized property /// /// The property that is part of the component /// The root component of the property public static Component GetSerializedPropertyRootComponent(SerializedProperty property) { return (Component)property.serializedObject.targetObject; } /// /// Iterates through objects to handle objects that are nested in the root object /// /// The type of the nested object /// Path to the object through other properties e.g. PlayerInformation.Health /// The root object from which this path leads to the property /// Include base classes and interfaces as well /// Returns the nested object casted to the type T public static T GetNestedObject(string path, object obj, bool includeAllBases = false) { foreach (string part in path.Split('.')) { obj = GetFieldOrPropertyValue(part, obj, includeAllBases); } return (T)obj; } public static T GetFieldOrPropertyValue(string fieldName, object obj, bool includeAllBases = false, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) { FieldInfo field = obj.GetType().GetField(fieldName, bindings); if (field != null) { return (T)field.GetValue(obj); } PropertyInfo property = obj.GetType().GetProperty(fieldName, bindings); if (property != null) { return (T)property.GetValue(obj, null); } if (includeAllBases) { foreach (Type type in GetBaseClassesAndInterfaces(obj.GetType())) { field = type.GetField(fieldName, bindings); if (field != null) { return (T)field.GetValue(obj); } property = type.GetProperty(fieldName, bindings); if (property != null) { return (T)property.GetValue(obj, null); } } } return default(T); } public static bool SetFieldOrPropertyValue(string fieldName, object obj, object value, bool includeAllBases = false, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) { FieldInfo field = obj.GetType().GetField(fieldName, bindings); if (field != null) { field.SetValue(obj, value); return true; } PropertyInfo property = obj.GetType().GetProperty(fieldName, bindings); if (property != null) { property.SetValue(obj, value, null); return true; } if (includeAllBases) { foreach (Type type in GetBaseClassesAndInterfaces(obj.GetType())) { field = type.GetField(fieldName, bindings); if (field != null) { field.SetValue(obj, value); return true; } property = type.GetProperty(fieldName, bindings); if (property != null) { property.SetValue(obj, value, null); return true; } } } return false; } public static IEnumerable GetBaseClassesAndInterfaces(this Type type, bool includeSelf = false) { List allTypes = new List(); if (includeSelf) { allTypes.Add(type); } if (type.BaseType == typeof(object)) { allTypes.AddRange(type.GetInterfaces()); } else { allTypes.AddRange( Enumerable .Repeat(type.BaseType, 1) .Concat(type.GetInterfaces()) .Concat(type.BaseType.GetBaseClassesAndInterfaces()) .Distinct()); } return allTypes; } } }