/// <summary>
        /// Creates a StringMemberHelper to get a display string.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="memberName">The member name.</param>
        /// <param name="allowInstanceMember">If <c>true</c>, then StringMemberHelper will look for instance members.</param>
        /// <param name="allowStaticMember">If <c>true</c>, then StringMemberHelper will look for static members.</param>
        /// <exception cref="System.InvalidOperationException">Require either allowInstanceMember or allowStaticMember to be true.</exception>
        public InspectorPropertyValueGetter(InspectorProperty property, string memberName, bool allowInstanceMember = true, bool allowStaticMember = true)
        {
            this.memberProperty = property.FindParent(x => x.Info.GetMemberInfo() != null, true);

            // TODO: Expression temporarily disabled.
            //if (memberName != null && memberName.Length > 0 && memberName[0] == '$')
            //{
            //    var expression = memberName.Substring(1);
            //    this.isStaticExpression = property.ParentValueProperty == null && property.Tree.IsStatic;

            //    this.expressionMethod = ExpressionCompilerUtility.CompileExpression(expression, this.isStaticExpression, property.ParentType, out this.errorMessage);

            //    if (this.expressionMethod != null && this.expressionMethod.Method.ReturnType.IsCastableTo(typeof(TReturnType)) == false)
            //    {
            //        this.errorMessage = "Cannot cast type of " + this.expressionMethod.Method.ReturnType + " to type of " + typeof(TReturnType).Name + ".";
            //        this.expressionMethod = null;
            //    }
            //}
            //else
            {
                var parentType = this.memberProperty.ParentType;

                var finder = MemberFinder.Start(parentType)
                             .HasReturnType <TReturnType>(true)
                             .IsNamed(memberName)
                             .HasNoParameters();

                if (!allowInstanceMember && !allowStaticMember)
                {
                    throw new InvalidOperationException("Require either allowInstanceMember and/or allowStaticMember to be true.");
                }
                else if (!allowInstanceMember)
                {
                    finder.IsStatic();
                }
                else if (!allowStaticMember)
                {
                    finder.IsInstance();
                }

                MemberInfo member;
                if (finder.TryGetMember(out member, out this.errorMessage))
                {
                    if (member is MethodInfo)
                    {
                        memberName += "()";
                    }

                    if (member.IsStatic())
                    {
                        this.staticValueGetter = DeepReflection.CreateValueGetter <TReturnType>(parentType, memberName);
                    }
                    else
                    {
                        this.instanceValueGetter = DeepReflection.CreateWeakInstanceValueGetter <TReturnType>(parentType, memberName);
                    }
                }
            }
        }
    protected override void DrawPropertyGroupLayout(InspectorProperty property, TargetSideAttribute attribute, GUIContent label)
    {
        bool result = DeepReflection.CreateWeakInstanceValueGetter <bool>(property.ParentType, "mainSide")(property.ParentValues[0]);

        result = !result;

        CrossSceneDrawer.DrawPropertyGroupLayout <TargetSideAttribute>(this, property, attribute, label, result);
    }
Ejemplo n.º 3
0
    protected override void DrawPropertyLayout(GUIContent label)
    {
        var property  = this.Property;
        var attribute = this.Attribute;

        bool result = DeepReflection.CreateWeakInstanceValueGetter <bool>(property.ParentType, "mainSide")(property.ParentValues[0]);

        CrossSceneDrawer.DrawPropertyGroupLayout <MainSideAttribute>(this, property, attribute, label, result);
    }
        static UnityNetworkingUtility()
        {
            NetworkBehaviourType = AssemblyUtilities.GetTypeByCachedFullName("UnityEngine.Networking.NetworkBehaviour");
            SyncListType         = AssemblyUtilities.GetTypeByCachedFullName("UnityEngine.Networking.SyncList`1");

            if (NetworkBehaviourType != null)
            {
                getNetworkChannelMethod  = DeepReflection.CreateWeakInstanceValueGetter <int>(NetworkBehaviourType, "GetNetworkChannel()");
                getNetworkIntervalMethod = DeepReflection.CreateWeakInstanceValueGetter <float>(NetworkBehaviourType, "GetNetworkSendInterval()");
            }
        }
