Beispiel #1
0
        protected override void Initialize()
        {
            var property  = this.Property;
            var attribute = this.Attribute;

            this.contextMenuInfos = property.Context.GetGlobal("CustomContextMenu", (Dictionary <CustomContextMenuAttribute, ContextMenuInfo>)null);
            this.populated        = property.Context.GetGlobal("CustomContextMenu_Populated", false);

            if (contextMenuInfos.Value == null)
            {
                contextMenuInfos.Value = new Dictionary <CustomContextMenuAttribute, ContextMenuInfo>();
            }

            if (!contextMenuInfos.Value.TryGetValue(attribute, out this.info))
            {
                this.info = new ContextMenuInfo();

                var methodInfo = property.ParentType
                                 .FindMember()
                                 .IsMethod()
                                 .IsInstance()
                                 .HasNoParameters()
                                 .ReturnsVoid()
                                 .IsNamed(attribute.MethodName)
                                 .GetMember <MethodInfo>(out this.info.ErrorMessage);

                if (this.info.ErrorMessage == null)
                {
                    this.info.Name         = attribute.MenuItem;
                    this.info.MethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller(methodInfo);
                }

                contextMenuInfos.Value[attribute] = this.info;
            }
        }
Beispiel #2
0
        private static ValueGetter <TOwner, TValue> GetCachedGetter(MemberInfo member)
        {
            Delegate del;

            if (GetterSetterCaches <TOwner> .Getters.TryGetInnerValue(member, typeof(TValue), out del))
            {
                return((ValueGetter <TOwner, TValue>)del);
            }
            else
            {
                ValueGetter <TOwner, TValue> result;

                var fieldInfo    = member as FieldInfo;
                var propertyInfo = member as PropertyInfo;

                if (fieldInfo != null)
                {
                    result = EmitUtilities.CreateInstanceFieldGetter <TOwner, TValue>(fieldInfo);
                }
                else if (propertyInfo != null)
                {
                    result = EmitUtilities.CreateInstancePropertyGetter <TOwner, TValue>(propertyInfo);
                }
                else
                {
                    throw new ArgumentException("Cannot create a GetterSetter for a member of type + " + member.GetType().Name + "!");
                }

                GetterSetterCaches <TOwner> .Getters.AddInner(member, typeof(TValue), result);

                return(result);
            }
        }
Beispiel #3
0
        static AnimationCurveDrawer()
        {
            MethodInfo mi   = null;
            var        type = AssemblyUtilities.GetTypeByCachedFullName("UnityEditorInternal.AnimationCurvePreviewCache");

            if (type != null)
            {
                var method = type.GetMethod("ClearCache", Flags.StaticAnyVisibility);
                var pars   = method.GetParameters();
                if (pars != null && pars.Length == 0)
                {
                    mi = method;
                }
            }

            if (mi != null)
            {
                clearCache = EmitUtilities.CreateStaticMethodCaller(mi);
            }
#if SIRENIX_INTERNAL
            else
            {
                Debug.LogError("AnimationCurve fix no longer works, has Unity fixed it?");
            }
#endif
        }
