Drawing to the scene from an EditorWindow

I'm getting my feed wet with extending the Unity tools. Long story short I want to make a custom grid that I can use to snap specific objects. Right now I'm trying to make a window that shows you the grid that you can define. My issue here is that this the line drawing doesn't seem to update in a window very well.

If I toggle it on or off... doesn't update. If it's on and I select a viewport, it draw, but If I change a number, it does not update. If I change a number and select a viewport, it now draws the previous iteration as well as the last one.

I'm not even sure if I'm using the correct draw functions here. drawing gizmos didn't seem to work. As well, I got a memory leak error from this. So, any suggestions as to a better method or a way to force a draw update in the viewports.

Here is the code I have so far.

class TileWindow extends EditorWindow
{
    var showGrid:boolean=false;
    var xTiles:int=24;
    var zTiles:int=24;
    var tileSize:float=1;
    var xOffset:float=0;
    var zOffset:float=0;
    var topLeft:Vector3;
    var topRight:Vector3;
    var botLeft:Vector3;
    var botRight:Vector3;

    @MenuItem ("Window/Tile View")
    static function ShowWindow () {
        EditorWindow.GetWindow (TileWindow);
    }

    function OnGUI () {
        showGrid=EditorGUILayout.Toggle("Grid View",showGrid);
        tileSize=EditorGUILayout.FloatField("Tile Size",tileSize);
        xTiles=EditorGUILayout.FloatField("X Tiles",xTiles);
        zTiles=EditorGUILayout.FloatField("Z Tiles",zTiles);
    }

    function OnInspectorUpdate () {
        xOffset=-(xTiles*tileSize)/2;
        zOffset=-(zTiles*tileSize)/2;

        if (showGrid){
            for (i=0;i<xTiles;i++){
                for (j=0;j<zTiles;j++){
                    topLeft= Vector3(xOffset+(tileSize*i),0,zOffset+(tileSize*j));
                    topRight=Vector3(xOffset+(tileSize*i+tileSize),0,zOffset+(tileSize*j));
                    botLeft= Vector3(xOffset+(tileSize*i),0,zOffset+(tileSize*j+tileSize));
                    botRight=Vector3(xOffset+(tileSize*i+tileSize),0,zOffset+(tileSize*j+tileSize));
                    Debug.DrawLine(topLeft,topRight,Color.red);
                    Debug.DrawLine(botLeft,botRight,Color.red);
                    Debug.DrawLine(topLeft,botLeft,Color.red);
                    Debug.DrawLine(topRight,botRight,Color.red);

                }
            }
        }
    }
}

Oliver’s answer is not entirely correct but is the correct approach. This is how I solved this problem:

// Window has been selected
void OnFocus()
{
	// Remove delegate listener if it has previously
	// been assigned.
	SceneView.onSceneGUIDelegate -= this.OnSceneGUI;

	// Add (or re-add) the delegate.
	SceneView.onSceneGUIDelegate += this.OnSceneGUI;
}
  
void OnDestroy()
{
	// When the window is destroyed, remove the delegate
	// so that it will no longer do any drawing.
	SceneView.onSceneGUIDelegate -= this.OnSceneGUI;
}
  
void OnSceneGUI(SceneView sceneView)
{
	// Do your drawing here using Handles.

	Handles.BeginGUI();
	// Do your drawing here using GUI.
	Handles.EndGUI();    
}

Once you have registered your OnSceneGUI method as a delegate listener to the onSceneGuiDelegate event in SceneView, it will be called whenever the editor draws the scene (so once for each window).

This will continue after the window is destroyed, so it must be release in OnDestroy.

The strange part is how the delegate is released and then register in OnFocus. Unfortunately EditorWindow has no Awake/Start type event. OnFocus is as a next-best. OnFocus can be called multiple times during a Window’s lifetime, and the delegate should not be registered more than once. There is no way to check whether the delegate has already been registered, but removing it first will solve this.

Here’s a more compact version using OnEnable/OnDisable instead, which is more reliable

void OnEnable () { SceneView.onSceneGUIDelegate += this.OnSceneGUI; }
void OnDisable () { SceneView.onSceneGUIDelegate -= this.OnSceneGUI; }
void OnSceneGUI ( SceneView sceneView )
{
    Handles.BeginGUI();
    // GUI Code here
    Handles.EndGUI();
}

SceneView.onSceneGUIDelegate is deprecated now. You should use SceneView.duringSceneGui instead.

I used the Delegate function of SceneView to manage this.
C# Code (should work in JavaScript…):

//Inside OnGUI or Update, does not make any difference.
if(SceneView.onSceneGUIDelegate != this.OnSceneGUI)
{
    SceneView.onSceneGUIDelegate += this.OnSceneGUI;
}

When you insert this you can have a simple OnSceneGUI() function in you EditorWindow class. BUT: The OnSceneGUI function has to have one parameter of the type SceneView. Like so:

public void OnSceneGUI (SceneView scnView)
{
	Handles.Button (new Vector3 (500.0f, 0, 500.0f), Quaternion.LookRotation (Vector3.up), 500.0f, 0.0f, Handles.RectangleCap);
}

The SceneView passed each call is the SceneView that is currently drawing, so you can draw different GUIs for each SceneView.

As you See, you can even use the Handles’ functions. If you intend to use regular GUI functions you first have to start a GUI Block with the corresponding Handle functions BeginGUI and EndGUI.

Well, the editor works a bit different than the game runtime. The GUI and the sceneview is only drawn if it's needed. Every EditorWindow have a Repaint function. The SceneView is also derived from EditorWindow. The SceneView class is not documented yet, but if you use visual studio (c#) you can view all members.

Just in case that you can't find it:

SceneView.lastActiveSceneView.Repaint();