Search Unity

EditorGUI and custom classes

Discussion in 'Scripting' started by djfunkey, Apr 22, 2014.

  1. djfunkey

    djfunkey

    Joined:
    Jul 16, 2012
    Posts:
    201
    What I am trying to achieve...
    A custom editor which shows the 3 variables; timeH, timeM, timeS, in a horizontal group, all editor-able by using intFields.

    I don't know how to get the desired result. Because the Editor script cannot use the TimeInterval as target. I am pretty sure. The example is the basic outline of my problem. Can someone please set me on the right path, that would be appreciated!

    Very basic example:
    Code (csharp):
    1.  
    2. //TimeManager.cs
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class TimeInterval {
    7.     public int timeH;
    8.     public int timeM;
    9.     public int timeS;
    10. }
    11.  
    12. public class TimeManager : MonoBehaviour {
    13.     public TimeInterval[] timeintervals;
    14. }
    15.  
    Code (csharp):
    1.  
    2. //TimeIntervalEditor.cs
    3. using UnityEngine;
    4. using System.Collections;
    5. using UnityEditor;
    6.  
    7. [CustomEditor(typeof(TimeInterval))]
    8. public class TimeIntervalEditor : Editor {
    9.     public override void OnInspectorGUI() {
    10.         DarwDefaultInspector();
    11.         TimeInterval myTarget = (TimeInterval) target;
    12.        
    13.         EditorGUILayout.BeginHorizontal();
    14.         myTarget.timeH = EditorGUI.IntField(GUILayoutUtility.GetRect(18,18), "Hour", myTarget.timeH);
    15.         myTarget.timeM = EditorGUI.IntField(GUILayoutUtility.GetRect(18,18), "Minute", myTarget.timeM);
    16.         myTarget.timeS = EditorGUI.IntField(GUILayoutUtility.GetRect(18,18), "Second", myTarget.timeS);
    17.         EditorGUILayout.EndHorizontal();
    18.     }
    19. }
    20.  
     
  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    And why is your TimeIntervalEditor doesn't work? (beside the misspelled "DrawDefaultInspector" and that you draw all IntField at the same place)
     
  3. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    GetRect reserves a rect area in the layout, so they aren't all in the same place

    But i have to wonder why OP isnt just using EditorGUILayout.Intfields with BeginHorizontal

    Doing custom editors is for making inspectors for your components. TimeInterval does not extend monobehaviour, and is therefore not a component.
    Put TimeInterval inside TimeManager, and mark it serializable, and change the TimeIntervalEditor into a TimeManagerEditor
     
  4. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    Damn, you're right... I always forget it because my inspector does support it.
     
  5. djfunkey

    djfunkey

    Joined:
    Jul 16, 2012
    Posts:
    201
    So basically your saying I should do something like this?
    Code (csharp):
    1.  
    2. //TimeManager.cs
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class TimeManager : MonoBehaviour {
    7.  
    8.     [System.Serializable]
    9.     public class TimeInterval {
    10.         public int timeH;
    11.         public int timeM;
    12.         public int timeS;
    13.     }
    14.  
    15.     public TimeInterval[] timeintervals;
    16. }
    17.  
    Code (csharp):
    1.  
    2. //TimeIntervalEditor.cs
    3. using UnityEngine;
    4. using System.Collections;
    5. using UnityEditor;
    6.  
    7. [CustomEditor(typeof(TimeManager))]
    8. public class TimeManagerEditor : Editor {
    9.     public override void OnInspectorGUI() {
    10.  
    11.         DrawDefaultInspector();
    12.         TimeManager.TimeInterval myTarget = (TimeManager.TimeInterval) target;
    13.  
    14.         EditorGUILayout.BeginHorizontal();
    15.         myTarget.timeH = EditorGUI.IntField(GUILayoutUtility.GetRect(18,18), "Hour", myTarget.timeH);
    16.         myTarget.timeM = EditorGUI.IntField(GUILayoutUtility.GetRect(18,18), "Minute", myTarget.timeM);
    17.         myTarget.timeS = EditorGUI.IntField(GUILayoutUtility.GetRect(18,18), "Second", myTarget.timeS);
    18.         EditorGUILayout.EndHorizontal();
    19.     }
    20. }
    21.  
    If this is wrong, can you show me some basic coding solution to this problem, it would be greatly appreciated :)
     
  6. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Target will have to be typeof TimeManager, and then you can inspect the array target.timeIntervals, and do something like
    Code (csharp):
    1. foreach (TimeInterval ti in timeIntervals){
    2.  BeginHorzintal...
    3.   /.../
    4.   EndHorizontal
    5. }
     
  7. djfunkey

    djfunkey

    Joined:
    Jul 16, 2012
    Posts:
    201
    Unfortunately this does not solve the problem for me :confused:
    The Intfields are located outside the arrays in the editor inspector.
    This is what it looks like at the moment:
    $TimeManagerOrig.PNG
    This is how I would like the editor to look like:
    $TimeManagerEdited.PNG
    this is the code I have in place:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class TimeManager : MonoBehaviour { 
    6.        
    7.     [System.Serializable]  
    8.     public class TimeInterval {    
    9.         public int timeH;      
    10.         public int timeM;      
    11.         public int timeS;      
    12.     }
    13.  
    14.     public TimeInterval[] timeintervals;    
    15. }
    16.  
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityEditor;
    5.  
    6. [CustomEditor(typeof(TimeManager))]
    7. public class TimeManagerEditor : Editor {  
    8.     public override void OnInspectorGUI() {
    9.  
    10.         TimeManager myTarget = (TimeManager) target;   
    11.  
    12.         foreach(TimeManager.TimeInterval ti in myTarget.timeintervals) {
    13.             EditorGUILayout.BeginHorizontal();
    14.             ti.timeH = EditorGUILayout.IntField("hours", ti.timeH);
    15.             EditorGUILayout.EndHorizontal();   
    16.         }
    17.  
    18.         DrawDefaultInspector();
    19.     }  
    20. }
    21.  
     
  8. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Sorry I'm late replying.

    The problem is you are drawing the default inspector, but then trying to draw your own as well.

    Looking at the problem with fresh eyes, you're probably going to better off using property drawers, try this:

    Code (csharp):
    1.  
    2. //TimeInterval.cs
    3. using UnityEngine;
    4. [System.Serializable]
    5. public class TimeInterval {
    6.     public int timeH;
    7.     public int timeM;
    8.     public int timeS;
    9. }
    10.  
    11.  
    12.  
    13. //TimeManager.cs
    14. using UnityEngine;
    15. using System.Collections;
    16. public class TimeManager: MonoBehaviour {
    17.     public TimeInterval[] intervals;
    18. }
    19.  
    20.  
    21.  
    22. //TimeIntervalDrawer.cs (in editor directory)
    23. using UnityEngine;
    24. using UnityEditor;
    25. using System.Collections;
    26. [CustomPropertyDrawer( typeof( TimeInterval ) )]
    27. public class TimeIntervalDrawer : PropertyDrawer {
    28.     public override void OnGUI ( Rect position, SerializedProperty property, GUIContent label ) {
    29.         position = EditorGUI.IndentedRect( position );
    30.         position.width /= 3f;
    31.         int oldIndentLevel = EditorGUI.indentLevel;
    32.         EditorGUI.indentLevel = 0;
    33.         EditorGUIUtility.labelWidth = 50f;
    34.         EditorGUI.PropertyField( position, property.FindPropertyRelative( "timeH" ) );
    35.         position.x += position.width;
    36.         EditorGUI.PropertyField( position, property.FindPropertyRelative( "timeM" ) );
    37.         position.x += position.width;
    38.         EditorGUI.PropertyField( position, property.FindPropertyRelative( "timeS" ) );
    39.         EditorGUI.indentLevel = oldIndentLevel;
    40.     }
    41. }
    42.  
    43.  
    44.