/// <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); }
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()"); } }
static GUIHelper() { var guiLayoutEntryType = typeof(GUI).Assembly.GetType("UnityEngine.GUILayoutEntry"); var hostViewType = typeof(Editor).Assembly.GetType("UnityEditor.HostView"); var guiViewType = typeof(Editor).Assembly.GetType("UnityEditor.GUIView"); inspectorWindowType = typeof(Editor).Assembly.GetType("UnityEditor.InspectorWindow"); GetRectOnGUILayoutEntry = EmitUtilities.CreateWeakInstanceFieldGetter <Rect>(guiLayoutEntryType, guiLayoutEntryType.GetField("rect", Flags.AllMembers)); EditorScreenPointOffsetGetter = DeepReflection.CreateValueGetter <Vector2>(typeof(GUIUtility), "s_EditorScreenPointOffset"); CurrentWindowIDGetter = DeepReflection.CreateValueGetter <int>(guiViewType, "current.GetInstanceID()"); CurrentWindowHasFocusGetter = DeepReflection.CreateValueGetter <bool>(guiViewType, "current.hasFocus"); GetIsDockedWindowGetter = DeepReflection.CreateValueGetter <EditorWindow, bool>("docked"); ContextWidthGetter = DeepReflection.CreateValueGetter <float>(typeof(EditorGUIUtility), "contextWidth"); ActualLabelWidthGetter = EmitUtilities.CreateStaticFieldGetter <float>(typeof(EditorGUIUtility).GetField("s_LabelWidth", Flags.AllMembers)); //ActualLabelWidthSetter = EmitUtilities.CreateStaticFieldSetter<float>(typeof(EditorGUIUtility).GetField("s_LabelWidth", Flags.AllMembers)); var guiViewGetter = DeepReflection.CreateWeakStaticValueGetter(guiViewType, guiViewType, "current"); var actualViewGetter = DeepReflection.CreateWeakInstanceValueGetter <EditorWindow>(hostViewType, "actualView"); var borderSizeGetter = DeepReflection.CreateWeakInstanceValueGetter <RectOffset>(hostViewType, "borderSize"); CurrentWindowGetter = () => actualViewGetter(guiViewGetter()); CurrentWindowBorderSizeGetter = () => borderSizeGetter(guiViewGetter()); SetBoldDefaultFontSetter = (Action <bool>)Delegate.CreateDelegate(typeof(Action <bool>), typeof(EditorGUIUtility).FindMember() .IsStatic() .IsMethod() .HasParameters <bool>() .ReturnsVoid() .IsNamed("SetBoldDefaultFont") .GetMember <MethodInfo>(), true); GetBoldDefaultFontGetter = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), typeof(EditorGUIUtility).FindMember() .IsStatic() .IsMethod() .HasNoParameters() .HasReturnType <bool>() .IsNamed("GetBoldDefaultFont") .GetMember <MethodInfo>(), true); GUILayoutEntriesCursorIndexGetter = DeepReflection.CreateValueGetter <int>(typeof(GUILayoutUtility), "current.topLevel.m_Cursor"); GUILayoutEntriesGetter = DeepReflection.CreateValueGetter <IList>(typeof(GUILayoutUtility), "current.topLevel.entries"); CurrentIndentAmountGetter = DeepReflection.CreateValueGetter <float>(typeof(EditorGUI), "indent"); GetTopLevelLayoutRectGetter = DeepReflection.CreateValueGetter <Rect>(typeof(GUILayoutUtility), "current.topLevel.rect"); GetEditorWindowRectGetter = DeepReflection.CreateValueGetter <Rect>(typeof(Editor).Assembly.GetType("UnityEditor.Toolbar"), "get.parent.screenPosition"); }
/// <summary> /// 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); } } } }
/// <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); } }
/// <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; }
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; }
/// <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 }); } } }
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 } } }
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); }
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); }
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); } } }