Beispiel #4
0
 public ObjectMemberAccessor(FieldInfo fieldInfo)
 {
     memberInfo = fieldInfo;
     utf8Name   = Encoding.UTF8.GetBytes(fieldInfo.Name);
     getter     = EmitUtilities.CreateInstanceGetter <K, T>(fieldInfo);
     setter     = EmitUtilities.CreateInstanceSetter <K, T>(fieldInfo);
 }
        static UnityExtensions()
        {
            var field = typeof(UnityEngine.Object).GetField("m_CachedPtr", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            if (field != null)
            {
                UnityObjectCachedPtrFieldGetter = EmitUtilities.CreateInstanceFieldGetter <UnityEngine.Object, IntPtr>(field);
            }
        }
Beispiel #6
0
 /// <summary>
 /// Initializes the <see cref="UnityDecoratorAttributeDrawer{TDrawer, TAttribute}"/> class.
 /// </summary>
 static UnityDecoratorAttributeDrawer()
 {
     if (InternalAttributeFieldInfo == null)
     {
         Debug.LogError("Could not find the internal Unity field 'DecoratorDrawer.m_Attribute'; UnityDecoratorDrawer alias '" + typeof(UnityDecoratorAttributeDrawer <TDrawer, TAttribute, TAttributeConstraint>).GetNiceName() + "' has been disabled.");
     }
     else
     {
         SetAttribute = EmitUtilities.CreateInstanceFieldSetter <TDrawer, Attribute>(InternalAttributeFieldInfo);
     }
 }
 static UnityPropertyDrawer()
 {
     if (InternalFieldInfoFieldInfo == null)
     {
         Debug.LogError("Could not find the internal Unity field 'PropertyDrawer.m_FieldInfo'; UnityPropertyDrawer alias '" + typeof(UnityPropertyDrawer <TDrawer, TDrawnType>).GetNiceName() + "' has been disabled.");
     }
     else
     {
         SetFieldInfo = EmitUtilities.CreateInstanceFieldSetter <TDrawer, FieldInfo>(InternalFieldInfoFieldInfo);
     }
 }
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(InspectorProperty property, OnInspectorGUIAttribute attribute, GUIContent label)
        {
            if (property.Info.PropertyType == PropertyType.Method)
            {
                var methodConfig = property.Context.Get(this, "Config", (MethodContext)null);

                if (methodConfig.Value == null)
                {
                    methodConfig.Value = new MethodContext();

                    MethodInfo methodInfo = property.Info.MemberInfo as MethodInfo;

                    if (methodInfo.ReturnType != typeof(void))
                    {
                        methodConfig.Value.ErrorMessage = "The method '" + methodInfo.Name + "' must have a return type of type void.";
                    }
                    else if (methodInfo.GetParameters().Length > 0)
                    {
                        methodConfig.Value.ErrorMessage = "The method '" + methodInfo.Name + "' cannot take any parameters.";
                    }
                    else
                    {
                        methodConfig.Value.InstanceMethod = EmitUtilities.CreateWeakInstanceMethodCaller(methodInfo);
                    }
                }

                if (methodConfig.Value.ErrorMessage != null)
                {
                    SirenixEditorGUI.ErrorMessageBox(methodConfig.Value.ErrorMessage);
                }
                else
                {
                    if (methodConfig.Value.InstanceMethod != null)
                    {
                        methodConfig.Value.InstanceMethod(property.ParentValues[0]);
                    }
                }
            }
            else
            {
                if (attribute.PrependMethodName != null)
                {
                    this.DoInspectorGUI(property, "Prepend", attribute.PrependMethodName);
                }

                this.CallNextDrawer(property, label);

                if (attribute.AppendMethodName != null)
                {
                    this.DoInspectorGUI(property, "Append", attribute.AppendMethodName);
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="InspectorValuePropertyInfo{TOwner, TValue}"/> class.
        /// </summary>
        /// <param name="fieldInfo">The field to represent.</param>
        /// <param name="serializationBackend">The serialization backend.</param>
        /// <param name="allowEditable">Whether the property can be editable.</param>
        public InspectorValuePropertyInfo(FieldInfo fieldInfo, SerializationBackend serializationBackend, bool allowEditable)
            : base(fieldInfo, fieldInfo.FieldType.IsValueType ? PropertyType.ValueType : PropertyType.ReferenceType, serializationBackend, allowEditable)
        {
            MemberAliasFieldInfo aliasFieldInfo = fieldInfo as MemberAliasFieldInfo;

            if (aliasFieldInfo != null)
            {
                fieldInfo = aliasFieldInfo.AliasedField;
            }

            this.getter = EmitUtilities.CreateInstanceFieldGetter <TOwner, TValue>(fieldInfo);
            this.setter = EmitUtilities.CreateInstanceFieldSetter <TOwner, TValue>(fieldInfo);
        }
Beispiel #10
0
        static InspectorUtilities()
        {
            var mPropertyField = typeof(SerializedObject).GetField("m_Property", Flags.InstanceAnyVisibility);

            if (mPropertyField != null)
            {
                mPropertyFieldGetter = EmitUtilities.CreateInstanceFieldGetter <SerializedObject, IntPtr>(mPropertyField);
            }
            else
            {
                Debug.LogWarning("The internal Unity field SerializedObject.m_Property has been renamed in this version of Unity!");
            }
        }
        static BaseFormatter()
        {
            if (!Serializer.SerializeUnityEngineObjectReferences && !Serializer.DeserializeUnityEngineObjectReferences && typeof(T).ImplementsOrInherits(typeof(UnityEngine.Object)))
            {
                DefaultLoggers.DefaultLogger.LogWarning("A formatter has been created for the UnityEngine.Object type " + typeof(T).Name + " - this is *strongly* discouraged. Unity should be allowed to handle serialization and deserialization of its own weird objects. Remember to serialize with a UnityReferenceResolver as the external index reference resolver in the serialization context.\n\n Stacktrace: " + new System.Diagnostics.StackTrace().ToString());
            }

            var methods = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            Func <MethodInfo, SerializationCallback> selector;

            selector = (info) =>
            {
                var parameters = info.GetParameters();
                if (parameters.Length == 0)
                {
                    var action = EmitUtilities.CreateInstanceRefMethodCaller <T>(info);
                    return((ref T value, StreamingContext context) => action(ref value));
                }
                else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(StreamingContext) && parameters[0].ParameterType.IsByRef == false)
                {
                    var action = EmitUtilities.CreateInstanceRefMethodCaller <T, StreamingContext>(info);
                    return((ref T value, StreamingContext context) => action(ref value, context));
                }
                else
                {
                    DefaultLoggers.DefaultLogger.LogWarning("The method " + info.GetNiceName() + " has an invalid signature and will be ignored by the serialization system.");
                    return(null);
                }
            };

            OnSerializingCallbacks = methods.Where(n => n.IsDefined(typeof(OnSerializingAttribute), true))
                                     .Select(selector)
                                     .Where(n => n != null)
                                     .ToArray();

            OnSerializedCallbacks = methods.Where(n => n.IsDefined(typeof(OnSerializedAttribute), true))
                                    .Select(selector)
                                    .Where(n => n != null)
                                    .ToArray();

            OnDeserializingCallbacks = methods.Where(n => n.IsDefined(typeof(OnDeserializingAttribute), true))
                                       .Select(selector)
                                       .Where(n => n != null)
                                       .ToArray();

            OnDeserializedCallbacks = methods.Where(n => n.IsDefined(typeof(OnDeserializedAttribute), true))
                                      .Select(selector)
                                      .Where(n => n != null)
                                      .ToArray();
        }
Beispiel #12
0
        static InspectorUtilities()
        {
            string nativeObjectPtrName = UnityVersion.IsVersionOrGreater(2018, 3) ? "m_NativeObjectPtr" : "m_Property";

            var nativeObjectPtrField = typeof(SerializedObject).GetField(nativeObjectPtrName, Flags.InstanceAnyVisibility);

            if (nativeObjectPtrField != null)
            {
                SerializedObject_nativeObjectPtrGetter = EmitUtilities.CreateInstanceFieldGetter <SerializedObject, IntPtr>(nativeObjectPtrField);
            }
            else
            {
                Debug.LogWarning("The internal Unity field SerializedObject.m_Property (< 2018.3)/SerializedObject.m_NativeObjectPtr (>= 2018.3) has been renamed in this version of Unity!");
            }
        }
Beispiel #13
0
    protected override void Initialize()
    {
        this.isListElement = this.Property.Parent != null && this.Property.Parent.ChildResolver is IOrderedCollectionResolver;
        var isList       = !this.isListElement;
        var listProperty = isList ? this.Property : this.Property.Parent;

        this.baseMemberProperty     = listProperty.FindParent(x => x.Info.PropertyType == PropertyType.Value, true);
        this.globalSelectedProperty = this.baseMemberProperty.Context.GetGlobal("selectedIndex" + this.baseMemberProperty.GetHashCode(), (InspectorProperty)null);

        if (isList)
        {
            var parentType = this.baseMemberProperty.ParentValues[0].GetType();
            this.selectedIndexSetter = EmitUtilities.CreateWeakInstanceMethodCaller <int>(parentType.GetMethod(this.Attribute.SetSelectedMethod, Flags.AllMembers));
        }
    }
Beispiel #14
0
        static GUIHelper()
        {
            var guiLayoutEntryType = typeof(GUI).Assembly.GetType("UnityEngine.GUILayoutEntry");
            var hostViewType       = typeof(Editor).Assembly.GetType("UnityEditor.HostView");
            var guiViewType        = typeof(Editor).Assembly.GetType("UnityEditor.GUIView");

            inspectorWindowType = typeof(Editor).Assembly.GetType("UnityEditor.InspectorWindow");

            GetRectOnGUILayoutEntry       = EmitUtilities.CreateWeakInstanceFieldGetter <Rect>(guiLayoutEntryType, guiLayoutEntryType.GetField("rect", Flags.AllMembers));
            EditorScreenPointOffsetGetter = DeepReflection.CreateValueGetter <Vector2>(typeof(GUIUtility), "s_EditorScreenPointOffset");
            CurrentWindowIDGetter         = DeepReflection.CreateValueGetter <int>(guiViewType, "current.GetInstanceID()");
            CurrentWindowHasFocusGetter   = DeepReflection.CreateValueGetter <bool>(guiViewType, "current.hasFocus");
            GetIsDockedWindowGetter       = DeepReflection.CreateValueGetter <EditorWindow, bool>("docked");
            ContextWidthGetter            = DeepReflection.CreateValueGetter <float>(typeof(EditorGUIUtility), "contextWidth");
            ActualLabelWidthGetter        = EmitUtilities.CreateStaticFieldGetter <float>(typeof(EditorGUIUtility).GetField("s_LabelWidth", Flags.AllMembers));
            //ActualLabelWidthSetter = EmitUtilities.CreateStaticFieldSetter<float>(typeof(EditorGUIUtility).GetField("s_LabelWidth", Flags.AllMembers));

            var guiViewGetter    = DeepReflection.CreateWeakStaticValueGetter(guiViewType, guiViewType, "current");
            var actualViewGetter = DeepReflection.CreateWeakInstanceValueGetter <EditorWindow>(hostViewType, "actualView");
            var borderSizeGetter = DeepReflection.CreateWeakInstanceValueGetter <RectOffset>(hostViewType, "borderSize");

            CurrentWindowGetter           = () => actualViewGetter(guiViewGetter());
            CurrentWindowBorderSizeGetter = () => borderSizeGetter(guiViewGetter());

            SetBoldDefaultFontSetter = (Action <bool>)Delegate.CreateDelegate(typeof(Action <bool>),
                                                                              typeof(EditorGUIUtility).FindMember()
                                                                              .IsStatic()
                                                                              .IsMethod()
                                                                              .HasParameters <bool>()
                                                                              .ReturnsVoid()
                                                                              .IsNamed("SetBoldDefaultFont")
                                                                              .GetMember <MethodInfo>(), true);

            GetBoldDefaultFontGetter = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>),
                                                                            typeof(EditorGUIUtility).FindMember()
                                                                            .IsStatic()
                                                                            .IsMethod()
                                                                            .HasNoParameters()
                                                                            .HasReturnType <bool>()
                                                                            .IsNamed("GetBoldDefaultFont")
                                                                            .GetMember <MethodInfo>(), true);

            GUILayoutEntriesCursorIndexGetter = DeepReflection.CreateValueGetter <int>(typeof(GUILayoutUtility), "current.topLevel.m_Cursor");
            GUILayoutEntriesGetter            = DeepReflection.CreateValueGetter <IList>(typeof(GUILayoutUtility), "current.topLevel.entries");
            CurrentIndentAmountGetter         = DeepReflection.CreateValueGetter <float>(typeof(EditorGUI), "indent");
            GetTopLevelLayoutRectGetter       = DeepReflection.CreateValueGetter <Rect>(typeof(GUILayoutUtility), "current.topLevel.rect");
            GetEditorWindowRectGetter         = DeepReflection.CreateValueGetter <Rect>(typeof(Editor).Assembly.GetType("UnityEditor.Toolbar"), "get.parent.screenPosition");
        }
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(GUIContent label)
        {
            var property  = this.Property;
            var attribute = this.Attribute;

            var contextMenuInfos = property.Context.GetGlobal("CustomContextMenu", (Dictionary <CustomContextMenuAttribute, ContextMenuInfo>)null);
            var populated        = property.Context.GetGlobal("CustomContextMenu_Populated", false);

            populated.Value = false;

            if (contextMenuInfos.Value == null)
            {
                contextMenuInfos.Value = new Dictionary <CustomContextMenuAttribute, ContextMenuInfo>();
            }

            ContextMenuInfo info;

            if (!contextMenuInfos.Value.TryGetValue(attribute, out info))
            {
                info = new ContextMenuInfo();

                var methodInfo = property.ParentType
                                 .FindMember()
                                 .IsMethod()
                                 .IsInstance()
                                 .HasNoParameters()
                                 .ReturnsVoid()
                                 .IsNamed(attribute.MethodName)
                                 .GetMember <MethodInfo>(out info.ErrorMessage);

                if (info.ErrorMessage == null)
                {
                    info.Name         = attribute.MenuItem;
                    info.MethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller(methodInfo);
                }

                contextMenuInfos.Value[attribute] = info;
            }

            if (info.ErrorMessage != null)
            {
                SirenixEditorGUI.ErrorMessageBox(info.ErrorMessage);
            }

            this.CallNextDrawer(label);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="InspectorValuePropertyInfo{TOwner, TValue}"/> class.
        /// </summary>
        /// <param name="propertyInfo">The property to represent.</param>
        /// <param name="serializationBackend">The serialization backend.</param>
        /// <param name="allowEditable">Whether the property can be editable.</param>
        public InspectorValuePropertyInfo(PropertyInfo propertyInfo, SerializationBackend serializationBackend, bool allowEditable)
            : base(propertyInfo, propertyInfo.PropertyType.IsValueType ? PropertyType.ValueType : PropertyType.ReferenceType, serializationBackend, allowEditable)

        {
            MemberAliasPropertyInfo aliasPropertyInfo = propertyInfo as MemberAliasPropertyInfo;

            if (aliasPropertyInfo != null)
            {
                propertyInfo = aliasPropertyInfo.AliasedProperty;
            }

            this.getter = EmitUtilities.CreateInstancePropertyGetter <TOwner, TValue>(propertyInfo);

            if (propertyInfo.CanWrite)
            {
                this.setter = EmitUtilities.CreateInstancePropertySetter <TOwner, TValue>(propertyInfo);
            }
        }
Beispiel #17
0
        private static Action <TValue> GetCachedStaticSetter(MemberInfo member)
        {
            Delegate del;

            if (GetterSetterCaches <TOwner> .Setters.TryGetInnerValue(member, typeof(TValue), out del))
            {
                return((Action <TValue>)del);
            }
            else
            {
                Action <TValue> result = null;

                var fieldInfo    = member as FieldInfo;
                var propertyInfo = member as PropertyInfo;

                if (fieldInfo != null)
                {
                    if (!fieldInfo.IsLiteral)
                    {
                        result = EmitUtilities.CreateStaticFieldSetter <TValue>(fieldInfo);
                    }
                }
                else if (propertyInfo != null)
                {
                    if (propertyInfo.CanWrite)
                    {
                        result = EmitUtilities.CreateStaticPropertySetter <TValue>(propertyInfo);
                    }
                }
                else
                {
                    throw new ArgumentException("Cannot create a GetterSetter for a member of type + " + member.GetType().Name + "!");
                }

                GetterSetterCaches <TOwner> .Setters.AddInner(member, typeof(TValue), result);

                return(result);
            }
        }
Beispiel #18
0
        private static void EnsureInitialized()
        {
            if (!Initialized)
            {
                Initialized = true;

                try
                {
                    string haveAudioCallbackName = UnityVersion.IsVersionOrGreater(5, 6) ? "HasAudioCallback" : "HaveAudioCallback";

                    AudioUtil_HaveAudioCallback           = (Func <MonoBehaviour, bool>)Delegate.CreateDelegate(typeof(Func <MonoBehaviour, bool>), typeof(Editor).Assembly.GetType("UnityEditor.AudioUtil").GetMethod(haveAudioCallbackName, BindingFlags.Public | BindingFlags.Static));
                    AudioUtil_GetCustomFilterChannelCount = (Func <MonoBehaviour, int>)Delegate.CreateDelegate(typeof(Func <MonoBehaviour, int>), typeof(Editor).Assembly.GetType("UnityEditor.AudioUtil").GetMethod("GetCustomFilterChannelCount", BindingFlags.Public | BindingFlags.Static));
                    AudioFilterGUIType      = typeof(Editor).Assembly.GetType("UnityEditor.AudioFilterGUI");
                    DrawAudioFilterGUI      = EmitUtilities.CreateWeakInstanceMethodCaller <MonoBehaviour>(AudioFilterGUIType.GetMethod("DrawAudioFilterGUI", BindingFlags.Public | BindingFlags.Instance));
                    HasReflectedAudioFilter = true;
                }
                catch (Exception)
                {
                    Debug.LogWarning("The internal Unity class AudioFilterGUI has been changed; cannot properly mock a generic Unity inspector. This probably won't be very noticeable.");
                }
            }
        }
Beispiel #19
0
        private static SerializationCallback CreateCallback(MethodInfo info)
        {
            var parameters = info.GetParameters();

            if (parameters.Length == 0)
            {
#if CAN_EMIT
                var action = EmitUtilities.CreateInstanceRefMethodCaller <T>(info);
                return((ref T value, StreamingContext context) => action(ref value));
#else
                return((ref T value, StreamingContext context) =>
                {
                    object obj = value;
                    info.Invoke(obj, null);
                    value = (T)obj;
                });
#endif
            }
            else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(StreamingContext) && parameters[0].ParameterType.IsByRef == false)
            {
#if CAN_EMIT
                var action = EmitUtilities.CreateInstanceRefMethodCaller <T, StreamingContext>(info);
                return((ref T value, StreamingContext context) => action(ref value, context));
#else
                return((ref T value, StreamingContext context) =>
                {
                    object obj = value;
                    info.Invoke(obj, new object[] { context });
                    value = (T)obj;
                });
#endif
            }
            else
            {
                DefaultLoggers.DefaultLogger.LogWarning("The method " + info.GetNiceName() + " has an invalid signature and will be ignored by the serialization system.");
                return(null);
            }
        }
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(GUIContent label)
        {
            var entry     = this.ValueEntry;
            var attribute = this.Attribute;

            var context = entry.Property.Context.Get <ButtonContext>(this, "ButtonContext", (ButtonContext)null);

            if (context.Value == null)
            {
                context.Value             = new ButtonContext();
                context.Value.LabelHelper = new StringMemberHelper(this.Property, attribute.Label ?? attribute.MemberMethod.SplitPascalCase(), ref context.Value.ErrorMessage);

                if (context.Value.ErrorMessage == null)
                {
                    MethodInfo method;

                    if (MemberFinder.Start(entry.ParentType)
                        .IsMethod()
                        .IsNamed(attribute.MemberMethod)
                        .HasNoParameters()
                        .TryGetMember <MethodInfo>(out method, out context.Value.ErrorMessage))
                    {
                        if (method.IsStatic())
                        {
                            context.Value.StaticMethodCaller = EmitUtilities.CreateStaticMethodCaller(method);
                        }
                        else
                        {
                            context.Value.InstanceMethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller(method);
                        }
                    }
                    else if (MemberFinder.Start(entry.ParentType)
                             .IsMethod()
                             .IsNamed(attribute.MemberMethod)
                             .HasParameters <T>()
                             .TryGetMember <MethodInfo>(out method, out context.Value.ErrorMessage))
                    {
                        if (method.IsStatic())
                        {
                            context.Value.ErrorMessage = "Static parameterized method is currently not supported.";
                        }
                        else
                        {
                            context.Value.InstanceParameterMethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller <T>(method);
                        }
                    }
                }
            }

            if (context.Value.ErrorMessage != null)
            {
                SirenixEditorGUI.ErrorMessageBox(context.Value.ErrorMessage);
                this.CallNextDrawer(label);
            }
            else
            {
                EditorGUILayout.BeginHorizontal();

                EditorGUILayout.BeginVertical();
                this.CallNextDrawer(label);
                EditorGUILayout.EndVertical();

                if (GUILayout.Button(context.Value.LabelHelper.GetString(entry), EditorStyles.miniButton, GUILayoutOptions.ExpandWidth(false).MinWidth(20)))
                {
                    // Invoke method.
                    if (context.Value.StaticMethodCaller != null)
                    {
                        context.Value.StaticMethodCaller();
                    }
                    //else if(context.Value.StaticParameterMethodCaller != null)
                    //{
                    //	context.Value.StaticParameterMethodCaller(entry.SmartValue);
                    //}
                    else if (context.Value.InstanceMethodCaller != null)
                    {
                        context.Value.InstanceMethodCaller(entry.Property.ParentValues[0]);
                    }
                    else if (context.Value.InstanceParameterMethodCaller != null)
                    {
                        context.Value.InstanceParameterMethodCaller(entry.Property.ParentValues[0], entry.SmartValue);
                    }
                    else
                    {
                        Debug.LogError("No method found.");
                    }
                }

                EditorGUILayout.EndHorizontal();
            }
        }
Beispiel #21
0
        /// <summary>
        /// Initialized the drawer.
        /// </summary>
        protected override void Initialize()
        {
            MemberInfo member;

            // Min member
            if (this.Attribute.MinMember != null)
            {
                this.getterMinValue = new InspectorPropertyValueGetter <T>(this.Property, this.Attribute.MinMember);
                this.errorMessage   = this.getterMinValue.ErrorMessage;
            }

            // Max member
            if (this.Attribute.MaxMember != null)
            {
                this.getterMaxValue = new InspectorPropertyValueGetter <T>(this.Property, this.Attribute.MaxMember);
                this.errorMessage   = this.getterMaxValue.ErrorMessage;
            }

            // Foreground color member.
            if (!this.Attribute.ColorMember.IsNullOrWhitespace())
            {
                if (MemberFinder.Start(this.Property.ParentType)
                    .IsNamed(this.Attribute.ColorMember)
                    .HasReturnType <Color>()
                    .TryGetMember(out member, out this.errorMessage))
                {
                    if (member is FieldInfo || member is PropertyInfo)
                    {
                        if (member.IsStatic())
                        {
                            this.staticColorGetter = DeepReflection.CreateValueGetter <Color>(this.Property.ParentType, this.Attribute.ColorMember);
                        }
                        else
                        {
                            this.instanceColorGetter = DeepReflection.CreateWeakInstanceValueGetter <Color>(this.Property.ParentType, this.Attribute.ColorMember);
                        }
                    }
                    else if (member is MethodInfo)
                    {
                        if (member.IsStatic())
                        {
                            this.errorMessage = "Static method members are currently not supported.";
                        }
                        else
                        {
                            var method = member as MethodInfo;
                            var p      = method.GetParameters();

                            if (p.Length == 0)
                            {
                                this.instanceColorMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <Color>(method);
                            }
                            else if (p.Length == 1 && p[0].ParameterType == typeof(T))
                            {
                                this.instanceColorParameterMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <T, Color>(method);
                            }
                        }
                    }
                    else
                    {
                        this.errorMessage = "Unsupported member type.";
                    }
                }
            }

            // Background color member.
            if (!this.Attribute.BackgroundColorMember.IsNullOrWhitespace())
            {
                if (MemberFinder.Start(this.Property.ParentType)
                    .IsNamed(this.Attribute.BackgroundColorMember)
                    .HasReturnType <Color>()
                    .TryGetMember(out member, out this.errorMessage))
                {
                    if (member is FieldInfo || member is PropertyInfo)
                    {
                        if (member.IsStatic())
                        {
                            this.staticBackgroundColorGetter = DeepReflection.CreateValueGetter <Color>(this.Property.ParentType, this.Attribute.BackgroundColorMember);
                        }
                        else
                        {
                            this.instanceBackgroundColorGetter = DeepReflection.CreateWeakInstanceValueGetter <Color>(this.Property.ParentType, this.Attribute.BackgroundColorMember);
                        }
                    }
                    else if (member is MethodInfo)
                    {
                        if (member.IsStatic())
                        {
                            this.errorMessage = "Static method members are currently not supported.";
                        }
                        else
                        {
                            var method = member as MethodInfo;
                            var p      = method.GetParameters();

                            if (p.Length == 0)
                            {
                                this.instanceBackgroundColorMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <Color>(method);
                            }
                            else if (p.Length == 1 && p[0].ParameterType == typeof(T))
                            {
                                this.instanceBackgroundColorParameterMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <T, Color>(method);
                            }
                        }
                    }
                    else
                    {
                        this.errorMessage = "Unsupported member type.";
                    }
                }
            }

            // Custom value string getter
            if (this.Attribute.CustomValueStringMember != null && this.Attribute.CustomValueStringMember.Length > 0)
            {
                if (MemberFinder.Start(this.Property.ParentType)
                    .IsNamed(this.Attribute.CustomValueStringMember)
                    .HasReturnType <string>()
                    .TryGetMember(out member, out this.errorMessage))
                {
                    if (member is FieldInfo || member is PropertyInfo)
                    {
                        if (member.IsStatic())
                        {
                            this.staticGetValueLabel = DeepReflection.CreateValueGetter <string>(this.Property.ParentType, this.Attribute.CustomValueStringMember);
                        }
                        else
                        {
                            this.instanceGetValueLabel = DeepReflection.CreateWeakInstanceValueGetter <string>(this.Property.ParentType, this.Attribute.CustomValueStringMember);
                        }
                    }
                    else if (member is MethodInfo)
                    {
                        var method     = member as MethodInfo;
                        var parameters = method.GetParameters();

                        if (parameters.Length == 0)
                        {
                            string name = this.Attribute.CustomValueStringMember + "()";
                            if (member.IsStatic())
                            {
                                this.staticGetValueLabel = DeepReflection.CreateValueGetter <string>(this.Property.ParentType, name);
                            }
                            else
                            {
                                this.instanceGetValueLabel = DeepReflection.CreateWeakInstanceValueGetter <string>(this.Property.ParentType, name);
                            }
                        }
                        else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(T))
                        {
                            if (member.IsStatic())
                            {
                                // TODO: This should be emitted.
                                this.staticGetValueLabelValue = (v) => (string)method.Invoke(null, new object[] { v });
                            }
                            else
                            {
                                // TODO: This should be emitted.
                                this.instanceGetValueLabelValue = (o, v) => (string)method.Invoke(o, new object[] { v });
                            }
                        }
                        else
                        {
                            this.errorMessage = "Was unable to find any string field or property or string method with no parameters or exactly one " + typeof(T).GetNiceName() + " parameter named " + this.Attribute.CustomValueStringMember;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Initializes this instance.
        /// </summary>
        protected override void Initialize()
        {
            this.hideDetailedMessage = true;
            this.messageHelper       = new StringMemberHelper(this.Property, this.Attribute.Message);
            this.detailsHelper       = new StringMemberHelper(this.Property, this.Attribute.Details);
            this.errorMessage        = this.messageHelper.ErrorMessage ?? this.detailsHelper.ErrorMessage;

            if (this.Attribute.VisibleIf != null)
            {
                MemberInfo memberInfo;

                // Parameter functions
                if (this.Property.ValueEntry != null && this.Property.ParentType.FindMember()
                    .IsMethod()
                    .HasReturnType <bool>()
                    .HasParameters(this.Property.ValueEntry.BaseValueType)
                    .IsNamed(this.Attribute.VisibleIf)
                    .TryGetMember(out memberInfo, out this.errorMessage))
                {
                    if (this.errorMessage == null)
                    {
                        if (memberInfo is MethodInfo)
                        {
                            var method = memberInfo as MethodInfo;

                            if (memberInfo.IsStatic())
                            {
                                // TODO: Emit dis.
                                this.staticValidationParameterMethodCaller = p => (bool)method.Invoke(null, new object[] { p });
                            }
                            else
                            {
                                // TODO: Emit dis.
                                this.instanceValidationParameterMethodCaller = (i, p) => (bool)method.Invoke(i, new object[] { p });
                            }
                        }
                        else
                        {
                            this.errorMessage = "Invalid member type!";
                        }
                    }
                }

                // Fields, properties, and no-parameter functions.
                else if (this.Property.ParentType.FindMember()
                         .HasReturnType <bool>()
                         .HasNoParameters()
                         .IsNamed(this.Attribute.VisibleIf)
                         .TryGetMember(out memberInfo, out this.errorMessage))
                {
                    if (this.errorMessage == null)
                    {
                        if (memberInfo is FieldInfo)
                        {
                            if (memberInfo.IsStatic())
                            {
                                this.staticValidationCaller = EmitUtilities.CreateStaticFieldGetter <bool>(memberInfo as FieldInfo);
                            }
                            else
                            {
                                this.instanceValueGetter = EmitUtilities.CreateWeakInstanceFieldGetter(this.Property.ParentType, memberInfo as FieldInfo);
                            }
                        }
                        else if (memberInfo is PropertyInfo)
                        {
                            if (memberInfo.IsStatic())
                            {
                                this.staticValidationCaller = EmitUtilities.CreateStaticPropertyGetter <bool>(memberInfo as PropertyInfo);
                            }
                            else
                            {
                                this.instanceValueGetter = EmitUtilities.CreateWeakInstancePropertyGetter(this.Property.ParentType, memberInfo as PropertyInfo);
                            }
                        }
                        else if (memberInfo is MethodInfo)
                        {
                            if (memberInfo.IsStatic())
                            {
                                this.staticValidationCaller = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), memberInfo as MethodInfo);
                            }
                            else
                            {
                                this.instanceValidationMethodCaller = EmitUtilities.CreateWeakInstanceMethodCallerFunc <bool>(memberInfo as MethodInfo);
                            }
                        }
                        else
                        {
                            this.errorMessage = "Invalid member type!";
                        }
                    }
                }
            }
        }
Beispiel #23
0
        public static float Draw <T>(OdinDrawer drawerInstance, IPropertyValueEntry <T> entry, float progress, ProgressBarAttribute attribute, GUIContent label)
        {
            PropertyContext <ProgressBarContext <T> > contextBuffer;

            if (entry.Context.Get <ProgressBarContext <T> >(drawerInstance, "ProgressBarContext", out contextBuffer))
            {
                var parentType = entry.Property.FindParent(PropertyValueCategory.Member, true).ParentType;
                contextBuffer.Value = new ProgressBarContext <T>();

                if (!attribute.ColorMember.IsNullOrWhitespace())
                {
                    MemberInfo member;
                    if (MemberFinder.Start(parentType)
                        .IsNamed(attribute.ColorMember)
                        .HasReturnType <Color>()
                        .TryGetMember(out member, out contextBuffer.Value.ErrorMessage))
                    {
                        if (member is FieldInfo || member is PropertyInfo)
                        {
                            if (member.IsStatic())
                            {
                                contextBuffer.Value.StaticColorGetter = DeepReflection.CreateValueGetter <Color>(parentType, attribute.ColorMember);
                            }
                            else
                            {
                                contextBuffer.Value.InstanceColorGetter = DeepReflection.CreateWeakInstanceValueGetter <Color>(parentType, attribute.ColorMember);
                            }
                        }
                        else if (member is MethodInfo)
                        {
                            if (member.IsStatic())
                            {
                                contextBuffer.Value.ErrorMessage = "Static method members are currently not supported.";
                            }
                            else
                            {
                                var method = member as MethodInfo;
                                var p      = method.GetParameters();

                                if (p.Length == 0)
                                {
                                    contextBuffer.Value.InstanceColorMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <Color>(method);
                                }
                                else if (p.Length == 1 && p[0].ParameterType == typeof(T))
                                {
                                    contextBuffer.Value.InstanceColorParameterMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <T, Color>(method);
                                }
                            }
                        }
                        else
                        {
                            contextBuffer.Value.ErrorMessage = "Unsupported member type.";
                        }
                    }
                }
                if (!attribute.BackgroundColorMember.IsNullOrWhitespace())
                {
                    MemberInfo member;
                    if (MemberFinder.Start(parentType)
                        .IsNamed(attribute.BackgroundColorMember)
                        .HasReturnType <Color>()
                        .TryGetMember(out member, out contextBuffer.Value.ErrorMessage))
                    {
                        if (member is FieldInfo || member is PropertyInfo)
                        {
                            if (member.IsStatic())
                            {
                                contextBuffer.Value.StaticBackgroundColorGetter = DeepReflection.CreateValueGetter <Color>(parentType, attribute.BackgroundColorMember);
                            }
                            else
                            {
                                contextBuffer.Value.InstanceBackgroundColorGetter = DeepReflection.CreateWeakInstanceValueGetter <Color>(parentType, attribute.BackgroundColorMember);
                            }
                        }
                        else if (member is MethodInfo)
                        {
                            if (member.IsStatic())
                            {
                                contextBuffer.Value.ErrorMessage = "Static method members are currently not supported.";
                            }
                            else
                            {
                                var method = member as MethodInfo;
                                var p      = method.GetParameters();

                                if (p.Length == 0)
                                {
                                    contextBuffer.Value.InstanceBackgroundColorMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <Color>(method);
                                }
                                else if (p.Length == 1 && p[0].ParameterType == typeof(T))
                                {
                                    contextBuffer.Value.InstanceBackgroundColorParameterMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <T, Color>(method);
                                }
                            }
                        }
                        else
                        {
                            contextBuffer.Value.ErrorMessage = "Unsupported member type.";
                        }
                    }
                }
            }

            var context = contextBuffer.Value;

            // Error message
            if (context.ErrorMessage != null)
            {
                AllEditorGUI.ErrorMessageBox(context.ErrorMessage);
            }

            // Construct rect.
            Rect rect;

            if (label != null)
            {
                rect = EditorGUILayout.GetControlRect(true, attribute.Height > EditorGUIUtility.singleLineHeight ? attribute.Height : EditorGUIUtility.singleLineHeight);
                rect = EditorGUI.PrefixLabel(rect, label);
                rect = rect.AlignMiddle(attribute.Height);
            }
            else
            {
                rect = EditorGUILayout.GetControlRect(false, attribute.Height);
                GUIHelper.IndentRect(ref rect);
            }

            // Draw
            if (Event.current.type == EventType.Repaint)
            {
                var parent = entry.Property.FindParent(PropertyValueCategory.Member, true).ParentValues[0];

                Color color =
                    context.StaticColorGetter != null?context.StaticColorGetter() :
                        context.InstanceColorGetter != null?context.InstanceColorGetter(parent) :
                            context.InstanceColorMethod != null?context.InstanceColorMethod(parent) :
                                context.InstanceColorParameterMethod != null?context.InstanceColorParameterMethod(parent, entry.SmartValue) :
                                    new Color(attribute.R, attribute.G, attribute.B, 1f);

                Color backgroundColor =
                    context.StaticBackgroundColorGetter != null?context.StaticBackgroundColorGetter() :
                        context.InstanceBackgroundColorGetter != null?context.InstanceBackgroundColorGetter(parent) :
                            context.InstanceBackgroundColorMethod != null?context.InstanceBackgroundColorMethod(parent) :
                                context.InstanceBackgroundColorParameterMethod != null?context.InstanceBackgroundColorParameterMethod(parent, entry.SmartValue) :
                                    new Color(0.16f, 0.16f, 0.16f, 1f);

                AllEditorGUI.DrawSolidRect(rect, backgroundColor);
                AllEditorGUI.DrawSolidRect(rect.AlignLeft(rect.width * Mathf.Clamp01(progress)), color);
                AllEditorGUI.DrawBorders(rect, 1, new Color(0.16f, 0.16f, 0.16f, 1f));
            }

            if (GUI.enabled)
            {
                int controlID = GUIUtility.GetControlID(FocusType.Passive);
                if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && rect.Contains(Event.current.mousePosition) ||
                    GUIUtility.hotControl == controlID && (Event.current.type == EventType.MouseMove || Event.current.type == EventType.MouseDrag))
                {
                    Event.current.Use();
                    GUIUtility.hotControl = controlID;
                    GUIHelper.RequestRepaint();
                    GUI.changed = true;

                    progress = (Event.current.mousePosition.x - rect.xMin) / rect.width;
                }
                else if (GUIUtility.hotControl == controlID && Event.current.rawType == EventType.MouseUp)
                {
                    GUIUtility.hotControl = 0;
                }
            }

            return(progress);
        }
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(InspectorProperty property, InfoBoxAttribute attribute, GUIContent label)
        {
            PropertyContext <InfoBoxContext> context = null;

            context = property.Context.Get(this, "Config_" + this.GetHashCode(), (InfoBoxContext)null);
            if (context.Value == null)
            {
                context.Value = new InfoBoxContext()
                {
                    MessageHelper = new StringMemberHelper(property.ParentType, attribute.Message)
                };

                context.Value.ErrorMessage = context.Value.MessageHelper.ErrorMessage;

                MemberInfo memberInfo;

                if (attribute.VisibleIf != null)
                {
                    // Parameter functions
                    if (property.ValueEntry != null &&
                        property.ParentType.FindMember()
                        .IsMethod()
                        .HasReturnType <bool>()
                        .HasParameters(property.ValueEntry.BaseValueType)
                        .IsNamed(attribute.VisibleIf)
                        .TryGetMember(out memberInfo, out context.Value.ErrorMessage))
                    {
                        if (context.Value.ErrorMessage == null)
                        {
                            if (memberInfo is MethodInfo)
                            {
                                if (memberInfo.IsStatic())
                                {
                                    context.Value.StaticValidationParameterMethod = memberInfo as MethodInfo;
                                }
                                else
                                {
                                    context.Value.InstanceValidationParameterMethod = memberInfo as MethodInfo;
                                }
                            }
                            else
                            {
                                context.Value.ErrorMessage = "Invalid member type!";
                            }
                        }
                    }
                    // Fields, properties, and no-parameter functions.
                    else if (property.ParentType.FindMember()
                             .HasReturnType <bool>()
                             .HasNoParameters()
                             .IsNamed(attribute.VisibleIf)
                             .TryGetMember(out memberInfo, out context.Value.ErrorMessage))
                    {
                        if (context.Value.ErrorMessage == null)
                        {
                            if (memberInfo is FieldInfo)
                            {
                                if (memberInfo.IsStatic())
                                {
                                    context.Value.StaticValidationCaller = EmitUtilities.CreateStaticFieldGetter <bool>(memberInfo as FieldInfo);
                                }
                                else
                                {
                                    context.Value.InstanceValueGetter = EmitUtilities.CreateWeakInstanceFieldGetter(property.ParentType, memberInfo as FieldInfo);
                                }
                            }
                            else if (memberInfo is PropertyInfo)
                            {
                                if (memberInfo.IsStatic())
                                {
                                    context.Value.StaticValidationCaller = EmitUtilities.CreateStaticPropertyGetter <bool>(memberInfo as PropertyInfo);
                                }
                                else
                                {
                                    context.Value.InstanceValueGetter = EmitUtilities.CreateWeakInstancePropertyGetter(property.ParentType, memberInfo as PropertyInfo);
                                }
                            }
                            else if (memberInfo is MethodInfo)
                            {
                                if (memberInfo.IsStatic())
                                {
                                    context.Value.StaticValidationCaller = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), memberInfo as MethodInfo);
                                }
                                else
                                {
                                    context.Value.InstanceValidationMethodCaller = EmitUtilities.CreateWeakInstanceMethodCallerFunc <bool>(memberInfo as MethodInfo);
                                }
                            }
                            else
                            {
                                context.Value.ErrorMessage = "Invalid member type!";
                            }
                        }
                    }
                }
            }

            if (context.Value.ErrorMessage != null)
            {
                SirenixEditorGUI.ErrorMessageBox(context.Value.ErrorMessage);
            }
            else
            {
                if (Event.current.type == EventType.Layout)
                {
                    var parentValue = property.ParentValues[0];

                    try
                    {
                        context.Value.DrawMessageBox =
                            attribute.VisibleIf == null ||
                            (context.Value.StaticValidationParameterMethod != null && (bool)context.Value.StaticValidationParameterMethod.Invoke(null, new object[] { property.ValueEntry.WeakSmartValue })) ||
                            (context.Value.InstanceValidationParameterMethod != null && (bool)context.Value.InstanceValidationParameterMethod.Invoke(null, new object[] { property.ParentValues[0], property.ValueEntry.WeakSmartValue })) ||
                            (context.Value.InstanceValidationMethodCaller != null && context.Value.InstanceValidationMethodCaller(property.ParentValues[0])) ||
                            (context.Value.InstanceValueGetter != null && (bool)context.Value.InstanceValueGetter(ref parentValue)) ||
                            (context.Value.StaticValidationCaller != null && context.Value.StaticValidationCaller());
                    }
                    catch (System.Exception ex)
                    {
                        Debug.LogException(ex);
                    }
                }

                if (context.Value.DrawMessageBox)
                {
                    switch (attribute.InfoMessageType)
                    {
                    case InfoMessageType.None:
                        SirenixEditorGUI.MessageBox(context.Value.MessageHelper.GetString(property));
                        break;

                    case InfoMessageType.Info:
                        SirenixEditorGUI.InfoMessageBox(context.Value.MessageHelper.GetString(property));
                        break;

                    case InfoMessageType.Warning:
                        SirenixEditorGUI.WarningMessageBox(context.Value.MessageHelper.GetString(property));
                        break;

                    case InfoMessageType.Error:
                        SirenixEditorGUI.ErrorMessageBox(context.Value.MessageHelper.GetString(property));
                        break;

                    default:
                        SirenixEditorGUI.ErrorMessageBox("Unknown InfoBoxType: " + attribute.InfoMessageType.ToString());
                        break;
                    }
                }
            }

            this.CallNextDrawer(property, label);
        }