Ejemplo n.º 5
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");
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Creates a StringMemberHelper to get a display string.
        /// </summary>
        /// <param name="objectType">The type of the object, to get a member string from.</param>
        /// <param name="path">The input string. If the first character is a '$', then StringMemberHelper will look for a member string field, property or method.</param>
        /// <param name="allowInstanceMember">If <c>true</c>, then StringMemberHelper will look for instance members.</param>
        /// <param name="allowStaticMember">If <c>true</c>, then StringMemberHelper will look for static members.</param>
        public StringMemberHelper(Type objectType, string path, bool allowInstanceMember = true, bool allowStaticMember = true)
        {
            this.rawString  = path;
            this.objectType = objectType;

            if (path != null && objectType != null && path.Length > 0 && path[0] == '$')
            {
                path = path.Substring(1);
                MemberInfo member;

                var finder = MemberFinder.Start(objectType)
                             .HasReturnType <object>(true)
                             .IsNamed(path)
                             .HasNoParameters();

                if (!allowInstanceMember && !allowStaticMember)
                {
                    throw new InvalidOperationException("Require either allowInstanceMember or allowStaticMember to be true.");
                }
                else if (!allowInstanceMember)
                {
                    finder.IsStatic();
                }
                else if (!allowStaticMember)
                {
                    finder.IsInstance();
                }

                if (finder.TryGetMember(out member, out this.errorMessage))
                {
                    if (member is MethodInfo)
                    {
                        path += "()";
                    }

                    if (member.IsStatic())
                    {
                        this.staticValueGetter = DeepReflection.CreateValueGetter <object>(objectType, path);
                    }
                    else
                    {
                        this.instanceValueGetter = DeepReflection.CreateWeakInstanceValueGetter <object>(objectType, path);
                    }
                }
            }
        }
Ejemplo n.º 7
0
        /// <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);
            }
        }
Ejemplo n.º 8
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;
                        }
                    }
                }
            }
        }
        public static void HandleIfAttributesCondition(OdinDrawer drawer, InspectorProperty property, string memberName, object value, out bool result, out string errorMessage)
        {
            var context = property.Context.Get(drawer, "IfAttributeContext", (IfAttributesContext)null);

            if (context.Value == null)
            {
                context.Value = new IfAttributesContext();
                MemberInfo memberInfo = property.ParentType
                                        .FindMember()
                                        .IsNamed(memberName)
                                        .HasNoParameters()
                                        .GetMember(out context.Value.ErrorMessage);

                if (memberInfo != null)
                {
                    string name = (memberInfo is MethodInfo) ? memberInfo.Name + "()" : memberInfo.Name;

                    if (memberInfo.GetReturnType() == typeof(bool))
                    {
                        if (memberInfo.IsStatic())
                        {
                            context.Value.StaticMemberGetter = DeepReflection.CreateValueGetter <bool>(property.ParentType, name);
                        }
                        else
                        {
                            context.Value.InstanceMemberGetter = DeepReflection.CreateWeakInstanceValueGetter <bool>(property.ParentType, name);
                        }
                    }
                    else
                    {
                        if (value == null)
                        {
                            context.Value.ErrorMessage = "An member with a non-bool value was referenced, but no value was specified in the EnabledIf attribute.";
                        }
                        else
                        {
                            if (memberInfo.IsStatic())
                            {
                                context.Value.StaticObjectMemberGetter = DeepReflection.CreateValueGetter <object>(property.ParentType, name);
                            }
                            else
                            {
                                context.Value.InstanceObjectMemberGetter = DeepReflection.CreateWeakInstanceValueGetter <object>(property.ParentType, name);
                            }
                        }
                    }
                }
            }
            errorMessage = context.Value.ErrorMessage;

            if (Event.current.type != EventType.Layout)
            {
                result = context.Value.Result;
                return;
            }

            context.Value.Result = false;

            if (context.Value.ErrorMessage == null)
            {
                if (context.Value.InstanceMemberGetter != null)
                {
                    for (int i = 0; i < property.ParentValues.Count; i++)
                    {
                        if (context.Value.InstanceMemberGetter(property.ParentValues[i]))
                        {
                            context.Value.Result = true;
                            break;
                        }
                    }
                }
                else if (context.Value.InstanceObjectMemberGetter != null)
                {
                    for (int i = 0; i < property.ParentValues.Count; i++)
                    {
                        var val = context.Value.InstanceObjectMemberGetter(property.ParentValues[i]);
                        if (Equals(val, value))
                        {
                            context.Value.Result = true;
                            break;
                        }
                    }
                }
                else if (context.Value.StaticObjectMemberGetter != null)
                {
                    var val = context.Value.StaticObjectMemberGetter();
                    if (Equals(val, value))
                    {
                        context.Value.Result = true;
                    }
                }
                else if (context.Value.StaticMemberGetter != null)
                {
                    if (context.Value.StaticMemberGetter())
                    {
                        context.Value.Result = true;
                    }
                }
            }

            result = context.Value.Result;
        }
