/// <summary>
        /// Get the object this property points to
        /// </summary>
        public static object GetObject(this SerializedProperty p)
        {
            object o = p.serializedObject.targetObject;
            // Friendly array syntax - one . per path element
            // e.g. propName.Array.data[0] => propName[0]
            string path = p.propertyPath.Replace(".Array.data[", "[");

            string[] elements = path.Split('.');
            // Iterate through property path
            for (int i = 0; i < elements.Length; ++i)
            {
                if (p.IsArrayElement(elements[i]))
                {
                    string arrayName;
                    int    j   = GetArrayIndex(elements, i, out arrayName);
                    var    fi  = o.GetType().GetFieldPrivate(arrayName, FLAGS_ALL);
                    var    arr = (System.Array)fi.GetValue(o);
                    o = arr.GetValue(j);
                }
                else
                {
                    var fi = o.GetType().GetFieldPrivate(elements[i], FLAGS_ALL);
                    o = fi.GetValue(o);
                }
            }
            return(o);
        }
        public static FieldInfo GetField(this SerializedProperty p)
        {
            object    o  = p.serializedObject.targetObject;
            var       t  = o.GetType();
            FieldInfo fi = null;

            // Friendly array syntax - one . per path element
            // e.g. propName.Array.data[0] => propName[0]
            string[] elements = GetFriendlyPath(p);

            // Iterate through property path
            for (int i = 0; i < elements.Length; ++i)
            {
                if (p.IsArrayElement(elements[i]))
                {
                    string arrayName;
                    GetArrayIndex(elements, i, out arrayName);
                    fi = t.GetFieldPrivate(arrayName, FLAGS_ALL);
                }
                else
                {
                    fi = t.GetFieldPrivate(elements[i], FLAGS_ALL);
                }
                if (fi == null)
                {
                    return(null);
                }
                t = fi.FieldType;
            }
            return(fi);
        }
        public static FieldInfo GetField(this SerializedProperty p)
        {
            object    o  = p.serializedObject.targetObject;
            var       t  = o.GetType();
            FieldInfo fi = null;

            // Friendly array syntax - one . per path element
            // e.g. propName.Array.data[0] => propName[0]
            string[] elements = GetFriendlyPath(p);

            // Iterate through property path
            for (int i = 0; i < elements.Length; ++i)
            {
                if (p.IsArrayElement(elements[i]))
                {
                    string arrayName;
                    GetArrayIndex(elements, i, out arrayName);
                    fi = t.GetFieldPrivate(arrayName, FLAGS_ALL);
                }
                else
                {
                    fi = t.GetFieldPrivate(elements[i], FLAGS_ALL);
                }
                while (fi == null)
                {
                    // Might be an array (or array of arrays etc), so get underlying type and try to find field again
                    var tUnderlying = t.GetElementType();
                    if (tUnderlying != null)
                    {
                        t  = tUnderlying;
                        fi = t.GetFieldPrivate(elements[i], FLAGS_ALL);
                    }
                    else
                    {
                        break;
                    }
                }
                if (fi == null)
                {
                    return(null);
                }
                t = fi.FieldType;
            }
            return(fi);
        }
	/// <summary>
	/// Gets the height of the property.
	/// </summary>
	/// <returns>The property height.</returns>
	/// <param name="property">Property.</param>
	/// <param name="label">Label.</param>
	public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
	{
		// ensure property's decorator height is registered
		if (!decoratorHeights.ContainsKey(property.propertyPath))
		{
			decoratorHeights.Add(property.propertyPath, 0f);
		}
		decoratorHeights[property.propertyPath] = 0f;
		if (DrawerToUse != null)
		{
			return DrawerToUse.GetPropertyHeight(property, label);
		}
		else
		{
			float result = EditorGUI.GetPropertyHeight(property, label, true);
			if (!property.IsArrayElement())
			{
				foreach (PropertyAttribute attr in fieldInfo.GetCustomAttributes<PropertyAttribute>())
				{
					GUIDrawer drawer = SerializedPropertyX.GetGUIDrawer(fieldInfo, attr);
					if (drawer is DecoratorDrawer)
					{
						float height = (drawer as DecoratorDrawer).GetHeight();
						result -= height;
						decoratorHeights[property.propertyPath] += height;
					}
				}
			}
			return result;
		}
	}