Search Unity

CustomEditor - Draw Preview Window for a selected object in List?

Discussion in 'Immediate Mode GUI (IMGUI)' started by RoyalCoder, Feb 10, 2018.

  1. RoyalCoder

    RoyalCoder

    Joined:
    Oct 4, 2013
    Posts:
    301
    Hi friends,

    I'm trying to create/draw a Preview Window for a object listed in a custom List Class, e.g:

    ExampleLists class:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ExampleLists : MonoBehaviour {
    6.  
    7.     [System.Serializable]
    8.     public class ExampleClass{
    9.  
    10.         public string itemName;
    11.         public GameObject itemPrefab;
    12.     }
    13.  
    14.     public List<ExampleClass> exampleClassList = new List<ExampleClass>();
    15.  
    16. }
    17.  

    CustomEditor class:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6. [CustomEditor(typeof(ExampleLists))]
    7. public class TestEditorPreview : Editor {
    8.  
    9.     ExampleLists exampleLists;
    10.  
    11.  
    12.     public override void OnInspectorGUI()
    13.     {
    14.         serializedObject.Update();
    15.  
    16.         exampleLists = (ExampleLists)target;
    17.         //base.OnInspectorGUI();
    18.  
    19.         EditorGUILayout.PropertyField(serializedObject.FindProperty("exampleClassList"), new GUIContent("Examples Lists", "List of clasess."), true);
    20.  
    21.         serializedObject.ApplyModifiedProperties();
    22.     }
    23.  
    24. }
    25.  

    Screenshot images:


     
  2. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    1,188
    I've struggled with this myself. I'm sorry, I don't have the answer, but here are some thoughts: Drawing to the preview panel is trivial, it's also possible to get an object preview from a helper class and render it there. The problem is getting the currently selected object from the list.

    I've looked around and found that EditorGUIUtility.keyboardControl is updated when the selection of list elements changes. ControlIDs are only valid during the current GUI call, but they might be enough to identify the selected item. I don't know if it's possible to get an object by specifying the id, but potentially there is some way to search through the SerializedObject and request a controlID for every property and sub-property and then compare each value against the keyboardControl. Sounds like bad performance, but should theoretically work. So the theory is: Unity draws all fields and gives them an id. After that, you iterate through everything manually and request an id for each control (if you draw the control yourself, you already know the name/label and can use it as a hint. Finally, since the ids should be recreated deterministically (within one GUI call) you can check which property was the selected one. If you draw the controls yourself, this should work, if not, I'm unsure about retrieving the IDs.
     
    RoyalCoder likes this.
  3. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    I think you could find what you are looking for here.

    Enjoy :)
     
    RoyalCoder likes this.
  4. BinaryCats

    BinaryCats

    Joined:
    Feb 8, 2016
    Posts:
    317
    I literally made this the otherday haha. its much simpler than that post.

    Code (csharp):
    1.  
    2.     [UnityEditor.CustomEditor(typeof(BaseItemDataContainer), true)]
    3.     public class MyScriptEditor : UnityEditor.Editor
    4.     {
    5.         public override bool HasPreviewGUI() { return true; }
    6.         private PreviewRenderUtility _previewRenderUtility;
    7.         Editor gameObjectEditor;
    8.    
    9.         public override void OnPreviewGUI(Rect r, GUIStyle background)
    10.         {
    11.             GameObject obj = (target as BaseItemDataContainer).m_Item != null ? (target as BaseItemDataContainer).m_Item.gameObject : (target as BaseItemDataContainer).m_ItemGameObject;
    12.             if (obj)
    13.             {
    14.                 if (gameObjectEditor == null)
    15.                     gameObjectEditor = Editor.CreateEditor(obj);
    16.                 gameObjectEditor.OnPreviewGUI(r, background);
    17.             }
    18.      
    19.         }
    20.     }
    21.  
    obviously you will need to change BaseItemDataContainer to ExampleLists, and handle the preview object (obj) yourself
     
    RoyalCoder likes this.
  5. whileBreak

    whileBreak

    Joined:
    Aug 28, 2014
    Posts:
    289
    You need to use EditorGUI.DrawPreviewTexture(), I dont know if it works with EditorGUILayout

    Oh, also you can try my asset Voltage for editor UI. VoltageThumbnail does what you need. Sorry to promote, but it can help and is free. If you decide to try it, i'll be on the forums answering questions.
     
    RoyalCoder likes this.
  6. RoyalCoder

    RoyalCoder

    Joined:
    Oct 4, 2013
    Posts:
    301
    Hi @BinaryCats ,

    I tried what you suggest, it's working, but in a weird mode :D ...The object is rendered only if it's in the scene and active and it's a child of the object with attached script and also referenced in the reorderable list, script:

    Code (CSharp):
    1.     public override void OnPreviewGUI(Rect r, GUIStyle background)
    2.     {
    3.        
    4.         GameObject obj = (target as MyBaseItemDataContainer).MyCustomClass[0].prefabRef!= null ? (target as MyBaseItemDataContainer).MyCustomClass[0].prefabRef.gameObject : (target as MyBaseItemDataContainer).MyCustomClass[0].prefabRef;
    5.         if (obj)
    6.         {
    7.             if (gameObjectEditor == null)
    8.                 gameObjectEditor = CreateEditor(obj);
    9.                 gameObjectEditor.OnPreviewGUI(r, background);
    10.         }
    Any idea why ;)? Thanks!

    @whileBreak ,

    Thanks you very much, I will give'it a try!