Ejemplo n.º 10
0
        public IfAttributeHelper(InspectorProperty property, string memberName)
        {
            this.property = property;
            //this.memberName = memberName;

            string error;
            Type   returnType;

            if (memberName != null && memberName.Length > 0 && memberName[0] == '@')
            {
#if !ODIN_LIMITED_VERSION
                var expression = memberName.Substring(1);

                Type[]   parameters     = new Type[] { typeof(InspectorProperty) };
                string[] parameterNames = new string[] { "property" };

                this.expressionIsStatic = this.property.ParentValueProperty == null && this.property.Tree.IsStatic;
                this.expressionMethod   = ExpressionUtility.ParseExpression(expression, this.expressionIsStatic, this.property.ParentType, parameters, parameterNames, out error);

                returnType = this.expressionMethod != null ? this.expressionMethod.Method.ReturnType : null;
#else
                returnType = null;
                error      = "Expressions are only available in Odin Inspector Commercial and up.";
#endif
            }
            else
            {
                if (memberName != null && memberName.Length > 0 && memberName[0] == '$')
                {
                    memberName = memberName.Substring(1);
                }

                returnType = null;
                MemberInfo memberInfo = this.property.ParentType
                                        .FindMember()
                                        .IsNamed(memberName)
                                        .HasNoParameters()
                                        .GetMember(out error);

                if (memberInfo != null)
                {
                    string name = (memberInfo is MethodInfo) ? memberInfo.Name + "()" : memberInfo.Name;

                    if (memberInfo.GetReturnType() == typeof(bool))
                    {
                        if (memberInfo.IsStatic())
                        {
                            this.staticMemberGetter = DeepReflection.CreateValueGetter <bool>(this.property.ParentType, name);
                        }
                        else
                        {
                            this.instanceMemberGetter = DeepReflection.CreateWeakInstanceValueGetter <bool>(this.property.ParentType, name);
                        }
                    }
                    else
                    {
                        if (memberInfo.IsStatic())
                        {
                            this.staticObjectMemberGetter = DeepReflection.CreateValueGetter <object>(this.property.ParentType, name);
                        }
                        else
                        {
                            this.instanceObjectMemberGetter = DeepReflection.CreateWeakInstanceValueGetter <object>(this.property.ParentType, name);
                        }
                    }

                    returnType = memberInfo.GetReturnType();
                }
            }

            if (returnType != null) // Should only be null in case of errors.
            {
                this.useNullComparison = returnType != typeof(string) && (returnType.IsClass || returnType.IsInterface);
            }

            this.ErrorMessage = error;
        }
Ejemplo n.º 11
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 });
                }
            }
        }
