public void HandleDragAndDrop()
        {
            if (DragAndDrop.objectReferences.Length == 0 || !guiRect.Contains(Event.current.mousePosition))
            {
                return;
            }

            switch (Event.current.type)
            {
            //TODO: Cache this
            case EventType.DragUpdated:
            {
                List <Texture2D> sheets  = TileDragAndDrop.GetValidSpritesheets(DragAndDrop.objectReferences);
                List <Sprite>    sprites = TileDragAndDrop.GetValidSingleSprites(DragAndDrop.objectReferences);
                List <TileBase>  tiles   = TileDragAndDrop.GetValidTiles(DragAndDrop.objectReferences);
                m_HoverData = TileDragAndDrop.CreateHoverData(sheets, sprites, tiles);

                if (m_HoverData != null && m_HoverData.Count > 0)
                {
                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                    Event.current.Use();
                    GUI.changed = true;
                }
            }
            break;

            case EventType.DragPerform:
            {
                if (m_HoverData == null || m_HoverData.Count == 0)
                {
                    return;
                }

                RegisterUndo();

                bool wasEmpty = TilemapIsEmpty(tilemap);

                Vector2Int targetPosition = mouseGridPosition;
                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                Dictionary <Vector2Int, TileBase> tileSheet = TileDragAndDrop.ConvertToTileSheet(m_HoverData);
                foreach (KeyValuePair <Vector2Int, TileBase> item in tileSheet)
                {
                    SetTile(tilemap, targetPosition + item.Key, item.Value, Color.white, Matrix4x4.identity);
                }

                OnPaletteChanged();

                m_PaletteNeedsSave = true;
                FlushHoverData();
                GUI.changed = true;
                SavePaletteIfNecessary();

                if (wasEmpty)
                {
                    ResetPreviewInstance();
                    FrameEntirePalette();
                }

                Event.current.Use();
                GUIUtility.ExitGUI();
            }
            break;

            case EventType.Repaint:
                // Handled in Render()
                break;
            }

            if (m_HoverData != null && (
                    Event.current.type == EventType.DragExited ||
                    Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape))
            {
                DragAndDrop.visualMode = DragAndDropVisualMode.None;
                FlushHoverData();
                Event.current.Use();
            }
        }
        private void DuringSceneGui(SceneView sceneView)
        {
            Event evt = Event.current;

            if (evt.type != EventType.DragUpdated && evt.type != EventType.DragPerform && evt.type != EventType.DragExited && evt.type != EventType.Repaint)
            {
                return;
            }

            Grid activeGrid = GetActiveGrid();

            if (activeGrid == null || DragAndDrop.objectReferences.Length == 0)
            {
                return;
            }

            Vector3    localMouse        = GridEditorUtility.ScreenToLocal(activeGrid.transform, evt.mousePosition);
            Vector3Int mouseGridPosition = activeGrid.LocalToCell(localMouse);

            switch (evt.type)
            {
            //TODO: Cache this
            case EventType.DragUpdated:
                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                List <TileBase> tiles = TileDragAndDrop.GetValidTiles(DragAndDrop.objectReferences);
                instance.m_HoverData = TileDragAndDrop.CreateHoverData(null, null, tiles);
                if (instance.m_HoverData.Count > 0)
                {
                    Event.current.Use();
                    GUI.changed = true;
                }
                break;

            case EventType.DragPerform:
                if (instance.m_HoverData.Count > 0)
                {
                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                    var     tileSheet = TileDragAndDrop.ConvertToTileSheet(instance.m_HoverData);
                    Tilemap tilemap   = GetOrCreateActiveTilemap();
                    tilemap.ClearAllEditorPreviewTiles();
                    int i = 0;
                    foreach (KeyValuePair <Vector2Int, TileDragAndDropHoverData> item in instance.m_HoverData)
                    {
                        Vector3Int position = new Vector3Int(mouseGridPosition.x + item.Key.x, mouseGridPosition.y + item.Key.y, 0);
                        tilemap.SetTile(position, tileSheet[i++]);
                        tilemap.SetTransformMatrix(position, Matrix4x4.TRS(item.Value.positionOffset - tilemap.tileAnchor, Quaternion.identity, Vector3.one));
                    }
                    instance.m_HoverData = null;
                    GUI.changed          = true;
                    Event.current.Use();
                }
                break;

            case EventType.Repaint:
                if (instance.m_HoverData != null)
                {
                    Tilemap map = Selection.activeGameObject.GetComponentInParent <Tilemap>();

                    if (map != null)
                    {
                        map.ClearAllEditorPreviewTiles();
                    }

                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                    foreach (KeyValuePair <Vector2Int, TileDragAndDropHoverData> item in instance.m_HoverData)
                    {
                        Vector3Int gridPos = mouseGridPosition + new Vector3Int(item.Key.x, item.Key.y, 0);
                        if (item.Value.hoverObject is TileBase)
                        {
                            TileBase tile = item.Value.hoverObject as TileBase;
                            if (map != null)
                            {
                                map.SetEditorPreviewTile(gridPos, tile);
                            }
                        }
                    }
                }
                break;
            }

            if (instance.m_HoverData != null && (
                    Event.current.type == EventType.DragExited ||
                    Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape))
            {
                if (instance.m_HoverData.Count > 0)
                {
                    Tilemap map = Selection.activeGameObject.GetComponentInParent <Tilemap>();
                    if (map != null)
                    {
                        map.ClearAllEditorPreviewTiles();
                    }

                    Event.current.Use();
                }

                instance.m_HoverData = null;
            }
        }
        public void HandleDragAndDrop()
        {
            if (DragAndDrop.objectReferences.Length == 0 || !guiRect.Contains(Event.current.mousePosition))
            {
                return;
            }

            switch (Event.current.type)
            {
            //TODO: Cache this
            case EventType.DragUpdated:
            {
                List <Texture2D> sheets  = TileDragAndDrop.GetValidSpritesheets(DragAndDrop.objectReferences);
                List <Sprite>    sprites = TileDragAndDrop.GetValidSingleSprites(DragAndDrop.objectReferences);
                List <TileBase>  tiles   = TileDragAndDrop.GetValidTiles(DragAndDrop.objectReferences);
                m_HoverData = TileDragAndDrop.CreateHoverData(sheets, sprites, tiles, tilemap.cellLayout);

                if (m_HoverData != null && m_HoverData.Count > 0)
                {
                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                    Event.current.Use();
                    GUI.changed = true;
                }
            }
            break;

            case EventType.DragPerform:
            {
                if (m_HoverData == null || m_HoverData.Count == 0)
                {
                    return;
                }

                RegisterUndo();

                bool wasEmpty = TilemapIsEmpty(tilemap);

                Vector2Int targetPosition = mouseGridPosition;
                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                var tileSheet = TileDragAndDrop.ConvertToTileSheet(m_HoverData);
                int i         = 0;
                foreach (KeyValuePair <Vector2Int, TileDragAndDropHoverData> item in m_HoverData)
                {
                    if (i >= tileSheet.Count)
                    {
                        break;
                    }

                    var offset = Vector3.zero;
                    if (item.Value.hasOffset)
                    {
                        offset = item.Value.positionOffset - tilemap.tileAnchor;

                        var cellSize = tilemap.cellSize;
                        if (wasEmpty)
                        {
                            cellSize = item.Value.scaleFactor;
                        }
                        offset.x *= cellSize.x;
                        offset.y *= cellSize.y;
                        offset.z *= cellSize.z;
                    }

                    SetTile(tilemap
                            , targetPosition + item.Key
                            , tileSheet[i++]
                            , Color.white
                            , Matrix4x4.TRS(offset, Quaternion.identity, Vector3.one));
                }
                OnPaletteChanged();

                m_PaletteNeedsSave = true;
                FlushHoverData();
                GUI.changed = true;
                SavePaletteIfNecessary();

                if (wasEmpty)
                {
                    ResetPreviewInstance();
                    FrameEntirePalette();
                }

                Event.current.Use();
                GUIUtility.ExitGUI();
            }
            break;

            case EventType.Repaint:
                // Handled in Render()
                break;
            }

            if (m_HoverData != null && (
                    Event.current.type == EventType.DragExited ||
                    Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape))
            {
                DragAndDrop.visualMode = DragAndDropVisualMode.None;
                FlushHoverData();
                Event.current.Use();
            }
        }