Search Unity

  1. Check out the Unite LA keynote for updates on the Visual Effect Editor, the FPS Sample, ECS, Unity for Film and more! Watch it now!
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  4. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Property Drawer on elements of an array changing all elements.

Discussion in 'Extensions & OnGUI' started by LMan, Jan 10, 2017.

  1. LMan

    LMan

    Joined:
    Jun 1, 2013
    Posts:
    476
    I have a property drawer that is supposed to allow the selection of animator parameters from an enumPopup.


    Code (CSharp):
    1. [CustomPropertyDrawer(typeof(Reaction))]
    2. [CanEditMultipleObjects]
    3. public class ReactionDrawer : PropertyDrawer
    4. {
    5.     AnimatorController animCntrl;
    6.     AnimatorControllerParameter[] parameters;
    7.     string[] parameter_names = new string[0];
    8.     int selectedParameter = 0;
    9.  
    10.     // Draw the property inside the given rect
    11.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    12.     {
    13.        if(animCntrl == null)
    14.         {
    15.             if(Selection.activeGameObject != null)
    16.             {
    17.                 animCntrl = (AnimatorController)Selection.activeGameObject.GetComponent<Animator>().runtimeAnimatorController;
    18.             }
    19.             else
    20.             {
    21.                 return;
    22.             }
    23.                      
    24.             _init(); //populates the parameter and parameter names array
    25.         }
    26.         SerializedProperty parameter = property.FindPropertyRelative("parameter");
    27.         SerializedProperty type = property.FindPropertyRelative("type");
    28.  
    29.         // Using BeginProperty / EndProperty on the parent property means that
    30.         // prefab override logic works on the entire property.
    31.         EditorGUI.BeginProperty(position, label, property);
    32.  
    33.         // Draw label
    34.         position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
    35.  
    36.         var paramRect = new Rect(position.x, position.y, position.width/2, position.height);
    37.         var typeRect = new Rect(position.x + position.width/2 + 5, position.y, position.width/4, position.height);
    38.         var valRect = new Rect(position.x + (position.width/4)*3 + 5 , position.y, position.width/4, position.height);
    39.  
    40.         if (parameters.Length > 0)
    41.         {
    42.             selectedParameter = EditorGUI.Popup(paramRect, selectedParameter, parameter_names);
    43.             parameter.stringValue = parameters[selectedParameter].name;
    44.             SetParameterType(type);
    45.             EditorGUI.LabelField(typeRect, type.enumDisplayNames[type.enumValueIndex]);
    46.             DrawValueField(valRect, property);
    47.         }
    48.         else
    49.         {
    50.             EditorGUI.LabelField(new Rect(position.x, position.y, position.width, position.height), "No parameters found in Animator Controller");
    51.         }
    52.         EditorGUI.EndProperty();
    53.        
    54.     }
    The Reaction Property itself:
    Code (CSharp):
    1. [System.Serializable]
    2. public class Reaction
    3. {
    4.     public enum reactionType {boolean = 0, trigger = 1, integer = 2, floating = 3 , none = 4};
    5.  
    6.     public reactionType type = reactionType.none;
    7.     public string parameter;
    8.  
    9.     //rather than fool with types, keep them all.
    10.     public bool value_bool;
    11.     public int value_int;
    12.     public float value_float;
    13. }
    Pictured, you see the Reactor component, which keeps an array of Reactions.
    Reaction property Drawer.png

    What happens is that when I change the popup value in one box, it changes for all the elements in the array. What am I missing?
     
  2. CDF

    CDF

    Joined:
    Sep 14, 2013
    Posts:
    641
    maybe put a BeginChangeCheck and EndChangeCheck around setting the parameter.stringValue.
    "selectedParameter" is probably being re-used.

    Code (CSharp):
    1. EditorGUI.BeginChangeCheck();
    2.  
    3. int newSelectedParameter = EditorGUI.Popup(paramRect, selectedParameter, parameter_names);
    4.  
    5. if (EditorGUI.EndChangeCheck()) {
    6.  
    7.     selectedParameter = newSelectedParameter;
    8.     parameter.stringValue = parameters[selectedParameter].name;
    9.     SetParameterType(type);
    10. }
     
  3. LMan

    LMan

    Joined:
    Jun 1, 2013
    Posts:
    476
    Aha, I found the answer in another thread at last.

     
  4. LMan

    LMan

    Joined:
    Jun 1, 2013
    Posts:
    476
    At the moment, my solution is just to keep an int in the reaction property for recalling the index.
     
  5. mo_star

    mo_star

    Joined:
    Jul 2, 2014
    Posts:
    1
    Hey man I know its old topic, but could you elaborate how you achieved this. Where did you hold the reference to reactive property? I tried putting the reactive property inside the propertydrawer and it still does the same thing.

    I'm creating some custom editors and they are really pain in the butt. Took me 3 days to figure out the workflow of the editor creation code.

    Please help !!!

    Thanks in advance,
    Miran
     
  6. NolwennB

    NolwennB

    Joined:
    Mar 4, 2014
    Posts:
    8
    What I did, based on what LMan said :
    In your serializable class add
    public int index;

    In your PropertyDrawer, replace
    selectedParameter
    with
    property.FindPropertyRelative("index").intValue

    It works for me!
     
  7. BinaryCats

    BinaryCats

    Joined:
    Feb 8, 2016
    Posts:
    140
    What I do is parse the full path of the property, looking for "Array.Data[x]", and grab the value of x, and that is the index of the thing being drawn