Ejemplo n.º 12
0
        public static void HandleIfAttributesCondition(OdinDrawer drawer, InspectorProperty property, string memberName, object value, out bool result, out string errorMessage)
        {
            var context = property.Context.Get(drawer, "IfAttributeContext", (IfAttributesContext)null);

            if (context.Value == null)
            {
                Type returnType;

                context.Value = new IfAttributesContext();

                // TODO: Expressions temporarily disabled.
                //if (memberName != null && memberName.Length > 0 && memberName[0] == '$')
                //{
                //    var expression = memberName.Substring(1);

                //    context.Value.expressionIsStatic = property.ParentValueProperty == null && property.Tree.IsStatic;
                //    context.Value.ExpressionMethod = ExpressionCompilerUtility.CompileExpression(expression, context.Value.expressionIsStatic, property.ParentType, out context.Value.ErrorMessage);

                //    returnType = context.Value.ExpressionMethod != null ? context.Value.ExpressionMethod.Method.ReturnType : null;
                //}
                //else
                {
                    returnType = null;
                    MemberInfo memberInfo = property.ParentType
                                            .FindMember()
                                            .IsNamed(memberName)
                                            .HasNoParameters()
                                            .GetMember(out context.Value.ErrorMessage);

                    if (memberInfo != null)
                    {
                        string name = (memberInfo is MethodInfo) ? memberInfo.Name + "()" : memberInfo.Name;

                        if (memberInfo.GetReturnType() == typeof(bool))
                        {
                            if (memberInfo.IsStatic())
                            {
                                context.Value.StaticMemberGetter = DeepReflection.CreateValueGetter <bool>(property.ParentType, name);
                            }
                            else
                            {
                                context.Value.InstanceMemberGetter = DeepReflection.CreateWeakInstanceValueGetter <bool>(property.ParentType, name);
                            }
                        }
                        else
                        {
                            if (memberInfo.IsStatic())
                            {
                                context.Value.StaticObjectMemberGetter = DeepReflection.CreateValueGetter <object>(property.ParentType, name);
                            }
                            else
                            {
                                context.Value.InstanceObjectMemberGetter = DeepReflection.CreateWeakInstanceValueGetter <object>(property.ParentType, name);
                            }
                        }

                        returnType = memberInfo.GetReturnType();
                    }
                }

                if (returnType != null) // Should only be null in case of errors.
                {
                    context.Value.UseNullComparison = returnType != typeof(string) && (returnType.IsClass || returnType.IsInterface);
                }
            }
            errorMessage = context.Value.ErrorMessage;

            if (Event.current.type != EventType.Layout)
            {
                result = context.Value.Result;
                return;
            }

            context.Value.Result = false;

            if (context.Value.ErrorMessage == null)
            {
                // TODO: Expressions temporarily disabled.
                //if (context.Value.ExpressionMethod != null)
                //{
                //    for (int i = 0; i < property.ParentValues.Count; i++)
                //    {
                //        object val;
                //        if (context.Value.expressionIsStatic)
                //        {
                //            val = context.Value.ExpressionMethod.DynamicInvoke();
                //        }
                //        else
                //        {
                //            val = context.Value.ExpressionMethod.DynamicInvoke(property.ParentValues[i]);
                //        }

                //        if (context.Value.UseNullComparison)
                //        {
                //            if (val is UnityEngine.Object)
                //            {
                //                // Unity objects can be 'fake null', and to detect that we have to test the value as a Unity object.
                //                if (((UnityEngine.Object)val) != null)
                //                {
                //                    context.Value.Result = true;
                //                    break;
                //                }
                //            }
                //            else if (val != null)
                //            {
                //                context.Value.Result = true;
                //                break;
                //            }
                //        }
                //        else if (val is bool)
                //        {
                //            context.Value.Result = (bool)val;
                //            break;
                //        }
                //        else if (Equals(val, value))
                //        {
                //            context.Value.Result = true;
                //            break;
                //        }
                //    }
                //}
                //else
                if (context.Value.InstanceMemberGetter != null)
                {
                    for (int i = 0; i < property.ParentValues.Count; i++)
                    {
                        if (context.Value.InstanceMemberGetter(property.ParentValues[i]))
                        {
                            context.Value.Result = true;
                            break;
                        }
                    }
                }
                else if (context.Value.StaticMemberGetter != null)
                {
                    if (context.Value.StaticMemberGetter())
                    {
                        context.Value.Result = true;
                    }
                }
                else if (context.Value.InstanceObjectMemberGetter != null)
                {
                    for (int i = 0; i < property.ParentValues.Count; i++)
                    {
                        var val = context.Value.InstanceObjectMemberGetter(property.ParentValues[i]);
                        if (context.Value.UseNullComparison)
                        {
                            if (val is UnityEngine.Object)
                            {
                                // Unity objects can be 'fake null', and to detect that we have to test the value as a Unity object.
                                if (((UnityEngine.Object)val) != null)
                                {
                                    context.Value.Result = true;
                                    break;
                                }
                            }
                            else if (val != null)
                            {
                                context.Value.Result = true;
                                break;
                            }
                        }
                        else if (Equals(val, value))
                        {
                            context.Value.Result = true;
                            break;
                        }
                    }
                }
                else if (context.Value.StaticObjectMemberGetter != null)
                {
                    var val = context.Value.StaticObjectMemberGetter();
                    if (context.Value.UseNullComparison)
                    {
                        if (val is UnityEngine.Object)
                        {
                            // Unity objects can be 'fake null', and to detect that we have to test the value as a Unity object.
                            if (((UnityEngine.Object)val) != null)
                            {
                                context.Value.Result = true;
                            }
                        }
                        else if (val != null)
                        {
                            context.Value.Result = true;
                        }
                    }
                    else if (Equals(val, value))
                    {
                        context.Value.Result = true;
                    }
                }
            }

            result = context.Value.Result;
        }
        private void DoProperty <TBase>(IPropertyValueEntry weakEntry, ValueDropdownAttribute attribute, GUIContent label)
        {
            var entry  = (IPropertyValueEntry <TBase>)weakEntry;
            var config = entry.Property.Context.Get(this, "Config", (PropertyConfig <TBase>)null);

            if (config.Value == null)
            {
                config.Value = new PropertyConfig <TBase>();

                Type parentType;

                if (entry.ValueCategory == PropertyValueCategory.Member)
                {
                    parentType = entry.ParentType;
                    config.Value.GetParentValuesFromProperty = entry.Property;
                }
                else
                {
                    parentType = entry.Property.Parent.ParentType;
                    config.Value.GetParentValuesFromProperty = entry.Property.Parent;
                }

                MemberInfo memberInfo = parentType.FindMember()
                                        .HasReturnType <IList <TBase> >(true)
                                        .HasNoParameters()
                                        .IsNamed(attribute.MemberName)
                                        .GetMember <MemberInfo>(out config.Value.ErrorMessage);

                if (config.Value.ErrorMessage == null)
                {
                    string memberName = attribute.MemberName + ((memberInfo is MethodInfo) ? "()" : "");
                    if (memberInfo.IsStatic())
                    {
                        config.Value.StaticValueDropdownGetter = DeepReflection.CreateValueGetter <IList <TBase> >(parentType, memberName);
                    }
                    else
                    {
                        config.Value.InstanceValueDropdownGetter = DeepReflection.CreateWeakInstanceValueGetter <IList <TBase> >(parentType, memberName);
                    }
                    config.Value.IsValueDropdown = false;
                }
                else
                {
                    string errorMessage;

                    memberInfo = parentType.FindMember()
                                 .HasReturnType <IList <ValueDropdownItem <TBase> > >(true)
                                 .HasNoParameters()
                                 .IsNamed(attribute.MemberName)
                                 .GetMember <MemberInfo>(out errorMessage);

                    if (errorMessage == null)
                    {
                        string memberName = attribute.MemberName + ((memberInfo is MethodInfo) ? "()" : "");
                        if (memberInfo.IsStatic())
                        {
                            config.Value.ValueDropdownStaticValueDropdownGetter = DeepReflection.CreateValueGetter <IList <ValueDropdownItem <TBase> > >(parentType, memberName);
                        }
                        else
                        {
                            config.Value.ValueDropdownInstanceValueDropdownGetter = DeepReflection.CreateWeakInstanceValueGetter <IList <ValueDropdownItem <TBase> > >(parentType, memberName);
                        }
                        config.Value.ErrorMessage    = null;
                        config.Value.IsValueDropdown = true;
                    }
                    else
                    {
                        if (config.Value.ErrorMessage != errorMessage)
                        {
                            config.Value.ErrorMessage += " or\n" + errorMessage;
                        }

                        if (IsStrongList)
                        {
                            memberInfo = parentType.FindMember()
                                         .HasReturnType(typeof(IList <>).MakeGenericType(StrongListElementType), true)
                                         .HasNoParameters()
                                         .IsNamed(attribute.MemberName)
                                         .GetMember <MemberInfo>(out errorMessage);

                            if (errorMessage != null)
                            {
                                config.Value.ErrorMessage += " or\n" + errorMessage;

                                Type valueDropdown = typeof(ValueDropdownItem <>).MakeGenericType(StrongListElementType);

                                memberInfo = parentType.FindMember()
                                             .HasReturnType(typeof(IList <>).MakeGenericType(valueDropdown), true)
                                             .HasNoParameters()
                                             .IsNamed(attribute.MemberName)
                                             .GetMember <MemberInfo>(out errorMessage);

                                if (errorMessage != null)
                                {
                                    config.Value.ErrorMessage += " or\n" + errorMessage;
                                }
                                else
                                {
                                    config.Value.ErrorMessage   = null;
                                    config.Value.CallNextDrawer = true;
                                }
                            }
                            else
                            {
                                config.Value.ErrorMessage   = null;
                                config.Value.CallNextDrawer = true;
                            }
                        }
                    }
                }
            }

            if (config.Value.ErrorMessage != null)
            {
                if (entry.ValueCategory == PropertyValueCategory.Member)
                {
                    SirenixEditorGUI.ErrorMessageBox(config.Value.ErrorMessage);
                }

                this.CallNextDrawer(entry, label);
            }
            else if (config.Value.CallNextDrawer)
            {
                this.CallNextDrawer(entry, label);
            }
            else
            {
                if (config.Value.IsValueDropdown)
                {
                    IList <ValueDropdownItem <TBase> > selectList = config.Value.ValueDropdownStaticValueDropdownGetter != null?
                                                                    config.Value.ValueDropdownStaticValueDropdownGetter() :
                                                                        config.Value.ValueDropdownInstanceValueDropdownGetter(config.Value.GetParentValuesFromProperty.ParentValues[0]);

                    selectedValuesBuffer.Clear();

                    if (selectList != null && selectList.Count > 0)
                    {
                        for (int i = 0; i < entry.Values.Count; i++)
                        {
                            var val = entry.Values[i];
                            for (int j = 0; j < selectList.Count; j++)
                            {
                                if (EqualityComparer <TBase> .Default.Equals((TBase)val, selectList[j].Value))
                                {
                                    selectedValuesBuffer.Add(j);
                                }
                            }
                        }
                    }

                    if (SirenixEditorFields.Dropdown <ValueDropdownItem <TBase> >(label, selectedValuesBuffer, selectList, false))
                    {
                        if (selectedValuesBuffer.Count > 0)
                        {
                            entry.SmartValue = selectList[selectedValuesBuffer[0]].Value;
                        }
                    }
                }
                else
                {
                    IList <TBase> selectList = config.Value.StaticValueDropdownGetter != null?
                                               config.Value.StaticValueDropdownGetter() :
                                                   config.Value.InstanceValueDropdownGetter(config.Value.GetParentValuesFromProperty.ParentValues[0]);

                    if (GeneralDrawerConfig.Instance.UseImprovedEnumDropDown)
                    {
                        int  id;
                        bool hasFocus;
                        Rect rect;
                        Action <OdinSelector <TBase> > bindSelector;
                        Func <IEnumerable <TBase> >    getResult;

                        TempFeatureRichControlRect(label, out id, out hasFocus, out rect);

                        if (GenericSelector <TBase> .DrawSelectorButton(rect, entry.SmartValue + "", EditorStyles.popup, id, out bindSelector, out getResult))
                        {
                            var selector = new GenericSelector <TBase>(selectList);
                            selector.SetSelection(entry.SmartValue);
                            selector.ShowInPopup(new Vector2(rect.xMin, rect.yMax));
                            bindSelector(selector);
                        }

                        if (getResult != null)
                        {
                            entry.SmartValue = getResult().FirstOrDefault();
                        }
                    }
                    else
                    {
                        entry.SmartValue = SirenixEditorFields.Dropdown(label, entry.SmartValue, selectList);
                    }
                }
            }
        }
        /// <summary>
        /// Creates a StringMemberHelper to get a display string.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="memberName">The member name.</param>
        /// <param name="allowInstanceMember">If <c>true</c>, then StringMemberHelper will look for instance members.</param>
        /// <param name="allowStaticMember">If <c>true</c>, then StringMemberHelper will look for static members.</param>
        /// <exception cref="System.InvalidOperationException">Require either allowInstanceMember or allowStaticMember to be true.</exception>
        public InspectorPropertyValueGetter(InspectorProperty property, string memberName, bool allowInstanceMember = true, bool allowStaticMember = true)
        {
            this.actualProperty = property;
            this.memberProperty = property.FindParent(x => x.Info.GetMemberInfo() != null, true);

            if (memberName != null && memberName.Length > 0 && memberName[0] == '@')
            {
#if ODIN_LIMITED_VERSION
                this.errorMessage = "Expressions are only available in Odin Inspector Commercial and up.";
#else
                var expression = memberName.Substring(1);
                this.isStaticExpression = property.ParentValueProperty == null && property.Tree.IsStatic;

                Type[]   parameters     = new Type[] { typeof(InspectorProperty) };
                string[] parameterNames = new string[] { "property" };

                this.expressionMethod = ExpressionUtility.ParseExpression(expression, this.isStaticExpression, property.ParentType, parameters, parameterNames, out this.errorMessage);

                if (this.expressionMethod != null && this.expressionMethod.Method.ReturnType.IsCastableTo(typeof(TReturnType)) == false)
                {
                    this.errorMessage     = "Cannot cast type of " + this.expressionMethod.Method.ReturnType + " to type of " + typeof(TReturnType).Name + ".";
                    this.expressionMethod = null;
                }
#endif
            }
            else
            {
                if (memberName != null && memberName.Length > 0 && memberName[0] == '$')
                {
                    memberName = memberName.Substring(1);
                }

                var parentType = this.memberProperty.ParentType;

                var finder = MemberFinder.Start(parentType)
                             .HasReturnType <TReturnType>(true)
                             .IsNamed(memberName)
                             .HasNoParameters();

                if (!allowInstanceMember && !allowStaticMember)
                {
                    throw new InvalidOperationException("Require either allowInstanceMember and/or allowStaticMember to be true.");
                }
                else if (!allowInstanceMember)
                {
                    finder.IsStatic();
                }
                else if (!allowStaticMember)
                {
                    finder.IsInstance();
                }

                MemberInfo member;
                if (finder.TryGetMember(out member, out this.errorMessage))
                {
                    if (member is MethodInfo)
                    {
                        memberName += "()";
                    }

                    if (member.IsStatic())
                    {
                        this.staticValueGetter = DeepReflection.CreateValueGetter <TReturnType>(parentType, memberName);
                    }
                    else
                    {
                        this.instanceValueGetter = DeepReflection.CreateWeakInstanceValueGetter <TReturnType>(parentType, memberName);
                    }
                }
            }
        }
        private StringMemberHelper(Type objectType, bool isStatic, string text, InspectorProperty property)
        {
            this.rawString  = text;
            this.objectType = objectType;
            this.isStatic   = isStatic;

            if (string.IsNullOrEmpty(text) == false && objectType != null && text.Length > 0)
            {
                if (text[0] == '$')
                {
                    text = text.Substring(1);

                    var finder = MemberFinder.Start(objectType)
                                 .HasReturnType <object>(true)
                                 .IsNamed(text)
                                 .HasNoParameters();

                    if (isStatic)
                    {
                        finder = finder.IsStatic();
                    }

                    MemberInfo member;
                    if (finder.TryGetMember(out member, out this.errorMessage))
                    {
                        if (member is MethodInfo)
                        {
                            text += "()";
                        }

                        if (member.IsStatic())
                        {
                            this.staticValueGetter = DeepReflection.CreateValueGetter <object>(objectType, text);
                        }
                        else
                        {
                            this.instanceValueGetter = DeepReflection.CreateWeakInstanceValueGetter <object>(objectType, text);
                        }
                    }
                }
                else if (text[0] == '@')
                {
#if !ODIN_LIMITED_VERSION
                    Type[]   parameters     = null;
                    string[] parameterNames = null;

                    this.property = property;

                    if (property != null)
                    {
                        parameters     = new Type[] { typeof(InspectorProperty) };
                        parameterNames = new string[] { "property" };
                    }

                    this.expressionMethod = ExpressionUtility.ParseExpression(text.Substring(1), this.isStatic, objectType, parameters, parameterNames, out this.errorMessage);
#else
                    this.errorMessage += "\nExpressions are only available in Odin Inspector Commercial and up.";
#endif
                }
            }
        }