Beispiel #25
0
        /// <summary>
        /// Initializes the drawer.
        /// </summary>
        protected override void Initialize()
        {
            var  resolver   = this.Property.ChildResolver as ICollectionResolver;
            bool isReadOnly = resolver.IsReadOnly;

            var customListDrawerOptions = this.Property.GetAttribute <ListDrawerSettingsAttribute>() ?? new ListDrawerSettingsAttribute();

            isReadOnly = this.ValueEntry.IsEditable == false || isReadOnly || customListDrawerOptions.IsReadOnlyHasValue && customListDrawerOptions.IsReadOnly;

            info = new ListDrawerConfigInfo()
            {
                StartIndex = 0,
                Toggled    = this.ValueEntry.Context.GetPersistent <bool>(this, "ListDrawerToggled", customListDrawerOptions.ExpandedHasValue ? customListDrawerOptions.Expanded : GeneralDrawerConfig.Instance.OpenListsByDefault),
                RemoveAt   = -1,

                // Now set further down, so it can be kept updated every frame
                //Label = new GUIContent(label == null || string.IsNullOrEmpty(label.text) ? this.Property.ValueEntry.TypeOfValue.GetNiceName() : label.text, label == null ? string.Empty : label.tooltip),
                ShowAllWhilePaging      = false,
                EndIndex                = 0,
                CustomListDrawerOptions = customListDrawerOptions,
                IsReadOnly              = isReadOnly,
                Draggable               = !isReadOnly && (!customListDrawerOptions.IsReadOnlyHasValue),
                HideAddButton           = isReadOnly || customListDrawerOptions.HideAddButton,
                HideRemoveButton        = isReadOnly || customListDrawerOptions.HideRemoveButton,
            };

            info.ListConfig = GeneralDrawerConfig.Instance;
            info.Property   = this.Property;

            if (customListDrawerOptions.DraggableHasValue && !customListDrawerOptions.DraggableItems)
            {
                info.Draggable = false;
            }

            if (!(this.Property.ChildResolver is IOrderedCollectionResolver))
            {
                info.Draggable = false;
            }

            if (info.CustomListDrawerOptions.OnBeginListElementGUI != null)
            {
                string     error;
                MemberInfo memberInfo = this.Property.ParentType
                                        .FindMember()
                                        .IsMethod()
                                        .IsNamed(info.CustomListDrawerOptions.OnBeginListElementGUI)
                                        .HasParameters <int>()
                                        .ReturnsVoid()
                                        .GetMember <MethodInfo>(out error);

                if (memberInfo == null || error != null)
                {
                    // TOOD: Do something about this "There should really be an error message here." thing.
                    // For this to trigger both the member and the error message should be null. Can that happen?
                    this.errorMessage = error ?? "There should really be an error message here.";
                }
                else
                {
                    info.OnBeginListElementGUI = EmitUtilities.CreateWeakInstanceMethodCaller <int>(memberInfo as MethodInfo);
                }
            }

            if (info.CustomListDrawerOptions.OnEndListElementGUI != null)
            {
                string     error;
                MemberInfo memberInfo = this.Property.ParentType
                                        .FindMember()
                                        .IsMethod()
                                        .IsNamed(info.CustomListDrawerOptions.OnEndListElementGUI)
                                        .HasParameters <int>()
                                        .ReturnsVoid()
                                        .GetMember <MethodInfo>(out error);

                if (memberInfo == null || error != null)
                {
                    // TOOD: Do something about this "There should really be an error message here." thing.
                    // For this to trigger both the member and the error message should be null. Can that happen?
                    this.errorMessage = error ?? "There should really be an error message here.";
                }
                else
                {
                    info.OnEndListElementGUI = EmitUtilities.CreateWeakInstanceMethodCaller <int>(memberInfo as MethodInfo);
                }
            }

            if (info.CustomListDrawerOptions.OnTitleBarGUI != null)
            {
                string     error;
                MemberInfo memberInfo = this.Property.ParentType
                                        .FindMember()
                                        .IsMethod()
                                        .IsNamed(info.CustomListDrawerOptions.OnTitleBarGUI)
                                        .HasNoParameters()
                                        .ReturnsVoid()
                                        .GetMember <MethodInfo>(out error);

                if (memberInfo == null || error != null)
                {
                    // TOOD: Do something about this "There should really be an error message here." thing.
                    // For this to trigger both the member and the error message should be null. Can that happen?
                    this.errorMessage = error ?? "There should really be an error message here.";
                }
                else
                {
                    info.OnTitleBarGUI = EmitUtilities.CreateWeakInstanceMethodCaller(memberInfo as MethodInfo);
                }
            }

            if (info.CustomListDrawerOptions.ListElementLabelName != null)
            {
                string     error;
                MemberInfo memberInfo = resolver.ElementType
                                        .FindMember()
                                        .HasNoParameters()
                                        .IsNamed(info.CustomListDrawerOptions.ListElementLabelName)
                                        .HasReturnType <object>(true)
                                        .GetMember(out error);

                if (memberInfo == null || error != null)
                {
                    // TOOD: Do something about this "There should really be an error message here." thing.
                    // For this to trigger both the member and the error message should be null. Can that happen?
                    this.errorMessage = error ?? "There should really be an error message here.";
                }
                else
                {
                    string methodSuffix = memberInfo as MethodInfo == null ? "" : "()";
                    info.GetListElementLabelText = DeepReflection.CreateWeakInstanceValueGetter(resolver.ElementType, typeof(object), info.CustomListDrawerOptions.ListElementLabelName + methodSuffix);
                }
            }

            // Resolve custom add method member reference.
            if (info.CustomListDrawerOptions.CustomAddFunction != null)
            {
                string     error;
                MemberInfo memberInfo = this.Property.ParentType
                                        .FindMember()
                                        .HasNoParameters()
                                        .IsNamed(info.CustomListDrawerOptions.CustomAddFunction)
                                        .IsInstance()
                                        .HasReturnType(resolver.ElementType)
                                        .GetMember(out error);

                if (memberInfo == null || error != null)
                {
                    string error2;

                    memberInfo = this.Property.ParentType
                                 .FindMember()
                                 .IsMethod()
                                 .HasNoParameters()
                                 .IsNamed(info.CustomListDrawerOptions.CustomAddFunction)
                                 .IsInstance()
                                 .ReturnsVoid()
                                 .GetMember(out error2);

                    if (memberInfo == null || error2 != null)
                    {
                        this.errorMessage = error + " - or - " + error2;
                    }
                    else
                    {
                        info.GetCustomAddFunctionVoid = EmitUtilities.CreateWeakInstanceMethodCaller(memberInfo as MethodInfo);
                    }
                }
                else
                {
                    string methodSuffix = memberInfo as MethodInfo == null ? "" : "()";
                    info.GetCustomAddFunction = DeepReflection.CreateWeakInstanceValueGetter(
                        this.Property.ParentType,
                        resolver.ElementType,
                        info.CustomListDrawerOptions.CustomAddFunction + methodSuffix
                        );
                }
            }

            // Resolve custom remove index method member reference.
            if (info.CustomListDrawerOptions.CustomRemoveIndexFunction != null)
            {
                if (this.Property.ChildResolver is IOrderedCollectionResolver == false)
                {
                    this.errorMessage = "ListDrawerSettings.CustomRemoveIndexFunction is invalid on unordered collections. Use ListDrawerSetings.CustomRemoveElementFunction instead.";
                }
                else
                {
                    MethodInfo method = this.Property.ParentType
                                        .FindMember()
                                        .IsNamed(info.CustomListDrawerOptions.CustomRemoveIndexFunction)
                                        .IsMethod()
                                        .IsInstance()
                                        .HasParameters <int>()
                                        .ReturnsVoid()
                                        .GetMember <MethodInfo>(out this.errorMessage);

                    if (method != null)
                    {
                        info.CustomRemoveIndexFunction = EmitUtilities.CreateWeakInstanceMethodCaller <int>(method);
                    }
                }
            }
            // Resolve custom remove element method member reference.
            else if (info.CustomListDrawerOptions.CustomRemoveElementFunction != null)
            {
                var element = (this.Property.ChildResolver as ICollectionResolver).ElementType;

                MethodInfo method = this.Property.ParentType
                                    .FindMember()
                                    .IsNamed(info.CustomListDrawerOptions.CustomRemoveElementFunction)
                                    .IsMethod()
                                    .IsInstance()
                                    .HasParameters(element)
                                    .ReturnsVoid()
                                    .GetMember <MethodInfo>(out this.errorMessage);

                if (method != null)
                {
                    // TOOD: Emit dis.
                    info.CustomRemoveElementFunction = (o, e) => method.Invoke(o, new object[] { e });
                }
            }
        }
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(GUIContent label)
        {
            var property  = this.Property;
            var entry     = this.ValueEntry;
            var attribute = this.Attribute;

            var assetList    = property.Context.Get(this, "assetList", (AssetList)null);
            var propertyTree = property.Context.Get(this, "togglableAssetListPropertyTree", (PropertyTree)null);

            if (property.ValueEntry.WeakSmartValue == null)
            {
                return;
            }

            if (assetList.Value == null)
            {
                assetList.Value = new AssetList();
                assetList.Value.AutoPopulate    = attribute.AutoPopulate;
                assetList.Value.AssetNamePrefix = attribute.AssetNamePrefix;
                assetList.Value.Tags            = attribute.Tags != null?attribute.Tags.Trim().Split(',').Select(i => i.Trim()).ToArray() : null;

                assetList.Value.LayerNames = attribute.LayerNames != null?attribute.LayerNames.Trim().Split(',').Select(i => i.Trim()).ToArray() : null;

                assetList.Value.List = entry;
                assetList.Value.CollectionResolver = property.ChildResolver as IOrderedCollectionResolver;
                assetList.Value.Property           = entry.Property;

                if (attribute.Path != null)
                {
                    var path = attribute.Path.TrimStart('/', ' ').TrimEnd('/', ' ');
                    path = attribute.Path.Trim('/', ' ');

                    path = "Assets/" + path + "/";
                    path = Application.dataPath + "/" + path;

                    assetList.Value.AssetsFolderLocation = new DirectoryInfo(path);

                    path = attribute.Path.Trim('/', ' ');
                    assetList.Value.PrettyPath = "/" + path.TrimStart('/');
                }

                if (attribute.CustomFilterMethod != null)
                {
                    MethodInfo methodInfo;
                    string     error;
                    if (MemberFinder.Start(entry.ParentType)
                        .IsMethod()
                        .IsNamed(attribute.CustomFilterMethod)
                        .HasReturnType <bool>()
                        .HasParameters <TElement>()
                        .TryGetMember <MethodInfo>(out methodInfo, out error))
                    {
                        if (methodInfo.IsStatic)
                        {
                            assetList.Value.StaticCustomIncludeMethod = (Func <TElement, bool>)Delegate.CreateDelegate(typeof(Func <TElement, bool>), methodInfo, true);
                        }
                        else
                        {
                            assetList.Value.InstanceCustomIncludeMethod = EmitUtilities.CreateWeakInstanceMethodCaller <bool, TElement>(methodInfo);
                        }
                    }

                    assetList.Value.ErrorMessage = error;
                }

                // We can get away with lag on load.
                assetList.Value.MaxSearchDurationPrFrameInMS = 20;
                assetList.Value.EnsureListPopulation();
                assetList.Value.MaxSearchDurationPrFrameInMS = 1;

                //assetList.Value.List = list;

                //if (propertyTree.Value == null)
                //{
                propertyTree.Value = PropertyTree.Create(assetList.Value);
                propertyTree.Value.UpdateTree();
                propertyTree.Value.GetRootProperty(0).Label = label;
                //}
            }
            else if (Event.current.type == EventType.Layout)
            {
                assetList.Value.Property = entry.Property;
                assetList.Value.EnsureListPopulation();
                assetList.Value.SetToggleValues();
            }

            if (assetList.Value.ErrorMessage != null)
            {
                SirenixEditorGUI.ErrorMessageBox(assetList.Value.ErrorMessage);
            }
            assetList.Value.Property = entry.Property;
            propertyTree.Value.Draw(false);

            if (Event.current.type == EventType.Used)
            {
                assetList.Value.UpdateList();
            }
        }
