Search Unity

Docking Editor Windows Side By Side Via Script

Discussion in 'Scripting' started by DanielleOlson, Jul 19, 2013.

  1. DanielleOlson

    DanielleOlson

    Joined:
    Jul 19, 2013
    Posts:
    1
    Problem
    I've been pursuing the ability to fully customize editor tools for a while now, including being able to set up panels in a consistent way for all of the artists who use the tool. Currently the best I can do is have our multi-panel tools pop up with all the tabs stacked in a single window. It's not hard to just drag the tab to dock on the right side, but many artists and designers miss that the tab is even there, and then miss important functionality of the tool. On opening the tool, that solution looks like this:

    $StackedTabs.JPG


    Desired Outcome
    Since my goal is to help all of our content creators (I'm working on a large team of about 60) have a consistent interface with our custom data, the ability to format these panels is very important to me. My goal is for the tool to pop up with the panels already laid out, something like this:

    $FormattedTabs.JPG


    Misconceptions
    I've looked around a lot for other resources on this idea. The problem is very often confused for just opening a tab in the same window (like my first image):
    http://forum.unity3d.com/threads/122554-Docking-Window
    Or being done by hand:
    http://answers.unity3d.com/questions/16554/docking-editorwindow.html
    Some suggest saving an entire layout, which isn't an acceptable solution for me (artists and designers will often have their own custom layouts, and forcing them to alter this would make them less likely to use the tool as designed)
    http://answers.unity3d.com/questions/267097/editor-programming-experts-regarding-layouts.html


    It's Possible!
    This video shows exactly what I'm trying to accomplish:
    http://www.youtube.com/watch?v=-rSnaJ6Felg
    And the guy's forum name is Tertle!
    http://forum.unity3d.com/threads/186260-Tiler-tile-map-editor
    From the above thread, it seems very likely that reflection was used to achieve docking through script. Hey Tertle, if you happen upon this thread could you lend some insight as to how you got your docking to work, and if you ever overcame the problem your method was having on Macs?


    Conclusion
    Based on the evidence of my own trial and error and the findings above, I've come to the unfortunate conclusion that reflection is the only way to achieve custom window docking :( This means our tools will be subject to instability at new Unity releases, and just the development of the functionality itself will be a pain. My current plan of attack is to set up an overlay system for accessing the following internal classes:

    -ContainerWindow
    -SplitView
    -DockArea

    And trying to use the SplitView.PerformDrop method to get my EditorWindows where I want them to be. Again, not terribly happy about this, would love to do it some other way.


    Ideas?
    If anyone has tried this, successfully or unsuccessfully, it would be great to hear about your experiences. And if anyone from Unity has some input on the likelihood of this becoming a supported feature, that would be awesome too! I will provide updates on my progress, if I make any.

    //Danielle
     
  2. spolglase

    spolglase

    Joined:
    Jan 13, 2011
    Posts:
    14
    Did you ever figure this out. I'm running into the same problem. Did you ever figure out a solution using reflection?
     
  3. spolglase

    spolglase

    Joined:
    Jan 13, 2011
    Posts:
    14
    I've made some headway on this problem. However now I'm getting an exception on the PerformDrop call. Here's the message I sent to Tertle:

     
  4. spolglase

    spolglase

    Joined:
    Jan 13, 2011
    Posts:
    14
    I finally got it working. There were two important steps I was missing.

    The first was converting my Event.current.mousePosition Vector2 to a screen point using GUIUtility.GUIToScreenPoint().

    The second step I was missing was setting the s_OriginalDragSource static member of DockArea to be my child EditorWindow's DockArea. This is necessary because within the PerformDrop() call it needs to remove the child EditorWindow from the old DockArea and it will throw a null ref if it isn't properly set.

    You can see the new non-reflection code below:


    Code (csharp):
    1. public static void DockEditorWindow(Vector2 mousePos, EditorWindow parent, EditorWindow child)
    2. {
    3.      Vector2 screenPoint = GUIUtility.GUIToScreenPoint(mousePos);
    4.      DockArea area = parent.m_Parent as DockArea;
    5.      SplitView sv = area.m_parent as SplitView;
    6.      DropInfo di = sv.DragOver(child, screenPoint);
    7.      DockArea.s_OriginalDragSource = child.m_Parent;
    8.      sv.PerformDrop(child, di, screenPoint);
    9. }

    Also on a separate note this code works as of Unity 4.1.3. It's always possible that they change the internals of how this stuff works in later versions of Unity.
     
    Last edited: Dec 3, 2013
    Eldoir and Novack like this.
  5. Thundernerd

    Thundernerd

    Joined:
    Jan 24, 2014
    Posts:
    20
    Thanks so much for this. I was looking for a way to make this work but I couldn't figure out how. This was the only thread that had some sensible information. Had to do some reflection but I finally got it to work!

    And this is how I fixed it: https://gist.github.com/Thundernerd/5085ec29819b2960f5ff2ee32ad57cbb
     
    Last edited: Mar 16, 2017