Search Unity

Showing File of Serializable Class From Editor?

Discussion in 'Immediate Mode GUI (IMGUI)' started by PedroGV, May 7, 2016.

  1. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    When you create a serializable class, say ...:

    [Serializable]
    public class MyData
    {
    ...
    public float speed = 0f;
    }

    ... and you then include it as a public field in a MonoBehaviour, the editor shows the structure of MyData for any gameobject that consumes that MonoBehavior as if it where a kind of group.

    My question: is there a way to create a custom visualizer that adds a small icon next to the name that identifies the MyData structure on the editor so that when one clicks on that icon it shows on the Project Window the file containing the class that defines MyData?
     
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    That is possible. You should read about custom inspectors and property drawers.
     
  3. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    I have read them. In fact I have a few of both of my own, but, the thing is that I cannot find an operation to call that selects the file on the Project Window when the user clicks on the instance of the serializable property on the inspector.
     
  4. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    I am not sure you have a built-in callback when you select your serializable propertly.
    You can probably try and create something like that on your own by tracking the mouse events, figuring out if the user selected (clicked) inside the boundaries of your serialized property. If he did, you can use the Selection class for selecting an asset in the project window.
     
  5. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    What I did is adding a gui button on a property drawer to get selection events, however I found the following issues:

    1. You can use Selection, say, with EditorGUIUtility.PingObject to ping objects in the Hierarchy window (not in the Project Window).
    2. ProjectWindowUtil.ShowCreatedAsset only works with UnityEngine.Object classes (not System.Object).

    So, ShowCreatedAsset seems to be the way to go here, but since I'm creating a property viewer for a class that derives from System.Object (not from UnityEngine.Object) I cannot find a way to fetch a reference to the file asset.
     
  6. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    I dont think you can have afile asset for things that are not derived from UnityEngine.Object.

    Specifically, you can store only stuff derived from ScriptableObject
     
  7. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    I see that now. And still, any file ended in .cs is presented on the editor as a "script asset", so there must be a way to Ping that file on the Project Window even if the code inside does not derive from a UnityEngine.Object.
     
  8. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    You can select any object in the project window. For that you should use the Selection class.
    The Selection.activeObject property is of type UnityEngine.Object.

    What you should do is:
    1. Figure out which class you'd like to select in the project window (its name)
    2. (hacky part) find the class with the given filename. This may not always be correct!! you can define a class called A in a file called B.cs
    3. Use Selection.activeObject to select that object.
    Here is sample code that may be what you need:
    Code (CSharp):
    1. public void  SelectInProjectWindow(string className)
    2.     {
    3.         // Try to "guess" asset name based on the class name.
    4.         var asset = AssetDatabase.GetAllAssetPaths().Where(p => p.EndsWith(className + ".cs")).FirstOrDefault();
    5.  
    6.         if (asset != null)
    7.         {
    8.             Selection.activeObject = AssetDatabase.LoadAssetAtPath<MonoScript>(asset);
    9.         }
    10.     }
    There are many different cases where this can fail, because of the (hacky) step #2. For example - having multiple classes with the same name (but under different namespaces), etc.

    You cannot deduct the filename from the class name... perhaps this is enough for your needs though :)
     
    PedroGV likes this.
  9. PedroGV

    PedroGV

    Joined:
    Nov 1, 2010
    Posts:
    415
    You are a hero! That is what I was looking for since issue 2 does not apply in this case; so I can call SelectInProject(property.type). Thanks a lot!!!