protected override void Initialize() { var property = this.Property; var attribute = this.Attribute; this.contextMenuInfos = property.Context.GetGlobal("CustomContextMenu", (Dictionary <CustomContextMenuAttribute, ContextMenuInfo>)null); this.populated = property.Context.GetGlobal("CustomContextMenu_Populated", false); if (contextMenuInfos.Value == null) { contextMenuInfos.Value = new Dictionary <CustomContextMenuAttribute, ContextMenuInfo>(); } if (!contextMenuInfos.Value.TryGetValue(attribute, out this.info)) { this.info = new ContextMenuInfo(); var methodInfo = property.ParentType .FindMember() .IsMethod() .IsInstance() .HasNoParameters() .ReturnsVoid() .IsNamed(attribute.MethodName) .GetMember <MethodInfo>(out this.info.ErrorMessage); if (this.info.ErrorMessage == null) { this.info.Name = attribute.MenuItem; this.info.MethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller(methodInfo); } contextMenuInfos.Value[attribute] = this.info; } }
private static ValueGetter <TOwner, TValue> GetCachedGetter(MemberInfo member) { Delegate del; if (GetterSetterCaches <TOwner> .Getters.TryGetInnerValue(member, typeof(TValue), out del)) { return((ValueGetter <TOwner, TValue>)del); } else { ValueGetter <TOwner, TValue> result; var fieldInfo = member as FieldInfo; var propertyInfo = member as PropertyInfo; if (fieldInfo != null) { result = EmitUtilities.CreateInstanceFieldGetter <TOwner, TValue>(fieldInfo); } else if (propertyInfo != null) { result = EmitUtilities.CreateInstancePropertyGetter <TOwner, TValue>(propertyInfo); } else { throw new ArgumentException("Cannot create a GetterSetter for a member of type + " + member.GetType().Name + "!"); } GetterSetterCaches <TOwner> .Getters.AddInner(member, typeof(TValue), result); return(result); } }
static AnimationCurveDrawer() { MethodInfo mi = null; var type = AssemblyUtilities.GetTypeByCachedFullName("UnityEditorInternal.AnimationCurvePreviewCache"); if (type != null) { var method = type.GetMethod("ClearCache", Flags.StaticAnyVisibility); var pars = method.GetParameters(); if (pars != null && pars.Length == 0) { mi = method; } } if (mi != null) { clearCache = EmitUtilities.CreateStaticMethodCaller(mi); } #if SIRENIX_INTERNAL else { Debug.LogError("AnimationCurve fix no longer works, has Unity fixed it?"); } #endif }
public ObjectMemberAccessor(FieldInfo fieldInfo) { memberInfo = fieldInfo; utf8Name = Encoding.UTF8.GetBytes(fieldInfo.Name); getter = EmitUtilities.CreateInstanceGetter <K, T>(fieldInfo); setter = EmitUtilities.CreateInstanceSetter <K, T>(fieldInfo); }
static UnityExtensions() { var field = typeof(UnityEngine.Object).GetField("m_CachedPtr", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (field != null) { UnityObjectCachedPtrFieldGetter = EmitUtilities.CreateInstanceFieldGetter <UnityEngine.Object, IntPtr>(field); } }
/// <summary> /// Initializes the <see cref="UnityDecoratorAttributeDrawer{TDrawer, TAttribute}"/> class. /// </summary> static UnityDecoratorAttributeDrawer() { if (InternalAttributeFieldInfo == null) { Debug.LogError("Could not find the internal Unity field 'DecoratorDrawer.m_Attribute'; UnityDecoratorDrawer alias '" + typeof(UnityDecoratorAttributeDrawer <TDrawer, TAttribute, TAttributeConstraint>).GetNiceName() + "' has been disabled."); } else { SetAttribute = EmitUtilities.CreateInstanceFieldSetter <TDrawer, Attribute>(InternalAttributeFieldInfo); } }
static UnityPropertyDrawer() { if (InternalFieldInfoFieldInfo == null) { Debug.LogError("Could not find the internal Unity field 'PropertyDrawer.m_FieldInfo'; UnityPropertyDrawer alias '" + typeof(UnityPropertyDrawer <TDrawer, TDrawnType>).GetNiceName() + "' has been disabled."); } else { SetFieldInfo = EmitUtilities.CreateInstanceFieldSetter <TDrawer, FieldInfo>(InternalFieldInfoFieldInfo); } }
/// <summary> /// Draws the property. /// </summary> protected override void DrawPropertyLayout(InspectorProperty property, OnInspectorGUIAttribute attribute, GUIContent label) { if (property.Info.PropertyType == PropertyType.Method) { var methodConfig = property.Context.Get(this, "Config", (MethodContext)null); if (methodConfig.Value == null) { methodConfig.Value = new MethodContext(); MethodInfo methodInfo = property.Info.MemberInfo as MethodInfo; if (methodInfo.ReturnType != typeof(void)) { methodConfig.Value.ErrorMessage = "The method '" + methodInfo.Name + "' must have a return type of type void."; } else if (methodInfo.GetParameters().Length > 0) { methodConfig.Value.ErrorMessage = "The method '" + methodInfo.Name + "' cannot take any parameters."; } else { methodConfig.Value.InstanceMethod = EmitUtilities.CreateWeakInstanceMethodCaller(methodInfo); } } if (methodConfig.Value.ErrorMessage != null) { SirenixEditorGUI.ErrorMessageBox(methodConfig.Value.ErrorMessage); } else { if (methodConfig.Value.InstanceMethod != null) { methodConfig.Value.InstanceMethod(property.ParentValues[0]); } } } else { if (attribute.PrependMethodName != null) { this.DoInspectorGUI(property, "Prepend", attribute.PrependMethodName); } this.CallNextDrawer(property, label); if (attribute.AppendMethodName != null) { this.DoInspectorGUI(property, "Append", attribute.AppendMethodName); } } }
/// <summary> /// Initializes a new instance of the <see cref="InspectorValuePropertyInfo{TOwner, TValue}"/> class. /// </summary> /// <param name="fieldInfo">The field to represent.</param> /// <param name="serializationBackend">The serialization backend.</param> /// <param name="allowEditable">Whether the property can be editable.</param> public InspectorValuePropertyInfo(FieldInfo fieldInfo, SerializationBackend serializationBackend, bool allowEditable) : base(fieldInfo, fieldInfo.FieldType.IsValueType ? PropertyType.ValueType : PropertyType.ReferenceType, serializationBackend, allowEditable) { MemberAliasFieldInfo aliasFieldInfo = fieldInfo as MemberAliasFieldInfo; if (aliasFieldInfo != null) { fieldInfo = aliasFieldInfo.AliasedField; } this.getter = EmitUtilities.CreateInstanceFieldGetter <TOwner, TValue>(fieldInfo); this.setter = EmitUtilities.CreateInstanceFieldSetter <TOwner, TValue>(fieldInfo); }
static InspectorUtilities() { var mPropertyField = typeof(SerializedObject).GetField("m_Property", Flags.InstanceAnyVisibility); if (mPropertyField != null) { mPropertyFieldGetter = EmitUtilities.CreateInstanceFieldGetter <SerializedObject, IntPtr>(mPropertyField); } else { Debug.LogWarning("The internal Unity field SerializedObject.m_Property has been renamed in this version of Unity!"); } }
static BaseFormatter() { if (!Serializer.SerializeUnityEngineObjectReferences && !Serializer.DeserializeUnityEngineObjectReferences && typeof(T).ImplementsOrInherits(typeof(UnityEngine.Object))) { DefaultLoggers.DefaultLogger.LogWarning("A formatter has been created for the UnityEngine.Object type " + typeof(T).Name + " - this is *strongly* discouraged. Unity should be allowed to handle serialization and deserialization of its own weird objects. Remember to serialize with a UnityReferenceResolver as the external index reference resolver in the serialization context.\n\n Stacktrace: " + new System.Diagnostics.StackTrace().ToString()); } var methods = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Func <MethodInfo, SerializationCallback> selector; selector = (info) => { var parameters = info.GetParameters(); if (parameters.Length == 0) { var action = EmitUtilities.CreateInstanceRefMethodCaller <T>(info); return((ref T value, StreamingContext context) => action(ref value)); } else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(StreamingContext) && parameters[0].ParameterType.IsByRef == false) { var action = EmitUtilities.CreateInstanceRefMethodCaller <T, StreamingContext>(info); return((ref T value, StreamingContext context) => action(ref value, context)); } else { DefaultLoggers.DefaultLogger.LogWarning("The method " + info.GetNiceName() + " has an invalid signature and will be ignored by the serialization system."); return(null); } }; OnSerializingCallbacks = methods.Where(n => n.IsDefined(typeof(OnSerializingAttribute), true)) .Select(selector) .Where(n => n != null) .ToArray(); OnSerializedCallbacks = methods.Where(n => n.IsDefined(typeof(OnSerializedAttribute), true)) .Select(selector) .Where(n => n != null) .ToArray(); OnDeserializingCallbacks = methods.Where(n => n.IsDefined(typeof(OnDeserializingAttribute), true)) .Select(selector) .Where(n => n != null) .ToArray(); OnDeserializedCallbacks = methods.Where(n => n.IsDefined(typeof(OnDeserializedAttribute), true)) .Select(selector) .Where(n => n != null) .ToArray(); }
static InspectorUtilities() { string nativeObjectPtrName = UnityVersion.IsVersionOrGreater(2018, 3) ? "m_NativeObjectPtr" : "m_Property"; var nativeObjectPtrField = typeof(SerializedObject).GetField(nativeObjectPtrName, Flags.InstanceAnyVisibility); if (nativeObjectPtrField != null) { SerializedObject_nativeObjectPtrGetter = EmitUtilities.CreateInstanceFieldGetter <SerializedObject, IntPtr>(nativeObjectPtrField); } else { Debug.LogWarning("The internal Unity field SerializedObject.m_Property (< 2018.3)/SerializedObject.m_NativeObjectPtr (>= 2018.3) has been renamed in this version of Unity!"); } }
protected override void Initialize() { this.isListElement = this.Property.Parent != null && this.Property.Parent.ChildResolver is IOrderedCollectionResolver; var isList = !this.isListElement; var listProperty = isList ? this.Property : this.Property.Parent; this.baseMemberProperty = listProperty.FindParent(x => x.Info.PropertyType == PropertyType.Value, true); this.globalSelectedProperty = this.baseMemberProperty.Context.GetGlobal("selectedIndex" + this.baseMemberProperty.GetHashCode(), (InspectorProperty)null); if (isList) { var parentType = this.baseMemberProperty.ParentValues[0].GetType(); this.selectedIndexSetter = EmitUtilities.CreateWeakInstanceMethodCaller <int>(parentType.GetMethod(this.Attribute.SetSelectedMethod, Flags.AllMembers)); } }
static GUIHelper() { var guiLayoutEntryType = typeof(GUI).Assembly.GetType("UnityEngine.GUILayoutEntry"); var hostViewType = typeof(Editor).Assembly.GetType("UnityEditor.HostView"); var guiViewType = typeof(Editor).Assembly.GetType("UnityEditor.GUIView"); inspectorWindowType = typeof(Editor).Assembly.GetType("UnityEditor.InspectorWindow"); GetRectOnGUILayoutEntry = EmitUtilities.CreateWeakInstanceFieldGetter <Rect>(guiLayoutEntryType, guiLayoutEntryType.GetField("rect", Flags.AllMembers)); EditorScreenPointOffsetGetter = DeepReflection.CreateValueGetter <Vector2>(typeof(GUIUtility), "s_EditorScreenPointOffset"); CurrentWindowIDGetter = DeepReflection.CreateValueGetter <int>(guiViewType, "current.GetInstanceID()"); CurrentWindowHasFocusGetter = DeepReflection.CreateValueGetter <bool>(guiViewType, "current.hasFocus"); GetIsDockedWindowGetter = DeepReflection.CreateValueGetter <EditorWindow, bool>("docked"); ContextWidthGetter = DeepReflection.CreateValueGetter <float>(typeof(EditorGUIUtility), "contextWidth"); ActualLabelWidthGetter = EmitUtilities.CreateStaticFieldGetter <float>(typeof(EditorGUIUtility).GetField("s_LabelWidth", Flags.AllMembers)); //ActualLabelWidthSetter = EmitUtilities.CreateStaticFieldSetter<float>(typeof(EditorGUIUtility).GetField("s_LabelWidth", Flags.AllMembers)); var guiViewGetter = DeepReflection.CreateWeakStaticValueGetter(guiViewType, guiViewType, "current"); var actualViewGetter = DeepReflection.CreateWeakInstanceValueGetter <EditorWindow>(hostViewType, "actualView"); var borderSizeGetter = DeepReflection.CreateWeakInstanceValueGetter <RectOffset>(hostViewType, "borderSize"); CurrentWindowGetter = () => actualViewGetter(guiViewGetter()); CurrentWindowBorderSizeGetter = () => borderSizeGetter(guiViewGetter()); SetBoldDefaultFontSetter = (Action <bool>)Delegate.CreateDelegate(typeof(Action <bool>), typeof(EditorGUIUtility).FindMember() .IsStatic() .IsMethod() .HasParameters <bool>() .ReturnsVoid() .IsNamed("SetBoldDefaultFont") .GetMember <MethodInfo>(), true); GetBoldDefaultFontGetter = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), typeof(EditorGUIUtility).FindMember() .IsStatic() .IsMethod() .HasNoParameters() .HasReturnType <bool>() .IsNamed("GetBoldDefaultFont") .GetMember <MethodInfo>(), true); GUILayoutEntriesCursorIndexGetter = DeepReflection.CreateValueGetter <int>(typeof(GUILayoutUtility), "current.topLevel.m_Cursor"); GUILayoutEntriesGetter = DeepReflection.CreateValueGetter <IList>(typeof(GUILayoutUtility), "current.topLevel.entries"); CurrentIndentAmountGetter = DeepReflection.CreateValueGetter <float>(typeof(EditorGUI), "indent"); GetTopLevelLayoutRectGetter = DeepReflection.CreateValueGetter <Rect>(typeof(GUILayoutUtility), "current.topLevel.rect"); GetEditorWindowRectGetter = DeepReflection.CreateValueGetter <Rect>(typeof(Editor).Assembly.GetType("UnityEditor.Toolbar"), "get.parent.screenPosition"); }
/// <summary> /// Draws the property. /// </summary> protected override void DrawPropertyLayout(GUIContent label) { var property = this.Property; var attribute = this.Attribute; var contextMenuInfos = property.Context.GetGlobal("CustomContextMenu", (Dictionary <CustomContextMenuAttribute, ContextMenuInfo>)null); var populated = property.Context.GetGlobal("CustomContextMenu_Populated", false); populated.Value = false; if (contextMenuInfos.Value == null) { contextMenuInfos.Value = new Dictionary <CustomContextMenuAttribute, ContextMenuInfo>(); } ContextMenuInfo info; if (!contextMenuInfos.Value.TryGetValue(attribute, out info)) { info = new ContextMenuInfo(); var methodInfo = property.ParentType .FindMember() .IsMethod() .IsInstance() .HasNoParameters() .ReturnsVoid() .IsNamed(attribute.MethodName) .GetMember <MethodInfo>(out info.ErrorMessage); if (info.ErrorMessage == null) { info.Name = attribute.MenuItem; info.MethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller(methodInfo); } contextMenuInfos.Value[attribute] = info; } if (info.ErrorMessage != null) { SirenixEditorGUI.ErrorMessageBox(info.ErrorMessage); } this.CallNextDrawer(label); }
/// <summary> /// Initializes a new instance of the <see cref="InspectorValuePropertyInfo{TOwner, TValue}"/> class. /// </summary> /// <param name="propertyInfo">The property to represent.</param> /// <param name="serializationBackend">The serialization backend.</param> /// <param name="allowEditable">Whether the property can be editable.</param> public InspectorValuePropertyInfo(PropertyInfo propertyInfo, SerializationBackend serializationBackend, bool allowEditable) : base(propertyInfo, propertyInfo.PropertyType.IsValueType ? PropertyType.ValueType : PropertyType.ReferenceType, serializationBackend, allowEditable) { MemberAliasPropertyInfo aliasPropertyInfo = propertyInfo as MemberAliasPropertyInfo; if (aliasPropertyInfo != null) { propertyInfo = aliasPropertyInfo.AliasedProperty; } this.getter = EmitUtilities.CreateInstancePropertyGetter <TOwner, TValue>(propertyInfo); if (propertyInfo.CanWrite) { this.setter = EmitUtilities.CreateInstancePropertySetter <TOwner, TValue>(propertyInfo); } }
private static Action <TValue> GetCachedStaticSetter(MemberInfo member) { Delegate del; if (GetterSetterCaches <TOwner> .Setters.TryGetInnerValue(member, typeof(TValue), out del)) { return((Action <TValue>)del); } else { Action <TValue> result = null; var fieldInfo = member as FieldInfo; var propertyInfo = member as PropertyInfo; if (fieldInfo != null) { if (!fieldInfo.IsLiteral) { result = EmitUtilities.CreateStaticFieldSetter <TValue>(fieldInfo); } } else if (propertyInfo != null) { if (propertyInfo.CanWrite) { result = EmitUtilities.CreateStaticPropertySetter <TValue>(propertyInfo); } } else { throw new ArgumentException("Cannot create a GetterSetter for a member of type + " + member.GetType().Name + "!"); } GetterSetterCaches <TOwner> .Setters.AddInner(member, typeof(TValue), result); return(result); } }
private static void EnsureInitialized() { if (!Initialized) { Initialized = true; try { string haveAudioCallbackName = UnityVersion.IsVersionOrGreater(5, 6) ? "HasAudioCallback" : "HaveAudioCallback"; AudioUtil_HaveAudioCallback = (Func <MonoBehaviour, bool>)Delegate.CreateDelegate(typeof(Func <MonoBehaviour, bool>), typeof(Editor).Assembly.GetType("UnityEditor.AudioUtil").GetMethod(haveAudioCallbackName, BindingFlags.Public | BindingFlags.Static)); AudioUtil_GetCustomFilterChannelCount = (Func <MonoBehaviour, int>)Delegate.CreateDelegate(typeof(Func <MonoBehaviour, int>), typeof(Editor).Assembly.GetType("UnityEditor.AudioUtil").GetMethod("GetCustomFilterChannelCount", BindingFlags.Public | BindingFlags.Static)); AudioFilterGUIType = typeof(Editor).Assembly.GetType("UnityEditor.AudioFilterGUI"); DrawAudioFilterGUI = EmitUtilities.CreateWeakInstanceMethodCaller <MonoBehaviour>(AudioFilterGUIType.GetMethod("DrawAudioFilterGUI", BindingFlags.Public | BindingFlags.Instance)); HasReflectedAudioFilter = true; } catch (Exception) { Debug.LogWarning("The internal Unity class AudioFilterGUI has been changed; cannot properly mock a generic Unity inspector. This probably won't be very noticeable."); } } }
private static SerializationCallback CreateCallback(MethodInfo info) { var parameters = info.GetParameters(); if (parameters.Length == 0) { #if CAN_EMIT var action = EmitUtilities.CreateInstanceRefMethodCaller <T>(info); return((ref T value, StreamingContext context) => action(ref value)); #else return((ref T value, StreamingContext context) => { object obj = value; info.Invoke(obj, null); value = (T)obj; }); #endif } else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(StreamingContext) && parameters[0].ParameterType.IsByRef == false) { #if CAN_EMIT var action = EmitUtilities.CreateInstanceRefMethodCaller <T, StreamingContext>(info); return((ref T value, StreamingContext context) => action(ref value, context)); #else return((ref T value, StreamingContext context) => { object obj = value; info.Invoke(obj, new object[] { context }); value = (T)obj; }); #endif } else { DefaultLoggers.DefaultLogger.LogWarning("The method " + info.GetNiceName() + " has an invalid signature and will be ignored by the serialization system."); return(null); } }
/// <summary> /// Draws the property. /// </summary> protected override void DrawPropertyLayout(GUIContent label) { var entry = this.ValueEntry; var attribute = this.Attribute; var context = entry.Property.Context.Get <ButtonContext>(this, "ButtonContext", (ButtonContext)null); if (context.Value == null) { context.Value = new ButtonContext(); context.Value.LabelHelper = new StringMemberHelper(this.Property, attribute.Label ?? attribute.MemberMethod.SplitPascalCase(), ref context.Value.ErrorMessage); if (context.Value.ErrorMessage == null) { MethodInfo method; if (MemberFinder.Start(entry.ParentType) .IsMethod() .IsNamed(attribute.MemberMethod) .HasNoParameters() .TryGetMember <MethodInfo>(out method, out context.Value.ErrorMessage)) { if (method.IsStatic()) { context.Value.StaticMethodCaller = EmitUtilities.CreateStaticMethodCaller(method); } else { context.Value.InstanceMethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller(method); } } else if (MemberFinder.Start(entry.ParentType) .IsMethod() .IsNamed(attribute.MemberMethod) .HasParameters <T>() .TryGetMember <MethodInfo>(out method, out context.Value.ErrorMessage)) { if (method.IsStatic()) { context.Value.ErrorMessage = "Static parameterized method is currently not supported."; } else { context.Value.InstanceParameterMethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller <T>(method); } } } } if (context.Value.ErrorMessage != null) { SirenixEditorGUI.ErrorMessageBox(context.Value.ErrorMessage); this.CallNextDrawer(label); } else { EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginVertical(); this.CallNextDrawer(label); EditorGUILayout.EndVertical(); if (GUILayout.Button(context.Value.LabelHelper.GetString(entry), EditorStyles.miniButton, GUILayoutOptions.ExpandWidth(false).MinWidth(20))) { // Invoke method. if (context.Value.StaticMethodCaller != null) { context.Value.StaticMethodCaller(); } //else if(context.Value.StaticParameterMethodCaller != null) //{ // context.Value.StaticParameterMethodCaller(entry.SmartValue); //} else if (context.Value.InstanceMethodCaller != null) { context.Value.InstanceMethodCaller(entry.Property.ParentValues[0]); } else if (context.Value.InstanceParameterMethodCaller != null) { context.Value.InstanceParameterMethodCaller(entry.Property.ParentValues[0], entry.SmartValue); } else { Debug.LogError("No method found."); } } EditorGUILayout.EndHorizontal(); } }
/// <summary> /// Initialized the drawer. /// </summary> protected override void Initialize() { MemberInfo member; // Min member if (this.Attribute.MinMember != null) { this.getterMinValue = new InspectorPropertyValueGetter <T>(this.Property, this.Attribute.MinMember); this.errorMessage = this.getterMinValue.ErrorMessage; } // Max member if (this.Attribute.MaxMember != null) { this.getterMaxValue = new InspectorPropertyValueGetter <T>(this.Property, this.Attribute.MaxMember); this.errorMessage = this.getterMaxValue.ErrorMessage; } // Foreground color member. if (!this.Attribute.ColorMember.IsNullOrWhitespace()) { if (MemberFinder.Start(this.Property.ParentType) .IsNamed(this.Attribute.ColorMember) .HasReturnType <Color>() .TryGetMember(out member, out this.errorMessage)) { if (member is FieldInfo || member is PropertyInfo) { if (member.IsStatic()) { this.staticColorGetter = DeepReflection.CreateValueGetter <Color>(this.Property.ParentType, this.Attribute.ColorMember); } else { this.instanceColorGetter = DeepReflection.CreateWeakInstanceValueGetter <Color>(this.Property.ParentType, this.Attribute.ColorMember); } } else if (member is MethodInfo) { if (member.IsStatic()) { this.errorMessage = "Static method members are currently not supported."; } else { var method = member as MethodInfo; var p = method.GetParameters(); if (p.Length == 0) { this.instanceColorMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <Color>(method); } else if (p.Length == 1 && p[0].ParameterType == typeof(T)) { this.instanceColorParameterMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <T, Color>(method); } } } else { this.errorMessage = "Unsupported member type."; } } } // Background color member. if (!this.Attribute.BackgroundColorMember.IsNullOrWhitespace()) { if (MemberFinder.Start(this.Property.ParentType) .IsNamed(this.Attribute.BackgroundColorMember) .HasReturnType <Color>() .TryGetMember(out member, out this.errorMessage)) { if (member is FieldInfo || member is PropertyInfo) { if (member.IsStatic()) { this.staticBackgroundColorGetter = DeepReflection.CreateValueGetter <Color>(this.Property.ParentType, this.Attribute.BackgroundColorMember); } else { this.instanceBackgroundColorGetter = DeepReflection.CreateWeakInstanceValueGetter <Color>(this.Property.ParentType, this.Attribute.BackgroundColorMember); } } else if (member is MethodInfo) { if (member.IsStatic()) { this.errorMessage = "Static method members are currently not supported."; } else { var method = member as MethodInfo; var p = method.GetParameters(); if (p.Length == 0) { this.instanceBackgroundColorMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <Color>(method); } else if (p.Length == 1 && p[0].ParameterType == typeof(T)) { this.instanceBackgroundColorParameterMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <T, Color>(method); } } } else { this.errorMessage = "Unsupported member type."; } } } // Custom value string getter if (this.Attribute.CustomValueStringMember != null && this.Attribute.CustomValueStringMember.Length > 0) { if (MemberFinder.Start(this.Property.ParentType) .IsNamed(this.Attribute.CustomValueStringMember) .HasReturnType <string>() .TryGetMember(out member, out this.errorMessage)) { if (member is FieldInfo || member is PropertyInfo) { if (member.IsStatic()) { this.staticGetValueLabel = DeepReflection.CreateValueGetter <string>(this.Property.ParentType, this.Attribute.CustomValueStringMember); } else { this.instanceGetValueLabel = DeepReflection.CreateWeakInstanceValueGetter <string>(this.Property.ParentType, this.Attribute.CustomValueStringMember); } } else if (member is MethodInfo) { var method = member as MethodInfo; var parameters = method.GetParameters(); if (parameters.Length == 0) { string name = this.Attribute.CustomValueStringMember + "()"; if (member.IsStatic()) { this.staticGetValueLabel = DeepReflection.CreateValueGetter <string>(this.Property.ParentType, name); } else { this.instanceGetValueLabel = DeepReflection.CreateWeakInstanceValueGetter <string>(this.Property.ParentType, name); } } else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(T)) { if (member.IsStatic()) { // TODO: This should be emitted. this.staticGetValueLabelValue = (v) => (string)method.Invoke(null, new object[] { v }); } else { // TODO: This should be emitted. this.instanceGetValueLabelValue = (o, v) => (string)method.Invoke(o, new object[] { v }); } } else { this.errorMessage = "Was unable to find any string field or property or string method with no parameters or exactly one " + typeof(T).GetNiceName() + " parameter named " + this.Attribute.CustomValueStringMember; } } } } }
/// <summary> /// Initializes this instance. /// </summary> protected override void Initialize() { this.hideDetailedMessage = true; this.messageHelper = new StringMemberHelper(this.Property, this.Attribute.Message); this.detailsHelper = new StringMemberHelper(this.Property, this.Attribute.Details); this.errorMessage = this.messageHelper.ErrorMessage ?? this.detailsHelper.ErrorMessage; if (this.Attribute.VisibleIf != null) { MemberInfo memberInfo; // Parameter functions if (this.Property.ValueEntry != null && this.Property.ParentType.FindMember() .IsMethod() .HasReturnType <bool>() .HasParameters(this.Property.ValueEntry.BaseValueType) .IsNamed(this.Attribute.VisibleIf) .TryGetMember(out memberInfo, out this.errorMessage)) { if (this.errorMessage == null) { if (memberInfo is MethodInfo) { var method = memberInfo as MethodInfo; if (memberInfo.IsStatic()) { // TODO: Emit dis. this.staticValidationParameterMethodCaller = p => (bool)method.Invoke(null, new object[] { p }); } else { // TODO: Emit dis. this.instanceValidationParameterMethodCaller = (i, p) => (bool)method.Invoke(i, new object[] { p }); } } else { this.errorMessage = "Invalid member type!"; } } } // Fields, properties, and no-parameter functions. else if (this.Property.ParentType.FindMember() .HasReturnType <bool>() .HasNoParameters() .IsNamed(this.Attribute.VisibleIf) .TryGetMember(out memberInfo, out this.errorMessage)) { if (this.errorMessage == null) { if (memberInfo is FieldInfo) { if (memberInfo.IsStatic()) { this.staticValidationCaller = EmitUtilities.CreateStaticFieldGetter <bool>(memberInfo as FieldInfo); } else { this.instanceValueGetter = EmitUtilities.CreateWeakInstanceFieldGetter(this.Property.ParentType, memberInfo as FieldInfo); } } else if (memberInfo is PropertyInfo) { if (memberInfo.IsStatic()) { this.staticValidationCaller = EmitUtilities.CreateStaticPropertyGetter <bool>(memberInfo as PropertyInfo); } else { this.instanceValueGetter = EmitUtilities.CreateWeakInstancePropertyGetter(this.Property.ParentType, memberInfo as PropertyInfo); } } else if (memberInfo is MethodInfo) { if (memberInfo.IsStatic()) { this.staticValidationCaller = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), memberInfo as MethodInfo); } else { this.instanceValidationMethodCaller = EmitUtilities.CreateWeakInstanceMethodCallerFunc <bool>(memberInfo as MethodInfo); } } else { this.errorMessage = "Invalid member type!"; } } } } }
public static float Draw <T>(OdinDrawer drawerInstance, IPropertyValueEntry <T> entry, float progress, ProgressBarAttribute attribute, GUIContent label) { PropertyContext <ProgressBarContext <T> > contextBuffer; if (entry.Context.Get <ProgressBarContext <T> >(drawerInstance, "ProgressBarContext", out contextBuffer)) { var parentType = entry.Property.FindParent(PropertyValueCategory.Member, true).ParentType; contextBuffer.Value = new ProgressBarContext <T>(); if (!attribute.ColorMember.IsNullOrWhitespace()) { MemberInfo member; if (MemberFinder.Start(parentType) .IsNamed(attribute.ColorMember) .HasReturnType <Color>() .TryGetMember(out member, out contextBuffer.Value.ErrorMessage)) { if (member is FieldInfo || member is PropertyInfo) { if (member.IsStatic()) { contextBuffer.Value.StaticColorGetter = DeepReflection.CreateValueGetter <Color>(parentType, attribute.ColorMember); } else { contextBuffer.Value.InstanceColorGetter = DeepReflection.CreateWeakInstanceValueGetter <Color>(parentType, attribute.ColorMember); } } else if (member is MethodInfo) { if (member.IsStatic()) { contextBuffer.Value.ErrorMessage = "Static method members are currently not supported."; } else { var method = member as MethodInfo; var p = method.GetParameters(); if (p.Length == 0) { contextBuffer.Value.InstanceColorMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <Color>(method); } else if (p.Length == 1 && p[0].ParameterType == typeof(T)) { contextBuffer.Value.InstanceColorParameterMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <T, Color>(method); } } } else { contextBuffer.Value.ErrorMessage = "Unsupported member type."; } } } if (!attribute.BackgroundColorMember.IsNullOrWhitespace()) { MemberInfo member; if (MemberFinder.Start(parentType) .IsNamed(attribute.BackgroundColorMember) .HasReturnType <Color>() .TryGetMember(out member, out contextBuffer.Value.ErrorMessage)) { if (member is FieldInfo || member is PropertyInfo) { if (member.IsStatic()) { contextBuffer.Value.StaticBackgroundColorGetter = DeepReflection.CreateValueGetter <Color>(parentType, attribute.BackgroundColorMember); } else { contextBuffer.Value.InstanceBackgroundColorGetter = DeepReflection.CreateWeakInstanceValueGetter <Color>(parentType, attribute.BackgroundColorMember); } } else if (member is MethodInfo) { if (member.IsStatic()) { contextBuffer.Value.ErrorMessage = "Static method members are currently not supported."; } else { var method = member as MethodInfo; var p = method.GetParameters(); if (p.Length == 0) { contextBuffer.Value.InstanceBackgroundColorMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <Color>(method); } else if (p.Length == 1 && p[0].ParameterType == typeof(T)) { contextBuffer.Value.InstanceBackgroundColorParameterMethod = EmitUtilities.CreateWeakInstanceMethodCallerFunc <T, Color>(method); } } } else { contextBuffer.Value.ErrorMessage = "Unsupported member type."; } } } } var context = contextBuffer.Value; // Error message if (context.ErrorMessage != null) { AllEditorGUI.ErrorMessageBox(context.ErrorMessage); } // Construct rect. Rect rect; if (label != null) { rect = EditorGUILayout.GetControlRect(true, attribute.Height > EditorGUIUtility.singleLineHeight ? attribute.Height : EditorGUIUtility.singleLineHeight); rect = EditorGUI.PrefixLabel(rect, label); rect = rect.AlignMiddle(attribute.Height); } else { rect = EditorGUILayout.GetControlRect(false, attribute.Height); GUIHelper.IndentRect(ref rect); } // Draw if (Event.current.type == EventType.Repaint) { var parent = entry.Property.FindParent(PropertyValueCategory.Member, true).ParentValues[0]; Color color = context.StaticColorGetter != null?context.StaticColorGetter() : context.InstanceColorGetter != null?context.InstanceColorGetter(parent) : context.InstanceColorMethod != null?context.InstanceColorMethod(parent) : context.InstanceColorParameterMethod != null?context.InstanceColorParameterMethod(parent, entry.SmartValue) : new Color(attribute.R, attribute.G, attribute.B, 1f); Color backgroundColor = context.StaticBackgroundColorGetter != null?context.StaticBackgroundColorGetter() : context.InstanceBackgroundColorGetter != null?context.InstanceBackgroundColorGetter(parent) : context.InstanceBackgroundColorMethod != null?context.InstanceBackgroundColorMethod(parent) : context.InstanceBackgroundColorParameterMethod != null?context.InstanceBackgroundColorParameterMethod(parent, entry.SmartValue) : new Color(0.16f, 0.16f, 0.16f, 1f); AllEditorGUI.DrawSolidRect(rect, backgroundColor); AllEditorGUI.DrawSolidRect(rect.AlignLeft(rect.width * Mathf.Clamp01(progress)), color); AllEditorGUI.DrawBorders(rect, 1, new Color(0.16f, 0.16f, 0.16f, 1f)); } if (GUI.enabled) { int controlID = GUIUtility.GetControlID(FocusType.Passive); if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && rect.Contains(Event.current.mousePosition) || GUIUtility.hotControl == controlID && (Event.current.type == EventType.MouseMove || Event.current.type == EventType.MouseDrag)) { Event.current.Use(); GUIUtility.hotControl = controlID; GUIHelper.RequestRepaint(); GUI.changed = true; progress = (Event.current.mousePosition.x - rect.xMin) / rect.width; } else if (GUIUtility.hotControl == controlID && Event.current.rawType == EventType.MouseUp) { GUIUtility.hotControl = 0; } } return(progress); }
/// <summary> /// Draws the property. /// </summary> protected override void DrawPropertyLayout(InspectorProperty property, InfoBoxAttribute attribute, GUIContent label) { PropertyContext <InfoBoxContext> context = null; context = property.Context.Get(this, "Config_" + this.GetHashCode(), (InfoBoxContext)null); if (context.Value == null) { context.Value = new InfoBoxContext() { MessageHelper = new StringMemberHelper(property.ParentType, attribute.Message) }; context.Value.ErrorMessage = context.Value.MessageHelper.ErrorMessage; MemberInfo memberInfo; if (attribute.VisibleIf != null) { // Parameter functions if (property.ValueEntry != null && property.ParentType.FindMember() .IsMethod() .HasReturnType <bool>() .HasParameters(property.ValueEntry.BaseValueType) .IsNamed(attribute.VisibleIf) .TryGetMember(out memberInfo, out context.Value.ErrorMessage)) { if (context.Value.ErrorMessage == null) { if (memberInfo is MethodInfo) { if (memberInfo.IsStatic()) { context.Value.StaticValidationParameterMethod = memberInfo as MethodInfo; } else { context.Value.InstanceValidationParameterMethod = memberInfo as MethodInfo; } } else { context.Value.ErrorMessage = "Invalid member type!"; } } } // Fields, properties, and no-parameter functions. else if (property.ParentType.FindMember() .HasReturnType <bool>() .HasNoParameters() .IsNamed(attribute.VisibleIf) .TryGetMember(out memberInfo, out context.Value.ErrorMessage)) { if (context.Value.ErrorMessage == null) { if (memberInfo is FieldInfo) { if (memberInfo.IsStatic()) { context.Value.StaticValidationCaller = EmitUtilities.CreateStaticFieldGetter <bool>(memberInfo as FieldInfo); } else { context.Value.InstanceValueGetter = EmitUtilities.CreateWeakInstanceFieldGetter(property.ParentType, memberInfo as FieldInfo); } } else if (memberInfo is PropertyInfo) { if (memberInfo.IsStatic()) { context.Value.StaticValidationCaller = EmitUtilities.CreateStaticPropertyGetter <bool>(memberInfo as PropertyInfo); } else { context.Value.InstanceValueGetter = EmitUtilities.CreateWeakInstancePropertyGetter(property.ParentType, memberInfo as PropertyInfo); } } else if (memberInfo is MethodInfo) { if (memberInfo.IsStatic()) { context.Value.StaticValidationCaller = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), memberInfo as MethodInfo); } else { context.Value.InstanceValidationMethodCaller = EmitUtilities.CreateWeakInstanceMethodCallerFunc <bool>(memberInfo as MethodInfo); } } else { context.Value.ErrorMessage = "Invalid member type!"; } } } } } if (context.Value.ErrorMessage != null) { SirenixEditorGUI.ErrorMessageBox(context.Value.ErrorMessage); } else { if (Event.current.type == EventType.Layout) { var parentValue = property.ParentValues[0]; try { context.Value.DrawMessageBox = attribute.VisibleIf == null || (context.Value.StaticValidationParameterMethod != null && (bool)context.Value.StaticValidationParameterMethod.Invoke(null, new object[] { property.ValueEntry.WeakSmartValue })) || (context.Value.InstanceValidationParameterMethod != null && (bool)context.Value.InstanceValidationParameterMethod.Invoke(null, new object[] { property.ParentValues[0], property.ValueEntry.WeakSmartValue })) || (context.Value.InstanceValidationMethodCaller != null && context.Value.InstanceValidationMethodCaller(property.ParentValues[0])) || (context.Value.InstanceValueGetter != null && (bool)context.Value.InstanceValueGetter(ref parentValue)) || (context.Value.StaticValidationCaller != null && context.Value.StaticValidationCaller()); } catch (System.Exception ex) { Debug.LogException(ex); } } if (context.Value.DrawMessageBox) { switch (attribute.InfoMessageType) { case InfoMessageType.None: SirenixEditorGUI.MessageBox(context.Value.MessageHelper.GetString(property)); break; case InfoMessageType.Info: SirenixEditorGUI.InfoMessageBox(context.Value.MessageHelper.GetString(property)); break; case InfoMessageType.Warning: SirenixEditorGUI.WarningMessageBox(context.Value.MessageHelper.GetString(property)); break; case InfoMessageType.Error: SirenixEditorGUI.ErrorMessageBox(context.Value.MessageHelper.GetString(property)); break; default: SirenixEditorGUI.ErrorMessageBox("Unknown InfoBoxType: " + attribute.InfoMessageType.ToString()); break; } } } this.CallNextDrawer(property, label); }
/// <summary> /// Initializes the drawer. /// </summary> protected override void Initialize() { var resolver = this.Property.ChildResolver as ICollectionResolver; bool isReadOnly = resolver.IsReadOnly; var customListDrawerOptions = this.Property.GetAttribute <ListDrawerSettingsAttribute>() ?? new ListDrawerSettingsAttribute(); isReadOnly = this.ValueEntry.IsEditable == false || isReadOnly || customListDrawerOptions.IsReadOnlyHasValue && customListDrawerOptions.IsReadOnly; info = new ListDrawerConfigInfo() { StartIndex = 0, Toggled = this.ValueEntry.Context.GetPersistent <bool>(this, "ListDrawerToggled", customListDrawerOptions.ExpandedHasValue ? customListDrawerOptions.Expanded : GeneralDrawerConfig.Instance.OpenListsByDefault), RemoveAt = -1, // Now set further down, so it can be kept updated every frame //Label = new GUIContent(label == null || string.IsNullOrEmpty(label.text) ? this.Property.ValueEntry.TypeOfValue.GetNiceName() : label.text, label == null ? string.Empty : label.tooltip), ShowAllWhilePaging = false, EndIndex = 0, CustomListDrawerOptions = customListDrawerOptions, IsReadOnly = isReadOnly, Draggable = !isReadOnly && (!customListDrawerOptions.IsReadOnlyHasValue), HideAddButton = isReadOnly || customListDrawerOptions.HideAddButton, HideRemoveButton = isReadOnly || customListDrawerOptions.HideRemoveButton, }; info.ListConfig = GeneralDrawerConfig.Instance; info.Property = this.Property; if (customListDrawerOptions.DraggableHasValue && !customListDrawerOptions.DraggableItems) { info.Draggable = false; } if (!(this.Property.ChildResolver is IOrderedCollectionResolver)) { info.Draggable = false; } if (info.CustomListDrawerOptions.OnBeginListElementGUI != null) { string error; MemberInfo memberInfo = this.Property.ParentType .FindMember() .IsMethod() .IsNamed(info.CustomListDrawerOptions.OnBeginListElementGUI) .HasParameters <int>() .ReturnsVoid() .GetMember <MethodInfo>(out error); if (memberInfo == null || error != null) { // TOOD: Do something about this "There should really be an error message here." thing. // For this to trigger both the member and the error message should be null. Can that happen? this.errorMessage = error ?? "There should really be an error message here."; } else { info.OnBeginListElementGUI = EmitUtilities.CreateWeakInstanceMethodCaller <int>(memberInfo as MethodInfo); } } if (info.CustomListDrawerOptions.OnEndListElementGUI != null) { string error; MemberInfo memberInfo = this.Property.ParentType .FindMember() .IsMethod() .IsNamed(info.CustomListDrawerOptions.OnEndListElementGUI) .HasParameters <int>() .ReturnsVoid() .GetMember <MethodInfo>(out error); if (memberInfo == null || error != null) { // TOOD: Do something about this "There should really be an error message here." thing. // For this to trigger both the member and the error message should be null. Can that happen? this.errorMessage = error ?? "There should really be an error message here."; } else { info.OnEndListElementGUI = EmitUtilities.CreateWeakInstanceMethodCaller <int>(memberInfo as MethodInfo); } } if (info.CustomListDrawerOptions.OnTitleBarGUI != null) { string error; MemberInfo memberInfo = this.Property.ParentType .FindMember() .IsMethod() .IsNamed(info.CustomListDrawerOptions.OnTitleBarGUI) .HasNoParameters() .ReturnsVoid() .GetMember <MethodInfo>(out error); if (memberInfo == null || error != null) { // TOOD: Do something about this "There should really be an error message here." thing. // For this to trigger both the member and the error message should be null. Can that happen? this.errorMessage = error ?? "There should really be an error message here."; } else { info.OnTitleBarGUI = EmitUtilities.CreateWeakInstanceMethodCaller(memberInfo as MethodInfo); } } if (info.CustomListDrawerOptions.ListElementLabelName != null) { string error; MemberInfo memberInfo = resolver.ElementType .FindMember() .HasNoParameters() .IsNamed(info.CustomListDrawerOptions.ListElementLabelName) .HasReturnType <object>(true) .GetMember(out error); if (memberInfo == null || error != null) { // TOOD: Do something about this "There should really be an error message here." thing. // For this to trigger both the member and the error message should be null. Can that happen? this.errorMessage = error ?? "There should really be an error message here."; } else { string methodSuffix = memberInfo as MethodInfo == null ? "" : "()"; info.GetListElementLabelText = DeepReflection.CreateWeakInstanceValueGetter(resolver.ElementType, typeof(object), info.CustomListDrawerOptions.ListElementLabelName + methodSuffix); } } // Resolve custom add method member reference. if (info.CustomListDrawerOptions.CustomAddFunction != null) { string error; MemberInfo memberInfo = this.Property.ParentType .FindMember() .HasNoParameters() .IsNamed(info.CustomListDrawerOptions.CustomAddFunction) .IsInstance() .HasReturnType(resolver.ElementType) .GetMember(out error); if (memberInfo == null || error != null) { string error2; memberInfo = this.Property.ParentType .FindMember() .IsMethod() .HasNoParameters() .IsNamed(info.CustomListDrawerOptions.CustomAddFunction) .IsInstance() .ReturnsVoid() .GetMember(out error2); if (memberInfo == null || error2 != null) { this.errorMessage = error + " - or - " + error2; } else { info.GetCustomAddFunctionVoid = EmitUtilities.CreateWeakInstanceMethodCaller(memberInfo as MethodInfo); } } else { string methodSuffix = memberInfo as MethodInfo == null ? "" : "()"; info.GetCustomAddFunction = DeepReflection.CreateWeakInstanceValueGetter( this.Property.ParentType, resolver.ElementType, info.CustomListDrawerOptions.CustomAddFunction + methodSuffix ); } } // Resolve custom remove index method member reference. if (info.CustomListDrawerOptions.CustomRemoveIndexFunction != null) { if (this.Property.ChildResolver is IOrderedCollectionResolver == false) { this.errorMessage = "ListDrawerSettings.CustomRemoveIndexFunction is invalid on unordered collections. Use ListDrawerSetings.CustomRemoveElementFunction instead."; } else { MethodInfo method = this.Property.ParentType .FindMember() .IsNamed(info.CustomListDrawerOptions.CustomRemoveIndexFunction) .IsMethod() .IsInstance() .HasParameters <int>() .ReturnsVoid() .GetMember <MethodInfo>(out this.errorMessage); if (method != null) { info.CustomRemoveIndexFunction = EmitUtilities.CreateWeakInstanceMethodCaller <int>(method); } } } // Resolve custom remove element method member reference. else if (info.CustomListDrawerOptions.CustomRemoveElementFunction != null) { var element = (this.Property.ChildResolver as ICollectionResolver).ElementType; MethodInfo method = this.Property.ParentType .FindMember() .IsNamed(info.CustomListDrawerOptions.CustomRemoveElementFunction) .IsMethod() .IsInstance() .HasParameters(element) .ReturnsVoid() .GetMember <MethodInfo>(out this.errorMessage); if (method != null) { // TOOD: Emit dis. info.CustomRemoveElementFunction = (o, e) => method.Invoke(o, new object[] { e }); } } }
/// <summary> /// Draws the property. /// </summary> protected override void DrawPropertyLayout(GUIContent label) { var property = this.Property; var entry = this.ValueEntry; var attribute = this.Attribute; var assetList = property.Context.Get(this, "assetList", (AssetList)null); var propertyTree = property.Context.Get(this, "togglableAssetListPropertyTree", (PropertyTree)null); if (property.ValueEntry.WeakSmartValue == null) { return; } if (assetList.Value == null) { assetList.Value = new AssetList(); assetList.Value.AutoPopulate = attribute.AutoPopulate; assetList.Value.AssetNamePrefix = attribute.AssetNamePrefix; assetList.Value.Tags = attribute.Tags != null?attribute.Tags.Trim().Split(',').Select(i => i.Trim()).ToArray() : null; assetList.Value.LayerNames = attribute.LayerNames != null?attribute.LayerNames.Trim().Split(',').Select(i => i.Trim()).ToArray() : null; assetList.Value.List = entry; assetList.Value.CollectionResolver = property.ChildResolver as IOrderedCollectionResolver; assetList.Value.Property = entry.Property; if (attribute.Path != null) { var path = attribute.Path.TrimStart('/', ' ').TrimEnd('/', ' '); path = attribute.Path.Trim('/', ' '); path = "Assets/" + path + "/"; path = Application.dataPath + "/" + path; assetList.Value.AssetsFolderLocation = new DirectoryInfo(path); path = attribute.Path.Trim('/', ' '); assetList.Value.PrettyPath = "/" + path.TrimStart('/'); } if (attribute.CustomFilterMethod != null) { MethodInfo methodInfo; string error; if (MemberFinder.Start(entry.ParentType) .IsMethod() .IsNamed(attribute.CustomFilterMethod) .HasReturnType <bool>() .HasParameters <TElement>() .TryGetMember <MethodInfo>(out methodInfo, out error)) { if (methodInfo.IsStatic) { assetList.Value.StaticCustomIncludeMethod = (Func <TElement, bool>)Delegate.CreateDelegate(typeof(Func <TElement, bool>), methodInfo, true); } else { assetList.Value.InstanceCustomIncludeMethod = EmitUtilities.CreateWeakInstanceMethodCaller <bool, TElement>(methodInfo); } } assetList.Value.ErrorMessage = error; } // We can get away with lag on load. assetList.Value.MaxSearchDurationPrFrameInMS = 20; assetList.Value.EnsureListPopulation(); assetList.Value.MaxSearchDurationPrFrameInMS = 1; //assetList.Value.List = list; //if (propertyTree.Value == null) //{ propertyTree.Value = PropertyTree.Create(assetList.Value); propertyTree.Value.UpdateTree(); propertyTree.Value.GetRootProperty(0).Label = label; //} } else if (Event.current.type == EventType.Layout) { assetList.Value.Property = entry.Property; assetList.Value.EnsureListPopulation(); assetList.Value.SetToggleValues(); } if (assetList.Value.ErrorMessage != null) { SirenixEditorGUI.ErrorMessageBox(assetList.Value.ErrorMessage); } assetList.Value.Property = entry.Property; propertyTree.Value.Draw(false); if (Event.current.type == EventType.Used) { assetList.Value.UpdateList(); } }
/// <summary> /// Draws the property. /// </summary> protected override void DrawPropertyLayout(IPropertyValueEntry <T> entry, DetailedInfoBoxAttribute attribute, GUIContent label) { PropertyContext <InfoBoxContext> context = entry.Property.Context.Get(this, "Context", (InfoBoxContext)null); if (context.Value == null) { context.Value = new InfoBoxContext() { MessageHelper = new StringMemberHelper(entry.ParentType, attribute.Message), DetailsHelper = new StringMemberHelper(entry.ParentType, attribute.Details) }; context.Value.ErrorMessage = context.Value.MessageHelper.ErrorMessage ?? context.Value.DetailsHelper.ErrorMessage; if (attribute.VisibleIf != null) { MemberInfo memberInfo; // Parameter functions if (entry.ParentType.FindMember() .IsMethod() .HasReturnType <bool>() .HasParameters <T>() .IsNamed(attribute.VisibleIf) .TryGetMember(out memberInfo, out context.Value.ErrorMessage)) { if (context.Value.ErrorMessage == null) { if (memberInfo is MethodInfo) { if (memberInfo.IsStatic()) { context.Value.StaticValidationParameterMethodCaller = (Func <T, bool>)Delegate.CreateDelegate(typeof(Func <T, bool>), memberInfo as MethodInfo); } else { context.Value.InstanceValidationParameterMethodCaller = EmitUtilities.CreateWeakInstanceMethodCaller <bool, T>(memberInfo as MethodInfo); } } else { context.Value.ErrorMessage = "Invalid member type!"; } } } // Fields, properties, and no-parameter functions. else if (entry.ParentType.FindMember() .HasReturnType <bool>() .HasNoParameters() .IsNamed(attribute.VisibleIf) .TryGetMember(out memberInfo, out context.Value.ErrorMessage)) { if (context.Value.ErrorMessage == null) { if (memberInfo is FieldInfo) { if (memberInfo.IsStatic()) { context.Value.StaticValidationCaller = EmitUtilities.CreateStaticFieldGetter <bool>(memberInfo as FieldInfo); } else { context.Value.InstanceValueGetter = EmitUtilities.CreateWeakInstanceFieldGetter(entry.ParentType, memberInfo as FieldInfo); } } else if (memberInfo is PropertyInfo) { if (memberInfo.IsStatic()) { context.Value.StaticValidationCaller = EmitUtilities.CreateStaticPropertyGetter <bool>(memberInfo as PropertyInfo); } else { context.Value.InstanceValueGetter = EmitUtilities.CreateWeakInstancePropertyGetter(entry.ParentType, memberInfo as PropertyInfo); } } else if (memberInfo is MethodInfo) { if (memberInfo.IsStatic()) { context.Value.StaticValidationCaller = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), memberInfo as MethodInfo); } else { context.Value.InstanceValidationMethodCaller = EmitUtilities.CreateWeakInstanceMethodCallerFunc <bool>(memberInfo as MethodInfo); } } else { context.Value.ErrorMessage = "Invalid member type!"; } } } } } if (context.Value.ErrorMessage != null) { AllEditorGUI.ErrorMessageBox(context.Value.ErrorMessage); } else { if (Event.current.type == EventType.Layout) { var parentValue = entry.Property.ParentValues[0]; try { if (entry.Property.ValueEntry != null) { context.Value.DrawMessageBox = attribute.VisibleIf == null || (context.Value.StaticValidationParameterMethodCaller != null && context.Value.StaticValidationParameterMethodCaller(entry.SmartValue)) || (context.Value.InstanceValidationParameterMethodCaller != null && context.Value.InstanceValidationParameterMethodCaller(entry.Property.ParentValues[0], entry.SmartValue)) || (context.Value.InstanceValidationMethodCaller != null && context.Value.InstanceValidationMethodCaller(entry.Property.ParentValues[0])) || (context.Value.InstanceValueGetter != null && (bool)context.Value.InstanceValueGetter(ref parentValue)) || (context.Value.StaticValidationCaller != null && context.Value.StaticValidationCaller()); } } catch (System.Exception ex) { Debug.LogException(ex); } } if (context.Value.DrawMessageBox) { var foldedConfig = entry.Property.Context.GetPersistent <bool>(this, "InfoBoxExpanded", true); switch (attribute.InfoMessageType) { case InfoMessageType.None: foldedConfig.Value = AllEditorGUI.DetailedMessageBox(context.Value.MessageHelper.GetString(entry), context.Value.DetailsHelper.GetString(entry), UnityEditor.MessageType.None, foldedConfig.Value); break; case InfoMessageType.Info: foldedConfig.Value = AllEditorGUI.DetailedMessageBox(context.Value.MessageHelper.GetString(entry), context.Value.DetailsHelper.GetString(entry), UnityEditor.MessageType.Info, foldedConfig.Value); break; case InfoMessageType.Warning: foldedConfig.Value = AllEditorGUI.DetailedMessageBox(context.Value.MessageHelper.GetString(entry), context.Value.DetailsHelper.GetString(entry), UnityEditor.MessageType.Warning, foldedConfig.Value); break; case InfoMessageType.Error: foldedConfig.Value = AllEditorGUI.DetailedMessageBox(context.Value.MessageHelper.GetString(entry), context.Value.DetailsHelper.GetString(entry), UnityEditor.MessageType.Error, foldedConfig.Value); break; default: AllEditorGUI.ErrorMessageBox("Unknown InfoBoxType: " + attribute.InfoMessageType.ToString()); break; } } } this.CallNextDrawer(entry.Property, label); }
/// <summary> /// Draws the property. /// </summary> protected override void DrawPropertyLayout(IPropertyValueEntry <TList> entry, GUIContent label) { var property = entry.Property; var infoContext = property.Context.Get(this, "Context", (ListDrawerConfigInfo)null); var info = infoContext.Value; bool isReadOnly = false; if (entry.TypeOfValue.IsArray == false) { for (int i = 0; i < entry.ValueCount; i++) { if ((entry.WeakValues[i] as IList <TElement>).IsReadOnly) { isReadOnly = true; break; } } } if (info == null) { var customListDrawerOptions = property.Info.GetAttribute <ListDrawerSettingsAttribute>() ?? new ListDrawerSettingsAttribute(); isReadOnly = entry.IsEditable == false || isReadOnly || customListDrawerOptions.IsReadOnlyHasValue && customListDrawerOptions.IsReadOnly; info = infoContext.Value = new ListDrawerConfigInfo() { StartIndex = 0, Toggled = entry.Context.GetPersistent <bool>(this, "ListDrawerToggled", customListDrawerOptions.ExpandedHasValue ? customListDrawerOptions.Expanded : GeneralDrawerConfig.Instance.OpenListsByDefault), RemoveAt = -1, label = new GUIContent(label == null || string.IsNullOrEmpty(label.text) ? property.ValueEntry.TypeOfValue.GetNiceName() : label.text, label == null ? string.Empty : label.tooltip), ShowAllWhilePageing = false, EndIndex = 0, CustomListDrawerOptions = customListDrawerOptions, IsReadOnly = isReadOnly, Draggable = !isReadOnly && (!customListDrawerOptions.IsReadOnlyHasValue) }; info.listConfig = GeneralDrawerConfig.Instance; info.property = property; if (customListDrawerOptions.DraggableHasValue && !customListDrawerOptions.DraggableItems) { info.Draggable = false; } if (info.CustomListDrawerOptions.OnBeginListElementGUI != null) { string errorMessage; MemberInfo memberInfo = property.ParentType .FindMember() .IsMethod() .IsNamed(info.CustomListDrawerOptions.OnBeginListElementGUI) .HasParameters <int>() .ReturnsVoid() .GetMember <MethodInfo>(out errorMessage); if (memberInfo == null || errorMessage != null) { Debug.LogError(errorMessage ?? "There should really be an error message here."); } else { info.OnBeginListElementGUI = EmitUtilities.CreateWeakInstanceMethodCaller <int>(memberInfo as MethodInfo); } } if (info.CustomListDrawerOptions.OnEndListElementGUI != null) { string errorMessage; MemberInfo memberInfo = property.ParentType .FindMember() .IsMethod() .IsNamed(info.CustomListDrawerOptions.OnEndListElementGUI) .HasParameters <int>() .ReturnsVoid() .GetMember <MethodInfo>(out errorMessage); if (memberInfo == null || errorMessage != null) { Debug.LogError(errorMessage ?? "There should really be an error message here."); } else { info.OnEndListElementGUI = EmitUtilities.CreateWeakInstanceMethodCaller <int>(memberInfo as MethodInfo); } } if (info.CustomListDrawerOptions.OnTitleBarGUI != null) { string errorMessage; MemberInfo memberInfo = property.ParentType .FindMember() .IsMethod() .IsNamed(info.CustomListDrawerOptions.OnTitleBarGUI) .HasNoParameters() .ReturnsVoid() .GetMember <MethodInfo>(out errorMessage); if (memberInfo == null || errorMessage != null) { Debug.LogError(errorMessage ?? "There should really be an error message here."); } else { info.OnTitleBarGUI = EmitUtilities.CreateWeakInstanceMethodCaller(memberInfo as MethodInfo); } } if (info.CustomListDrawerOptions.ListElementLabelName != null) { string errorMessage; MemberInfo memberInfo = typeof(TElement) .FindMember() .HasNoParameters() .IsNamed(info.CustomListDrawerOptions.ListElementLabelName) .HasReturnType <object>(true) .GetMember(out errorMessage); if (memberInfo == null || errorMessage != null) { Debug.LogError(errorMessage ?? "There should really be an error message here."); } else { string methodSuffix = memberInfo as MethodInfo == null ? "" : "()"; info.GetListElementLabelText = DeepReflection.CreateWeakInstanceValueGetter(typeof(TElement), typeof(object), info.CustomListDrawerOptions.ListElementLabelName + methodSuffix); } } } info.listConfig = GeneralDrawerConfig.Instance; info.property = property; info.ListItemStyle.padding.left = info.Draggable ? 25 : 7; info.ListItemStyle.padding.right = info.IsReadOnly ? 4 : 20; if (Event.current.type == EventType.Repaint) { info.DropZoneTopLeft = GUIUtility.GUIToScreenPoint(new Vector2(0, 0)); } info.ListValueChanger = property.ValueEntry.GetListValueEntryChanger(); info.Count = property.Children.Count; info.IsEmpty = property.Children.Count == 0; SirenixEditorGUI.BeginIndentedVertical(SirenixGUIStyles.PropertyPadding); this.BeginDropZone(info); { this.DrawToolbar(info); if (SirenixEditorGUI.BeginFadeGroup(UniqueDrawerKey.Create(property, this), info.Toggled.Value)) { GUIHelper.PushLabelWidth(EditorGUIUtility.labelWidth - info.ListItemStyle.padding.left); this.DrawItems(info); GUIHelper.PopLabelWidth(); } SirenixEditorGUI.EndFadeGroup(); } this.EndDropZone(info); SirenixEditorGUI.EndIndentedVertical(); if (info.RemoveAt >= 0 && Event.current.type == EventType.Repaint) { info.ListValueChanger.RemoveListElementAt(info.RemoveAt, CHANGE_ID); info.RemoveAt = -1; GUIHelper.RequestRepaint(); } if (info.ObjectPicker != null && info.ObjectPicker.IsReadyToClaim && Event.current.type == EventType.Repaint) { var value = info.ObjectPicker.ClaimObject(); if (info.JumpToNextPageOnAdd) { info.StartIndex = int.MaxValue; } object[] values = new object[info.ListValueChanger.ValueCount]; values[0] = value; for (int j = 1; j < values.Length; j++) { values[j] = SerializationUtility.CreateCopy(value); } info.ListValueChanger.AddListElement(values, CHANGE_ID); } }
/// <summary> /// Not yet documented. /// </summary> protected override void DrawPropertyLayout(GUIContent label) { var entry = this.ValueEntry; var attribute = this.Attribute; var config = entry.Property.Context.Get(this, "Test", (CurrentContext)null); if (config.Value == null) { config.Value = new CurrentContext(); config.Value.Attribute = attribute; config.Value.Tags = attribute.Tags != null?attribute.Tags.Trim().Split(',').Select(i => i.Trim()).ToArray() : null; config.Value.LayerNames = attribute.LayerNames != null?attribute.LayerNames.Trim().Split(',').Select(i => i.Trim()).ToArray() : null; config.Value.Property = entry.Property; if (attribute.Path != null) { var path = attribute.Path.Trim('/', ' '); path = "Assets/" + path + "/"; path = Application.dataPath + "/" + path; config.Value.AssetsFolderLocation = new DirectoryInfo(path); path = attribute.Path.TrimStart('/').TrimEnd('/'); config.Value.PrettyPath = "/" + path.TrimStart('/'); } if (attribute.CustomFilterMethod != null) { MethodInfo methodInfo; string error; if (MemberFinder.Start(entry.ParentType) .IsMethod() .IsNamed(attribute.CustomFilterMethod) .HasReturnType <bool>() .HasParameters <TElement>() .TryGetMember <MethodInfo>(out methodInfo, out error)) { if (methodInfo.IsStatic) { config.Value.StaticCustomIncludeMethod = (Func <TElement, bool>)Delegate.CreateDelegate(typeof(Func <TElement, bool>), methodInfo, true); } else { config.Value.InstanceCustomIncludeMethod = EmitUtilities.CreateWeakInstanceMethodCaller <bool, TElement>(methodInfo); } } config.Value.ErrorMessage = error; } if (config.Value.ErrorMessage != null) { // We can get away with lag on load. config.Value.MaxSearchDurationPrFrameInMS = 20; config.Value.EnsureListPopulation(); config.Value.MaxSearchDurationPrFrameInMS = 1; } } var currentValue = (UnityEngine.Object)entry.WeakSmartValue; if (config.Value.ErrorMessage != null) { SirenixEditorGUI.ErrorMessageBox(config.Value.ErrorMessage); } else { config.Value.EnsureListPopulation(); } SirenixEditorGUI.BeginIndentedVertical(SirenixGUIStyles.PropertyPadding); { SirenixEditorGUI.BeginHorizontalToolbar(); if (label != null) { GUILayout.Label(label); } GUILayout.FlexibleSpace(); if (config.Value.PrettyPath != null) { GUILayout.Label(config.Value.PrettyPath, SirenixGUIStyles.RightAlignedGreyMiniLabel); SirenixEditorGUI.VerticalLineSeparator(); } if (config.Value.IsPopulated) { GUILayout.Label(config.Value.AvailableAsset.Count + " items", SirenixGUIStyles.RightAlignedGreyMiniLabel); GUIHelper.PushGUIEnabled(GUI.enabled && (config.Value.AvailableAsset.Count > 0 && config.Value.ErrorMessage == null)); } else { GUILayout.Label("Scanning " + config.Value.CurrentSearchingIndex + " / " + config.Value.NumberOfResultsToSearch, SirenixGUIStyles.RightAlignedGreyMiniLabel); GUIHelper.PushGUIEnabled(false); } SirenixEditorGUI.VerticalLineSeparator(); bool drawConflict = entry.Property.ParentValues.Count > 1; if (drawConflict == false) { var index = config.Value.AvailableAsset.IndexOf(currentValue) + 1; if (index > 0) { GUILayout.Label(index.ToString(), SirenixGUIStyles.RightAlignedGreyMiniLabel); } else { drawConflict = true; } } if (drawConflict) { GUILayout.Label("-", SirenixGUIStyles.RightAlignedGreyMiniLabel); } if (SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleLeft) && config.Value.IsPopulated) { var index = config.Value.AvailableAsset.IndexOf(currentValue) - 1; index = index < 0 ? config.Value.AvailableAsset.Count - 1 : index; entry.WeakSmartValue = config.Value.AvailableAsset[index]; } if (SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleDown) && config.Value.IsPopulated) { GenericMenu m = new GenericMenu(); var selected = currentValue; int itemsPrPage = 40; bool showPages = config.Value.AvailableAsset.Count > 50; string page = ""; int selectedPage = (config.Value.AvailableAsset.IndexOf(entry.WeakSmartValue as UnityEngine.Object) / itemsPrPage); for (int i = 0; i < config.Value.AvailableAsset.Count; i++) { var obj = config.Value.AvailableAsset[i]; if (obj != null) { var path = AssetDatabase.GetAssetPath(obj); var name = string.IsNullOrEmpty(path) ? obj.name : path.Substring(7).Replace("/", "\\"); var localEntry = entry; if (showPages) { var p = (i / itemsPrPage); page = (p * itemsPrPage) + " - " + Mathf.Min(((p + 1) * itemsPrPage), config.Value.AvailableAsset.Count - 1); if (selectedPage == p) { page += " (contains selected)"; } page += "/"; } m.AddItem(new GUIContent(page + name), obj == selected, () => { localEntry.Property.Tree.DelayActionUntilRepaint(() => localEntry.WeakSmartValue = obj); }); } } m.ShowAsContext(); } if (SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleRight) && config.Value.IsPopulated) { var index = config.Value.AvailableAsset.IndexOf(currentValue) + 1; entry.WeakSmartValue = config.Value.AvailableAsset[index % config.Value.AvailableAsset.Count]; } GUIHelper.PopGUIEnabled(); SirenixEditorGUI.EndHorizontalToolbar(); SirenixEditorGUI.BeginVerticalList(); SirenixEditorGUI.BeginListItem(false, padding); this.CallNextDrawer(null); SirenixEditorGUI.EndListItem(); SirenixEditorGUI.EndVerticalList(); } SirenixEditorGUI.EndIndentedVertical(); }
private void DoInspectorGUI(InspectorProperty property, string config, string methodName) { var methodConfig = property.Context.Get(this, config, (MethodContext)null); if (methodConfig.Value == null) { methodConfig.Value = new MethodContext(); MethodInfo methodInfo = property.ParentType .FindMember() .IsMethod() .IsNamed(methodName) .HasNoParameters() .ReturnsVoid() .GetMember <MethodInfo>(out methodConfig.Value.ErrorMessage); if (methodConfig.Value.ErrorMessage == null && methodInfo != null) { if (methodInfo.IsStatic) { methodConfig.Value.StaticMethod = EmitUtilities.CreateStaticMethodCaller(methodInfo); } else { methodConfig.Value.InstanceMethod = EmitUtilities.CreateWeakInstanceMethodCaller(methodInfo); } } else { string otherErrorMessage; methodInfo = property.ParentType .FindMember() .IsMethod() .IsNamed(methodName) .HasParameters(property.ValueEntry.BaseValueType) .IsStatic() .ReturnsVoid() .GetMember <MethodInfo>(out otherErrorMessage); if (otherErrorMessage == null) { methodConfig.Value.ErrorMessage = null; var delegateType = typeof(Action <>).MakeGenericType(property.ValueEntry.TypeOfValue); methodConfig.Value.StaticMethodWithParam = Delegate.CreateDelegate(delegateType, methodInfo); } else { methodConfig.Value.ErrorMessage += "\nor\n" + otherErrorMessage; } } } if (methodConfig.Value.ErrorMessage != null) { SirenixEditorGUI.ErrorMessageBox(methodConfig.Value.ErrorMessage); } else { if (methodConfig.Value.InstanceMethod != null) { methodConfig.Value.InstanceMethod(property.ParentValues[0]); } else if (methodConfig.Value.StaticMethodWithParam != null) { methodConfig.Value.StaticMethodWithParam.DynamicInvoke(property.ValueEntry.WeakSmartValue); } else { methodConfig.Value.StaticMethod(); } } }