Beispiel #27
0
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(IPropertyValueEntry <T> entry, DetailedInfoBoxAttribute attribute, GUIContent label)
        {
            PropertyContext <InfoBoxContext> context = entry.Property.Context.Get(this, "Context", (InfoBoxContext)null);

            if (context.Value == null)
            {
                context.Value = new InfoBoxContext()
                {
                    MessageHelper = new StringMemberHelper(entry.ParentType, attribute.Message),
                    DetailsHelper = new StringMemberHelper(entry.ParentType, attribute.Details)
                };

                context.Value.ErrorMessage = context.Value.MessageHelper.ErrorMessage ?? context.Value.DetailsHelper.ErrorMessage;

                if (attribute.VisibleIf != null)
                {
                    MemberInfo memberInfo;

                    // Parameter functions
                    if (entry.ParentType.FindMember()
                        .IsMethod()
                        .HasReturnType <bool>()
                        .HasParameters <T>()
                        .IsNamed(attribute.VisibleIf)
                        .TryGetMember(out memberInfo, out context.Value.ErrorMessage))
                    {
                        if (context.Value.ErrorMessage == null)
                        {
                            if (memberInfo is MethodInfo)
                            {
                                if (memberInfo.IsStatic())
                                {
                                    context.Value.StaticValidationParameterMethodCaller = (Func <T, bool>)Delegate.CreateDelegate(typeof(Func <T, bool>), memberInfo as MethodInfo);
                                }
                                else
                                {
                                    context.Value.InstanceValidationParameterMethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller <bool, T>(memberInfo as MethodInfo);
                                }
                            }
                            else
                            {
                                context.Value.ErrorMessage = "Invalid member type!";
                            }
                        }
                    }
                    // Fields, properties, and no-parameter functions.
                    else if (entry.ParentType.FindMember()
                             .HasReturnType <bool>()
                             .HasNoParameters()
                             .IsNamed(attribute.VisibleIf)
                             .TryGetMember(out memberInfo, out context.Value.ErrorMessage))
                    {
                        if (context.Value.ErrorMessage == null)
                        {
                            if (memberInfo is FieldInfo)
                            {
                                if (memberInfo.IsStatic())
                                {
                                    context.Value.StaticValidationCaller = EmitUtilities.CreateStaticFieldGetter <bool>(memberInfo as FieldInfo);
                                }
                                else
                                {
                                    context.Value.InstanceValueGetter = EmitUtilities.CreateWeakInstanceFieldGetter(entry.ParentType, memberInfo as FieldInfo);
                                }
                            }
                            else if (memberInfo is PropertyInfo)
                            {
                                if (memberInfo.IsStatic())
                                {
                                    context.Value.StaticValidationCaller = EmitUtilities.CreateStaticPropertyGetter <bool>(memberInfo as PropertyInfo);
                                }
                                else
                                {
                                    context.Value.InstanceValueGetter = EmitUtilities.CreateWeakInstancePropertyGetter(entry.ParentType, memberInfo as PropertyInfo);
                                }
                            }
                            else if (memberInfo is MethodInfo)
                            {
                                if (memberInfo.IsStatic())
                                {
                                    context.Value.StaticValidationCaller = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), memberInfo as MethodInfo);
                                }
                                else
                                {
                                    context.Value.InstanceValidationMethodCaller = EmitUtilities.CreateWeakInstanceMethodCallerFunc <bool>(memberInfo as MethodInfo);
                                }
                            }
                            else
                            {
                                context.Value.ErrorMessage = "Invalid member type!";
                            }
                        }
                    }
                }
            }

            if (context.Value.ErrorMessage != null)
            {
                AllEditorGUI.ErrorMessageBox(context.Value.ErrorMessage);
            }
            else
            {
                if (Event.current.type == EventType.Layout)
                {
                    var parentValue = entry.Property.ParentValues[0];

                    try
                    {
                        if (entry.Property.ValueEntry != null)
                        {
                            context.Value.DrawMessageBox =
                                attribute.VisibleIf == null ||
                                (context.Value.StaticValidationParameterMethodCaller != null && context.Value.StaticValidationParameterMethodCaller(entry.SmartValue)) ||
                                (context.Value.InstanceValidationParameterMethodCaller != null && context.Value.InstanceValidationParameterMethodCaller(entry.Property.ParentValues[0], entry.SmartValue)) ||
                                (context.Value.InstanceValidationMethodCaller != null && context.Value.InstanceValidationMethodCaller(entry.Property.ParentValues[0])) ||
                                (context.Value.InstanceValueGetter != null && (bool)context.Value.InstanceValueGetter(ref parentValue)) ||
                                (context.Value.StaticValidationCaller != null && context.Value.StaticValidationCaller());
                        }
                    }
                    catch (System.Exception ex)
                    {
                        Debug.LogException(ex);
                    }
                }

                if (context.Value.DrawMessageBox)
                {
                    var foldedConfig = entry.Property.Context.GetPersistent <bool>(this, "InfoBoxExpanded", true);

                    switch (attribute.InfoMessageType)
                    {
                    case InfoMessageType.None:
                        foldedConfig.Value = AllEditorGUI.DetailedMessageBox(context.Value.MessageHelper.GetString(entry), context.Value.DetailsHelper.GetString(entry), UnityEditor.MessageType.None, foldedConfig.Value);
                        break;

                    case InfoMessageType.Info:
                        foldedConfig.Value = AllEditorGUI.DetailedMessageBox(context.Value.MessageHelper.GetString(entry), context.Value.DetailsHelper.GetString(entry), UnityEditor.MessageType.Info, foldedConfig.Value);
                        break;

                    case InfoMessageType.Warning:
                        foldedConfig.Value = AllEditorGUI.DetailedMessageBox(context.Value.MessageHelper.GetString(entry), context.Value.DetailsHelper.GetString(entry), UnityEditor.MessageType.Warning, foldedConfig.Value);
                        break;

                    case InfoMessageType.Error:
                        foldedConfig.Value = AllEditorGUI.DetailedMessageBox(context.Value.MessageHelper.GetString(entry), context.Value.DetailsHelper.GetString(entry), UnityEditor.MessageType.Error, foldedConfig.Value);
                        break;

                    default:
                        AllEditorGUI.ErrorMessageBox("Unknown InfoBoxType: " + attribute.InfoMessageType.ToString());
                        break;
                    }
                }
            }

            this.CallNextDrawer(entry.Property, label);
        }
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(IPropertyValueEntry <TList> entry, GUIContent label)
        {
            var property    = entry.Property;
            var infoContext = property.Context.Get(this, "Context", (ListDrawerConfigInfo)null);
            var info        = infoContext.Value;

            bool isReadOnly = false;

            if (entry.TypeOfValue.IsArray == false)
            {
                for (int i = 0; i < entry.ValueCount; i++)
                {
                    if ((entry.WeakValues[i] as IList <TElement>).IsReadOnly)
                    {
                        isReadOnly = true;
                        break;
                    }
                }
            }

            if (info == null)
            {
                var customListDrawerOptions = property.Info.GetAttribute <ListDrawerSettingsAttribute>() ?? new ListDrawerSettingsAttribute();
                isReadOnly = entry.IsEditable == false || isReadOnly || customListDrawerOptions.IsReadOnlyHasValue && customListDrawerOptions.IsReadOnly;

                info = infoContext.Value = new ListDrawerConfigInfo()
                {
                    StartIndex              = 0,
                    Toggled                 = entry.Context.GetPersistent <bool>(this, "ListDrawerToggled", customListDrawerOptions.ExpandedHasValue ? customListDrawerOptions.Expanded : GeneralDrawerConfig.Instance.OpenListsByDefault),
                    RemoveAt                = -1,
                    label                   = new GUIContent(label == null || string.IsNullOrEmpty(label.text) ? property.ValueEntry.TypeOfValue.GetNiceName() : label.text, label == null ? string.Empty : label.tooltip),
                    ShowAllWhilePageing     = false,
                    EndIndex                = 0,
                    CustomListDrawerOptions = customListDrawerOptions,
                    IsReadOnly              = isReadOnly,
                    Draggable               = !isReadOnly && (!customListDrawerOptions.IsReadOnlyHasValue)
                };

                info.listConfig = GeneralDrawerConfig.Instance;
                info.property   = property;

                if (customListDrawerOptions.DraggableHasValue && !customListDrawerOptions.DraggableItems)
                {
                    info.Draggable = false;
                }

                if (info.CustomListDrawerOptions.OnBeginListElementGUI != null)
                {
                    string     errorMessage;
                    MemberInfo memberInfo = property.ParentType
                                            .FindMember()
                                            .IsMethod()
                                            .IsNamed(info.CustomListDrawerOptions.OnBeginListElementGUI)
                                            .HasParameters <int>()
                                            .ReturnsVoid()
                                            .GetMember <MethodInfo>(out errorMessage);

                    if (memberInfo == null || errorMessage != null)
                    {
                        Debug.LogError(errorMessage ?? "There should really be an error message here.");
                    }
                    else
                    {
                        info.OnBeginListElementGUI = EmitUtilities.CreateWeakInstanceMethodCaller <int>(memberInfo as MethodInfo);
                    }
                }

                if (info.CustomListDrawerOptions.OnEndListElementGUI != null)
                {
                    string     errorMessage;
                    MemberInfo memberInfo = property.ParentType
                                            .FindMember()
                                            .IsMethod()
                                            .IsNamed(info.CustomListDrawerOptions.OnEndListElementGUI)
                                            .HasParameters <int>()
                                            .ReturnsVoid()
                                            .GetMember <MethodInfo>(out errorMessage);

                    if (memberInfo == null || errorMessage != null)
                    {
                        Debug.LogError(errorMessage ?? "There should really be an error message here.");
                    }
                    else
                    {
                        info.OnEndListElementGUI = EmitUtilities.CreateWeakInstanceMethodCaller <int>(memberInfo as MethodInfo);
                    }
                }

                if (info.CustomListDrawerOptions.OnTitleBarGUI != null)
                {
                    string     errorMessage;
                    MemberInfo memberInfo = property.ParentType
                                            .FindMember()
                                            .IsMethod()
                                            .IsNamed(info.CustomListDrawerOptions.OnTitleBarGUI)
                                            .HasNoParameters()
                                            .ReturnsVoid()
                                            .GetMember <MethodInfo>(out errorMessage);

                    if (memberInfo == null || errorMessage != null)
                    {
                        Debug.LogError(errorMessage ?? "There should really be an error message here.");
                    }
                    else
                    {
                        info.OnTitleBarGUI = EmitUtilities.CreateWeakInstanceMethodCaller(memberInfo as MethodInfo);
                    }
                }

                if (info.CustomListDrawerOptions.ListElementLabelName != null)
                {
                    string     errorMessage;
                    MemberInfo memberInfo = typeof(TElement)
                                            .FindMember()
                                            .HasNoParameters()
                                            .IsNamed(info.CustomListDrawerOptions.ListElementLabelName)
                                            .HasReturnType <object>(true)
                                            .GetMember(out errorMessage);

                    if (memberInfo == null || errorMessage != null)
                    {
                        Debug.LogError(errorMessage ?? "There should really be an error message here.");
                    }
                    else
                    {
                        string methodSuffix = memberInfo as MethodInfo == null ? "" : "()";
                        info.GetListElementLabelText = DeepReflection.CreateWeakInstanceValueGetter(typeof(TElement), typeof(object), info.CustomListDrawerOptions.ListElementLabelName + methodSuffix);
                    }
                }
            }

            info.listConfig = GeneralDrawerConfig.Instance;
            info.property   = property;

            info.ListItemStyle.padding.left  = info.Draggable ? 25 : 7;
            info.ListItemStyle.padding.right = info.IsReadOnly ? 4 : 20;

            if (Event.current.type == EventType.Repaint)
            {
                info.DropZoneTopLeft = GUIUtility.GUIToScreenPoint(new Vector2(0, 0));
            }

            info.ListValueChanger = property.ValueEntry.GetListValueEntryChanger();
            info.Count            = property.Children.Count;
            info.IsEmpty          = property.Children.Count == 0;

            SirenixEditorGUI.BeginIndentedVertical(SirenixGUIStyles.PropertyPadding);
            this.BeginDropZone(info);
            {
                this.DrawToolbar(info);
                if (SirenixEditorGUI.BeginFadeGroup(UniqueDrawerKey.Create(property, this), info.Toggled.Value))
                {
                    GUIHelper.PushLabelWidth(EditorGUIUtility.labelWidth - info.ListItemStyle.padding.left);
                    this.DrawItems(info);
                    GUIHelper.PopLabelWidth();
                }
                SirenixEditorGUI.EndFadeGroup();
            }
            this.EndDropZone(info);
            SirenixEditorGUI.EndIndentedVertical();

            if (info.RemoveAt >= 0 && Event.current.type == EventType.Repaint)
            {
                info.ListValueChanger.RemoveListElementAt(info.RemoveAt, CHANGE_ID);

                info.RemoveAt = -1;
                GUIHelper.RequestRepaint();
            }

            if (info.ObjectPicker != null && info.ObjectPicker.IsReadyToClaim && Event.current.type == EventType.Repaint)
            {
                var value = info.ObjectPicker.ClaimObject();

                if (info.JumpToNextPageOnAdd)
                {
                    info.StartIndex = int.MaxValue;
                }

                object[] values = new object[info.ListValueChanger.ValueCount];

                values[0] = value;
                for (int j = 1; j < values.Length; j++)
                {
                    values[j] = SerializationUtility.CreateCopy(value);
                }

                info.ListValueChanger.AddListElement(values, CHANGE_ID);
            }
        }
