/// <summary> /// Finds the associated InspectedType for the given type. /// </summary> /// <param name="type">The type to find the type metadata for.</param> /// <returns>A TypeMetadata that models the given type.</returns> public static InspectedType Get(Type type) { InspectedType metadata; if (_cachedMetadata.TryGetValue(type, out metadata) == false) { metadata = new InspectedType(type); _cachedMetadata[type] = metadata; } return metadata; }
/// <summary> /// Returns true if the given property should be displayed in the /// inspector. This method assumes that the property type is inspectable. /// </summary> private static bool ShouldDisplayProperty(InspectedProperty property) { var memberInfo = property.MemberInfo; // If ShowInInspector is present, we will *always* display the // attribute. if (memberInfo.IsDefined(typeof(ShowInInspectorAttribute), /*inherit:*/ true)) { return(true); } // note: we do opt-out serialization annotations before opt-in // annotations so that we can still serialize a field but not // display it in the inspector (as the serialize annotations // automatically cause a field to be displayed) if (memberInfo.IsDefined(typeof(HideInInspector), /*inherit:*/ true) || memberInfo.IsDefined(typeof(NotSerializedAttribute), /*inherit:*/ true) || fiInstalledSerializerManager.SerializationOptOutAnnotations.Any(t => memberInfo.IsDefined(t, /*inherit*/ true))) { return(false); } // Show the property if any of the opt-in annotations are present. if (property.IsStatic == false && fiInstalledSerializerManager.SerializationOptInAnnotations.Any(t => memberInfo.IsDefined(t, /*inherit*/ true))) { return(true); } if (property.MemberInfo is PropertyInfo && fiSettings.InspectorRequireShowInInspector) { return(false); } return // IsSerializedByFullInspector will return false for BaseObject // types, so we want to special case support for them being // inspected. (typeof(BaseObject).Resolve().IsAssignableFrom(property.StorageType.Resolve()) || InspectedType.IsSerializedByFullInspector(property) || InspectedType.IsSerializedByUnity(property)); }
private void InitializeFromMemberName(string memberName) { var property = InspectedType.Get(typeof(T)).GetPropertyByName(memberName); if (property == null) { _errorMessage = "Unable to locate member `" + memberName + "` on type `" + typeof(T).CSharpName() + "`"; _fieldType = typeof(T); _attributes = null; _getValue = (o, c) => default(T); _setValue = (o, c, v) => { }; _label = memberName + " (unable to locate)"; return; } _fieldType = property.StorageType; _attributes = property.MemberInfo; _getValue = (o, c) => property.Read(o); _setValue = (o, c, v) => property.Write(o, v); _label = property.DisplayName; }
/// <summary> /// Attempts to remove the property with the given name. /// </summary> /// <param name="propertyName"> /// The name of the property to remove. /// </param> public static void RemoveProperty <T>(string propertyName) { var type = InspectedType.Get(typeof(T)); type._nameToProperty.Remove(propertyName); // reset all filter caches type._cachedMembers = new Dictionary <IInspectedMemberFilter, List <InspectedMember> >(); type._cachedMethods = new Dictionary <IInspectedMemberFilter, List <InspectedMethod> >(); type._cachedProperties = new Dictionary <IInspectedMemberFilter, List <InspectedProperty> >(); // remove it from _allmembers for (int i = 0; i < type._allMembers.Count; ++i) { var member = type._allMembers[i]; if (propertyName == member.Name) { type._allMembers.RemoveAt(i); break; } } }
/// <summary> /// Populate an pre-constructed instance with the data stored inside of the facade. /// </summary> /// <param name="instance">The object instance to populate.</param> public void PopulateInstance(ref T instance) { if (instance.GetType() != InstanceType) { Debug.LogWarning("PopulateInstance: Actual Facade type is different " + "(instance.GetType() = " + instance.GetType().CSharpName() + ", InstanceType = " + InstanceType.CSharpName() + ")"); } Type defaultSerializer = fiInstalledSerializerManager.DefaultMetadata.SerializerType; var serializer = (BaseSerializer)fiSingletons.Get(defaultSerializer); var serializationOperator = new ListSerializationOperator() { SerializedObjects = ObjectReferences }; InspectedType inspectedType = InspectedType.Get(instance.GetType()); foreach (var tuple in FacadeMembers) { string name = tuple.Key; InspectedProperty property = inspectedType.GetPropertyByName(name); if (property != null) { try { object deserializedMember = serializer.Deserialize( property.StorageType.Resolve(), tuple.Value, serializationOperator); property.Write(instance, deserializedMember); } catch (Exception e) { Debug.LogError("Skipping property " + name + " in facade due to " + "deserialization exception.\n" + e); } } } }
public override Facade <T> Edit(Rect region, GUIContent label, Facade <T> element, fiGraphMetadata metadata) { if (element == null) { element = new Facade <T>(); } if (element.InstanceType == null) { element.InstanceType = TypeOptions.Types[0]; } bool changedTypes; DrawHeader(ref region, label, element, out changedTypes); var facadeMembers = new Dictionary <string, string>(); var facadeReferences = new List <UnityObject>(); InspectedType inspectedType = InspectedType.Get(element.InstanceType); var serializer = (BaseSerializer)fiSingletons.Get(fiInstalledSerializerManager.DefaultMetadata.SerializerType); var deserializationOp = new ListSerializationOperator() { SerializedObjects = element.ObjectReferences }; var serializationOp = new ListSerializationOperator() { SerializedObjects = facadeReferences }; float usedHeight = 0; var anim = metadata.GetMetadata <fiAnimationMetadata>(); if (anim.IsAnimating) { fiEditorGUI.BeginFadeGroupHeight(LabelHeight, ref region, anim.AnimationHeight); fiEditorUtility.RepaintAllEditors(); } var properties = inspectedType.GetProperties(InspectedMemberFilters.InspectableMembers); for (int i = 0; i < properties.Count; ++i) { InspectedProperty property = properties[i]; object propertyValue = DeserializeProperty(serializer, deserializationOp, property, element); float height = fiEditorGUI.EditPropertyHeightDirect(property, propertyValue, metadata.Enter(property.Name)); Rect propertyRect = region; propertyRect.height = height; region.y += height; region.y += SplitterHeight; usedHeight += height + SplitterHeight; object updatedValue = fiEditorGUI.EditPropertyDirect(propertyRect, property, propertyValue, metadata.Enter(property.Name)); string data; if (TrySerializeProperty(serializer, serializationOp, property, updatedValue, out data)) { facadeMembers[property.Name] = data; } } if (anim.IsAnimating) { fiEditorGUI.EndFadeGroup(); } element.FacadeMembers = facadeMembers; element.ObjectReferences = facadeReferences; if (changedTypes && anim.UpdateHeight(usedHeight)) { fiEditorUtility.RepaintAllEditors(); } return(element); }
/// <summary> /// Initializes a new instance of the TypeMetadata class from a type. Use /// TypeCache to get instances of TypeMetadata; do not use this /// constructor directly. /// </summary> internal InspectedType(Type type) { ReflectedType = type; // determine if we are a collection or array; recall that arrays // implement the ICollection interface, however _isArray = type.IsArray; IsCollection = _isArray || type.IsImplementationOf(typeof(ICollection <>)); // We're not a collection, so lookup the properties on this type if (IsCollection == false) { _cachedMembers = new Dictionary <IInspectedMemberFilter, List <InspectedMember> >(); _cachedProperties = new Dictionary <IInspectedMemberFilter, List <InspectedProperty> >(); _cachedMethods = new Dictionary <IInspectedMemberFilter, List <InspectedMethod> >(); _allMembers = new List <InspectedMember>(); // Add the parent members first. They will be sorted properly and // the like. if (ReflectedType.Resolve().BaseType != null) { var inspectedParentType = InspectedType.Get(ReflectedType.Resolve().BaseType); _allMembers.AddRange(inspectedParentType._allMembers); } // Add local properties. var localMembers = CollectUnorderedLocalMembers(type).ToList(); if (fiSettings.EnableGlobalOrdering == false) { StableSort(localMembers, (a, b) => { double orderA = InspectorOrderAttribute.GetInspectorOrder(a.MemberInfo); double orderB = InspectorOrderAttribute.GetInspectorOrder(b.MemberInfo); return(Math.Sign(orderA - orderB)); }); } _allMembers.AddRange(localMembers); if (fiSettings.EnableGlobalOrdering) { StableSort(_allMembers, (a, b) => { double orderA = InspectorOrderAttribute.GetInspectorOrder(a.MemberInfo); double orderB = InspectorOrderAttribute.GetInspectorOrder(b.MemberInfo); return(Math.Sign(orderA - orderB)); }); } // Add our property names in _nameToProperty = new Dictionary <string, InspectedProperty>(); _formerlySerializedAsPropertyNames = new Dictionary <string, InspectedProperty>(); foreach (var member in _allMembers) { if (member.IsProperty == false) { continue; } if (fiSettings.EmitWarnings && _nameToProperty.ContainsKey(member.Name)) { Debug.LogWarning("Duplicate property with name=" + member.Name + " detected on " + ReflectedType.CSharpName()); } _nameToProperty[member.Name] = member.Property; foreach (FormerlySerializedAsAttribute attr in member.MemberInfo.GetCustomAttributes(typeof(FormerlySerializedAsAttribute), /*inherit:*/ true)) { _nameToProperty[attr.oldName] = member.Property; } } } }