Ejemplo n.º 16
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);
        }
Ejemplo n.º 17
0
        internal static ProgressBarContext <T> GetContext(OdinDrawer drawer, IPropertyValueEntry <T> entry, ProgressBarAttribute attribute)
        {
            PropertyContext <ProgressBarContext <T> > context;

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

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

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

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

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

                // Custom value string getter
                if (attribute.CustomValueStringMember != null && attribute.CustomValueStringMember.Length > 0)
                {
                    string member = attribute.CustomValueStringMember;
                    if (attribute.CustomValueStringMember[0] != '$')
                    {
                        member = "$" + attribute.CustomValueStringMember;
                    }

                    context.Value.CustomValueLabelGetter = new StringMemberHelper(
                        entry.Property.ParentType,
                        member,
                        ref context.Value.ErrorMessage);
                }
            }

            return(context.Value);
        }
Ejemplo n.º 18
0
        private void DoProperty <TBase>(IPropertyValueEntry weakEntry, ValueDropdownAttribute attribute, GUIContent label)
        {
            var entry  = (IPropertyValueEntry <TBase>)weakEntry;
            var config = entry.Property.Context.Get(this, "Config", (PropertyConfig <TBase>)null);

            if (config.Value == null)
            {
                config.Value = new PropertyConfig <TBase>();

                Type parentType;

                if (entry.ValueCategory == PropertyValueCategory.Member)
                {
                    parentType = entry.ParentType;
                    config.Value.GetParentValuesFromProperty = entry.Property;
                }
                else
                {
                    parentType = entry.Property.Parent.ParentType;
                    config.Value.GetParentValuesFromProperty = entry.Property.Parent;
                }

                MemberInfo memberInfo = parentType.FindMember()
                                        .HasReturnType <IList <TBase> >(true)
                                        .HasNoParameters()
                                        .IsNamed(attribute.MemberName)
                                        .GetMember <MemberInfo>(out config.Value.ErrorMessage);

                if (config.Value.ErrorMessage == null)
                {
                    string memberName = attribute.MemberName + ((memberInfo is MethodInfo) ? "()" : "");
                    if (memberInfo.IsStatic())
                    {
                        config.Value.StaticValueDropdownGetter = DeepReflection.CreateValueGetter <IList <TBase> >(parentType, memberName);
                    }
                    else
                    {
                        config.Value.InstanceValueDropdownGetter = DeepReflection.CreateWeakInstanceValueGetter <IList <TBase> >(parentType, memberName);
                    }
                    config.Value.IsValueDropdown = false;
                }
                else
                {
                    string errorMessage;

                    memberInfo = parentType.FindMember()
                                 .HasReturnType <IList <ValueDropdownItem <TBase> > >(true)
                                 .HasNoParameters()
                                 .IsNamed(attribute.MemberName)
                                 .GetMember <MemberInfo>(out errorMessage);

                    if (errorMessage == null)
                    {
                        string memberName = attribute.MemberName + ((memberInfo is MethodInfo) ? "()" : "");
                        if (memberInfo.IsStatic())
                        {
                            config.Value.ValueDropdownStaticValueDropdownGetter = DeepReflection.CreateValueGetter <IList <ValueDropdownItem <TBase> > >(parentType, memberName);
                        }
                        else
                        {
                            config.Value.ValueDropdownInstanceValueDropdownGetter = DeepReflection.CreateWeakInstanceValueGetter <IList <ValueDropdownItem <TBase> > >(parentType, memberName);
                        }
                        config.Value.ErrorMessage    = null;
                        config.Value.IsValueDropdown = true;
                    }
                    else
                    {
                        if (config.Value.ErrorMessage != errorMessage)
                        {
                            config.Value.ErrorMessage += " or\n" + errorMessage;
                        }

                        if (IsStrongList)
                        {
                            memberInfo = parentType.FindMember()
                                         .HasReturnType(typeof(IList <>).MakeGenericType(StrongListElementType), true)
                                         .HasNoParameters()
                                         .IsNamed(attribute.MemberName)
                                         .GetMember <MemberInfo>(out errorMessage);

                            if (errorMessage != null)
                            {
                                config.Value.ErrorMessage += " or\n" + errorMessage;

                                Type valueDropdown = typeof(ValueDropdownItem <>).MakeGenericType(StrongListElementType);

                                memberInfo = parentType.FindMember()
                                             .HasReturnType(typeof(IList <>).MakeGenericType(valueDropdown), true)
                                             .HasNoParameters()
                                             .IsNamed(attribute.MemberName)
                                             .GetMember <MemberInfo>(out errorMessage);

                                if (errorMessage != null)
                                {
                                    config.Value.ErrorMessage += " or\n" + errorMessage;
                                }
                                else
                                {
                                    config.Value.ErrorMessage   = null;
                                    config.Value.CallNextDrawer = true;
                                }
                            }
                            else
                            {
                                config.Value.ErrorMessage   = null;
                                config.Value.CallNextDrawer = true;
                            }
                        }
                    }
                }
            }

            if (config.Value.ErrorMessage != null)
            {
                if (entry.ValueCategory == PropertyValueCategory.Member)
                {
                    AllEditorGUI.ErrorMessageBox(config.Value.ErrorMessage);
                }

                this.CallNextDrawer(entry, label);
            }
            else if (config.Value.CallNextDrawer)
            {
                this.CallNextDrawer(entry, label);
            }
            else
            {
                if (config.Value.IsValueDropdown)
                {
                    IList <ValueDropdownItem <TBase> > selectList = config.Value.ValueDropdownStaticValueDropdownGetter != null?
                                                                    config.Value.ValueDropdownStaticValueDropdownGetter() :
                                                                        config.Value.ValueDropdownInstanceValueDropdownGetter(config.Value.GetParentValuesFromProperty.ParentValues[0]);

                    selectedValuesBuffer.Clear();

                    if (selectList != null && selectList.Count > 0)
                    {
                        for (int i = 0; i < entry.Values.Count; i++)
                        {
                            var val = entry.Values[i];
                            for (int j = 0; j < selectList.Count; j++)
                            {
                                if (EqualityComparer <TBase> .Default.Equals((TBase)val, selectList[j].Value))
                                {
                                    selectedValuesBuffer.Add(j);
                                }
                            }
                        }

                        //if (Event.current.type == EventType.Repaint && selectList.Count > 0 && selectedValuesBuffer.Count == 0 && entry.Values.Count == 1)
                        //{
                        //    entry.SmartValue = selectList[0].Value;
                        //}
                    }

                    if (SirenixEditorFields.Dropdown <ValueDropdownItem <TBase> >(label, selectedValuesBuffer, selectList, false))
                    {
                        if (selectedValuesBuffer.Count > 0)
                        {
                            entry.SmartValue = selectList[selectedValuesBuffer[0]].Value;
                        }
                    }

                    //IList<ValueDropdownItem<TBase>> selectList = config.Value.ValueDropdownStaticValueDropdownGetter != null ?
                    //    config.Value.ValueDropdownStaticValueDropdownGetter() :
                    //    config.Value.ValueDropdownInstanceValueDropdownGetter(config.Value.GetParentValuesFromProperty.ParentValues[0]);

                    //ValueDropdownItem<TBase> selected = new ValueDropdownItem<TBase>(null, entry.SmartValue);
                    //entry.SmartValue = SirenixEditorFields.Dropdown(label, selected, selectList).Value;
                }
                else
                {
                    IList <TBase> selectList = config.Value.StaticValueDropdownGetter != null?
                                               config.Value.StaticValueDropdownGetter() :
                                                   config.Value.InstanceValueDropdownGetter(config.Value.GetParentValuesFromProperty.ParentValues[0]);

                    entry.SmartValue = SirenixEditorFields.Dropdown(label, entry.SmartValue, selectList);
                }
            }
        }