Editor drag&drop override

Hi, I'm trying to override the default drag&drop behavior of assets from the project pane into the scene view, so that I can snap them to a grid while they are being dragged. Think of it as drag&dropping prefab tiles unto a grid in a tile-based level editor.

I've written a CustomEditor which intercepts the Drag events in the scene view, something like this (C#) :

void OnSceneGUI()
{
    if (Event.current.type == EventType.DragUpdated)
    {
        foreach (Object obj in DragAndDrop.objectReferences)
        {
            GameObject go = (GameObject)obj;
            go.transform.position = myGrid.SnapToNearestTileCenter(go.transform.position);
        }
    }
}

This does get called with a valid dragged object, but the transform position change is not propagated to the scene view, nor is it when the drag is released. Any idea on how to achieve that?

Thanks!

Answering my own question: this seems to work fine.

private GameObject draggedObj;
void OnSceneGUI()
{
    if (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform)
    {
        DragAndDrop.visualMode = DragAndDropVisualMode.Copy; // show a drag-add icon on the mouse cursor

        if (draggedObj == null)
            draggedObj = (GameObject)Object.Instantiate(DragAndDrop.objectReferences[0]);

        // compute mouse position on the world y=0 plane
        Ray mouseRay = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y, 0.0f));
        if (mouseRay.direction.y < 0.0f)
        {
            float t = -mouseRay.origin.y / mouseRay.direction.y;
            Vector3 mouseWorldPos = mouseRay.origin + t * mouseRay.direction;
            mouseWorldPos.y = 0.0f;

            draggedObj.transform.position = terrain.SnapToNearestTileCenter(mouseWorldPos);
        }

        if (Event.current.type == EventType.DragPerform)
        {
            DragAndDrop.AcceptDrag();
            draggedObj = null;
        }

        Event.current.Use();
    }
}

The idea is that the Event.current.Use() intercepts the drag so that the scene view doesn't do anything on its own. Instead, I instantiate a dragged object myself, which I can place as I like during the DragUpdated events.

Probably not overly clean, so if you've got better ideas / suggestions don't hesitate.