/// <summary> /// Initializes the <see cref="BaseEditorUtility"/> class. /// </summary> static BaseEditorUtility() { foreach (System.Type type in ReflectionX.AllTypes) { if (!type.IsAbstract && typeof(BaseEditor).IsAssignableFrom(type)) { MethodInfo initializeMethod = type.GetMethod("InitializeClass", ReflectionX.staticBindingFlags); if (initializeMethod != null) { initializeMethod.Invoke(null, null); } PropertyInfo featureGroupProp = type.GetProperty("FeatureGroup", ReflectionX.staticBindingFlags); if (featureGroupProp == null) { continue; } string featureGroup = featureGroupProp.GetValue(null, null) as string; if (string.IsNullOrEmpty(featureGroup)) { continue; } MethodInfo prefMenuMethod = type.GetMethod("DisplayHandlePreferences", ReflectionX.staticBindingFlags); if (prefMenuMethod == null || prefMenuMethod.DeclaringType != type) { continue; } EditorPreferenceMenu.AddPreferenceMenuItem(featureGroup, prefMenuMethod); } } }
/// <summary> /// Initializes the <see cref="BaseEditorUtility"/> class. /// </summary> static BaseEditorUtility() { foreach (System.Type type in ReflectionX.AllTypes) { if (!type.IsAbstract && typeof(BaseEditor).IsAssignableFrom(type)) { MethodInfo initializeMethod = type.GetStaticMethod("InitializeClass"); if (initializeMethod != null) { initializeMethod.Invoke(null, null); } PropertyInfo featureGroupProp = type.GetStaticProperty("ProductCategory"); if (featureGroupProp == null) { continue; } AssetStoreProduct product = (AssetStoreProduct)featureGroupProp.GetValue(null, null); if (product == AssetStoreProduct.None) { continue; } MethodInfo prefMenuMethod = type.GetStaticMethod("DisplayHandlePreferences"); if (prefMenuMethod == null || prefMenuMethod.DeclaringType != type) { continue; } EditorPreferenceMenu.AddPreferenceMenuItem(product, prefMenuMethod); } } }
/// <summary> /// Initializes the <see cref="Candlelight.PropertyBackingFieldDrawer"/> class. /// </summary> static PropertyBackingFieldDrawer() { // add preference menu item EditorPreferenceMenu.AddPreferenceMenuItem( "Property Backing Field", () => EditorGUILayout.LabelField("Thanks for your bug reports!") ); //register callbacks with UnityEditor.Undo Undo.postprocessModifications += OnPerformUndoableAction; Undo.undoRedoPerformed += OnUndoRedo; // get all types incompatible with this feature HashSet <System.Type> typesThatCannotBeBackingFields = new HashSet <System.Type>( ObjectX.AllTypes.Where( t => (t.IsClass || (t.IsValueType && !t.IsEnum && !t.IsPrimitive)) && t.GetCustomAttributes <System.SerializableAttribute>().Count() > 0 && !typeof(IPropertyBackingFieldCompatible).IsAssignableFrom(t) ) ); typesThatCannotBeBackingFields.Remove(typeof(string)); // collect T[] and List<T> for each incompatible type HashSet <System.Type> sequenceTypesThatCannotBeBackingFields = new HashSet <System.Type>(); foreach (System.Type incompatibleType in typesThatCannotBeBackingFields) { sequenceTypesThatCannotBeBackingFields.Add(incompatibleType.MakeArrayType()); sequenceTypesThatCannotBeBackingFields.Add( typeof(List <>).MakeGenericType(new System.Type[] { incompatibleType }) ); } // collect any fields that will cause problems with types that cannot be marked as backing fields Dictionary <System.Type, List <FieldInfo> > problematicFields = new Dictionary <System.Type, List <FieldInfo> >(); // examine all fields on the scripted types to find any problematic usages foreach (System.Type providerType in ObjectX.AllTypes) { foreach (FieldInfo field in providerType.GetFields(ObjectX.instanceBindingFlags)) { System.Type typeToValidate = field.FieldType; // skip the field if it is known to be compatible if ( !typesThatCannotBeBackingFields.Contains(typeToValidate) && !sequenceTypesThatCannotBeBackingFields.Contains(typeToValidate) ) { continue; } // skip the field if it is a built-in Unity type if (ObjectX.UnityRuntimeAssemblies.Contains(typeToValidate.Assembly)) { continue; } // skip the field if it is not serialized if (field.IsPrivate && field.GetCustomAttributes <SerializeField>().Count() == 0) { continue; } // skip the field if it is not designated as a backing field if (field.GetCustomAttributes <PropertyBackingFieldAttribute>().Count() == 0) { continue; } // add the type to the problem table if (typeToValidate.IsArray) { typeToValidate = typeToValidate.GetElementType(); } else if (typeToValidate.IsGenericType) { typeToValidate = typeToValidate.GetGenericArguments()[0]; } if (!problematicFields.ContainsKey(typeToValidate)) { problematicFields.Add(typeToValidate, new List <FieldInfo>()); } // add the field to the type's list of problematic usages problematicFields[typeToValidate].Add(field); } } // display messages for any problems foreach (KeyValuePair <System.Type, List <FieldInfo> > problematicType in problematicFields) { Debug.LogError( string.Format( "<b>{0}</b> must implement <b>{1}<{0}></b>, because it is marked with <b>{2}</b> on the following fields:\n{3}", problematicType.Key, typeof(IPropertyBackingFieldCompatible).FullName, typeof(PropertyBackingFieldAttribute).FullName, string.Join( "\n", ( from field in problematicType.Value select string.Format( " - <i>{0}.{1}</i>", field.DeclaringType, field.Name ) ).ToArray() ) ) ); } }