Search Unity

Is it possible to open ScriptableObjects in custom editor cindows with double click?

Discussion in 'Editor & General Support' started by M1st3rButt3r, Oct 22, 2020.

  1. M1st3rButt3r

    M1st3rButt3r

    Joined:
    Oct 22, 2020
    Posts:
    11
    Hey,
    I have a Question currently I am working on a custom Editor and I know how to load a file over an "Open File" Button but is there a way to open a ScriptableObject with a double click and then show the window?

    Thanks for answers!
    Bennet
     
  2. StaggartCreations

    StaggartCreations

    Joined:
    Feb 18, 2015
    Posts:
    2,266
    You can use the OnOpenAsset attribute for this, a little hidden gem

    Code (CSharp):
    1. [OnOpenAsset]
    2. //Handles opening the editor window when double-clicking project files
    3. public static bool OnOpenAsset(int instanceID, int line)
    4. {
    5.     DruidProject project = EditorUtility.InstanceIDToObject(instanceID) as DruidProject;
    6.     if (project != null)
    7.     {
    8.         DruidEditorWindow.OpenProjectFile(project);
    9.         return true;
    10.     }
    11.     return false;
    12. }
    Code (CSharp):
    1. //Handles correct behaviour when double-clicking a .watermesh asset assigned to a field
    2. [OnOpenAsset]
    3. public static bool OnOpenAsset(int instanceID, int line)
    4. {
    5.     Object target = EditorUtility.InstanceIDToObject(instanceID);
    6.  
    7.     if (target is Mesh)
    8.     {
    9.         var path = AssetDatabase.GetAssetPath(instanceID);
    10.    
    11.         if (Path.GetExtension(path) != ".watermesh") return false;
    12.  
    13.         Selection.activeObject = target;
    14.         return true;
    15.     }
    16.  
    17.     return false;
    18. }
     
    Last edited: May 27, 2022
  3. M1st3rButt3r

    M1st3rButt3r

    Joined:
    Oct 22, 2020
    Posts:
    11
    Thanks
     
  4. felipemullen

    felipemullen

    Joined:
    Mar 4, 2017
    Posts:
    44
    In case anyone needs an example of this, here is how it worked for me in an existing serializableObject class that I made an editorWindow for.

    (this is in 2022.0.b13)

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEditor.Callbacks;
    3. using UnityEngine;
    4.  
    5. public class GameStateFlow : ScriptableObject
    6. {
    7.     public GameStateNodeData[] NodeData;
    8.  
    9.     [OnOpenAssetAttribute(1)]
    10.     public static bool OpenGameStateWindow(int instanceID, int line)
    11.     {
    12.         bool windowIsOpen = EditorWindow.HasOpenInstances<GameStateGraphWindow>();
    13.         if (!windowIsOpen)
    14.         {
    15.             EditorWindow.CreateWindow<GameStateGraphWindow>();
    16.         }
    17.         else
    18.         {
    19.             EditorWindow.FocusWindowIfItsOpen<GameStateGraphWindow>();
    20.         }
    21.  
    22.         // Window should now be open, proceed to next step to open file
    23.         return false;
    24.     }
    25.  
    26.     [OnOpenAssetAttribute(2)]
    27.     public static bool OpenGameStateFlow(int instanceID, int line)
    28.     {
    29.         var window = EditorWindow.GetWindow<GameStateGraphWindow>();
    30.  
    31.         string assetPath = AssetDatabase.GetAssetPath(instanceID);
    32.         window.LoadFromFile(assetPath);
    33.  
    34.         return true;
    35.     }
    36. }
     
    Andz4R, tjumma and TreyH like this.
  5. cielbird

    cielbird

    Joined:
    Dec 15, 2017
    Posts:
    11
    I'm using my scriptable object in my game, so I can't have it in the Editor folder. This means I can't reference my EditorWindow class from my scriptable object. Does anyone have a solution for this?
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,935
    I don't think anyone said your scriptable object had to be in an editor folder.

    Just put your Editor window in an editor folder, and give it a static method that's decorated with the
    [OnOpenAsset]
    attribute, and keep all your editor code outside your runtime scriptable object.
     
    Fep310 and tjumma like this.
  7. Andz4R

    Andz4R

    Joined:
    Oct 26, 2016
    Posts:
    1
    Solved my problem! Thank you.

    I have a custom GraphViewEditorWindow and an associated Graph-ScriptableObject to store nodes, node data and edges. I was also looking for a way to open / focus the GraphViewEditorWindow upon double clicking any Graph-ScriptableObject and load its data.

    I changed the code a little bit because it seemed redundant to handle the double click callback in two seperate steps.

    Code (CSharp):
    1.     [OnOpenAssetAttribute]
    2.     public static bool OpenGraphAsset(int instanceID, int line)
    3.     {
    4. // This gets called whenever ANY asset is double clicked
    5. // So we gotta check if the asset is of the proper type
    6.         UnityEngine.Object asset = EditorUtility.InstanceIDToObject(instanceID);
    7.         if (!(asset is Graph)) return false;
    8.  
    9.         bool windowIsOpen = EditorWindow.HasOpenInstances<GraphEditorWindow>();
    10.         if (!windowIsOpen) EditorWindow.CreateWindow<GraphEditorWindow>();
    11.         else EditorWindow.FocusWindowIfItsOpen<GraphEditorWindow>();
    12.  
    13.         GraphEditorWindow window = EditorWindow.GetWindow<GraphEditorWindow>();
    14.         string assetPath = AssetDatabase.GetAssetPath(instanceID);
    15.         string fileName = System.IO.Path.GetFileNameWithoutExtension(assetPath);
    16.         window.LoadGraphAssetViaFileName(fileName);
    17.  
    18.         return true;
    19.     }
     
    Last edited: Nov 27, 2023
  8. Fly81

    Fly81

    Joined:
    Oct 6, 2021
    Posts:
    34
    The ScriptingReference page for OnOpenAssetAttribute has been removed from the documentation in versions higher than 2020.3.
    Is there a reason for this, are we not supposed to use it anymore? Did it get deprecated?
     
  9. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,935
    Not sure! I opened up a project in 2023.2 and the attribute is still present and works as expected.

    I just submitted a problem to documentation page. Otherwise, at a glance, I couldn't find anything else that was meant to be a substitute.
     
    Fly81 likes this.