How do I draw lines in a custom inspector?

I have a custom inspector, and I wish to draw lines, in order to provide some graphing functionality.

I have looked everywhere for a reliable answer, but I can not find anything for the actual inspector. I can create a new editor window to draw in, and I can draw to the actual scene view, but for my desired result I need to specifically draw in the inspector.

It was suggested that I directly call OpenGL commands, but that does not work, either. It is entirely possible that my problem is actually in deriving the correct screen position of which to draw to, but again, I am not entirely sure how I would do that. As is, my attempts to draw have come up with nothing.

alt text

How do I draw lines in a custom inspector?

Here’s an example how to setup a proper GL viewport inside a custom inspector:

edit
I just did some additional tests and it seems it’s a bit too difficult to setup a custom viewport inside the inspector as it would require detailed information about the InspectorWindow itself. That’s because the rendering context generally has it’s origin at the bottom left. To calculate the correct top left corner you need to know the overall height of the Inspector window.

I’ve created a more concrete example that will draw a framerate diagram in the inspector at runtime without setting a custom viewport, but just using the default GUI viewport and current matrix setup. This solves all coordinate problems but you have to take care about where you draw. You can easily draw anywhere inside the inspector window.

Material mat;
private void OnEnable()
{
    var shader = Shader.Find("Hidden/Internal-Colored");
    mat = new Material(shader);
}
private void OnDisable()
{
    DestroyImmediate(mat);
}

public override void OnInspectorGUI()
{
    DrawDefaultInspector();
    Rect rect = GUILayoutUtility.GetRect(10, 1000, 200, 200);
    if (Event.current.type == EventType.Repaint)
    {
        GUI.BeginClip(rect);
        GL.PushMatrix();
        GL.Clear(true, false, Color.black);
        mat.SetPass(0);
        
        GL.Begin(GL.LINES);
        GL.Color(Color.black);
        GL.Vertex3(0, 0, 0);
        GL.Vertex3(100, 100, 0);
        GL.End();
        GUI.EndClip();
    }
}

Here’s the [95252-inspectordrawlinesexample.zip|95252]. The result looks like this:
95253-inspectorlinedrawing.png

To explain some parts of that code snippet:

  • GUILayoutUtility.GetRect(10,10000,200,200) reserves a layout rectangle inside the custom inspector. The width is automatically adapted to the enclosing layout group (minwidth 10 and maxwidth 10000). The height is forced to 200 pixel.

  • GUI.BeginClip(rect) starts a new clipping area with the rect we just created. That makes all GUI coordinates relative to that area

  • GL.Clear will clear the whole viewport. In my example i only clear the depth buffer. Note that GL.Clear will clear the whole Viewport which is in case of a custom inspector the whole Inspector window. So clearing with a color shouldn’t be used.

  • mat.SetPass(0) it is important to enable a shader pass before you do any rendering. Otherwise Unity would use whatever shader was previously active and that could be quite random.

Some additional notes:

  • GUILayoutUtility.GetRect must be called outside of the EventType check. It’s important that this is executed for the Layout and Repaint event.
  • Any direct drawing has to be restricted to the Repaint event.
  • If you don’t use an orthographic projection you have to watch your z position.

Maybe I’m just lucky, but this works to me in Unity 2021.1.19 like a charm without any low-level GL instructions:

...
GUI.BeginClip(rect);
Handles.color = Color.red;
Handles.DrawAAPolyLine(Texture2D.whiteTexture, lineWidth, point1, point2, point3, ...);
GUI.EndClip();
...

_

I appreciate any feedback if this works for anybody else too, thank you.