A PropertyAttribute/PropertyDraw

作者: 2b75747cf703 | 来源:发表于2016-02-20 23:22 被阅读436次

    https://github.com/LMNRY/SetProperty

    // Copyright (c) 2014 Luminary LLC
    // Licensed under The MIT License (See LICENSE for full text)
    using UnityEngine;
    using UnityEditor;
    using System;
    using System.Collections;
    using System.Reflection;
    
    [CustomPropertyDrawer(typeof(SetPropertyAttribute))]
    public class SetPropertyDrawer : PropertyDrawer
    {
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            // Rely on the default inspector GUI
            EditorGUI.BeginChangeCheck ();
            EditorGUI.PropertyField(position, property, label);
    
            // Update only when necessary
            SetPropertyAttribute setProperty = attribute as SetPropertyAttribute;
            if (EditorGUI.EndChangeCheck())
            {
                // When a SerializedProperty is modified the actual field does not have the current value set (i.e.  
                // FieldInfo.GetValue() will return the prior value that was set) until after this OnGUI call has completed. 
                // Therefore, we need to mark this property as dirty, so that it can be updated with a subsequent OnGUI event 
                // (e.g. Repaint)
                setProperty.IsDirty = true;
            } 
            else if (setProperty.IsDirty)
            {
                // The propertyPath may reference something that is a child field of a field on this Object, so it is necessary
                // to find which object is the actual parent before attempting to set the property with the current value.
                object parent = GetParentObjectOfProperty(property.propertyPath, property.serializedObject.targetObject);
                Type type = parent.GetType();
                PropertyInfo pi = type.GetProperty(setProperty.Name);
                if (pi == null)
                {
                    Debug.LogError("Invalid property name: " + setProperty.Name + "\nCheck your [SetProperty] attribute");
                }
                else
                {
                    // Use FieldInfo instead of the SerializedProperty accessors as we'd have to deal with every 
                    // SerializedPropertyType and use the correct accessor
                    pi.SetValue(parent, fieldInfo.GetValue(parent), null);
                }
                setProperty.IsDirty = false;
            }
        }
        
        private object GetParentObjectOfProperty(string path, object obj)
        {
            string[] fields = path.Split('.');
    
            // We've finally arrived at the final object that contains the property
            if (fields.Length == 1)
            {
                return obj;
            }
    
            // We may have to walk public or private fields along the chain to finding our container object, so we have to allow for both
            FieldInfo fi = obj.GetType().GetField(fields[0], BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            obj = fi.GetValue(obj);
    
            // Keep searching for our object that contains the property
            return GetParentObjectOfProperty(string.Join(".", fields, 1, fields.Length - 1), obj);
        }
    }
    
    // Copyright (c) 2014 Luminary LLC
    // Licensed under The MIT License (See LICENSE for full text)
    using UnityEngine;
    using System.Collections;
    
    public class SetPropertyAttribute : PropertyAttribute
    {
        public string Name { get; private set; }
        public bool IsDirty { get; set; }
    
        public SetPropertyAttribute(string name)
        {
            this.Name = name;
        }
    }
    
    // Copyright (c) 2014 Luminary LLC
    // Licensed under The MIT License (See LICENSE for full text)
    using UnityEngine;
    using System.Collections;
    
    public class SetPropertyExample : MonoBehaviour 
    {
        [System.Serializable]
        public class VanillaClass
        {
            public enum ExtraType
            {
                None,
                HotFudge,
                Mint,
            }
    
            [SerializeField, SetProperty("Extra")]
            private ExtraType extra;
            public ExtraType Extra
            {
                get
                {
                    return extra;
                }
                set
                {
                    extra = value;
    
                    // For illustrative purposes
                    if (value == ExtraType.None)
                    {
                        Debug.Log("Simple!");
                    }
                    else
                    {
                        Debug.Log ("Yummy!");
                    }
                }
            }
        }
    
        [SerializeField, SetProperty("Number")]
        private float number;
        public float Number
        {
            get
            {
                return number;
            }
            private set
            {
                number = Mathf.Clamp01(value);
            }
        }
    
        [SerializeField, SetProperty("Text")]
        private string text;
        public string Text
        {
            get
            {
                return text;
            }
            set
            {
                text = value.ToUpper();
            }
        }
    
        public VanillaClass vanilla;
    }
    

    相关文章

      网友评论

        本文标题:A PropertyAttribute/PropertyDraw

        本文链接:https://www.haomeiwen.com/subject/mjivkttx.html