public override void MouseUp(MouseEventArgs e)
 {
     base.MouseUp(e);
     if (e.LeftButton != e.OldLeftButton)
     {
         if (!Editor.CanUndo)
         {
             Editor.CanUndo = true;
             TileGroupUndoAction.GetLatest().Ready = true;
         }
     }
     if (!e.LeftButton && !e.RightButton)
     {
         OriginPoint = null;
     }
 }
        public void DrawTiles(int oldx, int oldy, int newx, int newy, int layer)
        {
            MapViewerTiles MapViewer = this.MapViewer as MapViewerTiles;

            // Avoid drawing a line from top left to current tile
            if (oldx == -1 || oldy == -1)
            {
                oldx = newx;
                oldy = newy;
            }
            Point        Origin     = MapViewer.OriginPoint;
            bool         blanktile  = Editor.MainWindow.MapWidget.MapViewerTiles.TilesPanel.EraserButton.Selected;
            bool         point      = oldx == newx && oldy == newy;
            bool         line       = !point;
            List <Point> TempCoords = new List <Point>();

            if (Editor.MainWindow.MapWidget.MapViewerTiles.TilesPanel.FillButton.Selected)
            {
                int sx, sy, ex, ey;
                if (MapViewer.SelectionX != -1 && MapViewer.SelectionY != -1 && MapViewer.SelectionWidth != 0 && MapViewer.SelectionHeight != 0 && MapViewer.SelectionBackground.Visible)
                {
                    int mx = (int)Math.Floor(newx / 32d);
                    int my = (int)Math.Floor(newy / 32d);
                    sx = MapViewer.SelectionX;
                    ex = MapViewer.SelectionX + MapViewer.SelectionWidth;
                    sy = MapViewer.SelectionY;
                    ey = MapViewer.SelectionY + MapViewer.SelectionHeight;
                    if (!(mx >= sx && mx < ex && my >= sy && my < ey))
                    {
                        return;                                                // Outside selection
                    }
                }
                else
                {
                    sx = 0;
                    sy = 0;
                    ex = MapData.Width;
                    ey = MapData.Height;
                }
                for (int y = sy; y < ey; y++)
                {
                    for (int x = sx; x < ex; x++)
                    {
                        TempCoords.Add(new Point(x, y));
                    }
                }
            }
            else if (line) // Draw tiles between several tiles - use simple line drawing algorithm to determine the tiles to draw on
            {
                int x1 = oldx;
                int y1 = oldy;
                int x2 = newx;
                int y2 = newy;
                for (int x = x1 > x2 ? x2 : x1; (x1 > x2) ? (x <= x1) : (x <= x2); x++)
                {
                    double fact  = ((double)x - x1) / (x2 - x1);
                    int    y     = (int)Math.Round(y1 + ((y2 - y1) * fact));
                    int    tilex = (int)Math.Floor(x / 32d);
                    int    tiley = (int)Math.Floor(y / 32d);
                    if (!TempCoords.Exists(c => c.X == tilex && c.Y == tiley))
                    {
                        TempCoords.Add(new Point(tilex, tiley));
                    }
                }
                int sy = y1 > y2 ? y2 : y1;
                for (int y = y1 > y2 ? y2 : y1; (y1 > y2) ? (y <= y1) : (y <= y2); y++)
                {
                    double fact  = ((double)y - y1) / (y2 - y1);
                    int    x     = (int)Math.Round(x1 + ((x2 - x1) * fact));
                    int    tilex = (int)Math.Floor(x / 32d);
                    int    tiley = (int)Math.Floor(y / 32d);
                    if (!TempCoords.Exists(c => c.X == tilex && c.Y == tiley))
                    {
                        TempCoords.Add(new Point(tilex, tiley));
                    }
                }
            }
            else if (point) // Just one singular tile
            {
                TempCoords.Add(new Point((int)Math.Floor(newx / 32d), (int)Math.Floor(newy / 32d)));
            }

            SetLayerLocked(layer, false);
            for (int i = 0; i < TempCoords.Count; i++)
            {
                // Both of these depend on the origin, but we need them both at the top left as we begin drawing there
                // and to be able to compare them to use in the modulus, they both have to be adjusted
                int MapTileX = TempCoords[i].X;
                int MapTileY = TempCoords[i].Y;
                int OriginX  = MapViewer.OriginPoint.X;
                int OriginY  = MapViewer.OriginPoint.Y;
                if (MapViewer.CursorOrigin == Location.TopRight || MapViewer.CursorOrigin == Location.BottomRight)
                {
                    MapTileX -= MapViewer.CursorWidth;
                    OriginX  -= MapViewer.CursorWidth;
                }
                if (MapViewer.CursorOrigin == Location.BottomLeft || MapViewer.CursorOrigin == Location.BottomRight)
                {
                    MapTileY -= MapViewer.CursorHeight;
                    OriginY  -= MapViewer.CursorHeight;
                }
                // MapTileX and MapTileY are now the top left no matter the origin point
                int SelArea = MapViewer.TileDataList.Count;

                int OriginDiffX = (OriginX - MapTileX) % (MapViewer.CursorWidth + 1);
                int OriginDiffY = (OriginY - MapTileY) % (MapViewer.CursorHeight + 1);

                for (int j = 0; j < SelArea; j++)
                {
                    bool Blank = blanktile;

                    int actualx     = MapTileX + (j % (MapViewer.CursorWidth + 1));
                    int actualy     = MapTileY + (int)Math.Floor((double)j / (MapViewer.CursorWidth + 1));
                    int MapPosition = actualx + actualy * MapData.Width;
                    if (actualx < 0 || actualx >= MapData.Width || actualy < 0 || actualy >= MapData.Height)
                    {
                        continue;
                    }
                    if (MapViewer.SelectionX != -1 && MapViewer.SelectionY != -1 && MapViewer.SelectionWidth != 0 && MapViewer.SelectionHeight != 0 && MapViewer.SelectionBackground.Visible)
                    {
                        // NOT within the selection
                        if (!(actualx >= MapViewer.SelectionX && actualx < MapViewer.SelectionX + MapViewer.SelectionWidth &&
                              actualy >= MapViewer.SelectionY && actualy < MapViewer.SelectionY + MapViewer.SelectionHeight))
                        {
                            continue;
                        }
                    }

                    int selx = j % (MapViewer.CursorWidth + 1);
                    if (OriginDiffX < 0)
                    {
                        selx -= OriginDiffX;
                    }
                    if (OriginDiffX > 0)
                    {
                        selx -= OriginDiffX;
                    }
                    if (selx < 0)
                    {
                        selx += MapViewer.CursorWidth + 1;
                    }
                    selx %= MapViewer.CursorWidth + 1;
                    int sely = (int)Math.Floor((double)j / (MapViewer.CursorWidth + 1));
                    if (OriginDiffY < 0)
                    {
                        sely -= OriginDiffY;
                    }
                    if (OriginDiffY > 0)
                    {
                        sely -= OriginDiffY;
                    }
                    if (sely < 0)
                    {
                        sely += MapViewer.CursorHeight + 1;
                    }
                    sely %= MapViewer.CursorHeight + 1;

                    TileData tiledata = MapViewer.TileDataList[sely * (MapViewer.CursorWidth + 1) + selx];
                    TileType tiletype = TileType.Tileset;
                    int      tileid   = -1;
                    int      index    = -1;
                    if (tiledata != null)
                    {
                        tiletype = tiledata.TileType;
                        tileid   = tiledata.ID;
                        index    = tiledata.Index;
                    }
                    else
                    {
                        Blank = true;
                    }

                    TileData OldTile = MapData.Layers[layer].Tiles[MapPosition];
                    TileData NewTile = null;
                    if (!Blank)
                    {
                        NewTile = new TileData
                        {
                            TileType = tiletype,
                            Index    = index,
                            ID       = tileid
                        };
                    }

                    bool SameTile = true;
                    if (OldTile == null && NewTile != null ||
                        OldTile != null && NewTile == null)
                    {
                        SameTile = false;
                    }
                    else if (OldTile != null && OldTile.TileType != NewTile.TileType)
                    {
                        SameTile = false;
                    }
                    else if (OldTile != null && OldTile.Index != NewTile.Index)
                    {
                        SameTile = false;
                    }
                    else if (OldTile != null && OldTile.TileType != TileType.Autotile && OldTile.ID != NewTile.ID)
                    {
                        SameTile = false;
                    }

                    if (!SameTile)
                    {
                        MapData.Layers[layer].Tiles[MapPosition] = NewTile;
                        if (TileGroupUndoAction.GetLatest() == null || TileGroupUndoAction.GetLatest().Ready)
                        {
                            Editor.CanUndo = false;
                            TileGroupUndoAction.Log(MapID, layer);
                        }
                        TileGroupUndoAction.AddToLatest(MapPosition, NewTile, OldTile);
                        DrawTile(actualx, actualy, layer, NewTile, OldTile);
                    }
                }
            }
            SetLayerLocked(layer, true);
        }