Beispiel #29
0
        /// <summary>
        /// Not yet documented.
        /// </summary>
        protected override void DrawPropertyLayout(GUIContent label)
        {
            var entry     = this.ValueEntry;
            var attribute = this.Attribute;

            var config = entry.Property.Context.Get(this, "Test", (CurrentContext)null);

            if (config.Value == null)
            {
                config.Value           = new CurrentContext();
                config.Value.Attribute = attribute;
                config.Value.Tags      = attribute.Tags != null?attribute.Tags.Trim().Split(',').Select(i => i.Trim()).ToArray() : null;

                config.Value.LayerNames = attribute.LayerNames != null?attribute.LayerNames.Trim().Split(',').Select(i => i.Trim()).ToArray() : null;

                config.Value.Property = entry.Property;
                if (attribute.Path != null)
                {
                    var path = attribute.Path.Trim('/', ' ');
                    path = "Assets/" + path + "/";
                    path = Application.dataPath + "/" + path;

                    config.Value.AssetsFolderLocation = new DirectoryInfo(path);

                    path = attribute.Path.TrimStart('/').TrimEnd('/');
                    config.Value.PrettyPath = "/" + path.TrimStart('/');
                }

                if (attribute.CustomFilterMethod != null)
                {
                    MethodInfo methodInfo;
                    string     error;
                    if (MemberFinder.Start(entry.ParentType)
                        .IsMethod()
                        .IsNamed(attribute.CustomFilterMethod)
                        .HasReturnType <bool>()
                        .HasParameters <TElement>()
                        .TryGetMember <MethodInfo>(out methodInfo, out error))
                    {
                        if (methodInfo.IsStatic)
                        {
                            config.Value.StaticCustomIncludeMethod = (Func <TElement, bool>)Delegate.CreateDelegate(typeof(Func <TElement, bool>), methodInfo, true);
                        }
                        else
                        {
                            config.Value.InstanceCustomIncludeMethod = EmitUtilities.CreateWeakInstanceMethodCaller <bool, TElement>(methodInfo);
                        }
                    }

                    config.Value.ErrorMessage = error;
                }

                if (config.Value.ErrorMessage != null)
                {
                    // We can get away with lag on load.
                    config.Value.MaxSearchDurationPrFrameInMS = 20;
                    config.Value.EnsureListPopulation();
                    config.Value.MaxSearchDurationPrFrameInMS = 1;
                }
            }

            var currentValue = (UnityEngine.Object)entry.WeakSmartValue;

            if (config.Value.ErrorMessage != null)
            {
                SirenixEditorGUI.ErrorMessageBox(config.Value.ErrorMessage);
            }
            else
            {
                config.Value.EnsureListPopulation();
            }

            SirenixEditorGUI.BeginIndentedVertical(SirenixGUIStyles.PropertyPadding);
            {
                SirenixEditorGUI.BeginHorizontalToolbar();
                if (label != null)
                {
                    GUILayout.Label(label);
                }

                GUILayout.FlexibleSpace();
                if (config.Value.PrettyPath != null)
                {
                    GUILayout.Label(config.Value.PrettyPath, SirenixGUIStyles.RightAlignedGreyMiniLabel);
                    SirenixEditorGUI.VerticalLineSeparator();
                }

                if (config.Value.IsPopulated)
                {
                    GUILayout.Label(config.Value.AvailableAsset.Count + " items", SirenixGUIStyles.RightAlignedGreyMiniLabel);
                    GUIHelper.PushGUIEnabled(GUI.enabled && (config.Value.AvailableAsset.Count > 0 && config.Value.ErrorMessage == null));
                }
                else
                {
                    GUILayout.Label("Scanning " + config.Value.CurrentSearchingIndex + " / " + config.Value.NumberOfResultsToSearch, SirenixGUIStyles.RightAlignedGreyMiniLabel);
                    GUIHelper.PushGUIEnabled(false);
                }

                SirenixEditorGUI.VerticalLineSeparator();

                bool drawConflict = entry.Property.ParentValues.Count > 1;
                if (drawConflict == false)
                {
                    var index = config.Value.AvailableAsset.IndexOf(currentValue) + 1;
                    if (index > 0)
                    {
                        GUILayout.Label(index.ToString(), SirenixGUIStyles.RightAlignedGreyMiniLabel);
                    }
                    else
                    {
                        drawConflict = true;
                    }
                }

                if (drawConflict)
                {
                    GUILayout.Label("-", SirenixGUIStyles.RightAlignedGreyMiniLabel);
                }

                if (SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleLeft) && config.Value.IsPopulated)
                {
                    var index = config.Value.AvailableAsset.IndexOf(currentValue) - 1;
                    index = index < 0 ? config.Value.AvailableAsset.Count - 1 : index;
                    entry.WeakSmartValue = config.Value.AvailableAsset[index];
                }

                if (SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleDown) && config.Value.IsPopulated)
                {
                    GenericMenu m            = new GenericMenu();
                    var         selected     = currentValue;
                    int         itemsPrPage  = 40;
                    bool        showPages    = config.Value.AvailableAsset.Count > 50;
                    string      page         = "";
                    int         selectedPage = (config.Value.AvailableAsset.IndexOf(entry.WeakSmartValue as UnityEngine.Object) / itemsPrPage);
                    for (int i = 0; i < config.Value.AvailableAsset.Count; i++)
                    {
                        var obj = config.Value.AvailableAsset[i];
                        if (obj != null)
                        {
                            var path       = AssetDatabase.GetAssetPath(obj);
                            var name       = string.IsNullOrEmpty(path) ? obj.name : path.Substring(7).Replace("/", "\\");
                            var localEntry = entry;

                            if (showPages)
                            {
                                var p = (i / itemsPrPage);
                                page = (p * itemsPrPage) + " - " + Mathf.Min(((p + 1) * itemsPrPage), config.Value.AvailableAsset.Count - 1);
                                if (selectedPage == p)
                                {
                                    page += " (contains selected)";
                                }
                                page += "/";
                            }

                            m.AddItem(new GUIContent(page + name), obj == selected, () =>
                            {
                                localEntry.Property.Tree.DelayActionUntilRepaint(() => localEntry.WeakSmartValue = obj);
                            });
                        }
                    }
                    m.ShowAsContext();
                }

                if (SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleRight) && config.Value.IsPopulated)
                {
                    var index = config.Value.AvailableAsset.IndexOf(currentValue) + 1;
                    entry.WeakSmartValue = config.Value.AvailableAsset[index % config.Value.AvailableAsset.Count];
                }

                GUIHelper.PopGUIEnabled();

                SirenixEditorGUI.EndHorizontalToolbar();
                SirenixEditorGUI.BeginVerticalList();
                SirenixEditorGUI.BeginListItem(false, padding);
                this.CallNextDrawer(null);
                SirenixEditorGUI.EndListItem();
                SirenixEditorGUI.EndVerticalList();
            }
            SirenixEditorGUI.EndIndentedVertical();
        }
        private void DoInspectorGUI(InspectorProperty property, string config, string methodName)
        {
            var methodConfig = property.Context.Get(this, config, (MethodContext)null);

            if (methodConfig.Value == null)
            {
                methodConfig.Value = new MethodContext();

                MethodInfo methodInfo = property.ParentType
                                        .FindMember()
                                        .IsMethod()
                                        .IsNamed(methodName)
                                        .HasNoParameters()
                                        .ReturnsVoid()
                                        .GetMember <MethodInfo>(out methodConfig.Value.ErrorMessage);

                if (methodConfig.Value.ErrorMessage == null && methodInfo != null)
                {
                    if (methodInfo.IsStatic)
                    {
                        methodConfig.Value.StaticMethod = EmitUtilities.CreateStaticMethodCaller(methodInfo);
                    }
                    else
                    {
                        methodConfig.Value.InstanceMethod = EmitUtilities.CreateWeakInstanceMethodCaller(methodInfo);
                    }
                }
                else
                {
                    string otherErrorMessage;
                    methodInfo = property.ParentType
                                 .FindMember()
                                 .IsMethod()
                                 .IsNamed(methodName)
                                 .HasParameters(property.ValueEntry.BaseValueType)
                                 .IsStatic()
                                 .ReturnsVoid()
                                 .GetMember <MethodInfo>(out otherErrorMessage);

                    if (otherErrorMessage == null)
                    {
                        methodConfig.Value.ErrorMessage = null;
                        var delegateType = typeof(Action <>).MakeGenericType(property.ValueEntry.TypeOfValue);
                        methodConfig.Value.StaticMethodWithParam = Delegate.CreateDelegate(delegateType, methodInfo);
                    }
                    else
                    {
                        methodConfig.Value.ErrorMessage += "\nor\n" + otherErrorMessage;
                    }
                }
            }

            if (methodConfig.Value.ErrorMessage != null)
            {
                SirenixEditorGUI.ErrorMessageBox(methodConfig.Value.ErrorMessage);
            }
            else
            {
                if (methodConfig.Value.InstanceMethod != null)
                {
                    methodConfig.Value.InstanceMethod(property.ParentValues[0]);
                }
                else if (methodConfig.Value.StaticMethodWithParam != null)
                {
                    methodConfig.Value.StaticMethodWithParam.DynamicInvoke(property.ValueEntry.WeakSmartValue);
                }
                else
                {
                    methodConfig.Value.StaticMethod();
                }
            }
        }