Search Unity

Drag and Drop Custom Asset to Heirarchy

Discussion in 'Immediate Mode GUI (IMGUI)' started by exodrifter, Dec 12, 2014.

  1. exodrifter

    exodrifter

    Joined:
    Mar 17, 2013
    Posts:
    10
    I'm trying to figure out how to allow the user to drag and drop a custom asset into the hierarchy, like it would be for an AudioClip.

    So far, I have the following code in my custom inspector:
    Code (CSharp):
    1. [CustomEditor(typeof(RenPyScriptAsset))]
    2. [InitializeOnLoad]
    3. public class RenPyScriptAssetEditor : UnityEditor.Editor
    4. {
    5.     static RenPyScriptAssetEditor()
    6.     {
    7.         // Adds a callback for when the hierarchy window processes GUI events
    8.         // for every GameObject in the heirarchy.
    9.         EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemCallback;
    10.     }
    11.  
    12.     private static void HierarchyWindowItemCallback(int pID, Rect pRect)
    13.     {
    14.         if (Event.current.type == EventType.DragExited) {
    15.             // get all the drag and drop information ready for processing.
    16.             DragAndDrop.AcceptDrag();
    17.  
    18.             // used to emulate selection of new objects.
    19.             var selectedObjects = new List<GameObject>();
    20.  
    21.             // run through each object that was dragged in.
    22.             foreach (var objectRef in DragAndDrop.objectReferences) {
    23.                 // if the object is the particular asset type...
    24.                 if (objectRef is RenPyScriptAsset) {
    25.                     // we create a new GameObject using the asset's name.
    26.                     var gameObject = new GameObject(objectRef.name);
    27.  
    28.                     // we attach component X, associated with asset X.
    29.                     var display = gameObject.AddComponent<RenPyDisplay>();
    30.  
    31.                     // we place asset X within component X.
    32.                     display.Script = objectRef as RenPyScriptAsset;
    33.  
    34.                     // add to the list of selected objects.
    35.                     selectedObjects.Add(gameObject);
    36.                 }
    37.             }
    38.  
    39.             // we didn't drag any assets of type AssetX, so do nothing.
    40.             if (selectedObjects.Count == 0) return;
    41.  
    42.             // emulate selection of newly created objects.
    43.             Selection.objects = selectedObjects.ToArray();
    44.  
    45.             // make sure this call is the only one that processes the event.
    46.             Event.current.Use();
    47.         }
    48.     }
    49.     ...
    50. }
    This example stole a lot of code from this StackOverflow question. Unfortunately, while this does work, it doesn't work exactly the same way. Using this method doesn't show the correct cursor when I hover over the heirarchy window. Instead, it shows the cursor that tells me I can't do the operation. It also fails to select the GameObjects in the hierarchy that have been created and it adds GameObjects at the wrong time (It does it when the drag exits).

    What do I do to make this work like any other supported asset (Sprites, AudioClips, Prefabs, etc) when you drag it to the hierarchy?
     
    Last edited: Dec 12, 2014
  2. Tran-Ngoc-Tam

    Tran-Ngoc-Tam

    Joined:
    Jul 26, 2016
    Posts:
    182
    Sorry for the very late answer, but I found the solution for the wrong cursor today, just catch another DragUpdated event and change DragAndDrop.visualMode to appropriated value. Here is an example code:
    Code (CSharp):
    1. private static void OnHierarchyGUI(int instanceID, Rect r)
    2.         {
    3.             if (Event.current.type == EventType.DragUpdated ||
    4.                 Event.current.type == EventType.DragExited)
    5.             {
    6.                 DragAndDrop.AcceptDrag();
    7.                 Object[] draggedObjects = DragAndDrop.objectReferences;
    8.                 if (draggedObjects != null &&
    9.                     draggedObjects.Length == 1)
    10.                 {
    11.                     if (draggedObjects[0] is LPTData)
    12.                     {
    13.                         if (Event.current.type == EventType.DragUpdated)
    14.                         {
    15.                             DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
    16.                         }
    17.                         else if (Event.current.type == EventType.DragExited)
    18.                         {
    19.                             LPTData data = draggedObjects[0] as LPTData;
    20.                             GameObject terrain = CreateGameObjectUtilities.CreateAdvancedTerrainWithExistingData(data);
    21.                             Selection.activeGameObject = terrain;
    22.                         }
    23.                         Event.current.Use();
    24.                     }
    25.                 }
    26.             }
    27.         }