Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Vector4 Property Drawers

Discussion in 'Scripting' started by hogwash, Dec 20, 2012.

  1. hogwash

    hogwash

    Joined:
    Oct 12, 2012
    Posts:
    117
    Hey guys,

    Just wanted to post some code I wrote in order to make Vector4's work with property drawers. Hope you find it helpful.

    Cheers,
    Tom.

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class CompactAttribute : PropertyAttribute
    4. {
    5. }
    Code (csharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. [CustomPropertyDrawer(typeof(CompactAttribute))]
    5. public class CompactDrawer : PropertyDrawer
    6. {
    7.     public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label)
    8.     {
    9.         System.Type objectType = prop.serializedObject.targetObject.GetType();
    10.         System.Type propertyType = objectType.GetField(prop.name).FieldType;
    11.        
    12.         if (propertyType == typeof(Vector4))
    13.         {
    14.             SerializedProperty xProp = prop.FindPropertyRelative("x");
    15.             SerializedProperty yProp = prop.FindPropertyRelative("y");
    16.             SerializedProperty zProp = prop.FindPropertyRelative("z");
    17.             SerializedProperty wProp = prop.FindPropertyRelative("w");
    18.             Vector4 vector4Value = new Vector4(xProp.floatValue, yProp.floatValue, zProp.floatValue, wProp.floatValue);
    19.            
    20.             EditorGUIUtility.LookLikeControls();
    21.             position.x += 4;
    22.             position.width -= 8;
    23.             EditorGUI.BeginChangeCheck();
    24.             vector4Value = EditorGUI.Vector4Field(position, label.text, vector4Value);
    25.             if (EditorGUI.EndChangeCheck())
    26.             {
    27.                 xProp.floatValue = vector4Value.x;
    28.                 yProp.floatValue = vector4Value.y;
    29.                 zProp.floatValue = vector4Value.z;
    30.                 wProp.floatValue = vector4Value.w;
    31.             }
    32.         }
    33.         else
    34.         {
    35.             switch (prop.propertyType)
    36.             {
    37.             case SerializedPropertyType.Vector2:
    38.                 {
    39.                     EditorGUIUtility.LookLikeControls();
    40.                     position.x += 4;
    41.                     position.width -= 8;
    42.                     EditorGUI.BeginChangeCheck();
    43.                     Vector2 vector2Value = EditorGUI.Vector2Field(position, label.text, prop.vector2Value);
    44.                     if (EditorGUI.EndChangeCheck())
    45.                     {
    46.                         prop.vector2Value = vector2Value;
    47.                     }
    48.                 }
    49.                 break;
    50.             case SerializedPropertyType.Vector3:
    51.                 {
    52.                     EditorGUIUtility.LookLikeControls();
    53.                     position.x += 4;
    54.                     position.width -= 8;
    55.                     EditorGUI.BeginChangeCheck();
    56.                     Vector3 vector3Value = EditorGUI.Vector3Field(position, label.text, prop.vector3Value);
    57.                     if (EditorGUI.EndChangeCheck())
    58.                     {
    59.                         prop.vector3Value = vector3Value;
    60.                     }
    61.                 }
    62.                 break;
    63.             default:
    64.                 {
    65.                     Debug.LogError("Compact attribute only works for Vector2, Vector3 and Vector4");
    66.                 }
    67.                 break;
    68.             }
    69.         }
    70.     }
    71.    
    72.     public override float GetPropertyHeight(SerializedProperty prop, GUIContent label)
    73.     {
    74.         return base.GetPropertyHeight(prop, label) * 2 + 4;
    75.     }
    76. }
     
    Selzier and david-mal like this.
  2. Selzier

    Selzier

    Joined:
    Sep 23, 2014
    Posts:
    652
    Thanks!
     
  3. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    You do know that this post is 8+ years old? The SerializedProperty supports Vector4 natively for ages. So there's no need for a reflection based hack that will break as soon as your property is nested or inside an array.
     
  4. Selzier

    Selzier

    Joined:
    Sep 23, 2014
    Posts:
    652
    - Vector4 did not work with SerializedProperty (or maybe you can show code that does work?)
    - My Vector4's are in an array and work fine.

    Thanks to OP for the post, even being 8 years old, solved the problem with my custom property drawers.
     
  5. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    What exactly do you mean by that? What did not work? The SerializedProperty class has a vector4Value, that works exactly like the vector 2 and 3 version. Vector4 values are also natively supported by the default editor / inspector. So what exact issues do you have?
     
  6. Selzier

    Selzier

    Joined:
    Sep 23, 2014
    Posts:
    652
    Ok I see the problem. Because I'm rendering a custom property drawer, I need to reference the SerializedProperty not the vector4Value.

    Vector4 is Offset & Size:


    Calling EditorGUI.FloatField for vector4Value.x did not allow for saving changes made to the float. For this, I had to use
    SerializedProperty xProp = property.FindPropertyRelative("offset").FindPropertyRelative("x");

    OP was helpful as I couldn't figure how to get SerializedProperty of the Vector4 which required calling 2 FindPropertyRelative, first for the custom class and second for the Vector4.