public override InspectorPropertyInfo GetChildInfo(int childIndex) { if (childIndex < 0 || childIndex >= this.ChildCount) { throw new IndexOutOfRangeException(); } InspectorPropertyInfo result; if (!this.childInfos.TryGetValue(childIndex, out result)) { result = InspectorPropertyInfo.CreateValue( name: CollectionResolverUtilities.DefaultIndexToChildName(childIndex), order: childIndex, serializationBackend: this.Property.BaseValueEntry.SerializationBackend, getterSetter: new GetterSetter <TCollection, TElement>( getter: (ref TCollection collection) => this.GetElement(collection, childIndex), setter: (ref TCollection collection, TElement element) => this.SetElement(collection, element, childIndex)), attributes: this.Property.Attributes.Where(attr => !attr.GetType().IsDefined(typeof(DontApplyToListElementsAttribute), true)).ToArray()); this.childInfos[childIndex] = result; } return(result); }
public override InspectorPropertyInfo GetChildInfo(int childIndex) { InspectorPropertyInfo info; if (this.childInfos.TryGetValue(childIndex, out info)) { return(info); } var parameter = this.parameters[childIndex]; var type = parameter.ParameterType; if (type.IsByRef) { type = type.GetElementType(); } var getterSetterType = typeof(GetterSetter <>).MakeGenericType(type); var getterSetter = Activator.CreateInstance(getterSetterType, new object[] { this.parameterValues, childIndex }) as IValueGetterSetter; info = InspectorPropertyInfo.CreateValue(parameter.Name, childIndex, SerializationBackend.None, getterSetter, parameter.GetAttributes()); this.childInfos[childIndex] = info; return(info); }
public override void ProcessMemberProperties(List <InspectorPropertyInfo> memberInfos) { var attr = this.GetClassDefinedTypeInfoBox(this.Property); var p = InspectorPropertyInfo.CreateForMember(InjectedMemberInfo, false, SerializationBackend.None, new Attribute[] { new OnInspectorGUIAttribute(), new InfoBoxAttribute(attr.Message), new PropertyOrderAttribute(-100000) }); memberInfos.Insert(0, p); }
protected override InspectorPropertyInfo[] GetPropertyInfos() { this.targetType = this.ValueEntry.TypeOfValue; var members = targetType.GetAllMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); var infos = new List <InspectorPropertyInfo>(); this.allowObsoleteMembers = this.Property.Context.GetGlobal("ALLOW_OBSOLETE_STATIC_MEMBERS", false); foreach (var member in members.Where(Filter).OrderBy(Order)) { var attributes = new List <Attribute>(); InspectorPropertyInfoUtility.ProcessAttributes(this.Property, member, attributes); if (member is MethodInfo && !attributes.HasAttribute <ButtonAttribute>() && !attributes.HasAttribute <OnInspectorGUIAttribute>()) { attributes.Add(new ButtonAttribute(ButtonSizes.Medium)); } var info = InspectorPropertyInfo.CreateForMember(member, true, SerializationBackend.None, attributes); InspectorPropertyInfo previousPropertyWithName = null; int previousPropertyIndex = -1; for (int j = 0; j < infos.Count; j++) { if (infos[j].PropertyName == info.PropertyName) { previousPropertyIndex = j; previousPropertyWithName = infos[j]; break; } } if (previousPropertyWithName != null) { bool createAlias = true; if (member.SignaturesAreEqual(previousPropertyWithName.GetMemberInfo())) { createAlias = false; infos.RemoveAt(previousPropertyIndex); } if (createAlias) { var alias = InspectorPropertyInfoUtility.GetPrivateMemberAlias(previousPropertyWithName.GetMemberInfo(), previousPropertyWithName.TypeOfOwner.GetNiceName(), " -> "); infos[previousPropertyIndex] = InspectorPropertyInfo.CreateForMember(alias, true, SerializationBackend.None, attributes); } } infos.Add(info); } return(InspectorPropertyInfoUtility.BuildPropertyGroupsAndFinalize(this.Property, targetType, infos, false)); }
public static void AddProcessedMember(this IList <InspectorPropertyInfo> infos, InspectorProperty parentProperty, MemberInfo member, bool allowEditable = true, SerializationBackend backend = SerializationBackend.None, params Attribute[] attributes) { var list = new List <Attribute>(); if (attributes != null) { list.AddRange(attributes); } InspectorPropertyInfoUtility.ProcessAttributes(parentProperty, member, list); infos.Add(InspectorPropertyInfo.CreateForMember(member, allowEditable, backend, list)); }
public static InspectorPropertyInfo CreateGroup(string name, Type typeOfOwner, int order, InspectorPropertyInfo[] groupInfos, IEnumerable <Attribute> attributes) { if (name == null) { throw new ArgumentNullException("name"); } if (typeOfOwner == null) { throw new ArgumentNullException("typeOfOwner"); } if (groupInfos == null) { throw new ArgumentNullException("groupInfos"); } if (name.Contains('.')) { throw new ArgumentException("Group names or paths may not contain '.'; was given the path/name '" + name + "'."); } if (name.Length == 0 || name[0] != '#') { throw new ArgumentException("The first character in a property group name must be '#'; was given the name '" + name + "'."); } var result = new InspectorPropertyInfo(); result.memberInfos = groupInfos.SelectMany(n => n.GetMemberInfos()).ToArray(); if (attributes == null) { result.attributes = new List <Attribute>(); } else { result.attributes = attributes.ToList(); } result.Order = order; result.typeOfOwner = typeOfOwner; result.PropertyName = name; result.PropertyType = PropertyType.Group; result.SerializationBackend = SerializationBackend.None; result.IsEditable = false; result.groupInfos = groupInfos; return(result); }
/// <summary> /// Initializes a new instance of the <see cref="ComplexTypePropertyChildren"/> class. /// </summary> /// <param name="property">The property to handle children for.</param> /// <exception cref="System.ArgumentException"> /// Property to create complex type children for has no value entry. /// or /// Property must be either a reference type or a value type property. /// </exception> public ComplexTypePropertyChildren(InspectorProperty property) : base(property) { if (property.ValueEntry == null) { throw new ArgumentException("Property to create complex type children for has no value entry."); } if (property.Info.PropertyType != PropertyType.ReferenceType && property.Info.PropertyType != PropertyType.ValueType) { throw new ArgumentException("Property must be either a reference type or a value type property."); } this.ComplexType = property.ValueEntry.TypeOfValue; this.infos = InspectorPropertyInfo.Get(this.ComplexType, property.Tree.IncludesSpeciallySerializedMembers && property.ValueEntry.SerializationBackend != SerializationBackend.Unity); }
public static InspectorPropertyInfo CreateForUnityProperty(string unityPropertyName, Type typeOfOwner, Type typeOfValue, bool isEditable, IEnumerable <Attribute> attributes) { if (unityPropertyName == null) { throw new ArgumentNullException("unityPropertyName"); } if (typeOfOwner == null) { throw new ArgumentNullException("typeOfOwner"); } if (typeOfValue == null) { throw new ArgumentNullException("typeOfValue"); } if (unityPropertyName.Contains('.')) { throw new ArgumentException("Property names may not contain '.'; was given the name '" + unityPropertyName + "'."); } var result = new InspectorPropertyInfo(); result.memberInfos = new MemberInfo[0]; result.typeOfOwner = typeOfOwner; result.typeOfValue = typeOfValue; result.PropertyName = unityPropertyName; result.PropertyType = PropertyType.Value; result.SerializationBackend = SerializationBackend.Unity; result.IsEditable = isEditable; if (attributes == null) { result.attributes = new List <Attribute>(); } else { result.attributes = attributes.Where(attr => attr != null).ToList(); } result.isUnityPropertyOnly = true; return(result); }
public static InspectorPropertyInfo CreateForDelegate(string name, int order, Type typeOfOwner, Delegate @delegate, IEnumerable <Attribute> attributes) { if (name == null) { throw new ArgumentNullException("name"); } if (typeOfOwner == null) { throw new ArgumentNullException("typeOfOwner"); } if (@delegate == null) { throw new ArgumentNullException("@delegate"); } if (name.Contains('.')) { throw new ArgumentException("Property names may not contain '.'; was given the name '" + name + "'."); } var result = new InspectorPropertyInfo(); result.memberInfos = new MemberInfo[0]; result.typeOfOwner = typeOfOwner; result.PropertyName = name; result.PropertyType = PropertyType.Method; result.SerializationBackend = SerializationBackend.None; if (attributes == null) { result.attributes = new List <Attribute>(); } else { result.attributes = attributes.Where(attr => attr != null).ToList(); } result.@delegate = @delegate; return(result); }
public static InspectorPropertyInfo CreateValue(string name, int order, SerializationBackend serializationBackend, IValueGetterSetter getterSetter, IEnumerable <Attribute> attributes) { if (name == null) { throw new ArgumentNullException("name"); } if (getterSetter == null) { throw new ArgumentNullException("getterSetter"); } if (name.Contains('.')) { throw new ArgumentException("Property names may not contain '.'; was given the name '" + name + "'."); } var result = new InspectorPropertyInfo(); result.memberInfos = new MemberInfo[0]; result.typeOfOwner = getterSetter.OwnerType; result.typeOfValue = getterSetter.ValueType; if (attributes == null) { result.attributes = new List <Attribute>(); } else { result.attributes = attributes.Where(attr => attr != null).ToList(); } result.PropertyName = name; result.PropertyType = PropertyType.Value; result.SerializationBackend = serializationBackend; result.IsEditable = !getterSetter.IsReadonly; result.getterSetter = getterSetter; return(result); }
public override InspectorPropertyInfo GetChildInfo(int childIndex) { if (childIndex == 0) { var member = typeof(Rect).GetProperty("position"); List <Attribute> attributes = new List <Attribute>(); return(InspectorPropertyInfo.CreateForMember(this.Property, member, true, attributes)); } else if (childIndex == 1) { var member = typeof(Rect).GetProperty("size"); List <Attribute> attributes = new List <Attribute>(); return(InspectorPropertyInfo.CreateForMember(this.Property, member, true, attributes)); } else { throw new NotImplementedException(); } }
public override InspectorPropertyInfo GetChildInfo(int childIndex) { this.EnsureUpdated(); InspectorPropertyInfo result; if (!this.childInfos.TryGetValue(childIndex, out result)) { result = InspectorPropertyInfo.CreateValue( name: CollectionResolverUtilities.DefaultIndexToChildName(childIndex), order: childIndex, serializationBackend: this.Property.BaseValueEntry.SerializationBackend, getterSetter: new GetterSetter <TDictionary, EditableKeyValuePair <TKey, TValue> >( getter: this.CreateGetter(childIndex), setter: this.CreateSetter(childIndex)), attributes: this.Property.Attributes); this.childInfos[childIndex] = result; } return(result); }
public static void AddProcessedMember(this IList <InspectorPropertyInfo> infos, InspectorProperty parentProperty, string name, bool allowEditable = true, SerializationBackend backend = SerializationBackend.None, params Attribute[] attributes) { var type = ProcessingOwnerType; type = (parentProperty.ValueEntry != null) ? parentProperty.ValueEntry.TypeOfValue : ProcessingOwnerType; var members = type.GetMember(name, MemberTypes.Field | MemberTypes.Method | MemberTypes.Property, Flags.AllMembers); if (members.Length == 0 || members.Length > 1) { throw new ArgumentException("Could not find precisely 1 member on type '" + type.GetNiceName() + "' with name '" + name + "'; found " + members.Length + " members."); } var list = new List <Attribute>(); if (attributes != null) { list.AddRange(attributes); } InspectorPropertyInfoUtility.ProcessAttributes(parentProperty, members[0], list); infos.Add(InspectorPropertyInfo.CreateForMember(members[0], allowEditable, backend, list)); }
private static OdinDrawer[] GetAllDrawers(Type valueType, Type attributeType, List <DrawerInfo> drawers, bool forceUniqueDrawerInstances = false) { List <DrawerInfo> results = new List <DrawerInfo>(); if (valueType == typeof(NoType)) { valueType = null; } if (valueType != null) { // First, look for drawers which draw this exact type and/or attribute results.AddRange(GetExactTypeDrawerInfos(valueType, attributeType, drawers)); // Then look for generic drawers where this type can fulfill the generic constraints results.AddRange(GetGenericTypeDrawerInfos(valueType, attributeType, drawers)); } // Look for exact omni attribute drawers results.AddRange(GetExactTypeDrawerInfos(null, attributeType, drawers)); // Look for generic omni attribute drawers results.AddRange(GetGenericTypeDrawerInfos(null, attributeType, drawers)); foreach (var locator in CustomDrawerLocators) { results.AddRange(locator.GetDrawers(valueType, attributeType)); } return(results.Distinct() .OrderByDescending(info => info.Priority) .ThenBy(info => info.DrawerType.Name) .Select(info => { try { return GetDrawer(info.DrawerType, forceUniqueDrawerInstances); } catch (Exception ex) { Debug.Log("Encountered the following exception when trying to instantiate a drawer of type " + info.DrawerType.GetNiceName()); Debug.LogException(ex); return null; } }) .Where(drawer => drawer != null && (valueType == null || drawer.CanDrawTypeFilter(valueType))) .Append(() => { // Add composite drawer last, if it can be added - it is the final fallback for types with sub properties if (valueType != null && attributeType == null && !typeof(UnityEngine.Object).IsAssignableFrom(valueType) && InspectorPropertyInfo.Get(valueType, true).Length > 0) { return CompositeDrawer; } return null; }) .Where(drawer => drawer != null) .ToArray()); }
public static InspectorPropertyInfo CreateForMember(MemberInfo member, bool allowEditable, SerializationBackend serializationBackend, List <Attribute> attributes) { if (member == null) { throw new ArgumentNullException("member"); } if (!(member is FieldInfo || member is PropertyInfo || member is MethodInfo)) { throw new ArgumentException("Can only create inspector properties for field, property and method members."); } if (member is MethodInfo && serializationBackend != SerializationBackend.None) { throw new ArgumentException("Serialization backend can only be None for method members."); } if (member is MethodInfo && allowEditable) { //throw new ArgumentException("allowEditable can only be false for method members."); allowEditable = false; } if (allowEditable && member is FieldInfo && (member as FieldInfo).IsLiteral) { allowEditable = false; } string name = null; if (member is MethodInfo) { var mi = member as MethodInfo; var parameters = mi.GetParameters(); if (parameters.Length > 0) { name = mi.GetNiceName(); } } if (name == null) { name = member.Name; } if (name.Contains(".")) { var index = name.LastIndexOf(".") + 1; if (index < name.Length) { name = name.Substring(index); } else { throw new ArgumentException("A member name somehow had a '.' as the last character. This shouldn't be possible, but the '" + member.Name + "' has messed things up for everyone now. Good job!"); } } var result = new InspectorPropertyInfo(); if (member.IsDefined(typeof(OmitFromPrefabModificationPathsAttribute), true)) { name = "#" + name; } result.memberInfos = new MemberInfo[] { member }; result.PropertyName = name; result.PropertyType = member is MethodInfo ? PropertyType.Method : PropertyType.Value; result.SerializationBackend = serializationBackend; if (attributes == null) { result.attributes = new List <Attribute>(); } else { result.attributes = attributes; for (int i = attributes.Count - 1; i >= 0; i--) { var attr = attributes[i]; if (attr == null) { attributes.RemoveAt(i); continue; } var orderAttr = attr as PropertyOrderAttribute; if (orderAttr != null) { result.Order = orderAttr.Order; } } } result.typeOfOwner = member.DeclaringType; if (member is FieldInfo || member is PropertyInfo) { var valueType = member.GetReturnType(); result.typeOfValue = valueType; result.getterSetter = GetEmittedGetterSetterCreator(member.DeclaringType, valueType)(member, !allowEditable); //if (member is FieldInfo) //{ // //TwoArgsObjectArray[0] = member; // //TwoArgsObjectArray[1] = !allowEditable; // //var con = getterSetterType.GetConstructor(GetterSetterFieldConstructorSignature); // //result.getterSetter = (IValueGetterSetter)con.Invoke(TwoArgsObjectArray); // //result.getterSetter = (IValueGetterSetter)Activator.CreateInstance(typeof(GetterSetter<,>).MakeGenericType(member.DeclaringType, valueType), member, !allowEditable); // result.getterSetter = GetEmittedFieldGetterSetterCreator(member.DeclaringType, valueType)(member as FieldInfo, !allowEditable); //} //else //{ // //OneArgObjectArray[0] = member; // //var con = getterSetterType.GetConstructor(GetterSetterPropertyConstructorSignature); // //result.getterSetter = (IValueGetterSetter)con.Invoke(OneArgObjectArray); // //result.getterSetter = (IValueGetterSetter)Activator.CreateInstance(typeof(GetterSetter<,>).MakeGenericType(member.DeclaringType, valueType), member); //} result.IsEditable = allowEditable && !attributes.HasAttribute <ReadOnlyAttribute>() && !result.getterSetter.IsReadonly; } return(result); }
internal static InspectorProperty Create(PropertyTree tree, InspectorProperty parent, InspectorPropertyInfo info, int index) { // Validate parameters first if (tree == null) { throw new ArgumentNullException("tree"); } if (info == null) { if (parent == null) { throw new ArgumentException("A parent is expected when the given InspectorPropertyInfo is null."); } if (parent.Children.IsCollection == false) { throw new ArgumentException("The children of the given parent must be from a collection when the given InspectorPropertyInfo is null."); } } if (parent != null) { if (tree != parent.Tree) { throw new ArgumentException("The given tree and the given parent's tree are not the same tree."); } if (parent.Children is DisabledPropertyChildren) { throw new ArgumentException("A given parent must be able to have children to create a child property for it."); } if (index < 0 || index >= parent.Children.Count) { throw new IndexOutOfRangeException("The given index for the property to create is out of bounds."); } } else { index = -1; } // Now start building a property InspectorProperty property = new InspectorProperty(); property.Tree = tree; if (parent != null) { property.Path = parent.Children.GetPath(index); } else { property.Path = info.PropertyName; } property.Parent = parent; property.Index = index; property.Context = new PropertyContextContainer(property); if (property.Path == null) { Debug.Log("Property path is null for property " + property.NiceName + "!"); } { InspectorProperty current = property; do { current = current.Parent; }while (current != null && current.BaseValueEntry == null); property.ParentValueProperty = current; } if (property.ParentValueProperty != null) { property.ParentType = property.ParentValueProperty.ValueEntry.TypeOfValue; property.ParentValues = new ImmutableList(property.ParentValueProperty.ValueEntry.WeakValues); } else { property.ParentType = tree.TargetType; property.ParentValues = new ImmutableList(tree.WeakTargets); } if (info != null) { property.Info = info; property.Name = info.PropertyName; property.NiceName = ObjectNames.NicifyVariableName(property.Name.TrimStart('#')); property.Label = new GUIContent(property.NiceName); } else { // Collection elements inherit the info of the collection itself // and have their name set a little further down property.Info = parent.Info; } if (property.Info.PropertyType == PropertyType.ValueType || property.Info.PropertyType == PropertyType.ReferenceType) { property.BaseValueEntry = PropertyValueEntry.Create(property, InspectorProperty.GetBaseContainedValueType(property)); property.ValueEntry = property.BaseValueEntry; } if (info == null) { property.ForceUpdatePropertyNameAndPath(index); } // Do NOT update the property here. Property updating may cause this property to be requested before // it has been registered, resulting in an infinite loop. It is the calling code's responsibility to // update the property before usage. return(property); }
public static void AddDelegate(this IList <InspectorPropertyInfo> infos, string name, Delegate @delegate, int order = 0, params Attribute[] attributes) { infos.Add(InspectorPropertyInfo.CreateForDelegate(name, order, typeof(object), (Delegate)@delegate, attributes)); }
public override bool ChildPropertyRequiresRefresh(int index, InspectorPropertyInfo info) { return(this.GetChildInfo(index) != info); }
public override bool ChildPropertyRequiresRefresh(int index, InspectorPropertyInfo info) { return(false); }
//internal void ForceUpdatePropertyNameAndPath(int? newIndex) //{ // if (newIndex != null) // { // this.Index = newIndex.Value; // } // this.unityPropertyPath = null; // this.prefabModificationPath = null; // if (this.Parent != null) // { // this.Path = this.Parent.Children.GetPath(this.Index); // } // else // { // this.Path = this.Info.PropertyName; // } // // Children may be null, as this may be called before the property has ever updated itself // if (this.Children != null) // { // this.Children.ClearCaches(); // for (int i = 0; i < this.Children.Count; i++) // { // this.Children[i].ForceUpdatePropertyNameAndPath(null); // } // } //} internal static InspectorProperty Create(PropertyTree tree, InspectorProperty parent, InspectorPropertyInfo info, int index, bool isSecretRoot) { // Validate parameters first if (tree == null) { throw new ArgumentNullException("tree"); } if (info == null) { throw new ArgumentNullException("info"); } if (parent != null) { if (tree != parent.Tree) { throw new ArgumentException("The given tree and the given parent's tree are not the same tree."); } if (index < 0 || index >= parent.Children.Count) { throw new IndexOutOfRangeException("The given index for the property to create is out of bounds."); } } // Now start building a property InspectorProperty property = new InspectorProperty(); // Set some basic values property.Tree = tree; property.Info = info; property.Parent = parent; property.Index = index; property.Context = new PropertyContextContainer(property); // Find property path { if (parent != null) { property.Path = parent.Children.GetPath(index); } else { property.Path = info.PropertyName; } if (property.Path == null) { Debug.Log("Property path is null for property " + ObjectNames.NicifyVariableName(info.PropertyName.TrimStart('#', '$')) + "!"); } } // Find parent value property if (parent != null) { InspectorProperty current = property; do { current = current.Parent; }while (current != null && current.BaseValueEntry == null); property.ParentValueProperty = current; } // Set parent type and values if (property.ParentValueProperty != null) { property.ParentType = property.ParentValueProperty.ValueEntry.TypeOfValue; property.ParentValues = new ImmutableList(property.ParentValueProperty.ValueEntry.WeakValues); } else { property.ParentType = tree.TargetType; property.ParentValues = new ImmutableList(tree.WeakTargets); } // Find serializing/owning property { InspectorProperty current = property.ParentValueProperty; while (current != null && !current.ValueEntry.TypeOfValue.InheritsFrom(typeof(UnityEngine.Object))) { current = current.ParentValueProperty; } if (current != null) { property.SerializationRoot = current; } else { property.SerializationRoot = isSecretRoot ? property : tree.SecretRootProperty; } } // Set name and label { property.Name = info.PropertyName; var mi = property.Info.GetMemberInfo() as MethodInfo; if (mi != null) { var name = property.Name; var parensIndex = name.IndexOf('('); if (parensIndex >= 0) { name = name.Substring(0, parensIndex); } property.NiceName = name.TrimStart('#', '$').SplitPascalCase(); } else { property.NiceName = ObjectNames.NicifyVariableName(property.Name.TrimStart('#', '$')); } property.Label = new GUIContent(property.NiceName); } // Create a value entry if necessary if (property.Info.PropertyType == PropertyType.Value) { property.BaseValueEntry = PropertyValueEntry.Create(property, info.TypeOfValue, isSecretRoot); property.ValueEntry = property.BaseValueEntry; } // Do NOT update the property here. Property updating may cause this property to be requested before // it has been registered, resulting in an infinite loop. It is the calling code's responsibility to // update the property before usage. if (!isSecretRoot) { property.RefreshProcessedAttributes(); property.ChildResolver = tree.PropertyResolverLocator.GetResolver(property); property.Children = new PropertyChildren(property); } return(property); }
public abstract bool ChildPropertyRequiresRefresh(int index, InspectorPropertyInfo info);
public static void AddValue <TValue>(this IList <InspectorPropertyInfo> infos, string name, Func <TValue> getter, Action <TValue> setter, int order = 0, SerializationBackend backend = SerializationBackend.None, params Attribute[] attributes) { infos.Add(InspectorPropertyInfo.CreateValue(name, order, backend, new GetterSetter <object, TValue>(getter, setter), attributes)); }
public static void AddMember(this IList <InspectorPropertyInfo> infos, MemberInfo member, bool allowEditable = true, SerializationBackend backend = SerializationBackend.None, params Attribute[] attributes) { infos.Add(InspectorPropertyInfo.CreateForMember(member, allowEditable, backend, attributes ?? new Attribute[0])); }